xref: /titanic_52/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.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 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_SLI4_C);
32 
33 static int		emlxs_sli4_init_extents(emlxs_hba_t *hba,
34 				MAILBOXQ *mbq);
35 static uint32_t		emlxs_sli4_read_status(emlxs_hba_t *hba);
36 
37 static int		emlxs_init_bootstrap_mb(emlxs_hba_t *hba);
38 
39 static uint32_t		emlxs_sli4_read_sema(emlxs_hba_t *hba);
40 
41 static uint32_t		emlxs_sli4_read_mbdb(emlxs_hba_t *hba);
42 
43 static void		emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint32_t value);
44 
45 static void		emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint32_t value);
46 
47 static void		emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint32_t value);
48 
49 static void		emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint32_t value);
50 
51 static void		emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint32_t value);
52 
53 static int		emlxs_sli4_create_queues(emlxs_hba_t *hba,
54 				MAILBOXQ *mbq);
55 static int		emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba,
56 				MAILBOXQ *mbq);
57 static int		emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba,
58 				MAILBOXQ *mbq);
59 
60 static int		emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq);
61 
62 static int		emlxs_sli4_map_hdw(emlxs_hba_t *hba);
63 
64 static void		emlxs_sli4_unmap_hdw(emlxs_hba_t *hba);
65 
66 static int32_t		emlxs_sli4_online(emlxs_hba_t *hba);
67 
68 static void		emlxs_sli4_offline(emlxs_hba_t *hba,
69 				uint32_t reset_requested);
70 
71 static uint32_t		emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart,
72 				uint32_t skip_post, uint32_t quiesce);
73 static void		emlxs_sli4_hba_kill(emlxs_hba_t *hba);
74 
75 static uint32_t		emlxs_sli4_hba_init(emlxs_hba_t *hba);
76 
77 static uint32_t		emlxs_sli4_bde_setup(emlxs_port_t *port,
78 				emlxs_buf_t *sbp);
79 
80 static void		emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba,
81 				CHANNEL *cp, IOCBQ *iocb_cmd);
82 static uint32_t		emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba,
83 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
84 static uint32_t		emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba,
85 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
86 #ifdef SFCT_SUPPORT
87 static uint32_t		emlxs_sli4_prep_fct_iocb(emlxs_port_t *port,
88 				emlxs_buf_t *cmd_sbp, int channel);
89 static uint32_t		emlxs_sli4_fct_bde_setup(emlxs_port_t *port,
90 				emlxs_buf_t *sbp);
91 #endif /* SFCT_SUPPORT */
92 
93 static uint32_t		emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port,
94 				emlxs_buf_t *sbp, int ring);
95 static uint32_t		emlxs_sli4_prep_ip_iocb(emlxs_port_t *port,
96 				emlxs_buf_t *sbp);
97 static uint32_t		emlxs_sli4_prep_els_iocb(emlxs_port_t *port,
98 				emlxs_buf_t *sbp);
99 static uint32_t		emlxs_sli4_prep_ct_iocb(emlxs_port_t *port,
100 				emlxs_buf_t *sbp);
101 static void		emlxs_sli4_poll_intr(emlxs_hba_t *hba);
102 static int32_t		emlxs_sli4_intx_intr(char *arg);
103 
104 #ifdef MSI_SUPPORT
105 static uint32_t		emlxs_sli4_msi_intr(char *arg1, char *arg2);
106 #endif /* MSI_SUPPORT */
107 
108 static void		emlxs_sli4_resource_free(emlxs_hba_t *hba);
109 
110 static int		emlxs_sli4_resource_alloc(emlxs_hba_t *hba);
111 extern void		emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba);
112 
113 static XRIobj_t		*emlxs_sli4_alloc_xri(emlxs_port_t *port,
114 				emlxs_buf_t *sbp, RPIobj_t *rpip,
115 				uint32_t type);
116 static void		emlxs_sli4_enable_intr(emlxs_hba_t *hba);
117 
118 static void		emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att);
119 
120 static void		emlxs_sli4_timer(emlxs_hba_t *hba);
121 
122 static void		emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
123 
124 static void		emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
125 
126 extern XRIobj_t 	*emlxs_sli4_reserve_xri(emlxs_port_t *port,
127 				RPIobj_t *rpip, uint32_t type, uint16_t rx_id);
128 static int		emlxs_check_hdw_ready(emlxs_hba_t *);
129 
130 static uint32_t		emlxs_sli4_reg_did(emlxs_port_t *port,
131 				uint32_t did, SERV_PARM *param,
132 				emlxs_buf_t *sbp, fc_unsol_buf_t *ubp,
133 				IOCBQ *iocbq);
134 
135 static uint32_t		emlxs_sli4_unreg_node(emlxs_port_t *port,
136 				emlxs_node_t *node, emlxs_buf_t *sbp,
137 				fc_unsol_buf_t *ubp, IOCBQ *iocbq);
138 
139 static void		emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba,
140 				CQE_ASYNC_t *cqe);
141 static void		emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba,
142 				CQE_ASYNC_t *cqe);
143 
144 
145 static uint16_t		emlxs_sli4_rqid_to_index(emlxs_hba_t *hba,
146 				uint16_t rqid);
147 static uint16_t		emlxs_sli4_wqid_to_index(emlxs_hba_t *hba,
148 				uint16_t wqid);
149 static uint16_t		emlxs_sli4_cqid_to_index(emlxs_hba_t *hba,
150 				uint16_t cqid);
151 
152 /* Define SLI4 API functions */
153 emlxs_sli_api_t emlxs_sli4_api = {
154 	emlxs_sli4_map_hdw,
155 	emlxs_sli4_unmap_hdw,
156 	emlxs_sli4_online,
157 	emlxs_sli4_offline,
158 	emlxs_sli4_hba_reset,
159 	emlxs_sli4_hba_kill,
160 	emlxs_sli4_issue_iocb_cmd,
161 	emlxs_sli4_issue_mbox_cmd,
162 #ifdef SFCT_SUPPORT
163 	emlxs_sli4_prep_fct_iocb,
164 #else
165 	NULL,
166 #endif /* SFCT_SUPPORT */
167 	emlxs_sli4_prep_fcp_iocb,
168 	emlxs_sli4_prep_ip_iocb,
169 	emlxs_sli4_prep_els_iocb,
170 	emlxs_sli4_prep_ct_iocb,
171 	emlxs_sli4_poll_intr,
172 	emlxs_sli4_intx_intr,
173 	emlxs_sli4_msi_intr,
174 	emlxs_sli4_disable_intr,
175 	emlxs_sli4_timer,
176 	emlxs_sli4_poll_erratt,
177 	emlxs_sli4_reg_did,
178 	emlxs_sli4_unreg_node
179 };
180 
181 
182 /* ************************************************************************** */
183 
184 static void
185 emlxs_sli4_set_default_params(emlxs_hba_t *hba)
186 {
187 	emlxs_port_t *port = &PPORT;
188 
189 	bzero((char *)&hba->sli.sli4.param, sizeof (sli_params_t));
190 
191 	hba->sli.sli4.param.ProtocolType = 0x3; /* FC/FCoE */
192 
193 	hba->sli.sli4.param.SliHint2 = 0;
194 	hba->sli.sli4.param.SliHint1 = 0;
195 	hba->sli.sli4.param.IfType = 0;
196 	hba->sli.sli4.param.SliFamily = 0;
197 	hba->sli.sli4.param.Revision = 0x4; /* SLI4 */
198 	hba->sli.sli4.param.FT = 0;
199 
200 	hba->sli.sli4.param.EqeCntMethod = 0x1; /* Bit pattern */
201 	hba->sli.sli4.param.EqPageSize = 0x1; /* 4096 */
202 	hba->sli.sli4.param.EqeSize = 0x1; /* 4 byte */
203 	hba->sli.sli4.param.EqPageCnt = 8;
204 	hba->sli.sli4.param.EqeCntMask = 0x1F; /* 256-4096 elements */
205 
206 	hba->sli.sli4.param.CqeCntMethod = 0x1; /* Bit pattern */
207 	hba->sli.sli4.param.CqPageSize = 0x1; /* 4096 */
208 	hba->sli.sli4.param.CQV = 0;
209 	hba->sli.sli4.param.CqeSize = 0x3; /* 16 byte */
210 	hba->sli.sli4.param.CqPageCnt = 4;
211 	hba->sli.sli4.param.CqeCntMask = 0x70; /* 256-1024 elements */
212 
213 	hba->sli.sli4.param.MqeCntMethod = 0x1; /* Bit pattern */
214 	hba->sli.sli4.param.MqPageSize = 0x1; /* 4096 */
215 	hba->sli.sli4.param.MQV = 0;
216 	hba->sli.sli4.param.MqPageCnt = 8;
217 	hba->sli.sli4.param.MqeCntMask = 0x0F; /* 16-128 elements */
218 
219 	hba->sli.sli4.param.WqeCntMethod = 0; /* Page Count */
220 	hba->sli.sli4.param.WqPageSize = 0x1; /* 4096 */
221 	hba->sli.sli4.param.WQV = 0;
222 	hba->sli.sli4.param.WqeSize = 0x5; /* 64 byte */
223 	hba->sli.sli4.param.WqPageCnt = 4;
224 	hba->sli.sli4.param.WqeCntMask = 0x10; /* 256 elements */
225 
226 	hba->sli.sli4.param.RqeCntMethod = 0; /* Page Count */
227 	hba->sli.sli4.param.RqPageSize = 0x1; /* 4096 */
228 	hba->sli.sli4.param.RQV = 0;
229 	hba->sli.sli4.param.RqeSize = 0x2; /* 8 byte */
230 	hba->sli.sli4.param.RqPageCnt = 8;
231 	hba->sli.sli4.param.RqDbWin = 1;
232 	hba->sli.sli4.param.RqeCntMask = 0x100; /* 4096 elements */
233 
234 	hba->sli.sli4.param.Loopback = 0xf; /* unsupported */
235 	hba->sli.sli4.param.PHWQ = 0;
236 	hba->sli.sli4.param.PHON = 0;
237 	hba->sli.sli4.param.TRIR = 0;
238 	hba->sli.sli4.param.TRTY = 0;
239 	hba->sli.sli4.param.TCCA = 0;
240 	hba->sli.sli4.param.MWQE = 0;
241 	hba->sli.sli4.param.ASSI = 0;
242 	hba->sli.sli4.param.TERP = 0;
243 	hba->sli.sli4.param.TGT  = 0;
244 	hba->sli.sli4.param.AREG = 0;
245 	hba->sli.sli4.param.FBRR = 0;
246 	hba->sli.sli4.param.SGLR = 1;
247 	hba->sli.sli4.param.HDRR = 1;
248 	hba->sli.sli4.param.EXT  = 0;
249 	hba->sli.sli4.param.FCOE = 1;
250 
251 	hba->sli.sli4.param.SgeLength = (64 * 1024);
252 	hba->sli.sli4.param.SglAlign = 0x7 /* 4096 */;
253 	hba->sli.sli4.param.SglPageSize = 0x1; /* 4096 */
254 	hba->sli.sli4.param.SglPageCnt = 2;
255 
256 	hba->sli.sli4.param.MinRqSize = 128;
257 	hba->sli.sli4.param.MaxRqSize = 2048;
258 
259 	hba->sli.sli4.param.RPIMax = 0x3ff;
260 	hba->sli.sli4.param.XRIMax = 0x3ff;
261 	hba->sli.sli4.param.VFIMax = 0xff;
262 	hba->sli.sli4.param.VPIMax = 0xff;
263 
264 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
265 	    "Default SLI4 parameters set.");
266 
267 } /* emlxs_sli4_set_default_params() */
268 
269 
270 /*
271  * emlxs_sli4_online()
272  *
273  * This routine will start initialization of the SLI4 HBA.
274  */
275 static int32_t
276 emlxs_sli4_online(emlxs_hba_t *hba)
277 {
278 	emlxs_port_t *port = &PPORT;
279 	emlxs_config_t *cfg;
280 	emlxs_vpd_t *vpd;
281 	MAILBOXQ *mbq = NULL;
282 	MAILBOX4 *mb  = NULL;
283 	MATCHMAP *mp  = NULL;
284 	uint32_t i;
285 	uint32_t j;
286 	uint32_t rval = 0;
287 	uint8_t *vpd_data;
288 	uint32_t sli_mode;
289 	uint8_t *outptr;
290 	uint32_t status;
291 	uint32_t fw_check;
292 	uint32_t kern_update = 0;
293 	emlxs_firmware_t hba_fw;
294 	emlxs_firmware_t *fw;
295 	uint16_t ssvid;
296 	char buf[64];
297 
298 	cfg = &CFG;
299 	vpd = &VPD;
300 
301 	sli_mode = EMLXS_HBA_SLI4_MODE;
302 	hba->sli_mode = sli_mode;
303 
304 	/* Set the fw_check flag */
305 	fw_check = cfg[CFG_FW_CHECK].current;
306 
307 	if ((fw_check & 0x04) ||
308 	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
309 		kern_update = 1;
310 	}
311 
312 	hba->mbox_queue_flag = 0;
313 	hba->fc_edtov = FF_DEF_EDTOV;
314 	hba->fc_ratov = FF_DEF_RATOV;
315 	hba->fc_altov = FF_DEF_ALTOV;
316 	hba->fc_arbtov = FF_DEF_ARBTOV;
317 
318 	/* Networking not supported */
319 	if (cfg[CFG_NETWORK_ON].current) {
320 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
321 		    "Networking is not supported in SLI4, turning it off");
322 		cfg[CFG_NETWORK_ON].current = 0;
323 	}
324 
325 	hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
326 	if (hba->chan_count > MAX_CHANNEL) {
327 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
328 		    "Max channels exceeded, dropping num-wq from %d to 1",
329 		    cfg[CFG_NUM_WQ].current);
330 		cfg[CFG_NUM_WQ].current = 1;
331 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
332 	}
333 	hba->channel_fcp = 0; /* First channel */
334 
335 	/* Default channel for everything else is the last channel */
336 	hba->channel_ip = hba->chan_count - 1;
337 	hba->channel_els = hba->chan_count - 1;
338 	hba->channel_ct = hba->chan_count - 1;
339 
340 	hba->fc_iotag = 1;
341 	hba->io_count = 0;
342 	hba->channel_tx_count = 0;
343 
344 	/* Initialize the local dump region buffer */
345 	bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
346 	hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
347 	hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
348 	    | FC_MBUF_DMA32;
349 	hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L);
350 
351 	(void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region);
352 
353 	if (hba->sli.sli4.dump_region.virt == NULL) {
354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
355 		    "Unable to allocate dump region buffer.");
356 
357 		return (ENOMEM);
358 	}
359 
360 	/*
361 	 * Get a buffer which will be used repeatedly for mailbox commands
362 	 */
363 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
364 
365 	mb = (MAILBOX4 *)mbq;
366 
367 reset:
368 	/* Reset & Initialize the adapter */
369 	if (emlxs_sli4_hba_init(hba)) {
370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
371 		    "Unable to init hba.");
372 
373 		rval = EIO;
374 		goto failed1;
375 	}
376 
377 #ifdef FMA_SUPPORT
378 	/* Access handle validation */
379 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
380 	case SLI_INTF_IF_TYPE_2:
381 		if ((emlxs_fm_check_acc_handle(hba,
382 		    hba->pci_acc_handle) != DDI_FM_OK) ||
383 		    (emlxs_fm_check_acc_handle(hba,
384 		    hba->sli.sli4.bar0_acc_handle) != DDI_FM_OK)) {
385 			EMLXS_MSGF(EMLXS_CONTEXT,
386 			    &emlxs_invalid_access_handle_msg, NULL);
387 
388 			rval = EIO;
389 			goto failed1;
390 		}
391 		break;
392 
393 	default :
394 		if ((emlxs_fm_check_acc_handle(hba,
395 		    hba->pci_acc_handle) != DDI_FM_OK) ||
396 		    (emlxs_fm_check_acc_handle(hba,
397 		    hba->sli.sli4.bar1_acc_handle) != DDI_FM_OK) ||
398 		    (emlxs_fm_check_acc_handle(hba,
399 		    hba->sli.sli4.bar2_acc_handle) != DDI_FM_OK)) {
400 			EMLXS_MSGF(EMLXS_CONTEXT,
401 			    &emlxs_invalid_access_handle_msg, NULL);
402 
403 			rval = EIO;
404 			goto failed1;
405 		}
406 		break;
407 	}
408 #endif	/* FMA_SUPPORT */
409 
410 	/*
411 	 * Setup and issue mailbox READ REV command
412 	 */
413 	vpd->opFwRev = 0;
414 	vpd->postKernRev = 0;
415 	vpd->sli1FwRev = 0;
416 	vpd->sli2FwRev = 0;
417 	vpd->sli3FwRev = 0;
418 	vpd->sli4FwRev = 0;
419 
420 	vpd->postKernName[0] = 0;
421 	vpd->opFwName[0] = 0;
422 	vpd->sli1FwName[0] = 0;
423 	vpd->sli2FwName[0] = 0;
424 	vpd->sli3FwName[0] = 0;
425 	vpd->sli4FwName[0] = 0;
426 
427 	vpd->opFwLabel[0] = 0;
428 	vpd->sli1FwLabel[0] = 0;
429 	vpd->sli2FwLabel[0] = 0;
430 	vpd->sli3FwLabel[0] = 0;
431 	vpd->sli4FwLabel[0] = 0;
432 
433 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
434 
435 	emlxs_mb_get_sli4_params(hba, mbq);
436 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
437 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
438 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
439 		    mb->mbxCommand, mb->mbxStatus);
440 
441 		/* Set param defaults */
442 		emlxs_sli4_set_default_params(hba);
443 
444 	} else {
445 		/* Save parameters */
446 		bcopy((char *)&mb->un.varSLIConfig.payload,
447 		    (char *)&hba->sli.sli4.param, sizeof (sli_params_t));
448 
449 		emlxs_data_dump(port, "SLI_PARMS",
450 		    (uint32_t *)&hba->sli.sli4.param,
451 		    sizeof (sli_params_t), 0);
452 	}
453 
454 	/* Reuse mbq from previous mbox */
455 	bzero(mbq, sizeof (MAILBOXQ));
456 
457 	emlxs_mb_get_port_name(hba, mbq);
458 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
459 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
460 		    "Unable to get port names. Mailbox cmd=%x status=%x",
461 		    mb->mbxCommand, mb->mbxStatus);
462 
463 		bzero(hba->sli.sli4.port_name,
464 		    sizeof (hba->sli.sli4.port_name));
465 	} else {
466 		/* Save port names */
467 		bcopy((char *)&mb->un.varSLIConfig.payload,
468 		    (char *)&hba->sli.sli4.port_name,
469 		    sizeof (hba->sli.sli4.port_name));
470 	}
471 
472 	/* Reuse mbq from previous mbox */
473 	bzero(mbq, sizeof (MAILBOXQ));
474 
475 	emlxs_mb_read_rev(hba, mbq, 0);
476 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
477 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
478 		    "Unable to read rev. Mailbox cmd=%x status=%x",
479 		    mb->mbxCommand, mb->mbxStatus);
480 
481 		rval = EIO;
482 		goto failed1;
483 
484 	}
485 
486 	emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0);
487 	if (mb->un.varRdRev4.sliLevel != 4) {
488 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
489 		    "Invalid read rev Version for SLI4: 0x%x",
490 		    mb->un.varRdRev4.sliLevel);
491 
492 		rval = EIO;
493 		goto failed1;
494 	}
495 
496 	switch (mb->un.varRdRev4.dcbxMode) {
497 	case EMLXS_DCBX_MODE_CIN:	/* Mapped to nonFIP mode */
498 		hba->flag &= ~FC_FIP_SUPPORTED;
499 		break;
500 
501 	case EMLXS_DCBX_MODE_CEE:	/* Mapped to FIP mode */
502 		hba->flag |= FC_FIP_SUPPORTED;
503 		break;
504 
505 	default:
506 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
507 		    "Invalid read rev dcbx mode for SLI4: 0x%x",
508 		    mb->un.varRdRev4.dcbxMode);
509 
510 		rval = EIO;
511 		goto failed1;
512 	}
513 
514 	/* Set FC/FCoE mode */
515 	if (mb->un.varRdRev4.FCoE) {
516 		hba->sli.sli4.flag |= EMLXS_SLI4_FCOE_MODE;
517 	} else {
518 		hba->sli.sli4.flag &= ~EMLXS_SLI4_FCOE_MODE;
519 	}
520 
521 	/* Save information as VPD data */
522 	vpd->rBit = 1;
523 
524 	vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId);
525 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16);
526 
527 	vpd->opFwRev = (mb->un.varRdRev4.ULPFwId);
528 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16);
529 
530 	vpd->postKernRev = (mb->un.varRdRev4.ARMFwId);
531 	bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16);
532 
533 	vpd->biuRev = mb->un.varRdRev4.HwRev1;
534 	vpd->fcphHigh = mb->un.varRdRev4.fcphHigh;
535 	vpd->fcphLow = mb->un.varRdRev4.fcphLow;
536 	vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh;
537 	vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow;
538 
539 	/* Decode FW labels */
540 	if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
541 		bcopy(vpd->postKernName, vpd->sli4FwName, 16);
542 	}
543 	emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0,
544 	    sizeof (vpd->sli4FwName));
545 	emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0,
546 	    sizeof (vpd->opFwName));
547 	emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0,
548 	    sizeof (vpd->postKernName));
549 
550 	if (hba->model_info.chip == EMLXS_BE2_CHIP) {
551 		(void) strlcpy(vpd->sli4FwLabel, "be2.ufi",
552 		    sizeof (vpd->sli4FwLabel));
553 	} else if (hba->model_info.chip == EMLXS_BE3_CHIP) {
554 		(void) strlcpy(vpd->sli4FwLabel, "be3.ufi",
555 		    sizeof (vpd->sli4FwLabel));
556 	} else if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
557 		(void) strlcpy(vpd->sli4FwLabel, "xe201.grp",
558 		    sizeof (vpd->sli4FwLabel));
559 	} else {
560 		(void) strlcpy(vpd->sli4FwLabel, "sli4.fw",
561 		    sizeof (vpd->sli4FwLabel));
562 	}
563 
564 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
565 	    "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
566 	    vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName,
567 	    vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow,
568 	    mb->un.varRdRev4.dcbxMode);
569 
570 	/* No key information is needed for SLI4 products */
571 
572 	/* Get adapter VPD information */
573 	vpd->port_index = (uint32_t)-1;
574 
575 	/* Reuse mbq from previous mbox */
576 	bzero(mbq, sizeof (MAILBOXQ));
577 
578 	emlxs_mb_dump_vpd(hba, mbq, 0);
579 	vpd_data = hba->sli.sli4.dump_region.virt;
580 
581 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
582 	    MBX_SUCCESS) {
583 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
584 		    "No VPD found. status=%x", mb->mbxStatus);
585 	} else {
586 		EMLXS_MSGF(EMLXS_CONTEXT,
587 		    &emlxs_init_debug_msg,
588 		    "VPD dumped. rsp_cnt=%d status=%x",
589 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
590 
591 		if (mb->un.varDmp4.rsp_cnt) {
592 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
593 			    0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL);
594 
595 #ifdef FMA_SUPPORT
596 			if (hba->sli.sli4.dump_region.dma_handle) {
597 				if (emlxs_fm_check_dma_handle(hba,
598 				    hba->sli.sli4.dump_region.dma_handle)
599 				    != DDI_FM_OK) {
600 					EMLXS_MSGF(EMLXS_CONTEXT,
601 					    &emlxs_invalid_dma_handle_msg,
602 					    "sli4_online: hdl=%p",
603 					    hba->sli.sli4.dump_region.
604 					    dma_handle);
605 					rval = EIO;
606 					goto failed1;
607 				}
608 			}
609 #endif /* FMA_SUPPORT */
610 
611 		}
612 	}
613 
614 	if (vpd_data[0]) {
615 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data,
616 		    mb->un.varDmp4.rsp_cnt);
617 
618 		/*
619 		 * If there is a VPD part number, and it does not
620 		 * match the current default HBA model info,
621 		 * replace the default data with an entry that
622 		 * does match.
623 		 *
624 		 * After emlxs_parse_vpd model holds the VPD value
625 		 * for V2 and part_num hold the value for PN. These
626 		 * 2 values are NOT necessarily the same.
627 		 */
628 
629 		rval = 0;
630 		if ((vpd->model[0] != 0) &&
631 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
632 
633 			/* First scan for a V2 match */
634 
635 			for (i = 1; i < emlxs_pci_model_count; i++) {
636 				if (strcmp(&vpd->model[0],
637 				    emlxs_pci_model[i].model) == 0) {
638 					bcopy(&emlxs_pci_model[i],
639 					    &hba->model_info,
640 					    sizeof (emlxs_model_t));
641 					rval = 1;
642 					break;
643 				}
644 			}
645 		}
646 
647 		if (!rval && (vpd->part_num[0] != 0) &&
648 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
649 
650 			/* Next scan for a PN match */
651 
652 			for (i = 1; i < emlxs_pci_model_count; i++) {
653 				if (strcmp(&vpd->part_num[0],
654 				    emlxs_pci_model[i].model) == 0) {
655 					bcopy(&emlxs_pci_model[i],
656 					    &hba->model_info,
657 					    sizeof (emlxs_model_t));
658 					break;
659 				}
660 			}
661 		}
662 
663 		/* HP CNA port indices start at 1 instead of 0 */
664 		if (hba->model_info.chip & EMLXS_BE_CHIPS) {
665 			ssvid = ddi_get16(hba->pci_acc_handle,
666 			    (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER));
667 
668 			if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) {
669 				vpd->port_index--;
670 			}
671 		}
672 
673 		/*
674 		 * Now lets update hba->model_info with the real
675 		 * VPD data, if any.
676 		 */
677 
678 		/*
679 		 * Replace the default model description with vpd data
680 		 */
681 		if (vpd->model_desc[0] != 0) {
682 			(void) strncpy(hba->model_info.model_desc,
683 			    vpd->model_desc,
684 			    (sizeof (hba->model_info.model_desc)-1));
685 		}
686 
687 		/* Replace the default model with vpd data */
688 		if (vpd->model[0] != 0) {
689 			(void) strncpy(hba->model_info.model, vpd->model,
690 			    (sizeof (hba->model_info.model)-1));
691 		}
692 
693 		/* Replace the default program types with vpd data */
694 		if (vpd->prog_types[0] != 0) {
695 			emlxs_parse_prog_types(hba, vpd->prog_types);
696 		}
697 	}
698 
699 	/*
700 	 * Since the adapter model may have changed with the vpd data
701 	 * lets double check if adapter is not supported
702 	 */
703 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
704 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
705 		    "Unsupported adapter found.  "
706 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
707 		    hba->model_info.id, hba->model_info.device_id,
708 		    hba->model_info.ssdid, hba->model_info.model);
709 
710 		rval = EIO;
711 		goto failed1;
712 	}
713 
714 	(void) strncpy(vpd->boot_version, vpd->sli4FwName,
715 	    (sizeof (vpd->boot_version)-1));
716 
717 	/* Get fcode version property */
718 	emlxs_get_fcode_version(hba);
719 
720 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
721 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
722 	    vpd->opFwRev, vpd->sli1FwRev);
723 
724 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
725 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
726 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
727 
728 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
729 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
730 
731 	/*
732 	 * If firmware checking is enabled and the adapter model indicates
733 	 * a firmware image, then perform firmware version check
734 	 */
735 	hba->fw_flag = 0;
736 	hba->fw_timer = 0;
737 
738 	if (((fw_check & 0x1) &&
739 	    (hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
740 	    hba->model_info.fwid) ||
741 	    ((fw_check & 0x2) && hba->model_info.fwid)) {
742 
743 		/* Find firmware image indicated by adapter model */
744 		fw = NULL;
745 		for (i = 0; i < emlxs_fw_count; i++) {
746 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
747 				fw = &emlxs_fw_table[i];
748 				break;
749 			}
750 		}
751 
752 		/*
753 		 * If the image was found, then verify current firmware
754 		 * versions of adapter
755 		 */
756 		if (fw) {
757 			/* Obtain current firmware version info */
758 			if (hba->model_info.chip & EMLXS_BE_CHIPS) {
759 				(void) emlxs_be_read_fw_version(hba, &hba_fw);
760 			} else {
761 				hba_fw.kern = vpd->postKernRev;
762 				hba_fw.stub = vpd->opFwRev;
763 				hba_fw.sli1 = vpd->sli1FwRev;
764 				hba_fw.sli2 = vpd->sli2FwRev;
765 				hba_fw.sli3 = vpd->sli3FwRev;
766 				hba_fw.sli4 = vpd->sli4FwRev;
767 			}
768 
769 			if (!kern_update &&
770 			    ((fw->kern && (hba_fw.kern != fw->kern)) ||
771 			    (fw->stub && (hba_fw.stub != fw->stub)))) {
772 
773 				hba->fw_flag |= FW_UPDATE_NEEDED;
774 
775 			} else if ((fw->kern && (hba_fw.kern != fw->kern)) ||
776 			    (fw->stub && (hba_fw.stub != fw->stub)) ||
777 			    (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
778 			    (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
779 			    (fw->sli3 && (hba_fw.sli3 != fw->sli3)) ||
780 			    (fw->sli4 && (hba_fw.sli4 != fw->sli4))) {
781 
782 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
783 				    "Firmware update needed. "
784 				    "Updating. id=%d fw=%d",
785 				    hba->model_info.id, hba->model_info.fwid);
786 
787 #ifdef MODFW_SUPPORT
788 				/*
789 				 * Load the firmware image now
790 				 * If MODFW_SUPPORT is not defined, the
791 				 * firmware image will already be defined
792 				 * in the emlxs_fw_table
793 				 */
794 				emlxs_fw_load(hba, fw);
795 #endif /* MODFW_SUPPORT */
796 
797 				if (fw->image && fw->size) {
798 					uint32_t rc;
799 
800 					rc = emlxs_fw_download(hba,
801 					    (char *)fw->image, fw->size, 0);
802 					if ((rc != FC_SUCCESS) &&
803 					    (rc != EMLXS_REBOOT_REQUIRED)) {
804 						EMLXS_MSGF(EMLXS_CONTEXT,
805 						    &emlxs_init_msg,
806 						    "Firmware update failed.");
807 						hba->fw_flag |=
808 						    FW_UPDATE_NEEDED;
809 					}
810 #ifdef MODFW_SUPPORT
811 					/*
812 					 * Unload the firmware image from
813 					 * kernel memory
814 					 */
815 					emlxs_fw_unload(hba, fw);
816 #endif /* MODFW_SUPPORT */
817 
818 					fw_check = 0;
819 
820 					goto reset;
821 				}
822 
823 				hba->fw_flag |= FW_UPDATE_NEEDED;
824 
825 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
826 				    "Firmware image unavailable.");
827 			} else {
828 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
829 				    "Firmware update not needed.");
830 			}
831 		} else {
832 			/*
833 			 * This means either the adapter database is not
834 			 * correct or a firmware image is missing from the
835 			 * compile
836 			 */
837 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
838 			    "Firmware image unavailable. id=%d fw=%d",
839 			    hba->model_info.id, hba->model_info.fwid);
840 		}
841 	}
842 
843 	/* Reuse mbq from previous mbox */
844 	bzero(mbq, sizeof (MAILBOXQ));
845 
846 	emlxs_mb_dump_fcoe(hba, mbq, 0);
847 
848 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
849 	    MBX_SUCCESS) {
850 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
851 		    "No FCOE info found. status=%x", mb->mbxStatus);
852 	} else {
853 		EMLXS_MSGF(EMLXS_CONTEXT,
854 		    &emlxs_init_debug_msg,
855 		    "FCOE info dumped. rsp_cnt=%d status=%x",
856 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
857 		(void) emlxs_parse_fcoe(hba,
858 		    (uint8_t *)hba->sli.sli4.dump_region.virt,
859 		    mb->un.varDmp4.rsp_cnt);
860 	}
861 
862 	/* Reuse mbq from previous mbox */
863 	bzero(mbq, sizeof (MAILBOXQ));
864 
865 	status = 0;
866 	if (port->flag & EMLXS_INI_ENABLED) {
867 		status |= SLI4_FEATURE_FCP_INITIATOR;
868 	}
869 	if (port->flag & EMLXS_TGT_ENABLED) {
870 		status |= SLI4_FEATURE_FCP_TARGET;
871 	}
872 	if (cfg[CFG_NPIV_ENABLE].current) {
873 		status |= SLI4_FEATURE_NPIV;
874 	}
875 	if (cfg[CFG_RQD_MODE].current) {
876 		status |= SLI4_FEATURE_RQD;
877 	}
878 	if (cfg[CFG_PERF_HINT].current) {
879 		if (hba->sli.sli4.param.PHON) {
880 			status |= SLI4_FEATURE_PERF_HINT;
881 		}
882 	}
883 
884 	emlxs_mb_request_features(hba, mbq, status);
885 
886 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
887 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
888 		    "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
889 		    mb->mbxCommand, mb->mbxStatus);
890 
891 		rval = EIO;
892 		goto failed1;
893 	}
894 	emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0);
895 
896 	/* Check to see if we get the features we requested */
897 	if (status != mb->un.varReqFeatures.featuresEnabled) {
898 
899 		/* Just report descrepencies, don't abort the attach */
900 
901 		outptr = (uint8_t *)emlxs_request_feature_xlate(
902 		    mb->un.varReqFeatures.featuresRequested);
903 		(void) strlcpy(buf, (char *)outptr, sizeof (buf));
904 
905 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
906 		    "REQUEST_FEATURES: wanted:%s  got:%s",
907 		    &buf[0], emlxs_request_feature_xlate(
908 		    mb->un.varReqFeatures.featuresEnabled));
909 
910 	}
911 
912 	if ((port->flag & EMLXS_INI_ENABLED) &&
913 	    !(mb->un.varReqFeatures.featuresEnabled &
914 	    SLI4_FEATURE_FCP_INITIATOR)) {
915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
916 		    "Initiator mode not supported by adapter.");
917 
918 		rval = EIO;
919 
920 #ifdef SFCT_SUPPORT
921 		/* Check if we can fall back to just target mode */
922 		if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
923 		    (mb->un.varReqFeatures.featuresEnabled &
924 		    SLI4_FEATURE_FCP_TARGET) &&
925 		    (cfg[CFG_DTM_ENABLE].current == 1) &&
926 		    (cfg[CFG_TARGET_MODE].current == 1)) {
927 
928 			cfg[CFG_DTM_ENABLE].current = 0;
929 
930 			EMLXS_MSGF(EMLXS_CONTEXT,
931 			    &emlxs_init_failed_msg,
932 			    "Disabling dynamic target mode. "
933 			    "Enabling target mode only.");
934 
935 			/* This will trigger the driver to reattach */
936 			rval = EAGAIN;
937 		}
938 #endif /* SFCT_SUPPORT */
939 		goto failed1;
940 	}
941 
942 	if ((port->flag & EMLXS_TGT_ENABLED) &&
943 	    !(mb->un.varReqFeatures.featuresEnabled &
944 	    SLI4_FEATURE_FCP_TARGET)) {
945 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
946 		    "Target mode not supported by adapter.");
947 
948 		rval = EIO;
949 
950 #ifdef SFCT_SUPPORT
951 		/* Check if we can fall back to just initiator mode */
952 		if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
953 		    (mb->un.varReqFeatures.featuresEnabled &
954 		    SLI4_FEATURE_FCP_INITIATOR) &&
955 		    (cfg[CFG_DTM_ENABLE].current == 1) &&
956 		    (cfg[CFG_TARGET_MODE].current == 0)) {
957 
958 			cfg[CFG_DTM_ENABLE].current = 0;
959 
960 			EMLXS_MSGF(EMLXS_CONTEXT,
961 			    &emlxs_init_failed_msg,
962 			    "Disabling dynamic target mode. "
963 			    "Enabling initiator mode only.");
964 
965 			/* This will trigger the driver to reattach */
966 			rval = EAGAIN;
967 		}
968 #endif /* SFCT_SUPPORT */
969 		goto failed1;
970 	}
971 
972 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) {
973 		hba->flag |= FC_NPIV_ENABLED;
974 	}
975 
976 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_PERF_HINT) {
977 		hba->sli.sli4.flag |= EMLXS_SLI4_PHON;
978 		if (hba->sli.sli4.param.PHWQ) {
979 			hba->sli.sli4.flag |= EMLXS_SLI4_PHWQ;
980 		}
981 	}
982 
983 	/* Reuse mbq from previous mbox */
984 	bzero(mbq, sizeof (MAILBOXQ));
985 
986 	emlxs_mb_read_config(hba, mbq);
987 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
988 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
989 		    "Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
990 		    mb->mbxCommand, mb->mbxStatus);
991 
992 		rval = EIO;
993 		goto failed1;
994 	}
995 	emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0);
996 
997 	/* Set default extents */
998 	hba->sli.sli4.XRICount = mb->un.varRdConfig4.XRICount;
999 	hba->sli.sli4.XRIExtCount = 1;
1000 	hba->sli.sli4.XRIExtSize = hba->sli.sli4.XRICount;
1001 	hba->sli.sli4.XRIBase[0] = mb->un.varRdConfig4.XRIBase;
1002 
1003 	hba->sli.sli4.RPICount = mb->un.varRdConfig4.RPICount;
1004 	hba->sli.sli4.RPIExtCount = 1;
1005 	hba->sli.sli4.RPIExtSize = hba->sli.sli4.RPICount;
1006 	hba->sli.sli4.RPIBase[0] = mb->un.varRdConfig4.RPIBase;
1007 
1008 	hba->sli.sli4.VPICount = mb->un.varRdConfig4.VPICount;
1009 	hba->sli.sli4.VPIExtCount = 1;
1010 	hba->sli.sli4.VPIExtSize = hba->sli.sli4.VPICount;
1011 	hba->sli.sli4.VPIBase[0] = mb->un.varRdConfig4.VPIBase;
1012 
1013 	hba->sli.sli4.VFICount = mb->un.varRdConfig4.VFICount;
1014 	hba->sli.sli4.VFIExtCount = 1;
1015 	hba->sli.sli4.VFIExtSize = hba->sli.sli4.VFICount;
1016 	hba->sli.sli4.VFIBase[0] = mb->un.varRdConfig4.VFIBase;
1017 
1018 	hba->sli.sli4.FCFICount = mb->un.varRdConfig4.FCFICount;
1019 
1020 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1021 	    "CONFIG: xri:%d rpi:%d vpi:%d vfi:%d fcfi:%d",
1022 	    hba->sli.sli4.XRICount,
1023 	    hba->sli.sli4.RPICount,
1024 	    hba->sli.sli4.VPICount,
1025 	    hba->sli.sli4.VFICount,
1026 	    hba->sli.sli4.FCFICount);
1027 
1028 	if ((hba->sli.sli4.XRICount == 0) ||
1029 	    (hba->sli.sli4.RPICount == 0) ||
1030 	    (hba->sli.sli4.VPICount == 0) ||
1031 	    (hba->sli.sli4.VFICount == 0) ||
1032 	    (hba->sli.sli4.FCFICount == 0)) {
1033 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1034 		    "Invalid extent value(s) - xri:%d rpi:%d vpi:%d "
1035 		    "vfi:%d fcfi:%d",
1036 		    hba->sli.sli4.XRICount,
1037 		    hba->sli.sli4.RPICount,
1038 		    hba->sli.sli4.VPICount,
1039 		    hba->sli.sli4.VFICount,
1040 		    hba->sli.sli4.FCFICount);
1041 
1042 		rval = EIO;
1043 		goto failed1;
1044 	}
1045 
1046 	if (mb->un.varRdConfig4.extents) {
1047 		if (emlxs_sli4_init_extents(hba, mbq)) {
1048 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1049 			    "Unable to initialize extents.");
1050 
1051 			rval = EIO;
1052 			goto failed1;
1053 		}
1054 	}
1055 
1056 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1057 	    "CONFIG: port_name:%c %c %c %c",
1058 	    hba->sli.sli4.port_name[0],
1059 	    hba->sli.sli4.port_name[1],
1060 	    hba->sli.sli4.port_name[2],
1061 	    hba->sli.sli4.port_name[3]);
1062 
1063 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1064 	    "CONFIG: ldv:%d link_type:%d link_number:%d",
1065 	    mb->un.varRdConfig4.ldv,
1066 	    mb->un.varRdConfig4.link_type,
1067 	    mb->un.varRdConfig4.link_number);
1068 
1069 	if (mb->un.varRdConfig4.ldv) {
1070 		hba->sli.sli4.link_number = mb->un.varRdConfig4.link_number;
1071 	} else {
1072 		hba->sli.sli4.link_number = (uint32_t)-1;
1073 	}
1074 
1075 	if (hba->sli.sli4.VPICount) {
1076 		hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
1077 	}
1078 
1079 	/* Set the max node count */
1080 	if (cfg[CFG_NUM_NODES].current > 0) {
1081 		hba->max_nodes =
1082 		    min(cfg[CFG_NUM_NODES].current,
1083 		    hba->sli.sli4.RPICount);
1084 	} else {
1085 		hba->max_nodes = hba->sli.sli4.RPICount;
1086 	}
1087 
1088 	/* Set the io throttle */
1089 	hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE;
1090 
1091 	/* Set max_iotag */
1092 	/* We add 1 in case all XRI's are non-zero */
1093 	hba->max_iotag = hba->sli.sli4.XRICount + 1;
1094 
1095 	if (cfg[CFG_NUM_IOTAGS].current) {
1096 		hba->max_iotag = min(hba->max_iotag,
1097 		    (uint16_t)cfg[CFG_NUM_IOTAGS].current);
1098 	}
1099 
1100 	/* Set out-of-range iotag base */
1101 	hba->fc_oor_iotag = hba->max_iotag;
1102 
1103 	/* Save the link speed capabilities */
1104 	vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt;
1105 	emlxs_process_link_speed(hba);
1106 
1107 	/*
1108 	 * Allocate some memory for buffers
1109 	 */
1110 	if (emlxs_mem_alloc_buffer(hba) == 0) {
1111 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1112 		    "Unable to allocate memory buffers.");
1113 
1114 		rval = ENOMEM;
1115 		goto failed1;
1116 	}
1117 
1118 	if (emlxs_sli4_resource_alloc(hba)) {
1119 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1120 		    "Unable to allocate resources.");
1121 
1122 		rval = ENOMEM;
1123 		goto failed2;
1124 	}
1125 	emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0);
1126 	emlxs_sli4_zero_queue_stat(hba);
1127 
1128 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1129 	if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) {
1130 		hba->fca_tran->fca_num_npivports = hba->vpi_max;
1131 	}
1132 #endif /* >= EMLXS_MODREV5 */
1133 
1134 	/* Reuse mbq from previous mbox */
1135 	bzero(mbq, sizeof (MAILBOXQ));
1136 
1137 	if (emlxs_sli4_post_sgl_pages(hba, mbq)) {
1138 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1139 		    "Unable to post sgl pages.");
1140 
1141 		rval = EIO;
1142 		goto failed3;
1143 	}
1144 
1145 	/* Reuse mbq from previous mbox */
1146 	bzero(mbq, sizeof (MAILBOXQ));
1147 
1148 	if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) {
1149 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1150 		    "Unable to post header templates.");
1151 
1152 		rval = EIO;
1153 		goto failed3;
1154 	}
1155 
1156 	/*
1157 	 * Add our interrupt routine to kernel's interrupt chain & enable it
1158 	 * If MSI is enabled this will cause Solaris to program the MSI address
1159 	 * and data registers in PCI config space
1160 	 */
1161 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
1162 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1163 		    "Unable to add interrupt(s).");
1164 
1165 		rval = EIO;
1166 		goto failed3;
1167 	}
1168 
1169 	/* Reuse mbq from previous mbox */
1170 	bzero(mbq, sizeof (MAILBOXQ));
1171 
1172 	/* This MUST be done after EMLXS_INTR_ADD */
1173 	if (emlxs_sli4_create_queues(hba, mbq)) {
1174 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1175 		    "Unable to create queues.");
1176 
1177 		rval = EIO;
1178 		goto failed3;
1179 	}
1180 
1181 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
1182 
1183 	/* Get and save the current firmware version (based on sli_mode) */
1184 	emlxs_decode_firmware_rev(hba, vpd);
1185 
1186 
1187 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
1188 
1189 	if (SLI4_FC_MODE) {
1190 		/* Reuse mbq from previous mbox */
1191 		bzero(mbq, sizeof (MAILBOXQ));
1192 
1193 		emlxs_mb_config_link(hba, mbq);
1194 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1195 		    MBX_SUCCESS) {
1196 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1197 			    "Unable to configure link. Mailbox cmd=%x "
1198 			    "status=%x",
1199 			    mb->mbxCommand, mb->mbxStatus);
1200 
1201 			rval = EIO;
1202 			goto failed3;
1203 		}
1204 	}
1205 
1206 	/* Reuse mbq from previous mbox */
1207 	bzero(mbq, sizeof (MAILBOXQ));
1208 
1209 	/*
1210 	 * We need to get login parameters for NID
1211 	 */
1212 	(void) emlxs_mb_read_sparam(hba, mbq);
1213 	mp = (MATCHMAP *)mbq->bp;
1214 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1215 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1216 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
1217 		    mb->mbxCommand, mb->mbxStatus);
1218 
1219 		rval = EIO;
1220 		goto failed3;
1221 	}
1222 
1223 	/* Free the buffer since we were polling */
1224 	emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1225 	mp = NULL;
1226 
1227 	/* If no serial number in VPD data, then use the WWPN */
1228 	if (vpd->serial_num[0] == 0) {
1229 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
1230 		for (i = 0; i < 12; i++) {
1231 			status = *outptr++;
1232 			j = ((status & 0xf0) >> 4);
1233 			if (j <= 9) {
1234 				vpd->serial_num[i] =
1235 				    (char)((uint8_t)'0' + (uint8_t)j);
1236 			} else {
1237 				vpd->serial_num[i] =
1238 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
1239 			}
1240 
1241 			i++;
1242 			j = (status & 0xf);
1243 			if (j <= 9) {
1244 				vpd->serial_num[i] =
1245 				    (char)((uint8_t)'0' + (uint8_t)j);
1246 			} else {
1247 				vpd->serial_num[i] =
1248 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
1249 			}
1250 		}
1251 
1252 		/*
1253 		 * Set port number and port index to zero
1254 		 * The WWN's are unique to each port and therefore port_num
1255 		 * must equal zero. This effects the hba_fru_details structure
1256 		 * in fca_bind_port()
1257 		 */
1258 		vpd->port_num[0] = 0;
1259 		vpd->port_index = 0;
1260 
1261 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1262 		    "CONFIG: WWPN: port_index=0");
1263 	}
1264 
1265 	/* Make final attempt to set a port index */
1266 	if (vpd->port_index == (uint32_t)-1) {
1267 		dev_info_t *p_dip;
1268 		dev_info_t *c_dip;
1269 
1270 		p_dip = ddi_get_parent(hba->dip);
1271 		c_dip = ddi_get_child(p_dip);
1272 
1273 		vpd->port_index = 0;
1274 		while (c_dip && (hba->dip != c_dip)) {
1275 			c_dip = ddi_get_next_sibling(c_dip);
1276 
1277 			if (strcmp(ddi_get_name(c_dip), "ethernet") == 0) {
1278 				continue;
1279 			}
1280 
1281 			vpd->port_index++;
1282 		}
1283 
1284 		EMLXS_MSGF(EMLXS_CONTEXT,
1285 		    &emlxs_init_debug_msg,
1286 		    "CONFIG: Device tree: port_index=%d",
1287 		    vpd->port_index);
1288 	}
1289 
1290 	if (vpd->port_num[0] == 0) {
1291 		if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) {
1292 			(void) snprintf(vpd->port_num,
1293 			    (sizeof (vpd->port_num)-1),
1294 			    "%d", vpd->port_index);
1295 		}
1296 	}
1297 
1298 	if (vpd->id[0] == 0) {
1299 		(void) snprintf(vpd->id, (sizeof (vpd->id)-1),
1300 		    "%s %d",
1301 		    hba->model_info.model_desc, vpd->port_index);
1302 
1303 	}
1304 
1305 	if (vpd->manufacturer[0] == 0) {
1306 		(void) strncpy(vpd->manufacturer, hba->model_info.manufacturer,
1307 		    (sizeof (vpd->manufacturer)-1));
1308 	}
1309 
1310 	if (vpd->part_num[0] == 0) {
1311 		(void) strncpy(vpd->part_num, hba->model_info.model,
1312 		    (sizeof (vpd->part_num)-1));
1313 	}
1314 
1315 	if (vpd->model_desc[0] == 0) {
1316 		(void) snprintf(vpd->model_desc, (sizeof (vpd->model_desc)-1),
1317 		    "%s %d",
1318 		    hba->model_info.model_desc, vpd->port_index);
1319 	}
1320 
1321 	if (vpd->model[0] == 0) {
1322 		(void) strncpy(vpd->model, hba->model_info.model,
1323 		    (sizeof (vpd->model)-1));
1324 	}
1325 
1326 	if (vpd->prog_types[0] == 0) {
1327 		emlxs_build_prog_types(hba, vpd);
1328 	}
1329 
1330 	/* Create the symbolic names */
1331 	(void) snprintf(hba->snn, (sizeof (hba->snn)-1),
1332 	    "Emulex %s FV%s DV%s %s",
1333 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
1334 	    (char *)utsname.nodename);
1335 
1336 	(void) snprintf(hba->spn, (sizeof (hba->spn)-1),
1337 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1338 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
1339 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
1340 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1341 
1342 
1343 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
1344 	emlxs_sli4_enable_intr(hba);
1345 
1346 	/* Check persist-linkdown */
1347 	if (cfg[CFG_PERSIST_LINKDOWN].current) {
1348 		EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1349 		goto done;
1350 	}
1351 
1352 #ifdef SFCT_SUPPORT
1353 	if ((port->mode == MODE_TARGET) &&
1354 	    !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1355 		goto done;
1356 	}
1357 #endif /* SFCT_SUPPORT */
1358 
1359 	/* Reuse mbq from previous mbox */
1360 	bzero(mbq, sizeof (MAILBOXQ));
1361 
1362 	/*
1363 	 * Setup and issue mailbox INITIALIZE LINK command
1364 	 * At this point, the interrupt will be generated by the HW
1365 	 */
1366 	emlxs_mb_init_link(hba, mbq,
1367 	    cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
1368 
1369 	rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
1370 	if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) {
1371 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1372 		    "Unable to initialize link. "
1373 		    "Mailbox cmd=%x status=%x",
1374 		    mb->mbxCommand, mb->mbxStatus);
1375 
1376 		rval = EIO;
1377 		goto failed3;
1378 	}
1379 
1380 	/* Wait for link to come up */
1381 	i = cfg[CFG_LINKUP_DELAY].current;
1382 	while (i && (hba->state < FC_LINK_UP)) {
1383 		/* Check for hardware error */
1384 		if (hba->state == FC_ERROR) {
1385 			EMLXS_MSGF(EMLXS_CONTEXT,
1386 			    &emlxs_init_failed_msg,
1387 			    "Adapter error.", mb->mbxCommand,
1388 			    mb->mbxStatus);
1389 
1390 			rval = EIO;
1391 			goto failed3;
1392 		}
1393 
1394 		BUSYWAIT_MS(1000);
1395 		i--;
1396 	}
1397 
1398 done:
1399 	/*
1400 	 * The leadville driver will now handle the FLOGI at the driver level
1401 	 */
1402 
1403 	if (mbq) {
1404 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1405 		mbq = NULL;
1406 		mb = NULL;
1407 	}
1408 	return (0);
1409 
1410 failed3:
1411 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1412 
1413 	if (mp) {
1414 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1415 		mp = NULL;
1416 	}
1417 
1418 
1419 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
1420 		(void) EMLXS_INTR_REMOVE(hba);
1421 	}
1422 
1423 	emlxs_sli4_resource_free(hba);
1424 
1425 failed2:
1426 	(void) emlxs_mem_free_buffer(hba);
1427 
1428 failed1:
1429 	if (mbq) {
1430 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1431 		mbq = NULL;
1432 		mb = NULL;
1433 	}
1434 
1435 	if (hba->sli.sli4.dump_region.virt) {
1436 		(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1437 	}
1438 
1439 	if (rval == 0) {
1440 		rval = EIO;
1441 	}
1442 
1443 	return (rval);
1444 
1445 } /* emlxs_sli4_online() */
1446 
1447 
1448 static void
1449 emlxs_sli4_offline(emlxs_hba_t *hba, uint32_t reset_requested)
1450 {
1451 	/* Reverse emlxs_sli4_online */
1452 
1453 	mutex_enter(&EMLXS_PORT_LOCK);
1454 	if (hba->flag & FC_INTERLOCKED) {
1455 		mutex_exit(&EMLXS_PORT_LOCK);
1456 		goto killed;
1457 	}
1458 	mutex_exit(&EMLXS_PORT_LOCK);
1459 
1460 	if (reset_requested) {
1461 		(void) emlxs_sli4_hba_reset(hba, 0, 0, 0);
1462 	}
1463 
1464 	/* Shutdown the adapter interface */
1465 	emlxs_sli4_hba_kill(hba);
1466 
1467 killed:
1468 
1469 	/* Free SLI shared memory */
1470 	emlxs_sli4_resource_free(hba);
1471 
1472 	/* Free driver shared memory */
1473 	(void) emlxs_mem_free_buffer(hba);
1474 
1475 	/* Free the host dump region buffer */
1476 	(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1477 
1478 } /* emlxs_sli4_offline() */
1479 
1480 
1481 /*ARGSUSED*/
1482 static int
1483 emlxs_sli4_map_hdw(emlxs_hba_t *hba)
1484 {
1485 	emlxs_port_t		*port = &PPORT;
1486 	dev_info_t		*dip;
1487 	ddi_device_acc_attr_t	dev_attr;
1488 	int			status;
1489 
1490 	dip = (dev_info_t *)hba->dip;
1491 	dev_attr = emlxs_dev_acc_attr;
1492 
1493 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1494 	case SLI_INTF_IF_TYPE_0:
1495 
1496 		/* Map in Hardware BAR pages that will be used for */
1497 		/* communication with HBA. */
1498 		if (hba->sli.sli4.bar1_acc_handle == 0) {
1499 			status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX,
1500 			    (caddr_t *)&hba->sli.sli4.bar1_addr,
1501 			    0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle);
1502 			if (status != DDI_SUCCESS) {
1503 				EMLXS_MSGF(EMLXS_CONTEXT,
1504 				    &emlxs_attach_failed_msg,
1505 				    "(PCI) ddi_regs_map_setup BAR1 failed. "
1506 				    "stat=%d mem=%p attr=%p hdl=%p",
1507 				    status, &hba->sli.sli4.bar1_addr, &dev_attr,
1508 				    &hba->sli.sli4.bar1_acc_handle);
1509 				goto failed;
1510 			}
1511 		}
1512 
1513 		if (hba->sli.sli4.bar2_acc_handle == 0) {
1514 			status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX,
1515 			    (caddr_t *)&hba->sli.sli4.bar2_addr,
1516 			    0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle);
1517 			if (status != DDI_SUCCESS) {
1518 				EMLXS_MSGF(EMLXS_CONTEXT,
1519 				    &emlxs_attach_failed_msg,
1520 				    "ddi_regs_map_setup BAR2 failed. status=%x",
1521 				    status);
1522 				goto failed;
1523 			}
1524 		}
1525 
1526 		/* offset from beginning of register space */
1527 		hba->sli.sli4.MPUEPSemaphore_reg_addr =
1528 		    (uint32_t *)(hba->sli.sli4.bar1_addr +
1529 		    CSR_MPU_EP_SEMAPHORE_OFFSET);
1530 		hba->sli.sli4.MBDB_reg_addr =
1531 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET);
1532 		hba->sli.sli4.CQDB_reg_addr =
1533 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET);
1534 		hba->sli.sli4.MQDB_reg_addr =
1535 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET);
1536 		hba->sli.sli4.WQDB_reg_addr =
1537 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET);
1538 		hba->sli.sli4.RQDB_reg_addr =
1539 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET);
1540 
1541 		hba->sli.sli4.STATUS_reg_addr = 0;
1542 		hba->sli.sli4.CNTL_reg_addr = 0;
1543 
1544 		hba->sli.sli4.ERR1_reg_addr =
1545 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET);
1546 		hba->sli.sli4.ERR2_reg_addr =
1547 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET);
1548 
1549 		hba->sli.sli4.PHYSDEV_reg_addr = 0;
1550 		break;
1551 
1552 	case SLI_INTF_IF_TYPE_2:
1553 
1554 		/* Map in Hardware BAR pages that will be used for */
1555 		/* communication with HBA. */
1556 		if (hba->sli.sli4.bar0_acc_handle == 0) {
1557 			status = ddi_regs_map_setup(dip, PCI_BAR0_RINDEX,
1558 			    (caddr_t *)&hba->sli.sli4.bar0_addr,
1559 			    0, 0, &dev_attr, &hba->sli.sli4.bar0_acc_handle);
1560 			if (status != DDI_SUCCESS) {
1561 				EMLXS_MSGF(EMLXS_CONTEXT,
1562 				    &emlxs_attach_failed_msg,
1563 				    "(PCI) ddi_regs_map_setup BAR0 failed. "
1564 				    "stat=%d mem=%p attr=%p hdl=%p",
1565 				    status, &hba->sli.sli4.bar0_addr, &dev_attr,
1566 				    &hba->sli.sli4.bar0_acc_handle);
1567 				goto failed;
1568 			}
1569 		}
1570 
1571 		/* offset from beginning of register space */
1572 		hba->sli.sli4.MPUEPSemaphore_reg_addr =
1573 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1574 		    SLIPORT_SEMAPHORE_OFFSET);
1575 		hba->sli.sli4.MBDB_reg_addr =
1576 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MB_DB_OFFSET);
1577 		hba->sli.sli4.CQDB_reg_addr =
1578 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_CQ_DB_OFFSET);
1579 		hba->sli.sli4.MQDB_reg_addr =
1580 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MQ_DB_OFFSET);
1581 		hba->sli.sli4.WQDB_reg_addr =
1582 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_WQ_DB_OFFSET);
1583 		hba->sli.sli4.RQDB_reg_addr =
1584 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_RQ_DB_OFFSET);
1585 
1586 		hba->sli.sli4.STATUS_reg_addr =
1587 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1588 		    SLIPORT_STATUS_OFFSET);
1589 		hba->sli.sli4.CNTL_reg_addr =
1590 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1591 		    SLIPORT_CONTROL_OFFSET);
1592 		hba->sli.sli4.ERR1_reg_addr =
1593 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1594 		    SLIPORT_ERROR1_OFFSET);
1595 		hba->sli.sli4.ERR2_reg_addr =
1596 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1597 		    SLIPORT_ERROR2_OFFSET);
1598 		hba->sli.sli4.PHYSDEV_reg_addr =
1599 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1600 		    PHYSDEV_CONTROL_OFFSET);
1601 
1602 		break;
1603 
1604 	case SLI_INTF_IF_TYPE_1:
1605 	case SLI_INTF_IF_TYPE_3:
1606 	default:
1607 		EMLXS_MSGF(EMLXS_CONTEXT,
1608 		    &emlxs_attach_failed_msg,
1609 		    "Map hdw: Unsupported if_type %08x",
1610 		    (hba->sli_intf & SLI_INTF_IF_TYPE_MASK));
1611 
1612 		goto failed;
1613 	}
1614 
1615 	if (hba->sli.sli4.bootstrapmb.virt == 0) {
1616 		MBUF_INFO	*buf_info;
1617 		MBUF_INFO	bufinfo;
1618 
1619 		buf_info = &bufinfo;
1620 
1621 		bzero(buf_info, sizeof (MBUF_INFO));
1622 		buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE;
1623 		buf_info->flags =
1624 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1625 		buf_info->align = ddi_ptob(dip, 1L);
1626 
1627 		(void) emlxs_mem_alloc(hba, buf_info);
1628 
1629 		if (buf_info->virt == NULL) {
1630 			goto failed;
1631 		}
1632 
1633 		hba->sli.sli4.bootstrapmb.virt = buf_info->virt;
1634 		hba->sli.sli4.bootstrapmb.phys = buf_info->phys;
1635 		hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE +
1636 		    MBOX_EXTENSION_SIZE;
1637 		hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle;
1638 		hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle;
1639 		bzero((char *)hba->sli.sli4.bootstrapmb.virt,
1640 		    EMLXS_BOOTSTRAP_MB_SIZE);
1641 	}
1642 
1643 	hba->chan_count = MAX_CHANNEL;
1644 
1645 	return (0);
1646 
1647 failed:
1648 
1649 	emlxs_sli4_unmap_hdw(hba);
1650 	return (ENOMEM);
1651 
1652 
1653 } /* emlxs_sli4_map_hdw() */
1654 
1655 
1656 /*ARGSUSED*/
1657 static void
1658 emlxs_sli4_unmap_hdw(emlxs_hba_t *hba)
1659 {
1660 	MBUF_INFO	bufinfo;
1661 	MBUF_INFO	*buf_info = &bufinfo;
1662 
1663 
1664 	if (hba->sli.sli4.bar0_acc_handle) {
1665 		ddi_regs_map_free(&hba->sli.sli4.bar0_acc_handle);
1666 		hba->sli.sli4.bar0_acc_handle = 0;
1667 	}
1668 
1669 	if (hba->sli.sli4.bar1_acc_handle) {
1670 		ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle);
1671 		hba->sli.sli4.bar1_acc_handle = 0;
1672 	}
1673 
1674 	if (hba->sli.sli4.bar2_acc_handle) {
1675 		ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle);
1676 		hba->sli.sli4.bar2_acc_handle = 0;
1677 	}
1678 
1679 	if (hba->sli.sli4.bootstrapmb.virt) {
1680 		bzero(buf_info, sizeof (MBUF_INFO));
1681 
1682 		if (hba->sli.sli4.bootstrapmb.phys) {
1683 			buf_info->phys = hba->sli.sli4.bootstrapmb.phys;
1684 			buf_info->data_handle =
1685 			    hba->sli.sli4.bootstrapmb.data_handle;
1686 			buf_info->dma_handle =
1687 			    hba->sli.sli4.bootstrapmb.dma_handle;
1688 			buf_info->flags = FC_MBUF_DMA;
1689 		}
1690 
1691 		buf_info->virt = hba->sli.sli4.bootstrapmb.virt;
1692 		buf_info->size = hba->sli.sli4.bootstrapmb.size;
1693 		emlxs_mem_free(hba, buf_info);
1694 
1695 		hba->sli.sli4.bootstrapmb.virt = NULL;
1696 	}
1697 
1698 	return;
1699 
1700 } /* emlxs_sli4_unmap_hdw() */
1701 
1702 
1703 static int
1704 emlxs_check_hdw_ready(emlxs_hba_t *hba)
1705 {
1706 	emlxs_port_t *port = &PPORT;
1707 	uint32_t status;
1708 	uint32_t i = 0;
1709 	uint32_t err1;
1710 	uint32_t err2;
1711 
1712 	/* Wait for reset completion */
1713 	while (i < 30) {
1714 
1715 		switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1716 		case SLI_INTF_IF_TYPE_0:
1717 			status = emlxs_sli4_read_sema(hba);
1718 
1719 			/* Check to see if any errors occurred during init */
1720 			if (status & ARM_POST_FATAL) {
1721 				EMLXS_MSGF(EMLXS_CONTEXT,
1722 				    &emlxs_reset_failed_msg,
1723 				    "SEMA Error: status=%x", status);
1724 
1725 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
1726 
1727 				return (1);
1728 			}
1729 
1730 			if ((status & ARM_UNRECOVERABLE_ERROR) ==
1731 			    ARM_UNRECOVERABLE_ERROR) {
1732 				EMLXS_MSGF(EMLXS_CONTEXT,
1733 				    &emlxs_reset_failed_msg,
1734 				    "Unrecoverable Error: status=%x", status);
1735 
1736 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
1737 
1738 				return (1);
1739 			}
1740 
1741 			if ((status & ARM_POST_MASK) == ARM_POST_READY) {
1742 				/* ARM Ready !! */
1743 				EMLXS_MSGF(EMLXS_CONTEXT,
1744 				    &emlxs_sli_detail_msg,
1745 				    "ARM Ready: status=%x", status);
1746 
1747 				return (0);
1748 			}
1749 			break;
1750 
1751 		case SLI_INTF_IF_TYPE_2:
1752 			status = emlxs_sli4_read_status(hba);
1753 
1754 			if (status & SLI_STATUS_READY) {
1755 				if (!(status & SLI_STATUS_ERROR)) {
1756 					/* ARM Ready !! */
1757 					EMLXS_MSGF(EMLXS_CONTEXT,
1758 					    &emlxs_sli_detail_msg,
1759 					    "ARM Ready: status=%x", status);
1760 
1761 					return (0);
1762 				}
1763 
1764 				err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1765 				    hba->sli.sli4.ERR1_reg_addr);
1766 				err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1767 				    hba->sli.sli4.ERR2_reg_addr);
1768 
1769 				if (status & SLI_STATUS_RESET_NEEDED) {
1770 					EMLXS_MSGF(EMLXS_CONTEXT,
1771 					    &emlxs_sli_detail_msg,
1772 					    "ARM Ready (Reset Needed): "
1773 					    "status=%x err1=%x "
1774 					    "err2=%x",
1775 					    status, err1, err2);
1776 
1777 					return (1);
1778 				}
1779 
1780 				EMLXS_MSGF(EMLXS_CONTEXT,
1781 				    &emlxs_reset_failed_msg,
1782 				    "Unrecoverable Error: status=%x err1=%x "
1783 				    "err2=%x",
1784 				    status, err1, err2);
1785 
1786 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
1787 
1788 				return (2);
1789 			}
1790 
1791 			break;
1792 
1793 		default:
1794 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1795 
1796 			return (3);
1797 		}
1798 
1799 		BUSYWAIT_MS(1000);
1800 		i++;
1801 	}
1802 
1803 	/* Timeout occurred */
1804 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1805 	case SLI_INTF_IF_TYPE_0:
1806 		err1 = ddi_get32(hba->pci_acc_handle,
1807 		    hba->sli.sli4.ERR1_reg_addr);
1808 		err2 = ddi_get32(hba->pci_acc_handle,
1809 		    hba->sli.sli4.ERR2_reg_addr);
1810 		break;
1811 
1812 	default:
1813 		err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1814 		    hba->sli.sli4.ERR1_reg_addr);
1815 		err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1816 		    hba->sli.sli4.ERR2_reg_addr);
1817 		break;
1818 	}
1819 
1820 	if (status & SLI_STATUS_ERROR) {
1821 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1822 		    "Ready Timeout: Port Error: status=%x err1=%x err2=%x",
1823 		    status, err1, err2);
1824 	} else {
1825 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1826 		    "Ready Timeout: status=%x err1=%x err2=%x",
1827 		    status, err1, err2);
1828 	}
1829 
1830 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1831 
1832 	return (3);
1833 
1834 } /* emlxs_check_hdw_ready() */
1835 
1836 
1837 static uint32_t
1838 emlxs_sli4_read_status(emlxs_hba_t *hba)
1839 {
1840 #ifdef FMA_SUPPORT
1841 	emlxs_port_t *port = &PPORT;
1842 #endif  /* FMA_SUPPORT */
1843 	uint32_t status;
1844 
1845 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1846 	case SLI_INTF_IF_TYPE_2:
1847 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1848 		    hba->sli.sli4.STATUS_reg_addr);
1849 #ifdef FMA_SUPPORT
1850 		/* Access handle validation */
1851 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1852 #endif  /* FMA_SUPPORT */
1853 		break;
1854 	default:
1855 		status = 0;
1856 		break;
1857 	}
1858 
1859 	return (status);
1860 
1861 } /* emlxs_sli4_read_status() */
1862 
1863 
1864 static uint32_t
1865 emlxs_sli4_read_sema(emlxs_hba_t *hba)
1866 {
1867 #ifdef FMA_SUPPORT
1868 	emlxs_port_t *port = &PPORT;
1869 #endif  /* FMA_SUPPORT */
1870 	uint32_t status;
1871 
1872 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1873 	case SLI_INTF_IF_TYPE_0:
1874 		status = ddi_get32(hba->sli.sli4.bar1_acc_handle,
1875 		    hba->sli.sli4.MPUEPSemaphore_reg_addr);
1876 #ifdef FMA_SUPPORT
1877 		/* Access handle validation */
1878 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle);
1879 #endif  /* FMA_SUPPORT */
1880 		break;
1881 
1882 	case SLI_INTF_IF_TYPE_2:
1883 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1884 		    hba->sli.sli4.MPUEPSemaphore_reg_addr);
1885 #ifdef FMA_SUPPORT
1886 		/* Access handle validation */
1887 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1888 #endif  /* FMA_SUPPORT */
1889 		break;
1890 	default:
1891 		status = 0;
1892 		break;
1893 	}
1894 
1895 	return (status);
1896 
1897 } /* emlxs_sli4_read_sema() */
1898 
1899 
1900 static uint32_t
1901 emlxs_sli4_read_mbdb(emlxs_hba_t *hba)
1902 {
1903 #ifdef FMA_SUPPORT
1904 	emlxs_port_t *port = &PPORT;
1905 #endif  /* FMA_SUPPORT */
1906 	uint32_t status;
1907 
1908 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1909 	case SLI_INTF_IF_TYPE_0:
1910 		status = ddi_get32(hba->sli.sli4.bar2_acc_handle,
1911 		    hba->sli.sli4.MBDB_reg_addr);
1912 
1913 #ifdef FMA_SUPPORT
1914 		/* Access handle validation */
1915 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle);
1916 #endif  /* FMA_SUPPORT */
1917 		break;
1918 
1919 	case SLI_INTF_IF_TYPE_2:
1920 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1921 		    hba->sli.sli4.MBDB_reg_addr);
1922 #ifdef FMA_SUPPORT
1923 		/* Access handle validation */
1924 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1925 #endif  /* FMA_SUPPORT */
1926 		break;
1927 	default:
1928 		status = 0;
1929 		break;
1930 	}
1931 
1932 	return (status);
1933 
1934 } /* emlxs_sli4_read_mbdb() */
1935 
1936 
1937 static void
1938 emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint32_t value)
1939 {
1940 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1941 	case SLI_INTF_IF_TYPE_0:
1942 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1943 		    hba->sli.sli4.MBDB_reg_addr, value);
1944 		break;
1945 
1946 	case SLI_INTF_IF_TYPE_2:
1947 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
1948 		    hba->sli.sli4.MBDB_reg_addr, value);
1949 		break;
1950 	}
1951 
1952 } /* emlxs_sli4_write_mbdb() */
1953 
1954 
1955 static void
1956 emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint32_t value)
1957 {
1958 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1959 	case SLI_INTF_IF_TYPE_0:
1960 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1961 		    hba->sli.sli4.CQDB_reg_addr, value);
1962 		break;
1963 
1964 	case SLI_INTF_IF_TYPE_2:
1965 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
1966 		    hba->sli.sli4.CQDB_reg_addr, value);
1967 		break;
1968 	}
1969 
1970 } /* emlxs_sli4_write_cqdb() */
1971 
1972 
1973 static void
1974 emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint32_t value)
1975 {
1976 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1977 	case SLI_INTF_IF_TYPE_0:
1978 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1979 		    hba->sli.sli4.RQDB_reg_addr, value);
1980 		break;
1981 
1982 	case SLI_INTF_IF_TYPE_2:
1983 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
1984 		    hba->sli.sli4.RQDB_reg_addr, value);
1985 		break;
1986 	}
1987 
1988 } /* emlxs_sli4_write_rqdb() */
1989 
1990 
1991 static void
1992 emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint32_t value)
1993 {
1994 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1995 	case SLI_INTF_IF_TYPE_0:
1996 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1997 		    hba->sli.sli4.MQDB_reg_addr, value);
1998 		break;
1999 
2000 	case SLI_INTF_IF_TYPE_2:
2001 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
2002 		    hba->sli.sli4.MQDB_reg_addr, value);
2003 		break;
2004 	}
2005 
2006 } /* emlxs_sli4_write_mqdb() */
2007 
2008 
2009 static void
2010 emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint32_t value)
2011 {
2012 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2013 	case SLI_INTF_IF_TYPE_0:
2014 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
2015 		    hba->sli.sli4.WQDB_reg_addr, value);
2016 		break;
2017 
2018 	case SLI_INTF_IF_TYPE_2:
2019 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
2020 		    hba->sli.sli4.WQDB_reg_addr, value);
2021 		break;
2022 	}
2023 
2024 } /* emlxs_sli4_write_wqdb() */
2025 
2026 
2027 static uint32_t
2028 emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo)
2029 {
2030 	emlxs_port_t *port = &PPORT;
2031 	uint32_t status = 0;
2032 	uint32_t err1;
2033 	uint32_t err2;
2034 
2035 	/* Wait for reset completion, tmo is in 10ms ticks */
2036 	while (tmo) {
2037 		status = emlxs_sli4_read_mbdb(hba);
2038 
2039 		/* Check to see if any errors occurred during init */
2040 		if (status & BMBX_READY) {
2041 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2042 			    "BMBX Ready: status=0x%x", status);
2043 
2044 			return (tmo);
2045 		}
2046 
2047 		BUSYWAIT_MS(10);
2048 		tmo--;
2049 	}
2050 
2051 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2052 	case SLI_INTF_IF_TYPE_0:
2053 		err1 = ddi_get32(hba->pci_acc_handle,
2054 		    hba->sli.sli4.ERR1_reg_addr);
2055 		err2 = ddi_get32(hba->pci_acc_handle,
2056 		    hba->sli.sli4.ERR2_reg_addr);
2057 		break;
2058 
2059 	default:
2060 		err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2061 		    hba->sli.sli4.ERR1_reg_addr);
2062 		err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2063 		    hba->sli.sli4.ERR2_reg_addr);
2064 		break;
2065 	}
2066 
2067 	/* Timeout occurred */
2068 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2069 	    "Timeout waiting for BMailbox: status=%x err1=%x err2=%x",
2070 	    status, err1, err2);
2071 
2072 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
2073 
2074 	return (0);
2075 
2076 } /* emlxs_check_bootstrap_ready() */
2077 
2078 
2079 static uint32_t
2080 emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo)
2081 {
2082 	emlxs_port_t *port = &PPORT;
2083 	uint32_t *iptr;
2084 	uint32_t addr30;
2085 
2086 	/*
2087 	 * This routine assumes the bootstrap mbox is loaded
2088 	 * with the mailbox command to be executed.
2089 	 *
2090 	 * First, load the high 30 bits of bootstrap mailbox
2091 	 */
2092 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>32) & 0xfffffffc);
2093 	addr30 |= BMBX_ADDR_HI;
2094 	emlxs_sli4_write_mbdb(hba, addr30);
2095 
2096 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
2097 	if (tmo == 0) {
2098 		return (0);
2099 	}
2100 
2101 	/* Load the low 30 bits of bootstrap mailbox */
2102 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>2) & 0xfffffffc);
2103 	emlxs_sli4_write_mbdb(hba, addr30);
2104 
2105 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
2106 	if (tmo == 0) {
2107 		return (0);
2108 	}
2109 
2110 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2111 
2112 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2113 	    "BootstrapMB: %p Completed %08x %08x %08x",
2114 	    hba->sli.sli4.bootstrapmb.virt,
2115 	    *iptr, *(iptr+1), *(iptr+2));
2116 
2117 	return (tmo);
2118 
2119 } /* emlxs_issue_bootstrap_mb() */
2120 
2121 
2122 static int
2123 emlxs_init_bootstrap_mb(emlxs_hba_t *hba)
2124 {
2125 #ifdef FMA_SUPPORT
2126 	emlxs_port_t *port = &PPORT;
2127 #endif /* FMA_SUPPORT */
2128 	uint32_t *iptr;
2129 	uint32_t tmo;
2130 
2131 	if (emlxs_check_hdw_ready(hba)) {
2132 		return (1);
2133 	}
2134 
2135 	if (hba->flag & FC_BOOTSTRAPMB_INIT) {
2136 		return (0);  /* Already initialized */
2137 	}
2138 
2139 	/* NOTE: tmo is in 10ms ticks */
2140 	tmo = emlxs_check_bootstrap_ready(hba, 3000);
2141 	if (tmo == 0) {
2142 		return (1);
2143 	}
2144 
2145 	/* Issue FW_INITIALIZE command */
2146 
2147 	/* Special words to initialize bootstrap mbox MUST be little endian */
2148 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2149 	*iptr = LE_SWAP32(FW_INITIALIZE_WORD0);
2150 	*(iptr+1) = LE_SWAP32(FW_INITIALIZE_WORD1);
2151 
2152 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2153 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
2154 
2155 	emlxs_data_dump(port, "FW_INIT", (uint32_t *)iptr, 6, 0);
2156 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
2157 		return (1);
2158 	}
2159 
2160 #ifdef FMA_SUPPORT
2161 	if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle)
2162 	    != DDI_FM_OK) {
2163 		EMLXS_MSGF(EMLXS_CONTEXT,
2164 		    &emlxs_invalid_dma_handle_msg,
2165 		    "init_bootstrap_mb: hdl=%p",
2166 		    hba->sli.sli4.bootstrapmb.dma_handle);
2167 		return (1);
2168 	}
2169 #endif
2170 	hba->flag |= FC_BOOTSTRAPMB_INIT;
2171 	return (0);
2172 
2173 } /* emlxs_init_bootstrap_mb() */
2174 
2175 
2176 
2177 
2178 static uint32_t
2179 emlxs_sli4_hba_init(emlxs_hba_t *hba)
2180 {
2181 	int rc;
2182 	uint16_t i;
2183 	emlxs_port_t *vport;
2184 	emlxs_config_t *cfg = &CFG;
2185 	CHANNEL *cp;
2186 	VPIobj_t *vpip;
2187 
2188 	/* Restart the adapter */
2189 	if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) {
2190 		return (1);
2191 	}
2192 
2193 	for (i = 0; i < hba->chan_count; i++) {
2194 		cp = &hba->chan[i];
2195 		cp->iopath = (void *)&hba->sli.sli4.wq[i];
2196 	}
2197 
2198 	/* Initialize all the port objects */
2199 	hba->vpi_max  = 0;
2200 	for (i = 0; i < MAX_VPORTS; i++) {
2201 		vport = &VPORT(i);
2202 		vport->hba = hba;
2203 		vport->vpi = i;
2204 
2205 		vpip = &vport->VPIobj;
2206 		vpip->index = i;
2207 		vpip->VPI = i;
2208 		vpip->port = vport;
2209 		vpip->state = VPI_STATE_OFFLINE;
2210 		vport->vpip = vpip;
2211 	}
2212 
2213 	/* Set the max node count */
2214 	if (hba->max_nodes == 0) {
2215 		if (cfg[CFG_NUM_NODES].current > 0) {
2216 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
2217 		} else {
2218 			hba->max_nodes = 4096;
2219 		}
2220 	}
2221 
2222 	rc = emlxs_init_bootstrap_mb(hba);
2223 	if (rc) {
2224 		return (rc);
2225 	}
2226 
2227 	hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0;
2228 	hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1;
2229 	hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2;
2230 
2231 	if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == SLI_INTF_IF_TYPE_0) {
2232 		/* Cache the UE MASK registers value for UE error detection */
2233 		hba->sli.sli4.ue_mask_lo = ddi_get32(hba->pci_acc_handle,
2234 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_LO_OFFSET));
2235 		hba->sli.sli4.ue_mask_hi = ddi_get32(hba->pci_acc_handle,
2236 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_HI_OFFSET));
2237 	}
2238 
2239 	return (0);
2240 
2241 } /* emlxs_sli4_hba_init() */
2242 
2243 
2244 /*ARGSUSED*/
2245 static uint32_t
2246 emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
2247 		uint32_t quiesce)
2248 {
2249 	emlxs_port_t *port = &PPORT;
2250 	emlxs_port_t *vport;
2251 	CHANNEL *cp;
2252 	emlxs_config_t *cfg = &CFG;
2253 	MAILBOXQ mboxq;
2254 	uint32_t value;
2255 	uint32_t i;
2256 	uint32_t rc;
2257 	uint16_t channelno;
2258 	uint32_t status;
2259 	uint32_t err1;
2260 	uint32_t err2;
2261 	uint8_t generate_event = 0;
2262 
2263 	if (!cfg[CFG_RESET_ENABLE].current) {
2264 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2265 		    "Adapter reset disabled.");
2266 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
2267 
2268 		return (1);
2269 	}
2270 
2271 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2272 	case SLI_INTF_IF_TYPE_0:
2273 		if (quiesce == 0) {
2274 			emlxs_sli4_hba_kill(hba);
2275 
2276 			/*
2277 			 * Initalize Hardware that will be used to bring
2278 			 * SLI4 online.
2279 			 */
2280 			rc = emlxs_init_bootstrap_mb(hba);
2281 			if (rc) {
2282 				return (rc);
2283 			}
2284 		}
2285 
2286 		bzero((void *)&mboxq, sizeof (MAILBOXQ));
2287 		emlxs_mb_resetport(hba, &mboxq);
2288 
2289 		if (quiesce == 0) {
2290 			if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
2291 			    MBX_POLL, 0) != MBX_SUCCESS) {
2292 				/* Timeout occurred */
2293 				EMLXS_MSGF(EMLXS_CONTEXT,
2294 				    &emlxs_reset_failed_msg,
2295 				    "Timeout: RESET");
2296 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
2297 				/* Log a dump event - not supported */
2298 				return (1);
2299 			}
2300 		} else {
2301 			if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq,
2302 			    MBX_POLL, 0) != MBX_SUCCESS) {
2303 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
2304 				/* Log a dump event - not supported */
2305 				return (1);
2306 			}
2307 		}
2308 		emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0);
2309 		break;
2310 
2311 	case SLI_INTF_IF_TYPE_2:
2312 		if (quiesce == 0) {
2313 			emlxs_sli4_hba_kill(hba);
2314 		}
2315 
2316 		rc = emlxs_check_hdw_ready(hba);
2317 		if (rc > 1) {
2318 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
2319 			    "Adapter not ready for reset.");
2320 			return (1);
2321 		}
2322 
2323 		if (rc == 1) {
2324 			err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2325 			    hba->sli.sli4.ERR1_reg_addr);
2326 			err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2327 			    hba->sli.sli4.ERR2_reg_addr);
2328 
2329 			/* Don't generate an event if dump was forced */
2330 			if ((err1 != 0x2) || (err2 != 0x2)) {
2331 				generate_event = 1;
2332 			}
2333 		}
2334 
2335 		/* Reset the port now */
2336 
2337 		mutex_enter(&EMLXS_PORT_LOCK);
2338 		value = SLI_CNTL_INIT_PORT;
2339 
2340 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
2341 		    hba->sli.sli4.CNTL_reg_addr, value);
2342 		mutex_exit(&EMLXS_PORT_LOCK);
2343 
2344 		break;
2345 	}
2346 
2347 	/* Reset the hba structure */
2348 	hba->flag &= FC_RESET_MASK;
2349 
2350 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
2351 		cp = &hba->chan[channelno];
2352 		cp->hba = hba;
2353 		cp->channelno = channelno;
2354 	}
2355 
2356 	hba->channel_tx_count = 0;
2357 	hba->io_count = 0;
2358 	hba->iodone_count = 0;
2359 	hba->topology = 0;
2360 	hba->linkspeed = 0;
2361 	hba->heartbeat_active = 0;
2362 	hba->discovery_timer = 0;
2363 	hba->linkup_timer = 0;
2364 	hba->loopback_tics = 0;
2365 
2366 	/* Reset the port objects */
2367 	for (i = 0; i < MAX_VPORTS; i++) {
2368 		vport = &VPORT(i);
2369 
2370 		vport->flag &= EMLXS_PORT_RESET_MASK;
2371 		vport->did = 0;
2372 		vport->prev_did = 0;
2373 		vport->lip_type = 0;
2374 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
2375 		bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
2376 
2377 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
2378 		vport->node_base.nlp_Rpi = 0;
2379 		vport->node_base.nlp_DID = 0xffffff;
2380 		vport->node_base.nlp_list_next = NULL;
2381 		vport->node_base.nlp_list_prev = NULL;
2382 		vport->node_base.nlp_active = 1;
2383 		vport->node_count = 0;
2384 
2385 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
2386 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
2387 		}
2388 	}
2389 
2390 	if (emlxs_check_hdw_ready(hba)) {
2391 		return (1);
2392 	}
2393 
2394 	if (generate_event) {
2395 		status = emlxs_sli4_read_status(hba);
2396 		if (status & SLI_STATUS_DUMP_IMAGE_PRESENT) {
2397 			emlxs_log_dump_event(port, NULL, 0);
2398 		}
2399 	}
2400 
2401 	return (0);
2402 
2403 } /* emlxs_sli4_hba_reset */
2404 
2405 
2406 #define	SGL_CMD		0
2407 #define	SGL_RESP	1
2408 #define	SGL_DATA	2
2409 #define	SGL_LAST	0x80
2410 
2411 /*ARGSUSED*/
2412 static ULP_SGE64 *
2413 emlxs_pkt_to_sgl(emlxs_port_t *port, fc_packet_t *pkt, ULP_SGE64 *sge,
2414     uint32_t sgl_type, uint32_t *pcnt)
2415 {
2416 #ifdef DEBUG_SGE
2417 	emlxs_hba_t *hba = HBA;
2418 #endif /* DEBUG_SGE */
2419 	ddi_dma_cookie_t *cp;
2420 	uint_t i;
2421 	uint_t last;
2422 	int32_t	size;
2423 	int32_t	sge_size;
2424 	uint64_t sge_addr;
2425 	int32_t	len;
2426 	uint32_t cnt;
2427 	uint_t cookie_cnt;
2428 	ULP_SGE64 stage_sge;
2429 
2430 	last = sgl_type & SGL_LAST;
2431 	sgl_type &= ~SGL_LAST;
2432 
2433 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2434 	switch (sgl_type) {
2435 	case SGL_CMD:
2436 		cp = pkt->pkt_cmd_cookie;
2437 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
2438 		size = (int32_t)pkt->pkt_cmdlen;
2439 		break;
2440 
2441 	case SGL_RESP:
2442 		cp = pkt->pkt_resp_cookie;
2443 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
2444 		size = (int32_t)pkt->pkt_rsplen;
2445 		break;
2446 
2447 
2448 	case SGL_DATA:
2449 		cp = pkt->pkt_data_cookie;
2450 		cookie_cnt = pkt->pkt_data_cookie_cnt;
2451 		size = (int32_t)pkt->pkt_datalen;
2452 		break;
2453 
2454 	default:
2455 		return (NULL);
2456 	}
2457 
2458 #else
2459 	switch (sgl_type) {
2460 	case SGL_CMD:
2461 		cp = &pkt->pkt_cmd_cookie;
2462 		cookie_cnt = 1;
2463 		size = (int32_t)pkt->pkt_cmdlen;
2464 		break;
2465 
2466 	case SGL_RESP:
2467 		cp = &pkt->pkt_resp_cookie;
2468 		cookie_cnt = 1;
2469 		size = (int32_t)pkt->pkt_rsplen;
2470 		break;
2471 
2472 
2473 	case SGL_DATA:
2474 		cp = &pkt->pkt_data_cookie;
2475 		cookie_cnt = 1;
2476 		size = (int32_t)pkt->pkt_datalen;
2477 		break;
2478 
2479 	default:
2480 		return (NULL);
2481 	}
2482 #endif	/* >= EMLXS_MODREV3 */
2483 
2484 	stage_sge.offset = 0;
2485 	stage_sge.type = 0;
2486 	stage_sge.last = 0;
2487 	cnt = 0;
2488 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
2489 
2490 		sge_size = cp->dmac_size;
2491 		sge_addr = cp->dmac_laddress;
2492 		while (sge_size && size) {
2493 			if (cnt) {
2494 				/* Copy staged SGE before we build next one */
2495 				BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2496 				    (uint8_t *)sge, sizeof (ULP_SGE64));
2497 				sge++;
2498 			}
2499 			len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
2500 			len = MIN(size, len);
2501 
2502 			stage_sge.addrHigh =
2503 			    PADDR_HI(sge_addr);
2504 			stage_sge.addrLow =
2505 			    PADDR_LO(sge_addr);
2506 			stage_sge.length = len;
2507 			if (sgl_type == SGL_DATA) {
2508 				stage_sge.offset = cnt;
2509 			}
2510 #ifdef DEBUG_SGE
2511 			emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge,
2512 			    4, 0);
2513 #endif /* DEBUG_SGE */
2514 			sge_addr += len;
2515 			sge_size -= len;
2516 
2517 			cnt += len;
2518 			size -= len;
2519 		}
2520 	}
2521 
2522 	if (last) {
2523 		stage_sge.last = 1;
2524 	}
2525 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
2526 	    sizeof (ULP_SGE64));
2527 
2528 	sge++;
2529 
2530 	if (pcnt) {
2531 		*pcnt = cnt;
2532 	}
2533 	return (sge);
2534 
2535 } /* emlxs_pkt_to_sgl */
2536 
2537 
2538 /*ARGSUSED*/
2539 uint32_t
2540 emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2541 {
2542 	emlxs_hba_t *hba = HBA;
2543 	fc_packet_t *pkt;
2544 	XRIobj_t *xrip;
2545 	ULP_SGE64 *sge;
2546 	emlxs_wqe_t *wqe;
2547 	IOCBQ *iocbq;
2548 	ddi_dma_cookie_t *cp_cmd;
2549 	ddi_dma_cookie_t *cp_data;
2550 	uint64_t sge_addr;
2551 	uint32_t cmd_cnt;
2552 	uint32_t resp_cnt;
2553 
2554 	iocbq = (IOCBQ *) &sbp->iocbq;
2555 	wqe = &iocbq->wqe;
2556 	pkt = PRIV2PKT(sbp);
2557 	xrip = sbp->xrip;
2558 	sge = xrip->SGList.virt;
2559 
2560 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2561 	cp_cmd = pkt->pkt_cmd_cookie;
2562 	cp_data = pkt->pkt_data_cookie;
2563 #else
2564 	cp_cmd  = &pkt->pkt_cmd_cookie;
2565 	cp_data = &pkt->pkt_data_cookie;
2566 #endif	/* >= EMLXS_MODREV3 */
2567 
2568 	iocbq = &sbp->iocbq;
2569 	if (iocbq->flag & IOCB_FCP_CMD) {
2570 
2571 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2572 			return (1);
2573 		}
2574 
2575 		/* CMD payload */
2576 		sge = emlxs_pkt_to_sgl(port, pkt, sge, SGL_CMD, &cmd_cnt);
2577 		if (! sge) {
2578 			return (1);
2579 		}
2580 
2581 		/* DATA payload */
2582 		if (pkt->pkt_datalen != 0) {
2583 			/* RSP payload */
2584 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2585 			    SGL_RESP, &resp_cnt);
2586 			if (! sge) {
2587 				return (1);
2588 			}
2589 
2590 			/* Data payload */
2591 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2592 			    SGL_DATA | SGL_LAST, 0);
2593 			if (! sge) {
2594 				return (1);
2595 			}
2596 sgl_done:
2597 			if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) {
2598 				sge_addr = cp_data->dmac_laddress;
2599 				wqe->FirstData.addrHigh = PADDR_HI(sge_addr);
2600 				wqe->FirstData.addrLow = PADDR_LO(sge_addr);
2601 				wqe->FirstData.tus.f.bdeSize =
2602 				    cp_data->dmac_size;
2603 			}
2604 		} else {
2605 			/* RSP payload */
2606 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2607 			    SGL_RESP | SGL_LAST, &resp_cnt);
2608 			if (! sge) {
2609 				return (1);
2610 			}
2611 		}
2612 
2613 		wqe->un.FcpCmd.Payload.addrHigh =
2614 		    PADDR_HI(cp_cmd->dmac_laddress);
2615 		wqe->un.FcpCmd.Payload.addrLow =
2616 		    PADDR_LO(cp_cmd->dmac_laddress);
2617 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt;
2618 		wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt;
2619 
2620 	} else {
2621 
2622 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2623 			/* CMD payload */
2624 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2625 			    SGL_CMD | SGL_LAST, &cmd_cnt);
2626 			if (! sge) {
2627 				return (1);
2628 			}
2629 		} else {
2630 			/* CMD payload */
2631 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2632 			    SGL_CMD, &cmd_cnt);
2633 			if (! sge) {
2634 				return (1);
2635 			}
2636 
2637 			/* RSP payload */
2638 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2639 			    SGL_RESP | SGL_LAST, &resp_cnt);
2640 			if (! sge) {
2641 				return (1);
2642 			}
2643 			wqe->un.GenReq.PayloadLength = cmd_cnt;
2644 		}
2645 
2646 		wqe->un.GenReq.Payload.addrHigh =
2647 		    PADDR_HI(cp_cmd->dmac_laddress);
2648 		wqe->un.GenReq.Payload.addrLow =
2649 		    PADDR_LO(cp_cmd->dmac_laddress);
2650 		wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt;
2651 	}
2652 	return (0);
2653 } /* emlxs_sli4_bde_setup */
2654 
2655 
2656 
2657 
2658 #ifdef SFCT_SUPPORT
2659 /*ARGSUSED*/
2660 static uint32_t
2661 emlxs_sli4_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2662 {
2663 	emlxs_hba_t *hba = HBA;
2664 	emlxs_wqe_t *wqe;
2665 	ULP_SGE64 stage_sge;
2666 	ULP_SGE64 *sge;
2667 	IOCB *iocb;
2668 	IOCBQ *iocbq;
2669 	MATCHMAP *mp;
2670 	MATCHMAP *fct_mp;
2671 	XRIobj_t *xrip;
2672 	uint64_t sge_addr;
2673 	uint32_t sge_size;
2674 	uint32_t cnt;
2675 	uint32_t len;
2676 	uint32_t size;
2677 	uint32_t *xrdy_vaddr;
2678 	stmf_data_buf_t *dbuf;
2679 
2680 	iocbq = &sbp->iocbq;
2681 	iocb = &iocbq->iocb;
2682 	wqe = &iocbq->wqe;
2683 	xrip = sbp->xrip;
2684 
2685 	if (!sbp->fct_buf) {
2686 		return (0);
2687 	}
2688 
2689 	size = sbp->fct_buf->db_data_size;
2690 
2691 	/*
2692 	 * The hardware will automaticlly round up
2693 	 * to multiple of 4.
2694 	 *
2695 	 * if (size & 3) {
2696 	 *	size = (size + 3) & 0xfffffffc;
2697 	 * }
2698 	 */
2699 	fct_mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2700 
2701 	if (sbp->fct_buf->db_sglist_length != 1) {
2702 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2703 		    "fct_bde_setup: Only 1 sglist entry supported: %d",
2704 		    sbp->fct_buf->db_sglist_length);
2705 		return (1);
2706 	}
2707 
2708 	sge = xrip->SGList.virt;
2709 
2710 	if (iocb->ULPCOMMAND == CMD_FCP_TRECEIVE64_CX) {
2711 
2712 		mp = emlxs_mem_buf_alloc(hba, EMLXS_XFER_RDY_SIZE);
2713 		if (!mp || !mp->virt || !mp->phys) {
2714 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2715 			    "fct_bde_setup: Cannot allocate XRDY memory");
2716 			return (1);
2717 		}
2718 		/* Save the MATCHMAP info to free this memory later */
2719 		iocbq->bp = mp;
2720 
2721 		/* Point to XRDY payload */
2722 		xrdy_vaddr = (uint32_t *)(mp->virt);
2723 
2724 		/* Fill in burstsize in payload */
2725 		*xrdy_vaddr++ = 0;
2726 		*xrdy_vaddr++ = LE_SWAP32(size);
2727 		*xrdy_vaddr = 0;
2728 
2729 		/* First 2 SGEs are XRDY and SKIP */
2730 		stage_sge.addrHigh = PADDR_HI(mp->phys);
2731 		stage_sge.addrLow = PADDR_LO(mp->phys);
2732 		stage_sge.length = EMLXS_XFER_RDY_SIZE;
2733 		stage_sge.offset = 0;
2734 		stage_sge.type = 0;
2735 		stage_sge.last = 0;
2736 
2737 		/* Words  0-3 */
2738 		wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh;
2739 		wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow;
2740 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = EMLXS_XFER_RDY_SIZE;
2741 		wqe->un.FcpCmd.PayloadLength = EMLXS_XFER_RDY_SIZE;
2742 
2743 	} else {	/* CMD_FCP_TSEND64_CX */
2744 		/* First 2 SGEs are SKIP */
2745 		stage_sge.addrHigh = 0;
2746 		stage_sge.addrLow = 0;
2747 		stage_sge.length = 0;
2748 		stage_sge.offset = 0;
2749 		stage_sge.type = EMLXS_SGE_TYPE_SKIP;
2750 		stage_sge.last = 0;
2751 
2752 		/* Words  0-3 */
2753 		wqe->un.FcpCmd.Payload.addrHigh = PADDR_HI(fct_mp->phys);
2754 		wqe->un.FcpCmd.Payload.addrLow = PADDR_LO(fct_mp->phys);
2755 
2756 		/* The BDE should match the contents of the first SGE payload */
2757 		len = MIN(EMLXS_MAX_SGE_SIZE, size);
2758 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = len;
2759 
2760 		/* The PayloadLength should be set to 0 for TSEND64. */
2761 		wqe->un.FcpCmd.PayloadLength = 0;
2762 	}
2763 
2764 	dbuf = sbp->fct_buf;
2765 	/*
2766 	 * TotalTransferCount equals to Relative Offset field (Word 4)
2767 	 * in both TSEND64 and TRECEIVE64 WQE.
2768 	 */
2769 	wqe->un.FcpCmd.TotalTransferCount = dbuf->db_relative_offset;
2770 
2771 	/* Copy staged SGE into SGL */
2772 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2773 	    (uint8_t *)sge, sizeof (ULP_SGE64));
2774 	sge++;
2775 
2776 	stage_sge.addrHigh = 0;
2777 	stage_sge.addrLow = 0;
2778 	stage_sge.length = 0;
2779 	stage_sge.offset = 0;
2780 	stage_sge.type = EMLXS_SGE_TYPE_SKIP;
2781 	stage_sge.last = 0;
2782 
2783 	/* Copy staged SGE into SGL */
2784 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2785 	    (uint8_t *)sge, sizeof (ULP_SGE64));
2786 	sge++;
2787 
2788 	sge_size = size;
2789 	sge_addr = fct_mp->phys;
2790 	cnt = 0;
2791 
2792 	/* Build SGEs */
2793 	while (sge_size) {
2794 		if (cnt) {
2795 			/* Copy staged SGE before we build next one */
2796 			BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2797 			    (uint8_t *)sge, sizeof (ULP_SGE64));
2798 			sge++;
2799 		}
2800 
2801 		len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
2802 
2803 		stage_sge.addrHigh = PADDR_HI(sge_addr);
2804 		stage_sge.addrLow = PADDR_LO(sge_addr);
2805 		stage_sge.length = len;
2806 		stage_sge.offset = cnt;
2807 		stage_sge.type = EMLXS_SGE_TYPE_DATA;
2808 
2809 		sge_addr += len;
2810 		sge_size -= len;
2811 		cnt += len;
2812 	}
2813 
2814 	stage_sge.last = 1;
2815 
2816 	if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) {
2817 		wqe->FirstData.addrHigh = stage_sge.addrHigh;
2818 		wqe->FirstData.addrLow = stage_sge.addrLow;
2819 		wqe->FirstData.tus.f.bdeSize = stage_sge.length;
2820 	}
2821 	/* Copy staged SGE into SGL */
2822 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2823 	    (uint8_t *)sge, sizeof (ULP_SGE64));
2824 
2825 	return (0);
2826 
2827 } /* emlxs_sli4_fct_bde_setup */
2828 #endif /* SFCT_SUPPORT */
2829 
2830 
2831 static void
2832 emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2833 {
2834 	emlxs_port_t *port = &PPORT;
2835 	emlxs_buf_t *sbp;
2836 	uint32_t channelno;
2837 	int32_t throttle;
2838 	emlxs_wqe_t *wqe;
2839 	emlxs_wqe_t *wqeslot;
2840 	WQ_DESC_t *wq;
2841 	uint32_t flag;
2842 	uint32_t wqdb;
2843 	uint16_t next_wqe;
2844 	off_t offset;
2845 #ifdef NODE_THROTTLE_SUPPORT
2846 	int32_t node_throttle;
2847 	NODELIST *marked_node = NULL;
2848 #endif /* NODE_THROTTLE_SUPPORT */
2849 
2850 
2851 	channelno = cp->channelno;
2852 	wq = (WQ_DESC_t *)cp->iopath;
2853 
2854 #ifdef DEBUG_FASTPATH
2855 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2856 	    "ISSUE WQE channel: %x  %p", channelno, wq);
2857 #endif /* DEBUG_FASTPATH */
2858 
2859 	throttle = 0;
2860 
2861 	/* Check if FCP ring and adapter is not ready */
2862 	/* We may use any ring for FCP_CMD */
2863 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
2864 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
2865 		    (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) {
2866 			emlxs_tx_put(iocbq, 1);
2867 			return;
2868 		}
2869 	}
2870 
2871 	/* Attempt to acquire CMD_RING lock */
2872 	if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) {
2873 		/* Queue it for later */
2874 		if (iocbq) {
2875 			if ((hba->io_count -
2876 			    hba->channel_tx_count) > 10) {
2877 				emlxs_tx_put(iocbq, 1);
2878 				return;
2879 			} else {
2880 
2881 				mutex_enter(&EMLXS_QUE_LOCK(channelno));
2882 			}
2883 		} else {
2884 			return;
2885 		}
2886 	}
2887 	/* EMLXS_QUE_LOCK acquired */
2888 
2889 	/* Throttle check only applies to non special iocb */
2890 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
2891 		/* Check if HBA is full */
2892 		throttle = hba->io_throttle - hba->io_active;
2893 		if (throttle <= 0) {
2894 			/* Hitting adapter throttle limit */
2895 			/* Queue it for later */
2896 			if (iocbq) {
2897 				emlxs_tx_put(iocbq, 1);
2898 			}
2899 
2900 			goto busy;
2901 		}
2902 	}
2903 
2904 	/* Check to see if we have room for this WQE */
2905 	next_wqe = wq->host_index + 1;
2906 	if (next_wqe >= wq->max_index) {
2907 		next_wqe = 0;
2908 	}
2909 
2910 	if (next_wqe == wq->port_index) {
2911 		/* Queue it for later */
2912 		if (iocbq) {
2913 			emlxs_tx_put(iocbq, 1);
2914 		}
2915 		goto busy;
2916 	}
2917 
2918 	/*
2919 	 * We have a command ring slot available
2920 	 * Make sure we have an iocb to send
2921 	 */
2922 	if (iocbq) {
2923 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2924 
2925 		/* Check if the ring already has iocb's waiting */
2926 		if (cp->nodeq.q_first != NULL) {
2927 			/* Put the current iocbq on the tx queue */
2928 			emlxs_tx_put(iocbq, 0);
2929 
2930 			/*
2931 			 * Attempt to replace it with the next iocbq
2932 			 * in the tx queue
2933 			 */
2934 			iocbq = emlxs_tx_get(cp, 0);
2935 		}
2936 
2937 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2938 	} else {
2939 		iocbq = emlxs_tx_get(cp, 1);
2940 	}
2941 
2942 sendit:
2943 	/* Process each iocbq */
2944 	while (iocbq) {
2945 		sbp = iocbq->sbp;
2946 
2947 #ifdef NODE_THROTTLE_SUPPORT
2948 		if (sbp && sbp->node && sbp->node->io_throttle) {
2949 			node_throttle = sbp->node->io_throttle -
2950 			    sbp->node->io_active;
2951 			if (node_throttle <= 0) {
2952 				/* Node is busy */
2953 				/* Queue this iocb and get next iocb from */
2954 				/* channel */
2955 
2956 				if (!marked_node) {
2957 					marked_node = sbp->node;
2958 				}
2959 
2960 				mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2961 				emlxs_tx_put(iocbq, 0);
2962 
2963 				if (cp->nodeq.q_first == marked_node) {
2964 					mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2965 					goto busy;
2966 				}
2967 
2968 				iocbq = emlxs_tx_get(cp, 0);
2969 				mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2970 				continue;
2971 			}
2972 		}
2973 		marked_node = 0;
2974 #endif /* NODE_THROTTLE_SUPPORT */
2975 
2976 		wqe = &iocbq->wqe;
2977 #ifdef DEBUG_FASTPATH
2978 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2979 		    "ISSUE QID %d WQE iotag:%x xri:%d", wq->qid,
2980 		    wqe->RequestTag, wqe->XRITag);
2981 #endif /* DEBUG_FASTPATH */
2982 
2983 		if (sbp) {
2984 			/* If exchange removed after wqe was prep'ed, drop it */
2985 			if (!(sbp->xrip)) {
2986 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2987 				    "Xmit WQE iotag:%x xri:%d aborted",
2988 				    wqe->RequestTag, wqe->XRITag);
2989 
2990 				/* Get next iocb from the tx queue */
2991 				iocbq = emlxs_tx_get(cp, 1);
2992 				continue;
2993 			}
2994 
2995 			if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) {
2996 
2997 				/* Perform delay */
2998 				if ((channelno == hba->channel_els) &&
2999 				    !(iocbq->flag & IOCB_FCP_CMD)) {
3000 					drv_usecwait(100000);
3001 				} else {
3002 					drv_usecwait(20000);
3003 				}
3004 			}
3005 
3006 			/* Check for ULP pkt request */
3007 			mutex_enter(&sbp->mtx);
3008 
3009 			if (sbp->node == NULL) {
3010 				/* Set node to base node by default */
3011 				iocbq->node = (void *)&port->node_base;
3012 				sbp->node = (void *)&port->node_base;
3013 			}
3014 
3015 			sbp->pkt_flags |= PACKET_IN_CHIPQ;
3016 			mutex_exit(&sbp->mtx);
3017 
3018 			atomic_inc_32(&hba->io_active);
3019 #ifdef NODE_THROTTLE_SUPPORT
3020 			if (sbp->node) {
3021 				atomic_inc_32(&sbp->node->io_active);
3022 			}
3023 #endif /* NODE_THROTTLE_SUPPORT */
3024 
3025 			sbp->xrip->flag |= EMLXS_XRI_PENDING_IO;
3026 #ifdef SFCT_SUPPORT
3027 #ifdef FCT_IO_TRACE
3028 			if (sbp->fct_cmd) {
3029 				emlxs_fct_io_trace(port, sbp->fct_cmd,
3030 				    EMLXS_FCT_IOCB_ISSUED);
3031 				emlxs_fct_io_trace(port, sbp->fct_cmd,
3032 				    icmd->ULPCOMMAND);
3033 			}
3034 #endif /* FCT_IO_TRACE */
3035 #endif /* SFCT_SUPPORT */
3036 			cp->hbaSendCmd_sbp++;
3037 			iocbq->channel = cp;
3038 		} else {
3039 			cp->hbaSendCmd++;
3040 		}
3041 
3042 		flag = iocbq->flag;
3043 
3044 		/*
3045 		 * At this point, we have a command ring slot available
3046 		 * and an iocb to send
3047 		 */
3048 		wq->release_depth--;
3049 		if (wq->release_depth == 0) {
3050 			wq->release_depth = WQE_RELEASE_DEPTH;
3051 			wqe->WQEC = 1;
3052 		}
3053 
3054 		HBASTATS.IocbIssued[channelno]++;
3055 		wq->num_proc++;
3056 
3057 		/* Send the iocb */
3058 		wqeslot = (emlxs_wqe_t *)wq->addr.virt;
3059 		wqeslot += wq->host_index;
3060 
3061 		wqe->CQId = wq->cqid;
3062 		if (hba->sli.sli4.param.PHWQ) {
3063 			WQE_PHWQ_WQID(wqe, wq->qid);
3064 		}
3065 		BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot,
3066 		    sizeof (emlxs_wqe_t));
3067 #ifdef DEBUG_WQE
3068 		emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0);
3069 #endif /* DEBUG_WQE */
3070 		offset = (off_t)((uint64_t)((unsigned long)
3071 		    wq->addr.virt) -
3072 		    (uint64_t)((unsigned long)
3073 		    hba->sli.sli4.slim2.virt));
3074 
3075 		EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset,
3076 		    4096, DDI_DMA_SYNC_FORDEV);
3077 
3078 		/* Ring the WQ Doorbell */
3079 		wqdb = wq->qid;
3080 		wqdb |= ((1 << 24) | (wq->host_index << 16));
3081 
3082 		/*
3083 		 * After this, the sbp / iocb / wqe should not be
3084 		 * accessed in the xmit path.
3085 		 */
3086 
3087 		emlxs_sli4_write_wqdb(hba, wqdb);
3088 		wq->host_index = next_wqe;
3089 
3090 #ifdef DEBUG_FASTPATH
3091 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3092 		    "WQ RING: %08x", wqdb);
3093 #endif /* DEBUG_FASTPATH */
3094 
3095 		if (!sbp) {
3096 			emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
3097 		}
3098 
3099 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
3100 			/* Check if HBA is full */
3101 			throttle = hba->io_throttle - hba->io_active;
3102 			if (throttle <= 0) {
3103 				goto busy;
3104 			}
3105 		}
3106 
3107 		/* Check to see if we have room for another WQE */
3108 		next_wqe++;
3109 		if (next_wqe >= wq->max_index) {
3110 			next_wqe = 0;
3111 		}
3112 
3113 		if (next_wqe == wq->port_index) {
3114 			/* Queue it for later */
3115 			goto busy;
3116 		}
3117 
3118 		/* Get the next iocb from the tx queue if there is one */
3119 		iocbq = emlxs_tx_get(cp, 1);
3120 	}
3121 
3122 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
3123 
3124 	return;
3125 
3126 busy:
3127 	wq->num_busy++;
3128 	if (throttle <= 0) {
3129 		HBASTATS.IocbThrottled++;
3130 	} else {
3131 		HBASTATS.IocbRingFull[channelno]++;
3132 	}
3133 
3134 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
3135 
3136 	return;
3137 
3138 } /* emlxs_sli4_issue_iocb_cmd() */
3139 
3140 
3141 /*ARGSUSED*/
3142 static uint32_t
3143 emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb,
3144     uint32_t tmo)
3145 {
3146 	emlxs_hba_t *hba = HBA;
3147 	MAILBOXQ	*mbq;
3148 	MAILBOX4	*mb4;
3149 	MATCHMAP	*mp;
3150 	uint32_t	*iptr;
3151 	uint32_t	mqdb;
3152 	off_t		offset;
3153 
3154 	mbq = (MAILBOXQ *)mb;
3155 	mb4 = (MAILBOX4 *)mb;
3156 	mp = (MATCHMAP *) mbq->nonembed;
3157 	hba->mbox_mqe = (void *)mqe;
3158 
3159 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
3160 	    (mb4->un.varSLIConfig.be.embedded)) {
3161 		/*
3162 		 * If this is an embedded mbox, everything should fit
3163 		 * into the mailbox area.
3164 		 */
3165 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
3166 		    MAILBOX_CMD_SLI4_BSIZE);
3167 
3168 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
3169 		    4096, DDI_DMA_SYNC_FORDEV);
3170 
3171 		if (mb->mbxCommand != MBX_HEARTBEAT) {
3172 			emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe,
3173 			    18, 0);
3174 		}
3175 	} else {
3176 		/* SLI_CONFIG and non-embedded */
3177 
3178 		/*
3179 		 * If this is not embedded, the MQ area
3180 		 * MUST contain a SGE pointer to a larger area for the
3181 		 * non-embedded mailbox command.
3182 		 * mp will point to the actual mailbox command which
3183 		 * should be copied into the non-embedded area.
3184 		 */
3185 		mb4->un.varSLIConfig.be.sge_cnt = 1;
3186 		mb4->un.varSLIConfig.be.payload_length = mp->size;
3187 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3188 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
3189 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
3190 		*iptr = mp->size;
3191 
3192 		BE_SWAP32_BUFFER(mp->virt, mp->size);
3193 
3194 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3195 		    DDI_DMA_SYNC_FORDEV);
3196 
3197 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
3198 		    MAILBOX_CMD_SLI4_BSIZE);
3199 
3200 		offset = (off_t)((uint64_t)((unsigned long)
3201 		    hba->sli.sli4.mq.addr.virt) -
3202 		    (uint64_t)((unsigned long)
3203 		    hba->sli.sli4.slim2.virt));
3204 
3205 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
3206 		    4096, DDI_DMA_SYNC_FORDEV);
3207 
3208 		emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0);
3209 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3210 		    "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt));
3211 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
3212 	}
3213 
3214 	/* Ring the MQ Doorbell */
3215 	mqdb = hba->sli.sli4.mq.qid;
3216 	mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK);
3217 
3218 	if (mb->mbxCommand != MBX_HEARTBEAT) {
3219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3220 		    "MQ RING: %08x", mqdb);
3221 	}
3222 
3223 	emlxs_sli4_write_mqdb(hba, mqdb);
3224 
3225 	return (MBX_SUCCESS);
3226 
3227 } /* emlxs_sli4_issue_mq() */
3228 
3229 
3230 /*ARGSUSED*/
3231 static uint32_t
3232 emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo)
3233 {
3234 	emlxs_port_t	*port = &PPORT;
3235 	MAILBOXQ	*mbq;
3236 	MAILBOX4	*mb4;
3237 	MATCHMAP	*mp = NULL;
3238 	uint32_t	*iptr;
3239 	int		nonembed = 0;
3240 
3241 	mbq = (MAILBOXQ *)mb;
3242 	mb4 = (MAILBOX4 *)mb;
3243 	mp = (MATCHMAP *) mbq->nonembed;
3244 	hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt;
3245 
3246 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
3247 	    (mb4->un.varSLIConfig.be.embedded)) {
3248 		/*
3249 		 * If this is an embedded mbox, everything should fit
3250 		 * into the bootstrap mailbox area.
3251 		 */
3252 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3253 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
3254 		    MAILBOX_CMD_SLI4_BSIZE);
3255 
3256 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3257 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV);
3258 		emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0);
3259 	} else {
3260 		/*
3261 		 * If this is not embedded, the bootstrap mailbox area
3262 		 * MUST contain a SGE pointer to a larger area for the
3263 		 * non-embedded mailbox command.
3264 		 * mp will point to the actual mailbox command which
3265 		 * should be copied into the non-embedded area.
3266 		 */
3267 		nonembed = 1;
3268 		mb4->un.varSLIConfig.be.sge_cnt = 1;
3269 		mb4->un.varSLIConfig.be.payload_length = mp->size;
3270 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3271 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
3272 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
3273 		*iptr = mp->size;
3274 
3275 		BE_SWAP32_BUFFER(mp->virt, mp->size);
3276 
3277 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3278 		    DDI_DMA_SYNC_FORDEV);
3279 
3280 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3281 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
3282 		    MAILBOX_CMD_SLI4_BSIZE);
3283 
3284 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3285 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
3286 		    DDI_DMA_SYNC_FORDEV);
3287 
3288 		emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0);
3289 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3290 		    "Extension Addr %p %p", mp->phys,
3291 		    (uint32_t *)((uint8_t *)mp->virt));
3292 		iptr = (uint32_t *)((uint8_t *)mp->virt);
3293 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
3294 	}
3295 
3296 
3297 	/* NOTE: tmo is in 10ms ticks */
3298 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
3299 		return (MBX_TIMEOUT);
3300 	}
3301 
3302 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
3303 	    (mb4->un.varSLIConfig.be.embedded)) {
3304 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3305 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL);
3306 
3307 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3308 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
3309 		    MAILBOX_CMD_SLI4_BSIZE);
3310 
3311 		emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0);
3312 
3313 	} else {
3314 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3315 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
3316 		    DDI_DMA_SYNC_FORKERNEL);
3317 
3318 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3319 		    DDI_DMA_SYNC_FORKERNEL);
3320 
3321 		BE_SWAP32_BUFFER(mp->virt, mp->size);
3322 
3323 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3324 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
3325 		    MAILBOX_CMD_SLI4_BSIZE);
3326 
3327 		emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0);
3328 		iptr = (uint32_t *)((uint8_t *)mp->virt);
3329 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
3330 	}
3331 
3332 #ifdef FMA_SUPPORT
3333 	if (nonembed && mp) {
3334 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
3335 		    != DDI_FM_OK) {
3336 			EMLXS_MSGF(EMLXS_CONTEXT,
3337 			    &emlxs_invalid_dma_handle_msg,
3338 			    "sli4_issue_bootstrap: mp_hdl=%p",
3339 			    mp->dma_handle);
3340 			return (MBXERR_DMA_ERROR);
3341 		}
3342 	}
3343 
3344 	if (emlxs_fm_check_dma_handle(hba,
3345 	    hba->sli.sli4.bootstrapmb.dma_handle)
3346 	    != DDI_FM_OK) {
3347 		EMLXS_MSGF(EMLXS_CONTEXT,
3348 		    &emlxs_invalid_dma_handle_msg,
3349 		    "sli4_issue_bootstrap: hdl=%p",
3350 		    hba->sli.sli4.bootstrapmb.dma_handle);
3351 		return (MBXERR_DMA_ERROR);
3352 	}
3353 #endif
3354 
3355 	return (MBX_SUCCESS);
3356 
3357 } /* emlxs_sli4_issue_bootstrap() */
3358 
3359 
3360 /*ARGSUSED*/
3361 static uint32_t
3362 emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
3363     uint32_t tmo)
3364 {
3365 	emlxs_port_t	*port;
3366 	MAILBOX4	*mb4;
3367 	MAILBOX		*mb;
3368 	mbox_rsp_hdr_t	*hdr_rsp;
3369 	MATCHMAP	*mp;
3370 	uint32_t	*iptr;
3371 	uint32_t	rc;
3372 	uint32_t	i;
3373 	uint32_t	tmo_local;
3374 
3375 	if (!mbq->port) {
3376 		mbq->port = &PPORT;
3377 	}
3378 
3379 	port = (emlxs_port_t *)mbq->port;
3380 
3381 	mb4 = (MAILBOX4 *)mbq;
3382 	mb = (MAILBOX *)mbq;
3383 
3384 	mb->mbxStatus = MBX_SUCCESS;
3385 	rc = MBX_SUCCESS;
3386 
3387 	/* Check for minimum timeouts */
3388 	switch (mb->mbxCommand) {
3389 	/* Mailbox commands that erase/write flash */
3390 	case MBX_DOWN_LOAD:
3391 	case MBX_UPDATE_CFG:
3392 	case MBX_LOAD_AREA:
3393 	case MBX_LOAD_EXP_ROM:
3394 	case MBX_WRITE_NV:
3395 	case MBX_FLASH_WR_ULA:
3396 	case MBX_DEL_LD_ENTRY:
3397 	case MBX_LOAD_SM:
3398 	case MBX_DUMP_MEMORY:
3399 	case MBX_WRITE_VPARMS:
3400 	case MBX_ACCESS_VDATA:
3401 		if (tmo < 300) {
3402 			tmo = 300;
3403 		}
3404 		break;
3405 
3406 	case MBX_SLI_CONFIG: {
3407 		mbox_req_hdr_t *hdr_req;
3408 
3409 		hdr_req = (mbox_req_hdr_t *)
3410 		    &mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3411 
3412 		if (hdr_req->subsystem == IOCTL_SUBSYSTEM_COMMON) {
3413 			switch (hdr_req->opcode) {
3414 			case COMMON_OPCODE_WRITE_OBJ:
3415 			case COMMON_OPCODE_READ_OBJ:
3416 			case COMMON_OPCODE_READ_OBJ_LIST:
3417 			case COMMON_OPCODE_DELETE_OBJ:
3418 			case COMMON_OPCODE_SET_BOOT_CFG:
3419 			case COMMON_OPCODE_GET_PROFILE_CFG:
3420 			case COMMON_OPCODE_SET_PROFILE_CFG:
3421 			case COMMON_OPCODE_GET_PROFILE_LIST:
3422 			case COMMON_OPCODE_SET_ACTIVE_PROFILE:
3423 			case COMMON_OPCODE_GET_PROFILE_CAPS:
3424 			case COMMON_OPCODE_GET_MR_PROFILE_CAPS:
3425 			case COMMON_OPCODE_SET_MR_PROFILE_CAPS:
3426 			case COMMON_OPCODE_SET_FACTORY_PROFILE_CFG:
3427 			case COMMON_OPCODE_SEND_ACTIVATION:
3428 			case COMMON_OPCODE_RESET_LICENSES:
3429 			case COMMON_OPCODE_SET_PHYSICAL_LINK_CFG_V1:
3430 			case COMMON_OPCODE_GET_VPD_DATA:
3431 				if (tmo < 300) {
3432 					tmo = 300;
3433 				}
3434 				break;
3435 			default:
3436 				if (tmo < 30) {
3437 					tmo = 30;
3438 				}
3439 			}
3440 		} else if (hdr_req->subsystem == IOCTL_SUBSYSTEM_FCOE) {
3441 			switch (hdr_req->opcode) {
3442 			case FCOE_OPCODE_SET_FCLINK_SETTINGS:
3443 				if (tmo < 300) {
3444 					tmo = 300;
3445 				}
3446 				break;
3447 			default:
3448 				if (tmo < 30) {
3449 					tmo = 30;
3450 				}
3451 			}
3452 		} else {
3453 			if (tmo < 30) {
3454 				tmo = 30;
3455 			}
3456 		}
3457 
3458 		/*
3459 		 * Also: VENDOR_MANAGE_FFV  (0x13, 0x02) (not currently used)
3460 		 */
3461 
3462 		break;
3463 	}
3464 	default:
3465 		if (tmo < 30) {
3466 			tmo = 30;
3467 		}
3468 		break;
3469 	}
3470 
3471 	/* Convert tmo seconds to 10 millisecond tics */
3472 	tmo_local = tmo * 100;
3473 
3474 	mutex_enter(&EMLXS_PORT_LOCK);
3475 
3476 	/* Adjust wait flag */
3477 	if (flag != MBX_NOWAIT) {
3478 		if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) {
3479 			flag = MBX_SLEEP;
3480 		} else {
3481 			flag = MBX_POLL;
3482 		}
3483 	} else {
3484 		/* Must have interrupts enabled to perform MBX_NOWAIT */
3485 		if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) {
3486 
3487 			mb->mbxStatus = MBX_HARDWARE_ERROR;
3488 			mutex_exit(&EMLXS_PORT_LOCK);
3489 
3490 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3491 			    "Interrupts disabled. %s failed.",
3492 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
3493 
3494 			return (MBX_HARDWARE_ERROR);
3495 		}
3496 	}
3497 
3498 	/* Check for hardware error ; special case SLI_CONFIG */
3499 	if ((hba->flag & FC_HARDWARE_ERROR) &&
3500 	    ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
3501 	    (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
3502 	    COMMON_OPCODE_RESET))) {
3503 		mb->mbxStatus = MBX_HARDWARE_ERROR;
3504 
3505 		mutex_exit(&EMLXS_PORT_LOCK);
3506 
3507 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3508 		    "Hardware error reported. %s failed. status=%x mb=%p",
3509 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb);
3510 
3511 		return (MBX_HARDWARE_ERROR);
3512 	}
3513 
3514 	if (hba->mbox_queue_flag) {
3515 		/* If we are not polling, then queue it for later */
3516 		if (flag == MBX_NOWAIT) {
3517 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3518 			    "Busy.      %s: mb=%p NoWait.",
3519 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3520 
3521 			emlxs_mb_put(hba, mbq);
3522 
3523 			HBASTATS.MboxBusy++;
3524 
3525 			mutex_exit(&EMLXS_PORT_LOCK);
3526 
3527 			return (MBX_BUSY);
3528 		}
3529 
3530 		while (hba->mbox_queue_flag) {
3531 			mutex_exit(&EMLXS_PORT_LOCK);
3532 
3533 			if (tmo_local-- == 0) {
3534 				EMLXS_MSGF(EMLXS_CONTEXT,
3535 				    &emlxs_mbox_event_msg,
3536 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
3537 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3538 				    tmo);
3539 
3540 				/* Non-lethalStatus mailbox timeout */
3541 				/* Does not indicate a hardware error */
3542 				mb->mbxStatus = MBX_TIMEOUT;
3543 				return (MBX_TIMEOUT);
3544 			}
3545 
3546 			BUSYWAIT_MS(10);
3547 			mutex_enter(&EMLXS_PORT_LOCK);
3548 
3549 			/* Check for hardware error ; special case SLI_CONFIG */
3550 			if ((hba->flag & FC_HARDWARE_ERROR) &&
3551 			    ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
3552 			    (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
3553 			    COMMON_OPCODE_RESET))) {
3554 				mb->mbxStatus = MBX_HARDWARE_ERROR;
3555 
3556 				mutex_exit(&EMLXS_PORT_LOCK);
3557 
3558 				EMLXS_MSGF(EMLXS_CONTEXT,
3559 				    &emlxs_mbox_detail_msg,
3560 				    "Hardware error reported. %s failed. "
3561 				    "status=%x mb=%p",
3562 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3563 				    mb->mbxStatus, mb);
3564 
3565 				return (MBX_HARDWARE_ERROR);
3566 			}
3567 		}
3568 	}
3569 
3570 	/* Initialize mailbox area */
3571 	emlxs_mb_init(hba, mbq, flag, tmo);
3572 
3573 	if (mb->mbxCommand == MBX_DOWN_LINK) {
3574 		hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK;
3575 	}
3576 
3577 	mutex_exit(&EMLXS_PORT_LOCK);
3578 	switch (flag) {
3579 
3580 	case MBX_NOWAIT:
3581 		if (mb->mbxCommand != MBX_HEARTBEAT) {
3582 			if (mb->mbxCommand != MBX_DOWN_LOAD
3583 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3584 				EMLXS_MSGF(EMLXS_CONTEXT,
3585 				    &emlxs_mbox_detail_msg,
3586 				    "Sending.   %s: mb=%p NoWait. embedded %d",
3587 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3588 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3589 				    (mb4->un.varSLIConfig.be.embedded)));
3590 			}
3591 		}
3592 
3593 		iptr = hba->sli.sli4.mq.addr.virt;
3594 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
3595 		hba->sli.sli4.mq.host_index++;
3596 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
3597 			hba->sli.sli4.mq.host_index = 0;
3598 		}
3599 
3600 		if (mbq->bp) {
3601 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3602 			    "BDE virt %p phys %p size x%x",
3603 			    ((MATCHMAP *)mbq->bp)->virt,
3604 			    ((MATCHMAP *)mbq->bp)->phys,
3605 			    ((MATCHMAP *)mbq->bp)->size);
3606 			emlxs_data_dump(port, "DATA",
3607 			    (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0);
3608 		}
3609 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
3610 		break;
3611 
3612 	case MBX_POLL:
3613 		if (mb->mbxCommand != MBX_DOWN_LOAD
3614 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3615 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3616 			    "Sending.   %s: mb=%p Poll. embedded %d",
3617 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3618 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3619 			    (mb4->un.varSLIConfig.be.embedded)));
3620 		}
3621 
3622 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
3623 
3624 		/* Clean up the mailbox area */
3625 		if (rc == MBX_TIMEOUT) {
3626 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3627 			    "Timeout.   %s: mb=%p tmo=%x Poll. embedded %d",
3628 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
3629 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3630 			    (mb4->un.varSLIConfig.be.embedded)));
3631 
3632 			hba->flag |= FC_MBOX_TIMEOUT;
3633 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
3634 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3635 
3636 		} else {
3637 			if (mb->mbxCommand != MBX_DOWN_LOAD
3638 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3639 				EMLXS_MSGF(EMLXS_CONTEXT,
3640 				    &emlxs_mbox_detail_msg,
3641 				    "Completed.   %s: mb=%p status=%x Poll. "
3642 				    "embedded %d",
3643 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
3644 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3645 				    (mb4->un.varSLIConfig.be.embedded)));
3646 			}
3647 
3648 			/* Process the result */
3649 			if (!(mbq->flag & MBQ_PASSTHRU)) {
3650 				if (mbq->mbox_cmpl) {
3651 					(void) (mbq->mbox_cmpl)(hba, mbq);
3652 				}
3653 			}
3654 
3655 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3656 		}
3657 
3658 		mp = (MATCHMAP *)mbq->nonembed;
3659 		if (mp) {
3660 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3661 			if (hdr_rsp->status) {
3662 				EMLXS_MSGF(EMLXS_CONTEXT,
3663 				    &emlxs_mbox_detail_msg,
3664 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3665 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3666 				    hdr_rsp->status, hdr_rsp->extra_status);
3667 
3668 				mb->mbxStatus = MBX_NONEMBED_ERROR;
3669 			}
3670 		}
3671 		rc = mb->mbxStatus;
3672 
3673 		/* Attempt to send pending mailboxes */
3674 		mbq = (MAILBOXQ *)emlxs_mb_get(hba);
3675 		if (mbq) {
3676 			/* Attempt to send pending mailboxes */
3677 			i =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
3678 			if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
3679 				emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3680 			}
3681 		}
3682 		break;
3683 
3684 	case MBX_SLEEP:
3685 		if (mb->mbxCommand != MBX_DOWN_LOAD
3686 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3687 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3688 			    "Sending.   %s: mb=%p Sleep. embedded %d",
3689 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3690 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3691 			    (mb4->un.varSLIConfig.be.embedded)));
3692 		}
3693 
3694 		iptr = hba->sli.sli4.mq.addr.virt;
3695 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
3696 		hba->sli.sli4.mq.host_index++;
3697 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
3698 			hba->sli.sli4.mq.host_index = 0;
3699 		}
3700 
3701 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
3702 
3703 		if (rc != MBX_SUCCESS) {
3704 			break;
3705 		}
3706 
3707 		/* Wait for completion */
3708 		/* The driver clock is timing the mailbox. */
3709 
3710 		mutex_enter(&EMLXS_MBOX_LOCK);
3711 		while (!(mbq->flag & MBQ_COMPLETED)) {
3712 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
3713 		}
3714 		mutex_exit(&EMLXS_MBOX_LOCK);
3715 
3716 		mp = (MATCHMAP *)mbq->nonembed;
3717 		if (mp) {
3718 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3719 			if (hdr_rsp->status) {
3720 				EMLXS_MSGF(EMLXS_CONTEXT,
3721 				    &emlxs_mbox_detail_msg,
3722 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3723 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3724 				    hdr_rsp->status, hdr_rsp->extra_status);
3725 
3726 				mb->mbxStatus = MBX_NONEMBED_ERROR;
3727 			}
3728 		}
3729 		rc = mb->mbxStatus;
3730 
3731 		if (rc == MBX_TIMEOUT) {
3732 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3733 			    "Timeout.   %s: mb=%p tmo=%x Sleep. embedded %d",
3734 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
3735 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3736 			    (mb4->un.varSLIConfig.be.embedded)));
3737 		} else {
3738 			if (mb->mbxCommand != MBX_DOWN_LOAD
3739 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3740 				EMLXS_MSGF(EMLXS_CONTEXT,
3741 				    &emlxs_mbox_detail_msg,
3742 				    "Completed.   %s: mb=%p status=%x Sleep. "
3743 				    "embedded %d",
3744 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
3745 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3746 				    (mb4->un.varSLIConfig.be.embedded)));
3747 			}
3748 		}
3749 		break;
3750 	}
3751 
3752 	return (rc);
3753 
3754 } /* emlxs_sli4_issue_mbox_cmd() */
3755 
3756 
3757 
3758 /*ARGSUSED*/
3759 static uint32_t
3760 emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
3761     uint32_t tmo)
3762 {
3763 	emlxs_port_t	*port = &PPORT;
3764 	MAILBOX		*mb;
3765 	mbox_rsp_hdr_t	*hdr_rsp;
3766 	MATCHMAP	*mp;
3767 	uint32_t	rc;
3768 	uint32_t	tmo_local;
3769 
3770 	mb = (MAILBOX *)mbq;
3771 
3772 	mb->mbxStatus = MBX_SUCCESS;
3773 	rc = MBX_SUCCESS;
3774 
3775 	if (tmo < 30) {
3776 		tmo = 30;
3777 	}
3778 
3779 	/* Convert tmo seconds to 10 millisecond tics */
3780 	tmo_local = tmo * 100;
3781 
3782 	flag = MBX_POLL;
3783 
3784 	/* Check for hardware error */
3785 	if (hba->flag & FC_HARDWARE_ERROR) {
3786 		mb->mbxStatus = MBX_HARDWARE_ERROR;
3787 		return (MBX_HARDWARE_ERROR);
3788 	}
3789 
3790 	/* Initialize mailbox area */
3791 	emlxs_mb_init(hba, mbq, flag, tmo);
3792 
3793 	switch (flag) {
3794 
3795 	case MBX_POLL:
3796 
3797 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
3798 
3799 		/* Clean up the mailbox area */
3800 		if (rc == MBX_TIMEOUT) {
3801 			hba->flag |= FC_MBOX_TIMEOUT;
3802 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
3803 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3804 
3805 		} else {
3806 			/* Process the result */
3807 			if (!(mbq->flag & MBQ_PASSTHRU)) {
3808 				if (mbq->mbox_cmpl) {
3809 					(void) (mbq->mbox_cmpl)(hba, mbq);
3810 				}
3811 			}
3812 
3813 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3814 		}
3815 
3816 		mp = (MATCHMAP *)mbq->nonembed;
3817 		if (mp) {
3818 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3819 			if (hdr_rsp->status) {
3820 				EMLXS_MSGF(EMLXS_CONTEXT,
3821 				    &emlxs_mbox_detail_msg,
3822 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3823 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3824 				    hdr_rsp->status, hdr_rsp->extra_status);
3825 
3826 				mb->mbxStatus = MBX_NONEMBED_ERROR;
3827 			}
3828 		}
3829 		rc = mb->mbxStatus;
3830 
3831 		break;
3832 	}
3833 
3834 	return (rc);
3835 
3836 } /* emlxs_sli4_issue_mbox_cmd4quiesce() */
3837 
3838 
3839 
3840 #ifdef SFCT_SUPPORT
3841 /*ARGSUSED*/
3842 extern uint32_t
3843 emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel)
3844 {
3845 	emlxs_hba_t *hba = HBA;
3846 	emlxs_config_t *cfg = &CFG;
3847 	fct_cmd_t *fct_cmd;
3848 	stmf_data_buf_t *dbuf;
3849 	scsi_task_t *fct_task;
3850 	fc_packet_t *pkt;
3851 	CHANNEL *cp;
3852 	XRIobj_t *xrip;
3853 	emlxs_node_t *ndlp;
3854 	IOCBQ *iocbq;
3855 	IOCB *iocb;
3856 	emlxs_wqe_t *wqe;
3857 	ULP_SGE64 stage_sge;
3858 	ULP_SGE64 *sge;
3859 	RPIobj_t *rpip;
3860 	int32_t	sge_size;
3861 	uint64_t sge_addr;
3862 	uint32_t did;
3863 	uint32_t timeout;
3864 
3865 	ddi_dma_cookie_t *cp_cmd;
3866 
3867 	pkt = PRIV2PKT(cmd_sbp);
3868 
3869 	cp = (CHANNEL *)cmd_sbp->channel;
3870 
3871 	iocbq = &cmd_sbp->iocbq;
3872 	iocb = &iocbq->iocb;
3873 
3874 	did = cmd_sbp->did;
3875 	if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) {
3876 
3877 		ndlp = cmd_sbp->node;
3878 		rpip = EMLXS_NODE_TO_RPI(port, ndlp);
3879 
3880 		if (!rpip) {
3881 			/* Use the fabric rpi */
3882 			rpip = port->vpip->fabric_rpip;
3883 		}
3884 
3885 		/* Next allocate an Exchange for this command */
3886 		xrip = emlxs_sli4_alloc_xri(port, cmd_sbp, rpip,
3887 		    EMLXS_XRI_SOL_BLS_TYPE);
3888 
3889 		if (!xrip) {
3890 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3891 			    "Adapter Busy. Unable to allocate exchange. "
3892 			    "did=0x%x", did);
3893 
3894 			return (FC_TRAN_BUSY);
3895 		}
3896 
3897 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3898 		    "FCT Abort Request: xri=%d iotag=%d sbp=%p rxid=%x",
3899 		    xrip->XRI, xrip->iotag, cmd_sbp, pkt->pkt_cmd_fhdr.rx_id);
3900 
3901 		cmd_sbp->xrip = xrip;
3902 
3903 		cp->ulpSendCmd++;
3904 
3905 		/* Initalize iocbq */
3906 		iocbq->port = (void *)port;
3907 		iocbq->node = (void *)ndlp;
3908 		iocbq->channel = (void *)cp;
3909 
3910 		/*
3911 		 * Don't give the abort priority, we want the IOCB
3912 		 * we are aborting to be processed first.
3913 		 */
3914 		iocbq->flag |= IOCB_SPECIAL;
3915 
3916 		wqe = &iocbq->wqe;
3917 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
3918 
3919 		wqe = &iocbq->wqe;
3920 		wqe->un.Abort.Criteria = ABORT_XRI_TAG;
3921 		wqe->RequestTag = xrip->iotag;
3922 		wqe->AbortTag = pkt->pkt_cmd_fhdr.rx_id;
3923 		wqe->Command = CMD_ABORT_XRI_CX;
3924 		wqe->Class = CLASS3;
3925 		wqe->CQId = 0xffff;
3926 		wqe->CmdType = WQE_TYPE_ABORT;
3927 
3928 		if (hba->state >= FC_LINK_UP) {
3929 			wqe->un.Abort.IA = 0;
3930 		} else {
3931 			wqe->un.Abort.IA = 1;
3932 		}
3933 
3934 		/* Set the pkt timer */
3935 		cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3936 		    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3937 
3938 		return (IOERR_SUCCESS);
3939 
3940 	} else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) {
3941 
3942 		timeout = pkt->pkt_timeout;
3943 		ndlp = cmd_sbp->node;
3944 		if (!ndlp) {
3945 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3946 			    "Unable to find rpi. did=0x%x", did);
3947 
3948 			emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
3949 			    IOERR_INVALID_RPI, 0);
3950 			return (0xff);
3951 		}
3952 
3953 		cp->ulpSendCmd++;
3954 
3955 		/* Initalize iocbq */
3956 		iocbq->port = (void *)port;
3957 		iocbq->node = (void *)ndlp;
3958 		iocbq->channel = (void *)cp;
3959 
3960 		wqe = &iocbq->wqe;
3961 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
3962 
3963 		xrip = emlxs_sli4_register_xri(port, cmd_sbp,
3964 		    pkt->pkt_cmd_fhdr.rx_id, did);
3965 
3966 		if (!xrip) {
3967 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3968 			    "Unable to register xri %x. did=0x%x",
3969 			    pkt->pkt_cmd_fhdr.rx_id, did);
3970 
3971 			emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
3972 			    IOERR_NO_XRI, 0);
3973 			return (0xff);
3974 		}
3975 
3976 		cmd_sbp->iotag = xrip->iotag;
3977 		cmd_sbp->channel = cp;
3978 
3979 #if (EMLXS_MODREV >= EMLXS_MODREV3)
3980 		cp_cmd = pkt->pkt_cmd_cookie;
3981 #else
3982 		cp_cmd  = &pkt->pkt_cmd_cookie;
3983 #endif	/* >= EMLXS_MODREV3 */
3984 
3985 		sge_size = pkt->pkt_cmdlen;
3986 		/* Make size a multiple of 4 */
3987 		if (sge_size & 3) {
3988 			sge_size = (sge_size + 3) & 0xfffffffc;
3989 		}
3990 		sge_addr = cp_cmd->dmac_laddress;
3991 		sge = xrip->SGList.virt;
3992 
3993 		stage_sge.addrHigh = PADDR_HI(sge_addr);
3994 		stage_sge.addrLow = PADDR_LO(sge_addr);
3995 		stage_sge.length = sge_size;
3996 		stage_sge.offset = 0;
3997 		stage_sge.type = 0;
3998 		stage_sge.last = 1;
3999 
4000 		/* Copy staged SGE into SGL */
4001 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
4002 		    (uint8_t *)sge, sizeof (ULP_SGE64));
4003 
4004 		/* Words  0-3 */
4005 		wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh;
4006 		wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow;
4007 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = sge_size;
4008 		wqe->un.FcpCmd.PayloadLength = sge_size;
4009 
4010 		/*  Word  6 */
4011 		wqe->ContextTag = ndlp->nlp_Rpi;
4012 		wqe->XRITag = xrip->XRI;
4013 
4014 		/*  Word  7 */
4015 		wqe->Command  = iocb->ULPCOMMAND;
4016 		wqe->Class = cmd_sbp->class;
4017 		wqe->ContextType = WQE_RPI_CONTEXT;
4018 		wqe->Timer = ((timeout > 0xff) ? 0 : timeout);
4019 
4020 		/*  Word  8 */
4021 		wqe->AbortTag = 0;
4022 
4023 		/*  Word  9 */
4024 		wqe->RequestTag = xrip->iotag;
4025 		wqe->OXId = (uint16_t)xrip->rx_id;
4026 
4027 		/*  Word  10 */
4028 		if (xrip->flag & EMLXS_XRI_BUSY) {
4029 			wqe->XC = 1;
4030 		}
4031 
4032 		if (!(hba->sli.sli4.param.PHWQ)) {
4033 			wqe->QOSd = 1;
4034 			wqe->DBDE = 1; /* Data type for BDE 0 */
4035 		}
4036 
4037 		/*  Word  11 */
4038 		wqe->CmdType = WQE_TYPE_TRSP;
4039 		wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4040 
4041 		/* Set the pkt timer */
4042 		cmd_sbp->ticks = hba->timer_tics + timeout +
4043 		    ((timeout > 0xff) ? 0 : 10);
4044 
4045 		if (pkt->pkt_cmdlen) {
4046 			EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
4047 			    DDI_DMA_SYNC_FORDEV);
4048 		}
4049 
4050 		return (IOERR_SUCCESS);
4051 	}
4052 
4053 	fct_cmd = cmd_sbp->fct_cmd;
4054 	did = fct_cmd->cmd_rportid;
4055 	dbuf = cmd_sbp->fct_buf;
4056 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
4057 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
4058 	if (!ndlp) {
4059 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4060 		    "Unable to find rpi. did=0x%x", did);
4061 
4062 		emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4063 		    IOERR_INVALID_RPI, 0);
4064 		return (0xff);
4065 	}
4066 
4067 
4068 	/* Initalize iocbq */
4069 	iocbq->port = (void *) port;
4070 	iocbq->node = (void *)ndlp;
4071 	iocbq->channel = (void *) cp;
4072 
4073 	wqe = &iocbq->wqe;
4074 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
4075 
4076 	xrip = cmd_sbp->xrip;
4077 	if (!xrip) {
4078 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4079 		    "Unable to find xri. did=0x%x", did);
4080 
4081 		emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4082 		    IOERR_NO_XRI, 0);
4083 		return (0xff);
4084 	}
4085 
4086 	if (emlxs_sli4_register_xri(port, cmd_sbp,
4087 	    xrip->XRI, ndlp->nlp_DID) == NULL) {
4088 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4089 		    "Unable to register xri. did=0x%x", did);
4090 
4091 		emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4092 		    IOERR_NO_XRI, 0);
4093 		return (0xff);
4094 	}
4095 	cmd_sbp->iotag = xrip->iotag;
4096 	cmd_sbp->channel = cp;
4097 
4098 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
4099 		timeout =
4100 		    ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
4101 	} else {
4102 		timeout = 0x80000000;
4103 	}
4104 	cmd_sbp->ticks =
4105 	    hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10);
4106 
4107 
4108 	iocb->ULPCT = 0;
4109 	if (fct_task->task_flags & TF_WRITE_DATA) {
4110 		iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX;
4111 		wqe->CmdType = WQE_TYPE_TRECEIVE;		/* Word 11 */
4112 
4113 	} else { /* TF_READ_DATA */
4114 
4115 		iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
4116 		wqe->CmdType = WQE_TYPE_TSEND;			/* Word 11 */
4117 
4118 		if ((dbuf->db_data_size >=
4119 		    fct_task->task_expected_xfer_length)) {
4120 			/* enable auto-rsp AP feature */
4121 			wqe->AR = 0x1;
4122 			iocb->ULPCT = 0x1; /* for cmpl */
4123 		}
4124 	}
4125 
4126 	(void) emlxs_sli4_fct_bde_setup(port, cmd_sbp);
4127 
4128 	/*  Word  6 */
4129 	wqe->ContextTag = ndlp->nlp_Rpi;
4130 	wqe->XRITag = xrip->XRI;
4131 
4132 	/*  Word  7 */
4133 	wqe->Command  = iocb->ULPCOMMAND;
4134 	wqe->Class = cmd_sbp->class;
4135 	wqe->ContextType = WQE_RPI_CONTEXT;
4136 	wqe->Timer = ((timeout > 0xff) ? 0 : timeout);
4137 	wqe->PU = 1;
4138 
4139 	/*  Word  8 */
4140 	wqe->AbortTag = 0;
4141 
4142 	/*  Word  9 */
4143 	wqe->RequestTag = xrip->iotag;
4144 	wqe->OXId = (uint16_t)fct_cmd->cmd_oxid;
4145 
4146 	/*  Word  10 */
4147 	if (xrip->flag & EMLXS_XRI_BUSY) {
4148 		wqe->XC = 1;
4149 	}
4150 
4151 	if (!(hba->sli.sli4.param.PHWQ)) {
4152 		wqe->QOSd = 1;
4153 		wqe->DBDE = 1; /* Data type for BDE 0 */
4154 	}
4155 
4156 	/*  Word  11 */
4157 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4158 
4159 	/*  Word  12 */
4160 	wqe->CmdSpecific = dbuf->db_data_size;
4161 
4162 	return (IOERR_SUCCESS);
4163 
4164 } /* emlxs_sli4_prep_fct_iocb() */
4165 #endif /* SFCT_SUPPORT */
4166 
4167 
4168 /*ARGSUSED*/
4169 extern uint32_t
4170 emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
4171 {
4172 	emlxs_hba_t *hba = HBA;
4173 	fc_packet_t *pkt;
4174 	CHANNEL *cp;
4175 	RPIobj_t *rpip;
4176 	XRIobj_t *xrip;
4177 	emlxs_wqe_t *wqe;
4178 	IOCBQ *iocbq;
4179 	IOCB *iocb;
4180 	NODELIST *node;
4181 	uint16_t iotag;
4182 	uint32_t did;
4183 	off_t offset;
4184 
4185 	pkt = PRIV2PKT(sbp);
4186 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4187 	cp = &hba->chan[channel];
4188 
4189 	iocbq = &sbp->iocbq;
4190 	iocbq->channel = (void *) cp;
4191 	iocbq->port = (void *) port;
4192 
4193 	wqe = &iocbq->wqe;
4194 	iocb = &iocbq->iocb;
4195 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
4196 	bzero((void *)iocb, sizeof (IOCB));
4197 
4198 	/* Find target node object */
4199 	node = (NODELIST *)iocbq->node;
4200 	rpip = EMLXS_NODE_TO_RPI(port, node);
4201 
4202 	if (!rpip) {
4203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4204 		    "Unable to find rpi. did=0x%x", did);
4205 
4206 		emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4207 		    IOERR_INVALID_RPI, 0);
4208 		return (0xff);
4209 	}
4210 
4211 	sbp->channel = cp;
4212 	/* Next allocate an Exchange for this command */
4213 	xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4214 	    EMLXS_XRI_SOL_FCP_TYPE);
4215 
4216 	if (!xrip) {
4217 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4218 		    "Adapter Busy. Unable to allocate exchange. did=0x%x", did);
4219 
4220 		return (FC_TRAN_BUSY);
4221 	}
4222 	sbp->bmp = NULL;
4223 	iotag = sbp->iotag;
4224 
4225 #ifdef DEBUG_FASTPATH
4226 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4227 	    "FCP: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4228 	    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4229 #endif /* DEBUG_FASTPATH */
4230 
4231 	/* Indicate this is a FCP cmd */
4232 	iocbq->flag |= IOCB_FCP_CMD;
4233 
4234 	if (emlxs_sli4_bde_setup(port, sbp)) {
4235 		emlxs_sli4_free_xri(port, sbp, xrip, 1);
4236 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4237 		    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4238 
4239 		return (FC_TRAN_BUSY);
4240 	}
4241 
4242 	/* DEBUG */
4243 #ifdef DEBUG_FCP
4244 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4245 	    "FCP: SGLaddr virt %p phys %p size %d", xrip->SGList.virt,
4246 	    xrip->SGList.phys, pkt->pkt_datalen);
4247 	emlxs_data_dump(port, "FCP: SGL", (uint32_t *)xrip->SGList.virt, 20, 0);
4248 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4249 	    "FCP: CMD virt %p len %d:%d:%d",
4250 	    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
4251 	emlxs_data_dump(port, "FCP: CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
4252 #endif /* DEBUG_FCP */
4253 
4254 	offset = (off_t)((uint64_t)((unsigned long)
4255 	    xrip->SGList.virt) -
4256 	    (uint64_t)((unsigned long)
4257 	    hba->sli.sli4.slim2.virt));
4258 
4259 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4260 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4261 
4262 	/* if device is FCP-2 device, set the following bit */
4263 	/* that says to run the FC-TAPE protocol. */
4264 	if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
4265 		wqe->ERP = 1;
4266 	}
4267 
4268 	if (pkt->pkt_datalen == 0) {
4269 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR;
4270 		wqe->Command = CMD_FCP_ICMND64_CR;
4271 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
4272 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
4273 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR;
4274 		wqe->Command = CMD_FCP_IREAD64_CR;
4275 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
4276 		wqe->PU = PARM_XFER_CHECK;
4277 	} else {
4278 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR;
4279 		wqe->Command = CMD_FCP_IWRITE64_CR;
4280 		wqe->CmdType = WQE_TYPE_FCP_DATA_OUT;
4281 	}
4282 	wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen;
4283 
4284 	if (!(hba->sli.sli4.param.PHWQ)) {
4285 		wqe->DBDE = 1; /* Data type for BDE 0 */
4286 	}
4287 	wqe->ContextTag = rpip->RPI;
4288 	wqe->ContextType = WQE_RPI_CONTEXT;
4289 	wqe->XRITag = xrip->XRI;
4290 	wqe->Timer =
4291 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4292 
4293 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
4294 		wqe->CCPE = 1;
4295 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
4296 	}
4297 
4298 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4299 	case FC_TRAN_CLASS2:
4300 		wqe->Class = CLASS2;
4301 		break;
4302 	case FC_TRAN_CLASS3:
4303 	default:
4304 		wqe->Class = CLASS3;
4305 		break;
4306 	}
4307 	sbp->class = wqe->Class;
4308 	wqe->RequestTag = iotag;
4309 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4310 
4311 	return (FC_SUCCESS);
4312 } /* emlxs_sli4_prep_fcp_iocb() */
4313 
4314 
4315 /*ARGSUSED*/
4316 static uint32_t
4317 emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4318 {
4319 	return (FC_TRAN_BUSY);
4320 
4321 } /* emlxs_sli4_prep_ip_iocb() */
4322 
4323 
4324 /*ARGSUSED*/
4325 static uint32_t
4326 emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4327 {
4328 	emlxs_hba_t *hba = HBA;
4329 	fc_packet_t *pkt;
4330 	IOCBQ *iocbq;
4331 	IOCB *iocb;
4332 	emlxs_wqe_t *wqe;
4333 	FCFIobj_t *fcfp;
4334 	RPIobj_t *reserved_rpip = NULL;
4335 	RPIobj_t *rpip = NULL;
4336 	XRIobj_t *xrip;
4337 	CHANNEL *cp;
4338 	uint32_t did;
4339 	uint32_t cmd;
4340 	ULP_SGE64 stage_sge;
4341 	ULP_SGE64 *sge;
4342 	ddi_dma_cookie_t *cp_cmd;
4343 	ddi_dma_cookie_t *cp_resp;
4344 	emlxs_node_t *node;
4345 	off_t offset;
4346 
4347 	pkt = PRIV2PKT(sbp);
4348 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4349 
4350 	iocbq = &sbp->iocbq;
4351 	wqe = &iocbq->wqe;
4352 	iocb = &iocbq->iocb;
4353 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
4354 	bzero((void *)iocb, sizeof (IOCB));
4355 	cp = &hba->chan[hba->channel_els];
4356 
4357 	/* Initalize iocbq */
4358 	iocbq->port = (void *) port;
4359 	iocbq->channel = (void *) cp;
4360 
4361 	sbp->channel = cp;
4362 	sbp->bmp = NULL;
4363 
4364 #if (EMLXS_MODREV >= EMLXS_MODREV3)
4365 	cp_cmd = pkt->pkt_cmd_cookie;
4366 	cp_resp = pkt->pkt_resp_cookie;
4367 #else
4368 	cp_cmd  = &pkt->pkt_cmd_cookie;
4369 	cp_resp = &pkt->pkt_resp_cookie;
4370 #endif	/* >= EMLXS_MODREV3 */
4371 
4372 	/* CMD payload */
4373 	sge = &stage_sge;
4374 	sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
4375 	sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress);
4376 	sge->length = pkt->pkt_cmdlen;
4377 	sge->offset = 0;
4378 	sge->type = 0;
4379 
4380 	cmd = *((uint32_t *)pkt->pkt_cmd);
4381 	cmd &= ELS_CMD_MASK;
4382 
4383 	/* Initalize iocb */
4384 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
4385 		/* ELS Response */
4386 
4387 		sbp->xrip = 0;
4388 		xrip = emlxs_sli4_register_xri(port, sbp,
4389 		    pkt->pkt_cmd_fhdr.rx_id, did);
4390 
4391 		if (!xrip) {
4392 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4393 			    "Unable to find XRI. rxid=%x",
4394 			    pkt->pkt_cmd_fhdr.rx_id);
4395 
4396 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4397 			    IOERR_NO_XRI, 0);
4398 			return (0xff);
4399 		}
4400 
4401 		rpip = xrip->rpip;
4402 
4403 		if (!rpip) {
4404 			/* This means that we had a node registered */
4405 			/* when the unsol request came in but the node */
4406 			/* has since been unregistered. */
4407 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4408 			    "Unable to find RPI. rxid=%x",
4409 			    pkt->pkt_cmd_fhdr.rx_id);
4410 
4411 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4412 			    IOERR_INVALID_RPI, 0);
4413 			return (0xff);
4414 		}
4415 
4416 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4417 		    "ELS: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4418 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4419 
4420 		iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX;
4421 		wqe->Command = CMD_XMIT_ELS_RSP64_CX;
4422 		wqe->CmdType = WQE_TYPE_GEN;
4423 		if (!(hba->sli.sli4.param.PHWQ)) {
4424 			wqe->DBDE = 1; /* Data type for BDE 0 */
4425 		}
4426 
4427 		wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh;
4428 		wqe->un.ElsRsp.Payload.addrLow = sge->addrLow;
4429 		wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
4430 		wqe->un.ElsCmd.PayloadLength = pkt->pkt_cmdlen;
4431 
4432 		wqe->un.ElsRsp.RemoteId = did;
4433 		wqe->PU = 0x3;
4434 		wqe->OXId = xrip->rx_id;
4435 
4436 		sge->last = 1;
4437 		/* Now sge is fully staged */
4438 
4439 		sge = xrip->SGList.virt;
4440 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
4441 		    sizeof (ULP_SGE64));
4442 
4443 		if (rpip->RPI == FABRIC_RPI) {
4444 			wqe->ContextTag = port->vpip->VPI;
4445 			wqe->ContextType = WQE_VPI_CONTEXT;
4446 		} else {
4447 			wqe->ContextTag = rpip->RPI;
4448 			wqe->ContextType = WQE_RPI_CONTEXT;
4449 		}
4450 
4451 		if ((cmd == ELS_CMD_ACC) && (sbp->ucmd == ELS_CMD_FLOGI)) {
4452 			wqe->un.ElsCmd.SP = 1;
4453 			wqe->un.ElsCmd.LocalId = 0xFFFFFE;
4454 		}
4455 
4456 	} else {
4457 		/* ELS Request */
4458 
4459 		fcfp = port->vpip->vfip->fcfp;
4460 		node = (emlxs_node_t *)iocbq->node;
4461 		rpip = EMLXS_NODE_TO_RPI(port, node);
4462 
4463 		if (!rpip) {
4464 			/* Use the fabric rpi */
4465 			rpip = port->vpip->fabric_rpip;
4466 		}
4467 
4468 		/* Next allocate an Exchange for this command */
4469 		xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4470 		    EMLXS_XRI_SOL_ELS_TYPE);
4471 
4472 		if (!xrip) {
4473 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4474 			    "Adapter Busy. Unable to allocate exchange. "
4475 			    "did=0x%x", did);
4476 
4477 			return (FC_TRAN_BUSY);
4478 		}
4479 
4480 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4481 		    "ELS: Prep xri=%d iotag=%d rpi=%d",
4482 		    xrip->XRI, xrip->iotag, rpip->RPI);
4483 
4484 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR;
4485 		wqe->Command = CMD_ELS_REQUEST64_CR;
4486 		wqe->CmdType = WQE_TYPE_ELS;
4487 		if (!(hba->sli.sli4.param.PHWQ)) {
4488 			wqe->DBDE = 1; /* Data type for BDE 0 */
4489 		}
4490 
4491 		wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh;
4492 		wqe->un.ElsCmd.Payload.addrLow = sge->addrLow;
4493 		wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
4494 
4495 		wqe->un.ElsCmd.RemoteId = did;
4496 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4497 
4498 		/* setup for rsp */
4499 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
4500 		iocb->ULPPU = 1;	/* Wd4 is relative offset */
4501 
4502 		sge->last = 0;
4503 
4504 		sge = xrip->SGList.virt;
4505 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
4506 		    sizeof (ULP_SGE64));
4507 
4508 		wqe->un.ElsCmd.PayloadLength =
4509 		    pkt->pkt_cmdlen; /* Byte offset of rsp data */
4510 
4511 		/* RSP payload */
4512 		sge = &stage_sge;
4513 		sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress);
4514 		sge->addrLow = PADDR_LO(cp_resp->dmac_laddress);
4515 		sge->length = pkt->pkt_rsplen;
4516 		sge->offset = 0;
4517 		sge->last = 1;
4518 		/* Now sge is fully staged */
4519 
4520 		sge = xrip->SGList.virt;
4521 		sge++;
4522 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
4523 		    sizeof (ULP_SGE64));
4524 #ifdef DEBUG_ELS
4525 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4526 		    "ELS: SGLaddr virt %p phys %p",
4527 		    xrip->SGList.virt, xrip->SGList.phys);
4528 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4529 		    "ELS: PAYLOAD virt %p phys %p",
4530 		    pkt->pkt_cmd, cp_cmd->dmac_laddress);
4531 		emlxs_data_dump(port, "ELS: SGL", (uint32_t *)xrip->SGList.virt,
4532 		    12, 0);
4533 #endif /* DEBUG_ELS */
4534 
4535 		switch (cmd) {
4536 		case ELS_CMD_FLOGI:
4537 			wqe->un.ElsCmd.SP = 1;
4538 
4539 			if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
4540 			    SLI_INTF_IF_TYPE_0) {
4541 				wqe->ContextTag = fcfp->FCFI;
4542 				wqe->ContextType = WQE_FCFI_CONTEXT;
4543 			} else {
4544 				wqe->ContextTag = port->vpip->VPI;
4545 				wqe->ContextType = WQE_VPI_CONTEXT;
4546 			}
4547 
4548 			if (hba->flag & FC_FIP_SUPPORTED) {
4549 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
4550 			}
4551 
4552 			if (hba->topology == TOPOLOGY_LOOP) {
4553 				wqe->un.ElsCmd.LocalId = port->did;
4554 			}
4555 
4556 			wqe->ELSId = WQE_ELSID_FLOGI;
4557 			break;
4558 		case ELS_CMD_FDISC:
4559 			wqe->un.ElsCmd.SP = 1;
4560 			wqe->ContextTag = port->vpip->VPI;
4561 			wqe->ContextType = WQE_VPI_CONTEXT;
4562 
4563 			if (hba->flag & FC_FIP_SUPPORTED) {
4564 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
4565 			}
4566 
4567 			wqe->ELSId = WQE_ELSID_FDISC;
4568 			break;
4569 		case ELS_CMD_LOGO:
4570 			if ((did == FABRIC_DID) &&
4571 			    (hba->flag & FC_FIP_SUPPORTED)) {
4572 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
4573 			}
4574 
4575 			wqe->ContextTag = port->vpip->VPI;
4576 			wqe->ContextType = WQE_VPI_CONTEXT;
4577 			wqe->ELSId = WQE_ELSID_LOGO;
4578 			break;
4579 		case ELS_CMD_PLOGI:
4580 			if (rpip->RPI == FABRIC_RPI) {
4581 				if (hba->flag & FC_PT_TO_PT) {
4582 					wqe->un.ElsCmd.SP = 1;
4583 					wqe->un.ElsCmd.LocalId = port->did;
4584 				}
4585 
4586 				wqe->ContextTag = port->vpip->VPI;
4587 				wqe->ContextType = WQE_VPI_CONTEXT;
4588 			} else {
4589 				wqe->ContextTag = rpip->RPI;
4590 				wqe->ContextType = WQE_RPI_CONTEXT;
4591 			}
4592 
4593 			wqe->ELSId = WQE_ELSID_PLOGI;
4594 			break;
4595 		default:
4596 			if (rpip->RPI == FABRIC_RPI) {
4597 				wqe->ContextTag = port->vpip->VPI;
4598 				wqe->ContextType = WQE_VPI_CONTEXT;
4599 			} else {
4600 				wqe->ContextTag = rpip->RPI;
4601 				wqe->ContextType = WQE_RPI_CONTEXT;
4602 			}
4603 
4604 			wqe->ELSId = WQE_ELSID_CMD;
4605 			break;
4606 		}
4607 
4608 #ifdef SFCT_SUPPORT
4609 		/* This allows fct to abort the request */
4610 		if (sbp->fct_cmd) {
4611 			sbp->fct_cmd->cmd_oxid = xrip->XRI;
4612 			sbp->fct_cmd->cmd_rxid = 0xFFFF;
4613 		}
4614 #endif /* SFCT_SUPPORT */
4615 	}
4616 
4617 	if (wqe->ContextType == WQE_VPI_CONTEXT) {
4618 		reserved_rpip = emlxs_rpi_reserve_notify(port, did, xrip);
4619 
4620 		if (!reserved_rpip) {
4621 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4622 			    "Unable to alloc reserved RPI. rxid=%x. Rejecting.",
4623 			    pkt->pkt_cmd_fhdr.rx_id);
4624 
4625 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4626 			    IOERR_INVALID_RPI, 0);
4627 			return (0xff);
4628 		}
4629 
4630 		/* Store the reserved rpi */
4631 		if (wqe->Command == CMD_ELS_REQUEST64_CR) {
4632 			wqe->OXId = reserved_rpip->RPI;
4633 		} else {
4634 			wqe->CmdSpecific = reserved_rpip->RPI;
4635 		}
4636 	}
4637 
4638 	offset = (off_t)((uint64_t)((unsigned long)
4639 	    xrip->SGList.virt) -
4640 	    (uint64_t)((unsigned long)
4641 	    hba->sli.sli4.slim2.virt));
4642 
4643 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4644 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4645 
4646 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
4647 		wqe->CCPE = 1;
4648 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
4649 	}
4650 
4651 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4652 	case FC_TRAN_CLASS2:
4653 		wqe->Class = CLASS2;
4654 		break;
4655 	case FC_TRAN_CLASS3:
4656 	default:
4657 		wqe->Class = CLASS3;
4658 		break;
4659 	}
4660 	sbp->class = wqe->Class;
4661 	wqe->XRITag = xrip->XRI;
4662 	wqe->RequestTag = xrip->iotag;
4663 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4664 	return (FC_SUCCESS);
4665 
4666 } /* emlxs_sli4_prep_els_iocb() */
4667 
4668 
4669 /*ARGSUSED*/
4670 static uint32_t
4671 emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4672 {
4673 	emlxs_hba_t *hba = HBA;
4674 	fc_packet_t *pkt;
4675 	IOCBQ *iocbq;
4676 	IOCB *iocb;
4677 	emlxs_wqe_t *wqe;
4678 	NODELIST *node = NULL;
4679 	CHANNEL *cp;
4680 	RPIobj_t *rpip;
4681 	XRIobj_t *xrip;
4682 	uint32_t did;
4683 	off_t offset;
4684 
4685 	pkt = PRIV2PKT(sbp);
4686 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4687 
4688 	iocbq = &sbp->iocbq;
4689 	wqe = &iocbq->wqe;
4690 	iocb = &iocbq->iocb;
4691 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
4692 	bzero((void *)iocb, sizeof (IOCB));
4693 
4694 	cp = &hba->chan[hba->channel_ct];
4695 
4696 	iocbq->port = (void *) port;
4697 	iocbq->channel = (void *) cp;
4698 
4699 	sbp->bmp = NULL;
4700 	sbp->channel = cp;
4701 
4702 	/* Initalize wqe */
4703 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
4704 		/* CT Response */
4705 
4706 		sbp->xrip = 0;
4707 		xrip = emlxs_sli4_register_xri(port, sbp,
4708 		    pkt->pkt_cmd_fhdr.rx_id, did);
4709 
4710 		if (!xrip) {
4711 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4712 			    "Unable to find XRI. rxid=%x",
4713 			    pkt->pkt_cmd_fhdr.rx_id);
4714 
4715 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4716 			    IOERR_NO_XRI, 0);
4717 			return (0xff);
4718 		}
4719 
4720 		rpip = xrip->rpip;
4721 
4722 		if (!rpip) {
4723 			/* This means that we had a node registered */
4724 			/* when the unsol request came in but the node */
4725 			/* has since been unregistered. */
4726 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4727 			    "Unable to find RPI. rxid=%x",
4728 			    pkt->pkt_cmd_fhdr.rx_id);
4729 
4730 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4731 			    IOERR_INVALID_RPI, 0);
4732 			return (0xff);
4733 		}
4734 
4735 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4736 		    "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4737 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4738 
4739 		if (emlxs_sli4_bde_setup(port, sbp)) {
4740 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4741 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4742 
4743 			return (FC_TRAN_BUSY);
4744 		}
4745 
4746 		if (!(hba->model_info.chip & EMLXS_BE_CHIPS)) {
4747 			wqe->un.XmitSeq.Rsvd0 = 0; /* Word3 now reserved */
4748 		}
4749 
4750 		if (!(hba->sli.sli4.param.PHWQ)) {
4751 			wqe->DBDE = 1; /* Data type for BDE 0 */
4752 		}
4753 
4754 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CR;
4755 		wqe->CmdType = WQE_TYPE_GEN;
4756 		wqe->Command = CMD_XMIT_SEQUENCE64_CR;
4757 		wqe->LenLoc = 2;
4758 
4759 		if (((SLI_CT_REQUEST *) pkt->pkt_cmd)->CommandResponse.bits.
4760 		    CmdRsp == (LE_SWAP16(SLI_CT_LOOPBACK))) {
4761 			wqe->un.XmitSeq.xo = 1;
4762 		} else {
4763 			wqe->un.XmitSeq.xo = 0;
4764 		}
4765 
4766 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
4767 			wqe->un.XmitSeq.ls = 1;
4768 		}
4769 
4770 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
4771 			wqe->un.XmitSeq.si = 1;
4772 		}
4773 
4774 		wqe->un.XmitSeq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
4775 		wqe->un.XmitSeq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4776 		wqe->un.XmitSeq.Type  = pkt->pkt_cmd_fhdr.type;
4777 		wqe->OXId = xrip->rx_id;
4778 		wqe->XC = 0; /* xri_tag is a new exchange */
4779 		wqe->CmdSpecific = wqe->un.GenReq.Payload.tus.f.bdeSize;
4780 
4781 	} else {
4782 		/* CT Request */
4783 
4784 		node = (emlxs_node_t *)iocbq->node;
4785 		rpip = EMLXS_NODE_TO_RPI(port, node);
4786 
4787 		if (!rpip) {
4788 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4789 			    "Unable to find rpi. did=0x%x rpi=%d",
4790 			    did, node->nlp_Rpi);
4791 
4792 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4793 			    IOERR_INVALID_RPI, 0);
4794 			return (0xff);
4795 		}
4796 
4797 		/* Next allocate an Exchange for this command */
4798 		xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4799 		    EMLXS_XRI_SOL_CT_TYPE);
4800 
4801 		if (!xrip) {
4802 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4803 			    "Adapter Busy. Unable to allocate exchange. "
4804 			    "did=0x%x", did);
4805 
4806 			return (FC_TRAN_BUSY);
4807 		}
4808 
4809 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4810 		    "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4811 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4812 
4813 		if (emlxs_sli4_bde_setup(port, sbp)) {
4814 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4815 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4816 
4817 			emlxs_sli4_free_xri(port, sbp, xrip, 1);
4818 			return (FC_TRAN_BUSY);
4819 		}
4820 
4821 		if (!(hba->sli.sli4.param.PHWQ)) {
4822 			wqe->DBDE = 1; /* Data type for BDE 0 */
4823 		}
4824 
4825 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR;
4826 		wqe->CmdType = WQE_TYPE_GEN;
4827 		wqe->Command = CMD_GEN_REQUEST64_CR;
4828 		wqe->un.GenReq.la = 1;
4829 		wqe->un.GenReq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
4830 		wqe->un.GenReq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4831 		wqe->un.GenReq.Type  = pkt->pkt_cmd_fhdr.type;
4832 
4833 #ifdef DEBUG_CT
4834 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4835 		    "CT: SGLaddr virt %p phys %p", xrip->SGList.virt,
4836 		    xrip->SGList.phys);
4837 		emlxs_data_dump(port, "CT: SGL", (uint32_t *)xrip->SGList.virt,
4838 		    12, 0);
4839 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4840 		    "CT: CMD virt %p len %d:%d",
4841 		    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
4842 		emlxs_data_dump(port, "CT: DATA", (uint32_t *)pkt->pkt_cmd,
4843 		    20, 0);
4844 #endif /* DEBUG_CT */
4845 
4846 #ifdef SFCT_SUPPORT
4847 		/* This allows fct to abort the request */
4848 		if (sbp->fct_cmd) {
4849 			sbp->fct_cmd->cmd_oxid = xrip->XRI;
4850 			sbp->fct_cmd->cmd_rxid = 0xFFFF;
4851 		}
4852 #endif /* SFCT_SUPPORT */
4853 	}
4854 
4855 	/* Setup for rsp */
4856 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4857 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
4858 	iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
4859 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
4860 
4861 	offset = (off_t)((uint64_t)((unsigned long)
4862 	    xrip->SGList.virt) -
4863 	    (uint64_t)((unsigned long)
4864 	    hba->sli.sli4.slim2.virt));
4865 
4866 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4867 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4868 
4869 	wqe->ContextTag = rpip->RPI;
4870 	wqe->ContextType = WQE_RPI_CONTEXT;
4871 	wqe->XRITag = xrip->XRI;
4872 	wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4873 
4874 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
4875 		wqe->CCPE = 1;
4876 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
4877 	}
4878 
4879 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4880 	case FC_TRAN_CLASS2:
4881 		wqe->Class = CLASS2;
4882 		break;
4883 	case FC_TRAN_CLASS3:
4884 	default:
4885 		wqe->Class = CLASS3;
4886 		break;
4887 	}
4888 	sbp->class = wqe->Class;
4889 	wqe->RequestTag = xrip->iotag;
4890 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4891 	return (FC_SUCCESS);
4892 
4893 } /* emlxs_sli4_prep_ct_iocb() */
4894 
4895 
4896 /*ARGSUSED*/
4897 static int
4898 emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
4899 {
4900 	uint32_t *ptr;
4901 	EQE_u eqe;
4902 	int rc = 0;
4903 	off_t offset;
4904 
4905 	mutex_enter(&EMLXS_PORT_LOCK);
4906 
4907 	ptr = eq->addr.virt;
4908 	ptr += eq->host_index;
4909 
4910 	offset = (off_t)((uint64_t)((unsigned long)
4911 	    eq->addr.virt) -
4912 	    (uint64_t)((unsigned long)
4913 	    hba->sli.sli4.slim2.virt));
4914 
4915 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
4916 	    4096, DDI_DMA_SYNC_FORKERNEL);
4917 
4918 	eqe.word = *ptr;
4919 	eqe.word = BE_SWAP32(eqe.word);
4920 
4921 	if (eqe.word & EQE_VALID) {
4922 		rc = 1;
4923 	}
4924 
4925 	mutex_exit(&EMLXS_PORT_LOCK);
4926 
4927 	return (rc);
4928 
4929 } /* emlxs_sli4_read_eq */
4930 
4931 
4932 static void
4933 emlxs_sli4_poll_intr(emlxs_hba_t *hba)
4934 {
4935 	int rc = 0;
4936 	int i;
4937 	char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
4938 
4939 	/* Check attention bits once and process if required */
4940 
4941 	for (i = 0; i < hba->intr_count; i++) {
4942 		rc = emlxs_sli4_read_eq(hba, &hba->sli.sli4.eq[i]);
4943 		if (rc == 1) {
4944 			break;
4945 		}
4946 	}
4947 
4948 	if (rc != 1) {
4949 		return;
4950 	}
4951 
4952 	(void) emlxs_sli4_msi_intr((char *)hba,
4953 	    (char *)(unsigned long)arg[i]);
4954 
4955 	return;
4956 
4957 } /* emlxs_sli4_poll_intr() */
4958 
4959 
4960 /*ARGSUSED*/
4961 static void
4962 emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
4963 {
4964 	emlxs_port_t *port = &PPORT;
4965 	uint8_t status;
4966 
4967 	/* Save the event tag */
4968 	if (hba->link_event_tag == cqe->un.link.event_tag) {
4969 		HBASTATS.LinkMultiEvent++;
4970 	} else if (hba->link_event_tag + 1 < cqe->un.link.event_tag) {
4971 		HBASTATS.LinkMultiEvent++;
4972 	}
4973 	hba->link_event_tag = cqe->un.link.event_tag;
4974 
4975 	switch (cqe->event_code) {
4976 	case ASYNC_EVENT_CODE_FCOE_LINK_STATE:
4977 		HBASTATS.LinkEvent++;
4978 
4979 		switch (cqe->un.link.link_status) {
4980 		case ASYNC_EVENT_PHYS_LINK_UP:
4981 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4982 			    "Link Async Event: PHYS_LINK_UP. val=%d "
4983 			    "type=%x event=%x",
4984 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
4985 			break;
4986 
4987 		case ASYNC_EVENT_LOGICAL_LINK_UP:
4988 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4989 			    "Link Async Event: LOGICAL_LINK_UP. val=%d "
4990 			    "type=%x event=%x",
4991 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
4992 
4993 			emlxs_sli4_handle_fcoe_link_event(hba, cqe);
4994 			break;
4995 
4996 		case ASYNC_EVENT_PHYS_LINK_DOWN:
4997 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4998 			    "Link Async Event: PHYS_LINK_DOWN. val=%d "
4999 			    "type=%x event=%x",
5000 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
5001 
5002 			emlxs_sli4_handle_fcoe_link_event(hba, cqe);
5003 			break;
5004 
5005 		case ASYNC_EVENT_LOGICAL_LINK_DOWN:
5006 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5007 			    "Link Async Event: LOGICAL_LINK_DOWN. val=%d "
5008 			    "type=%x event=%x",
5009 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
5010 
5011 			emlxs_sli4_handle_fcoe_link_event(hba, cqe);
5012 			break;
5013 		default:
5014 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5015 			    "Link Async Event: Unknown link status=%d event=%x",
5016 			    cqe->un.link.link_status, HBASTATS.LinkEvent);
5017 			break;
5018 		}
5019 		break;
5020 	case ASYNC_EVENT_CODE_FCOE_FIP:
5021 		switch (cqe->un.fcoe.evt_type) {
5022 		case ASYNC_EVENT_NEW_FCF_DISC:
5023 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5024 			    "FIP Async Event: FCF_FOUND %d:%d",
5025 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5026 
5027 			(void) emlxs_fcf_found_notify(port,
5028 			    cqe->un.fcoe.ref_index);
5029 			break;
5030 		case ASYNC_EVENT_FCF_TABLE_FULL:
5031 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5032 			    "FIP Async Event: FCFTAB_FULL %d:%d",
5033 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5034 
5035 			(void) emlxs_fcf_full_notify(port);
5036 			break;
5037 		case ASYNC_EVENT_FCF_DEAD:
5038 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5039 			    "FIP Async Event: FCF_LOST %d:%d",
5040 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5041 
5042 			(void) emlxs_fcf_lost_notify(port,
5043 			    cqe->un.fcoe.ref_index);
5044 			break;
5045 		case ASYNC_EVENT_VIRT_LINK_CLEAR:
5046 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5047 			    "FIP Async Event: CVL %d",
5048 			    cqe->un.fcoe.ref_index);
5049 
5050 			(void) emlxs_fcf_cvl_notify(port,
5051 			    emlxs_sli4_vpi_to_index(hba,
5052 			    cqe->un.fcoe.ref_index));
5053 			break;
5054 
5055 		case ASYNC_EVENT_FCF_MODIFIED:
5056 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5057 			    "FIP Async Event: FCF_CHANGED %d",
5058 			    cqe->un.fcoe.ref_index);
5059 
5060 			(void) emlxs_fcf_changed_notify(port,
5061 			    cqe->un.fcoe.ref_index);
5062 			break;
5063 		default:
5064 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5065 			    "FIP Async Event: Unknown event type=%d",
5066 			    cqe->un.fcoe.evt_type);
5067 			break;
5068 		}
5069 		break;
5070 	case ASYNC_EVENT_CODE_DCBX:
5071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5072 		    "DCBX Async Event: type=%d. Not supported.",
5073 		    cqe->event_type);
5074 		break;
5075 	case ASYNC_EVENT_CODE_GRP_5:
5076 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5077 		    "Group 5 Async Event: type=%d.", cqe->event_type);
5078 		if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) {
5079 			hba->qos_linkspeed = cqe->un.qos.qos_link_speed;
5080 		}
5081 		break;
5082 	case ASYNC_EVENT_CODE_FC_EVENT:
5083 		switch (cqe->event_type) {
5084 		case ASYNC_EVENT_FC_LINK_ATT:
5085 			HBASTATS.LinkEvent++;
5086 
5087 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5088 			    "FC Async Event: Link Attention. event=%x",
5089 			    HBASTATS.LinkEvent);
5090 
5091 			emlxs_sli4_handle_fc_link_att(hba, cqe);
5092 			break;
5093 		case ASYNC_EVENT_FC_SHARED_LINK_ATT:
5094 			HBASTATS.LinkEvent++;
5095 
5096 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5097 			    "FC Async Event: Shared Link Attention. event=%x",
5098 			    HBASTATS.LinkEvent);
5099 
5100 			emlxs_sli4_handle_fc_link_att(hba, cqe);
5101 			break;
5102 		default:
5103 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5104 			    "FC Async Event: Unknown event. type=%d event=%x",
5105 			    cqe->event_type, HBASTATS.LinkEvent);
5106 		}
5107 		break;
5108 	case ASYNC_EVENT_CODE_PORT:
5109 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5110 		    "SLI Port Async Event: type=%d", cqe->event_type);
5111 		if (cqe->event_type == ASYNC_EVENT_MISCONFIG_PORT) {
5112 			*((uint32_t *)cqe->un.port.link_status) =
5113 			    BE_SWAP32(*((uint32_t *)cqe->un.port.link_status));
5114 			status =
5115 			    cqe->un.port.link_status[hba->sli.sli4.link_number];
5116 
5117 			switch (status) {
5118 				case 0 :
5119 				break;
5120 
5121 				case 1 :
5122 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5123 				    "SLI Port Async Event: Physical media not "
5124 				    "detected");
5125 				cmn_err(CE_WARN,
5126 				    "^%s%d: Optics faulted/incorrectly "
5127 				    "installed/not installed - Reseat optics, "
5128 				    "if issue not resolved, replace.",
5129 				    DRIVER_NAME, hba->ddiinst);
5130 				break;
5131 
5132 				case 2 :
5133 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5134 				    "SLI Port Async Event: Wrong physical "
5135 				    "media detected");
5136 				cmn_err(CE_WARN,
5137 				    "^%s%d: Optics of two types installed - "
5138 				    "Remove one optic or install matching"
5139 				    "pair of optics.",
5140 				    DRIVER_NAME, hba->ddiinst);
5141 				break;
5142 
5143 				case 3 :
5144 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5145 				    "SLI Port Async Event: Unsupported "
5146 				    "physical media detected");
5147 				cmn_err(CE_WARN,
5148 				    "^%s%d:  Incompatible optics - Replace "
5149 				    "with compatible optics for card to "
5150 				    "function.",
5151 				    DRIVER_NAME, hba->ddiinst);
5152 				break;
5153 
5154 				default :
5155 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5156 				    "SLI Port Async Event: Physical media "
5157 				    "error, status=%x", status);
5158 				cmn_err(CE_WARN,
5159 				    "^%s%d: Misconfigured port: status=0x%x - "
5160 				    "Check optics on card.",
5161 				    DRIVER_NAME, hba->ddiinst, status);
5162 				break;
5163 			}
5164 		}
5165 		break;
5166 	case ASYNC_EVENT_CODE_VF:
5167 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5168 		    "VF Async Event: type=%d",
5169 		    cqe->event_type);
5170 		break;
5171 	case ASYNC_EVENT_CODE_MR:
5172 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5173 		    "MR Async Event: type=%d",
5174 		    cqe->event_type);
5175 		break;
5176 	default:
5177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5178 		    "Unknown Async Event: code=%d type=%d.",
5179 		    cqe->event_code, cqe->event_type);
5180 		break;
5181 	}
5182 
5183 } /* emlxs_sli4_process_async_event() */
5184 
5185 
5186 /*ARGSUSED*/
5187 static void
5188 emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe)
5189 {
5190 	emlxs_port_t *port = &PPORT;
5191 	MAILBOX4 *mb;
5192 	MATCHMAP *mbox_bp;
5193 	MATCHMAP *mbox_nonembed;
5194 	MAILBOXQ *mbq = NULL;
5195 	uint32_t size;
5196 	uint32_t *iptr;
5197 	int rc;
5198 	off_t offset;
5199 
5200 	if (cqe->consumed && !cqe->completed) {
5201 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5202 		    "CQ ENTRY: Mbox event. Entry consumed but not completed");
5203 		return;
5204 	}
5205 
5206 	mutex_enter(&EMLXS_PORT_LOCK);
5207 	switch (hba->mbox_queue_flag) {
5208 	case 0:
5209 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5210 		    "CQ ENTRY: Mbox event. No mailbox active.");
5211 
5212 		mutex_exit(&EMLXS_PORT_LOCK);
5213 		return;
5214 
5215 	case MBX_POLL:
5216 
5217 		/* Mark mailbox complete, this should wake up any polling */
5218 		/* threads. This can happen if interrupts are enabled while */
5219 		/* a polled mailbox command is outstanding. If we don't set */
5220 		/* MBQ_COMPLETED here, the polling thread may wait until */
5221 		/* timeout error occurs */
5222 
5223 		mutex_enter(&EMLXS_MBOX_LOCK);
5224 		mbq = (MAILBOXQ *)hba->mbox_mbq;
5225 		if (mbq) {
5226 			port = (emlxs_port_t *)mbq->port;
5227 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5228 			    "CQ ENTRY: Mbox event. Completing Polled command.");
5229 			mbq->flag |= MBQ_COMPLETED;
5230 		}
5231 		mutex_exit(&EMLXS_MBOX_LOCK);
5232 
5233 		mutex_exit(&EMLXS_PORT_LOCK);
5234 		return;
5235 
5236 	case MBX_SLEEP:
5237 	case MBX_NOWAIT:
5238 		/* Check mbox_timer, it acts as a service flag too */
5239 		/* The first to service the mbox queue will clear the timer */
5240 		if (hba->mbox_timer) {
5241 			hba->mbox_timer = 0;
5242 
5243 			mutex_enter(&EMLXS_MBOX_LOCK);
5244 			mbq = (MAILBOXQ *)hba->mbox_mbq;
5245 			mutex_exit(&EMLXS_MBOX_LOCK);
5246 		}
5247 
5248 		if (!mbq) {
5249 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5250 			    "Mailbox event. No service required.");
5251 			mutex_exit(&EMLXS_PORT_LOCK);
5252 			return;
5253 		}
5254 
5255 		mb = (MAILBOX4 *)mbq;
5256 		mutex_exit(&EMLXS_PORT_LOCK);
5257 		break;
5258 
5259 	default:
5260 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
5261 		    "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).",
5262 		    hba->mbox_queue_flag);
5263 
5264 		mutex_exit(&EMLXS_PORT_LOCK);
5265 		return;
5266 	}
5267 
5268 	/* Set port context */
5269 	port = (emlxs_port_t *)mbq->port;
5270 
5271 	offset = (off_t)((uint64_t)((unsigned long)
5272 	    hba->sli.sli4.mq.addr.virt) -
5273 	    (uint64_t)((unsigned long)
5274 	    hba->sli.sli4.slim2.virt));
5275 
5276 	/* Now that we are the owner, DMA Sync entire MQ if needed */
5277 	EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
5278 	    4096, DDI_DMA_SYNC_FORDEV);
5279 
5280 	BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb,
5281 	    MAILBOX_CMD_SLI4_BSIZE);
5282 
5283 	if (mb->mbxCommand != MBX_HEARTBEAT) {
5284 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5285 		    "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x",
5286 		    mb->mbxStatus, mb->mbxCommand);
5287 
5288 		emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe,
5289 		    12, 0);
5290 	}
5291 
5292 	if (mb->mbxCommand == MBX_SLI_CONFIG) {
5293 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5294 		    "Mbox sge_cnt: %d length: %d embed: %d",
5295 		    mb->un.varSLIConfig.be.sge_cnt,
5296 		    mb->un.varSLIConfig.be.payload_length,
5297 		    mb->un.varSLIConfig.be.embedded);
5298 	}
5299 
5300 	/* Now sync the memory buffer if one was used */
5301 	if (mbq->bp) {
5302 		mbox_bp = (MATCHMAP *)mbq->bp;
5303 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
5304 		    DDI_DMA_SYNC_FORKERNEL);
5305 #ifdef FMA_SUPPORT
5306 		if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle)
5307 		    != DDI_FM_OK) {
5308 			EMLXS_MSGF(EMLXS_CONTEXT,
5309 			    &emlxs_invalid_dma_handle_msg,
5310 			    "sli4_process_mbox_event: hdl=%p",
5311 			    mbox_bp->dma_handle);
5312 
5313 			mb->mbxStatus = MBXERR_DMA_ERROR;
5314 }
5315 #endif
5316 	}
5317 
5318 	/* Now sync the memory buffer if one was used */
5319 	if (mbq->nonembed) {
5320 		mbox_nonembed = (MATCHMAP *)mbq->nonembed;
5321 		size = mbox_nonembed->size;
5322 		EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size,
5323 		    DDI_DMA_SYNC_FORKERNEL);
5324 		iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt);
5325 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size);
5326 
5327 #ifdef FMA_SUPPORT
5328 		if (emlxs_fm_check_dma_handle(hba,
5329 		    mbox_nonembed->dma_handle) != DDI_FM_OK) {
5330 			EMLXS_MSGF(EMLXS_CONTEXT,
5331 			    &emlxs_invalid_dma_handle_msg,
5332 			    "sli4_process_mbox_event: hdl=%p",
5333 			    mbox_nonembed->dma_handle);
5334 
5335 			mb->mbxStatus = MBXERR_DMA_ERROR;
5336 		}
5337 #endif
5338 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
5339 	}
5340 
5341 	/* Mailbox has been completely received at this point */
5342 
5343 	if (mb->mbxCommand == MBX_HEARTBEAT) {
5344 		hba->heartbeat_active = 0;
5345 		goto done;
5346 	}
5347 
5348 	if (hba->mbox_queue_flag == MBX_SLEEP) {
5349 		if (mb->mbxCommand != MBX_DOWN_LOAD
5350 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
5351 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5352 			    "Received.  %s: status=%x Sleep.",
5353 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
5354 			    mb->mbxStatus);
5355 		}
5356 	} else {
5357 		if (mb->mbxCommand != MBX_DOWN_LOAD
5358 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
5359 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5360 			    "Completed. %s: status=%x",
5361 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
5362 			    mb->mbxStatus);
5363 		}
5364 	}
5365 
5366 	/* Filter out passthru mailbox */
5367 	if (mbq->flag & MBQ_PASSTHRU) {
5368 		goto done;
5369 	}
5370 
5371 	if (mb->mbxStatus) {
5372 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5373 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
5374 		    (uint32_t)mb->mbxStatus);
5375 	}
5376 
5377 	if (mbq->mbox_cmpl) {
5378 		rc = (mbq->mbox_cmpl)(hba, mbq);
5379 
5380 		/* If mbox was retried, return immediately */
5381 		if (rc) {
5382 			return;
5383 		}
5384 	}
5385 
5386 done:
5387 
5388 	/* Clean up the mailbox area */
5389 	emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus);
5390 
5391 	/* Attempt to send pending mailboxes */
5392 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
5393 	if (mbq) {
5394 		/* Attempt to send pending mailboxes */
5395 		rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
5396 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
5397 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5398 		}
5399 	}
5400 	return;
5401 
5402 } /* emlxs_sli4_process_mbox_event() */
5403 
5404 
5405 /*ARGSUSED*/
5406 static void
5407 emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp)
5408 {
5409 #ifdef DEBUG_FASTPATH
5410 	emlxs_port_t *port = &PPORT;
5411 #endif /* DEBUG_FASTPATH */
5412 	IOCBQ *iocbq;
5413 	IOCB *iocb;
5414 	uint32_t *iptr;
5415 	fc_packet_t *pkt;
5416 	emlxs_wqe_t *wqe;
5417 
5418 	iocbq = &sbp->iocbq;
5419 	wqe = &iocbq->wqe;
5420 	iocb = &iocbq->iocb;
5421 
5422 #ifdef DEBUG_FASTPATH
5423 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5424 	    "CQE to IOCB: cmd:%x tag:%x xri:%d", wqe->Command,
5425 	    wqe->RequestTag, wqe->XRITag);
5426 #endif /* DEBUG_FASTPATH */
5427 
5428 	iocb->ULPSTATUS = cqe->Status;
5429 	iocb->un.ulpWord[4] = cqe->Parameter;
5430 	iocb->ULPIOTAG = cqe->RequestTag;
5431 	iocb->ULPCONTEXT = wqe->XRITag;
5432 
5433 	switch (wqe->Command) {
5434 
5435 	case CMD_FCP_ICMND64_CR:
5436 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX;
5437 		break;
5438 
5439 	case CMD_FCP_IREAD64_CR:
5440 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX;
5441 		iocb->ULPPU = PARM_XFER_CHECK;
5442 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
5443 			iocb->un.fcpi64.fcpi_parm =
5444 			    wqe->un.FcpCmd.TotalTransferCount -
5445 			    cqe->CmdSpecific;
5446 		}
5447 		break;
5448 
5449 	case CMD_FCP_IWRITE64_CR:
5450 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX;
5451 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
5452 			if (wqe->un.FcpCmd.TotalTransferCount >
5453 			    cqe->CmdSpecific) {
5454 				iocb->un.fcpi64.fcpi_parm =
5455 				    wqe->un.FcpCmd.TotalTransferCount -
5456 				    cqe->CmdSpecific;
5457 			} else {
5458 				iocb->un.fcpi64.fcpi_parm = 0;
5459 			}
5460 		}
5461 		break;
5462 
5463 	case CMD_ELS_REQUEST64_CR:
5464 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX;
5465 		iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific;
5466 		if (iocb->ULPSTATUS == 0) {
5467 			iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
5468 		}
5469 		if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
5470 			/* For LS_RJT, the driver populates the rsp buffer */
5471 			pkt = PRIV2PKT(sbp);
5472 			iptr = (uint32_t *)pkt->pkt_resp;
5473 			*iptr++ = ELS_CMD_LS_RJT;
5474 			*iptr = cqe->Parameter;
5475 		}
5476 		break;
5477 
5478 	case CMD_GEN_REQUEST64_CR:
5479 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
5480 		iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
5481 		break;
5482 
5483 	case CMD_XMIT_SEQUENCE64_CR:
5484 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
5485 		break;
5486 
5487 	case CMD_ABORT_XRI_CX:
5488 		iocb->ULPCONTEXT = wqe->AbortTag;
5489 		break;
5490 
5491 	case CMD_FCP_TRECEIVE64_CX:
5492 		/* free memory for XRDY */
5493 		if (iocbq->bp) {
5494 			emlxs_mem_buf_free(hba, iocbq->bp);
5495 			iocbq->bp = 0;
5496 		}
5497 
5498 		/*FALLTHROUGH*/
5499 
5500 	case CMD_FCP_TSEND64_CX:
5501 	case CMD_FCP_TRSP64_CX:
5502 	default:
5503 		iocb->ULPCOMMAND = wqe->Command;
5504 
5505 	}
5506 } /* emlxs_CQE_to_IOCB() */
5507 
5508 
5509 /*ARGSUSED*/
5510 static void
5511 emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba)
5512 {
5513 	emlxs_port_t *port = &PPORT;
5514 	CHANNEL *cp;
5515 	emlxs_buf_t *sbp;
5516 	IOCBQ *iocbq;
5517 	uint16_t i;
5518 	uint32_t trigger = 0;
5519 	CQE_CmplWQ_t cqe;
5520 
5521 	mutex_enter(&EMLXS_FCTAB_LOCK);
5522 	for (i = 0; i < hba->max_iotag; i++) {
5523 		sbp = hba->fc_table[i];
5524 		if (sbp == NULL || sbp == STALE_PACKET) {
5525 			continue;
5526 		}
5527 		hba->fc_table[i] = STALE_PACKET;
5528 		hba->io_count--;
5529 		sbp->iotag = 0;
5530 		mutex_exit(&EMLXS_FCTAB_LOCK);
5531 
5532 		cp = sbp->channel;
5533 		bzero(&cqe, sizeof (CQE_CmplWQ_t));
5534 		cqe.RequestTag = i;
5535 		cqe.Status = IOSTAT_LOCAL_REJECT;
5536 		cqe.Parameter = IOERR_SEQUENCE_TIMEOUT;
5537 
5538 		cp->hbaCmplCmd_sbp++;
5539 
5540 #ifdef SFCT_SUPPORT
5541 #ifdef FCT_IO_TRACE
5542 		if (sbp->fct_cmd) {
5543 			emlxs_fct_io_trace(port, sbp->fct_cmd,
5544 			    EMLXS_FCT_IOCB_COMPLETE);
5545 		}
5546 #endif /* FCT_IO_TRACE */
5547 #endif /* SFCT_SUPPORT */
5548 
5549 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
5550 			atomic_dec_32(&hba->io_active);
5551 #ifdef NODE_THROTTLE_SUPPORT
5552 			if (sbp->node) {
5553 				atomic_dec_32(&sbp->node->io_active);
5554 			}
5555 #endif /* NODE_THROTTLE_SUPPORT */
5556 		}
5557 
5558 		/* Copy entry to sbp's iocbq */
5559 		iocbq = &sbp->iocbq;
5560 		emlxs_CQE_to_IOCB(hba, &cqe, sbp);
5561 
5562 		iocbq->next = NULL;
5563 
5564 		/* Exchange is no longer busy on-chip, free it */
5565 		emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1);
5566 
5567 		if (!(sbp->pkt_flags &
5568 		    (PACKET_POLLED | PACKET_ALLOCATED))) {
5569 			/* Add the IOCB to the channel list */
5570 			mutex_enter(&cp->rsp_lock);
5571 			if (cp->rsp_head == NULL) {
5572 				cp->rsp_head = iocbq;
5573 				cp->rsp_tail = iocbq;
5574 			} else {
5575 				cp->rsp_tail->next = iocbq;
5576 				cp->rsp_tail = iocbq;
5577 			}
5578 			mutex_exit(&cp->rsp_lock);
5579 			trigger = 1;
5580 		} else {
5581 			emlxs_proc_channel_event(hba, cp, iocbq);
5582 		}
5583 		mutex_enter(&EMLXS_FCTAB_LOCK);
5584 	}
5585 	mutex_exit(&EMLXS_FCTAB_LOCK);
5586 
5587 	if (trigger) {
5588 		for (i = 0; i < hba->chan_count; i++) {
5589 			cp = &hba->chan[i];
5590 			if (cp->rsp_head != NULL) {
5591 				emlxs_thread_trigger2(&cp->intr_thread,
5592 				    emlxs_proc_channel, cp);
5593 			}
5594 		}
5595 	}
5596 
5597 } /* emlxs_sli4_hba_flush_chipq() */
5598 
5599 
5600 /*ARGSUSED*/
5601 static void
5602 emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba,
5603     CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
5604 {
5605 	emlxs_port_t *port = &PPORT;
5606 	CHANNEL *cp;
5607 	uint16_t request_tag;
5608 
5609 	request_tag = cqe->RequestTag;
5610 
5611 	/* 1 to 1 mapping between CQ and channel */
5612 	cp = cq->channelp;
5613 
5614 	cp->hbaCmplCmd++;
5615 
5616 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5617 	    "CQ ENTRY: OOR Cmpl: iotag=%d", request_tag);
5618 
5619 	emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 4, 0);
5620 
5621 } /* emlxs_sli4_process_oor_wqe_cmpl() */
5622 
5623 
5624 /*ARGSUSED*/
5625 static void
5626 emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
5627 {
5628 	emlxs_port_t *port = &PPORT;
5629 	CHANNEL *cp;
5630 	emlxs_buf_t *sbp;
5631 	IOCBQ *iocbq;
5632 	uint16_t request_tag;
5633 #ifdef SFCT_SUPPORT
5634 #ifdef FCT_IO_TRACE
5635 	fct_cmd_t *fct_cmd;
5636 	emlxs_buf_t *cmd_sbp;
5637 #endif /* FCT_IO_TRACE */
5638 #endif /* SFCT_SUPPORT */
5639 
5640 	request_tag = cqe->RequestTag;
5641 
5642 	/* 1 to 1 mapping between CQ and channel */
5643 	cp = cq->channelp;
5644 
5645 	mutex_enter(&EMLXS_FCTAB_LOCK);
5646 	sbp = hba->fc_table[request_tag];
5647 
5648 	if (!sbp) {
5649 		cp->hbaCmplCmd++;
5650 		mutex_exit(&EMLXS_FCTAB_LOCK);
5651 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5652 		    "CQ ENTRY: NULL sbp. iotag=%d. Dropping...",
5653 		    request_tag);
5654 		return;
5655 	}
5656 
5657 	if (sbp == STALE_PACKET) {
5658 		cp->hbaCmplCmd_sbp++;
5659 		mutex_exit(&EMLXS_FCTAB_LOCK);
5660 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5661 		    "CQ ENTRY: Stale sbp. iotag=%d. Dropping...", request_tag);
5662 		return;
5663 	}
5664 
5665 	if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
5666 		atomic_add_32(&hba->io_active, -1);
5667 #ifdef NODE_THROTTLE_SUPPORT
5668 		if (sbp->node) {
5669 			atomic_add_32(&sbp->node->io_active, -1);
5670 		}
5671 #endif /* NODE_THROTTLE_SUPPORT */
5672 	}
5673 
5674 	if (!(sbp->xrip)) {
5675 		cp->hbaCmplCmd++;
5676 		mutex_exit(&EMLXS_FCTAB_LOCK);
5677 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5678 		    "CQ ENTRY: NULL sbp xrip %p. iotag=%d. Dropping...",
5679 		    sbp, request_tag);
5680 		return;
5681 	}
5682 
5683 #ifdef DEBUG_FASTPATH
5684 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5685 	    "CQ ENTRY: process wqe compl");
5686 #endif /* DEBUG_FASTPATH */
5687 	cp->hbaCmplCmd_sbp++;
5688 
5689 	/* Copy entry to sbp's iocbq */
5690 	iocbq = &sbp->iocbq;
5691 	emlxs_CQE_to_IOCB(hba, cqe, sbp);
5692 
5693 	iocbq->next = NULL;
5694 
5695 	if (cqe->XB) {
5696 		/* Mark exchange as ABORT in progress */
5697 		sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO;
5698 		sbp->xrip->flag |= EMLXS_XRI_BUSY;
5699 
5700 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5701 		    "CQ ENTRY: XRI BUSY: iotag=%d xri=%d", request_tag,
5702 		    sbp->xrip->XRI);
5703 
5704 		emlxs_sli4_free_xri(port, sbp, 0, 0);
5705 	} else {
5706 		/* Exchange is no longer busy on-chip, free it */
5707 		emlxs_sli4_free_xri(port, sbp, sbp->xrip, 0);
5708 	}
5709 
5710 	mutex_exit(&EMLXS_FCTAB_LOCK);
5711 
5712 #ifdef SFCT_SUPPORT
5713 #ifdef FCT_IO_TRACE
5714 	fct_cmd = sbp->fct_cmd;
5715 	if (fct_cmd) {
5716 		cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
5717 		mutex_enter(&cmd_sbp->fct_mtx);
5718 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE);
5719 		mutex_exit(&cmd_sbp->fct_mtx);
5720 	}
5721 #endif /* FCT_IO_TRACE */
5722 #endif /* SFCT_SUPPORT */
5723 
5724 	/*
5725 	 * If this is NOT a polled command completion
5726 	 * or a driver allocated pkt, then defer pkt
5727 	 * completion.
5728 	 */
5729 	if (!(sbp->pkt_flags &
5730 	    (PACKET_POLLED | PACKET_ALLOCATED))) {
5731 		/* Add the IOCB to the channel list */
5732 		mutex_enter(&cp->rsp_lock);
5733 		if (cp->rsp_head == NULL) {
5734 			cp->rsp_head = iocbq;
5735 			cp->rsp_tail = iocbq;
5736 		} else {
5737 			cp->rsp_tail->next = iocbq;
5738 			cp->rsp_tail = iocbq;
5739 		}
5740 		mutex_exit(&cp->rsp_lock);
5741 
5742 		/* Delay triggering thread till end of ISR */
5743 		cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
5744 	} else {
5745 		emlxs_proc_channel_event(hba, cp, iocbq);
5746 	}
5747 
5748 } /* emlxs_sli4_process_wqe_cmpl() */
5749 
5750 
5751 /*ARGSUSED*/
5752 static void
5753 emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq,
5754     CQE_RelWQ_t *cqe)
5755 {
5756 	emlxs_port_t *port = &PPORT;
5757 	WQ_DESC_t *wq;
5758 	CHANNEL *cp;
5759 	uint32_t i;
5760 	uint16_t wqi;
5761 
5762 	wqi = emlxs_sli4_wqid_to_index(hba, (uint16_t)cqe->WQid);
5763 
5764 	/* Verify WQ index */
5765 	if (wqi == 0xffff) {
5766 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5767 		    "CQ ENTRY: Invalid WQid:%d. Dropping...",
5768 		    cqe->WQid);
5769 		return;
5770 	}
5771 
5772 	wq = &hba->sli.sli4.wq[wqi];
5773 
5774 #ifdef DEBUG_FASTPATH
5775 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5776 	    "CQ ENTRY: process release wqe: old %d new %d", wq->port_index,
5777 	    cqe->WQindex);
5778 #endif /* DEBUG_FASTPATH */
5779 
5780 	wq->port_index = cqe->WQindex;
5781 
5782 	/* Cmd ring may be available. Try sending more iocbs */
5783 	for (i = 0; i < hba->chan_count; i++) {
5784 		cp = &hba->chan[i];
5785 		if (wq == (WQ_DESC_t *)cp->iopath) {
5786 			emlxs_sli4_issue_iocb_cmd(hba, cp, 0);
5787 		}
5788 	}
5789 
5790 } /* emlxs_sli4_process_release_wqe() */
5791 
5792 
5793 /*ARGSUSED*/
5794 emlxs_iocbq_t *
5795 emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr)
5796 {
5797 	emlxs_queue_t *q;
5798 	emlxs_iocbq_t *iocbq;
5799 	emlxs_iocbq_t *prev;
5800 	fc_frame_hdr_t *fchdr2;
5801 	RXQ_DESC_t *rxq;
5802 
5803 	switch (fchdr->type) {
5804 	case 1: /* ELS */
5805 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
5806 		break;
5807 	case 0x20: /* CT */
5808 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
5809 		break;
5810 	default:
5811 		return (NULL);
5812 	}
5813 
5814 	mutex_enter(&rxq->lock);
5815 
5816 	q = &rxq->active;
5817 	iocbq  = (emlxs_iocbq_t *)q->q_first;
5818 	prev = NULL;
5819 
5820 	while (iocbq) {
5821 
5822 		fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord;
5823 
5824 		if ((fchdr2->s_id == fchdr->s_id) &&
5825 		    (fchdr2->ox_id == fchdr->ox_id) &&
5826 		    (fchdr2->seq_id == fchdr->seq_id)) {
5827 			/* Remove iocbq */
5828 			if (prev) {
5829 				prev->next = iocbq->next;
5830 			}
5831 			if (q->q_first == (uint8_t *)iocbq) {
5832 				q->q_first = (uint8_t *)iocbq->next;
5833 			}
5834 			if (q->q_last == (uint8_t *)iocbq) {
5835 				q->q_last = (uint8_t *)prev;
5836 			}
5837 			q->q_cnt--;
5838 
5839 			break;
5840 		}
5841 
5842 		prev  = iocbq;
5843 		iocbq = iocbq->next;
5844 	}
5845 
5846 	mutex_exit(&rxq->lock);
5847 
5848 	return (iocbq);
5849 
5850 } /* emlxs_sli4_rxq_get() */
5851 
5852 
5853 /*ARGSUSED*/
5854 void
5855 emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq)
5856 {
5857 	emlxs_queue_t *q;
5858 	fc_frame_hdr_t *fchdr;
5859 	RXQ_DESC_t *rxq;
5860 
5861 	fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR;
5862 
5863 	switch (fchdr->type) {
5864 	case 1: /* ELS */
5865 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
5866 		break;
5867 	case 0x20: /* CT */
5868 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
5869 		break;
5870 	default:
5871 		return;
5872 	}
5873 
5874 	mutex_enter(&rxq->lock);
5875 
5876 	q = &rxq->active;
5877 
5878 	if (q->q_last) {
5879 		((emlxs_iocbq_t *)q->q_last)->next = iocbq;
5880 		q->q_cnt++;
5881 	} else {
5882 		q->q_first = (uint8_t *)iocbq;
5883 		q->q_cnt = 1;
5884 	}
5885 
5886 	q->q_last = (uint8_t *)iocbq;
5887 	iocbq->next = NULL;
5888 
5889 	mutex_exit(&rxq->lock);
5890 
5891 	return;
5892 
5893 } /* emlxs_sli4_rxq_put() */
5894 
5895 
5896 static void
5897 emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid)
5898 {
5899 	emlxs_hba_t *hba = HBA;
5900 	emlxs_rqdbu_t rqdb;
5901 
5902 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5903 	    "RQ POST: rqid=%d count=1", rqid);
5904 
5905 	/* Ring the RQ doorbell once to repost the RQ buffer */
5906 	rqdb.word = 0;
5907 	rqdb.db.Qid = rqid;
5908 	rqdb.db.NumPosted = 1;
5909 
5910 	emlxs_sli4_write_rqdb(hba, rqdb.word);
5911 
5912 } /* emlxs_sli4_rq_post() */
5913 
5914 
5915 /*ARGSUSED*/
5916 static void
5917 emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq,
5918     CQE_UnsolRcv_t *cqe)
5919 {
5920 	emlxs_port_t *port = &PPORT;
5921 	emlxs_port_t *vport;
5922 	RQ_DESC_t *hdr_rq;
5923 	RQ_DESC_t *data_rq;
5924 	MBUF_INFO *hdr_mp;
5925 	MBUF_INFO *data_mp;
5926 	MATCHMAP *seq_mp;
5927 	uint32_t *data;
5928 	fc_frame_hdr_t fchdr;
5929 	uint16_t hdr_rqi;
5930 	uint32_t host_index;
5931 	emlxs_iocbq_t *iocbq = NULL;
5932 	emlxs_iocb_t *iocb;
5933 	emlxs_node_t *node = NULL;
5934 	uint32_t i;
5935 	uint32_t seq_len;
5936 	uint32_t seq_cnt;
5937 	uint32_t buf_type;
5938 	char label[32];
5939 	emlxs_wqe_t *wqe;
5940 	CHANNEL *cp;
5941 	XRIobj_t *xrip;
5942 	RPIobj_t *rpip = NULL;
5943 	uint32_t	cmd;
5944 	uint32_t posted = 0;
5945 	uint32_t abort = 1;
5946 	off_t offset;
5947 	uint32_t status;
5948 	uint32_t data_size;
5949 	uint16_t rqid;
5950 	uint32_t hdr_size;
5951 	fc_packet_t *pkt;
5952 	emlxs_buf_t *sbp;
5953 
5954 	if (cqe->Code == CQE_TYPE_UNSOL_RCV_V1) {
5955 		CQE_UnsolRcvV1_t *cqeV1 = (CQE_UnsolRcvV1_t *)cqe;
5956 
5957 		status	  = cqeV1->Status;
5958 		data_size = cqeV1->data_size;
5959 		rqid	  = cqeV1->RQid;
5960 		hdr_size  = cqeV1->hdr_size;
5961 	} else {
5962 		status	  = cqe->Status;
5963 		data_size = cqe->data_size;
5964 		rqid	  = cqe->RQid;
5965 		hdr_size  = cqe->hdr_size;
5966 	}
5967 
5968 	/* Validate the CQE */
5969 
5970 	/* Check status */
5971 	switch (status) {
5972 	case RQ_STATUS_SUCCESS: /* 0x10 */
5973 		break;
5974 
5975 	case RQ_STATUS_BUFLEN_EXCEEDED:  /* 0x11 */
5976 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5977 		    "CQ ENTRY: Unsol Rcv: Payload truncated.");
5978 		break;
5979 
5980 	case RQ_STATUS_NEED_BUFFER: /* 0x12 */
5981 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5982 		    "CQ ENTRY: Unsol Rcv: Payload buffer needed.");
5983 		return;
5984 
5985 	case RQ_STATUS_FRAME_DISCARDED:  /* 0x13 */
5986 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5987 		    "CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
5988 		return;
5989 
5990 	default:
5991 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5992 		    "CQ ENTRY: Unsol Rcv: Unknown status=%x.",
5993 		    status);
5994 		break;
5995 	}
5996 
5997 	/* Make sure there is a frame header */
5998 	if (hdr_size < sizeof (fc_frame_hdr_t)) {
5999 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6000 		    "CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
6001 		return;
6002 	}
6003 
6004 	hdr_rqi = emlxs_sli4_rqid_to_index(hba, rqid);
6005 
6006 	/* Verify RQ index */
6007 	if (hdr_rqi == 0xffff) {
6008 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6009 		    "CQ ENTRY: Unsol Rcv: Invalid RQID:%d. Dropping...",
6010 		    rqid);
6011 		return;
6012 	}
6013 
6014 	hdr_rq  = &hba->sli.sli4.rq[hdr_rqi];
6015 	data_rq = &hba->sli.sli4.rq[hdr_rqi + 1];
6016 
6017 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6018 	    "CQ ENTRY: Unsol Rcv:%x rqid=%d,%d index=%d status=%x "
6019 	    "hdr_size=%d data_size=%d",
6020 	    cqe->Code, rqid, hdr_rqi, hdr_rq->host_index, status, hdr_size,
6021 	    data_size);
6022 
6023 	hdr_rq->num_proc++;
6024 
6025 	/* Update host index */
6026 	mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock);
6027 	host_index = hdr_rq->host_index;
6028 	hdr_rq->host_index++;
6029 
6030 	if (hdr_rq->host_index >= hdr_rq->max_index) {
6031 		hdr_rq->host_index = 0;
6032 	}
6033 	data_rq->host_index = hdr_rq->host_index;
6034 	mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock);
6035 
6036 	/* Get the next header rqb */
6037 	hdr_mp  = &hdr_rq->rqb[host_index];
6038 
6039 	offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) -
6040 	    (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt));
6041 
6042 	EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset,
6043 	    sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
6044 
6045 	LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr,
6046 	    sizeof (fc_frame_hdr_t));
6047 
6048 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6049 	    "RQ HDR[%d]: rctl:%x type:%x "
6050 	    "sid:%x did:%x oxid:%x rxid:%x",
6051 	    host_index, fchdr.r_ctl, fchdr.type,
6052 	    fchdr.s_id,  fchdr.d_id, fchdr.ox_id, fchdr.rx_id);
6053 
6054 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6055 	    "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
6056 	    host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt,
6057 	    fchdr.df_ctl, fchdr.ro);
6058 
6059 	/* Verify fc header type */
6060 	switch (fchdr.type) {
6061 	case 0: /* BLS */
6062 		if (fchdr.r_ctl != 0x81) {
6063 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6064 			    "RQ ENTRY: Unexpected FC rctl (0x%x) "
6065 			    "received. Dropping...",
6066 			    fchdr.r_ctl);
6067 
6068 			goto done;
6069 		}
6070 
6071 		/* Make sure there is no payload */
6072 		if (data_size != 0) {
6073 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6074 			    "RQ ENTRY: ABTS payload provided. Dropping...");
6075 
6076 			goto done;
6077 		}
6078 
6079 		buf_type = 0xFFFFFFFF;
6080 		(void) strlcpy(label, "ABTS", sizeof (label));
6081 		cp = &hba->chan[hba->channel_els];
6082 		break;
6083 
6084 	case 0x01: /* ELS */
6085 		/* Make sure there is a payload */
6086 		if (data_size == 0) {
6087 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6088 			    "RQ ENTRY: Unsol Rcv: No ELS payload provided. "
6089 			    "Dropping...");
6090 
6091 			goto done;
6092 		}
6093 
6094 		buf_type = MEM_ELSBUF;
6095 		(void) strlcpy(label, "Unsol ELS", sizeof (label));
6096 		cp = &hba->chan[hba->channel_els];
6097 		break;
6098 
6099 	case 0x20: /* CT */
6100 		/* Make sure there is a payload */
6101 		if (data_size == 0) {
6102 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6103 			    "RQ ENTRY: Unsol Rcv: No CT payload provided. "
6104 			    "Dropping...");
6105 
6106 			goto done;
6107 		}
6108 
6109 		buf_type = MEM_CTBUF;
6110 		(void) strlcpy(label, "Unsol CT", sizeof (label));
6111 		cp = &hba->chan[hba->channel_ct];
6112 		break;
6113 
6114 	case 0x08: /* FCT */
6115 		/* Make sure there is a payload */
6116 		if (data_size == 0) {
6117 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6118 			    "RQ ENTRY: Unsol Rcv: No FCP payload provided. "
6119 			    "Dropping...");
6120 
6121 			goto done;
6122 		}
6123 
6124 		buf_type = MEM_FCTBUF;
6125 		(void) strlcpy(label, "Unsol FCT", sizeof (label));
6126 		cp = &hba->chan[hba->CHANNEL_FCT];
6127 		break;
6128 
6129 	default:
6130 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6131 		    "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
6132 		    fchdr.type);
6133 
6134 		goto done;
6135 	}
6136 	/* Fc Header is valid */
6137 
6138 	/* Check if this is an active sequence */
6139 	iocbq = emlxs_sli4_rxq_get(hba, &fchdr);
6140 
6141 	if (!iocbq) {
6142 		if (fchdr.type != 0) {
6143 			if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) {
6144 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6145 				    "RQ ENTRY: %s: First of sequence not"
6146 				    " set.  Dropping...",
6147 				    label);
6148 
6149 				goto done;
6150 			}
6151 		}
6152 
6153 		if ((fchdr.type != 0) && (fchdr.seq_cnt != 0)) {
6154 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6155 			    "RQ ENTRY: %s: Sequence count not zero (%d).  "
6156 			    "Dropping...",
6157 			    label, fchdr.seq_cnt);
6158 
6159 			goto done;
6160 		}
6161 
6162 		/* Find vport */
6163 		for (i = 0; i < MAX_VPORTS; i++) {
6164 			vport = &VPORT(i);
6165 
6166 			if (vport->did == fchdr.d_id) {
6167 				port = vport;
6168 				break;
6169 			}
6170 		}
6171 
6172 		if (i == MAX_VPORTS) {
6173 			/* Allow unsol FLOGI & PLOGI for P2P */
6174 			if ((fchdr.type != 1 /* ELS*/) ||
6175 			    ((fchdr.d_id != FABRIC_DID) &&
6176 			    !(hba->flag & FC_PT_TO_PT))) {
6177 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6178 				    "RQ ENTRY: %s: Invalid did=%x. Dropping...",
6179 				    label, fchdr.d_id);
6180 
6181 				goto done;
6182 			}
6183 		}
6184 
6185 		/* Allocate an IOCBQ */
6186 		iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba, MEM_IOCB);
6187 
6188 		if (!iocbq) {
6189 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6190 			    "RQ ENTRY: %s: Out of IOCB "
6191 			    "resources.  Dropping...",
6192 			    label);
6193 
6194 			goto done;
6195 		}
6196 
6197 		seq_mp = NULL;
6198 		if (fchdr.type != 0) {
6199 			/* Allocate a buffer */
6200 			seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type);
6201 
6202 			if (!seq_mp) {
6203 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6204 				    "RQ ENTRY: %s: Out of buffer "
6205 				    "resources.  Dropping...",
6206 				    label);
6207 
6208 				goto done;
6209 			}
6210 
6211 			iocbq->bp = (uint8_t *)seq_mp;
6212 		}
6213 
6214 		node = (void *)emlxs_node_find_did(port, fchdr.s_id, 1);
6215 		if (node == NULL) {
6216 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6217 			    "RQ ENTRY: %s: Node not found. sid=%x",
6218 			    label, fchdr.s_id);
6219 		}
6220 
6221 		/* Initialize the iocbq */
6222 		iocbq->port = port;
6223 		iocbq->channel = cp;
6224 		iocbq->node = node;
6225 
6226 		iocb = &iocbq->iocb;
6227 		iocb->RXSEQCNT = 0;
6228 		iocb->RXSEQLEN = 0;
6229 
6230 		seq_len = 0;
6231 		seq_cnt = 0;
6232 
6233 	} else {
6234 
6235 		iocb = &iocbq->iocb;
6236 		port = iocbq->port;
6237 		node = (emlxs_node_t *)iocbq->node;
6238 
6239 		seq_mp = (MATCHMAP *)iocbq->bp;
6240 		seq_len = iocb->RXSEQLEN;
6241 		seq_cnt = iocb->RXSEQCNT;
6242 
6243 		/* Check sequence order */
6244 		if (fchdr.seq_cnt != seq_cnt) {
6245 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6246 			    "RQ ENTRY: %s: Out of order frame received "
6247 			    "(%d != %d).  Dropping...",
6248 			    label, fchdr.seq_cnt, seq_cnt);
6249 
6250 			goto done;
6251 		}
6252 	}
6253 
6254 	/* We now have an iocbq */
6255 
6256 	if (!port->vpip->vfip) {
6257 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6258 		    "RQ ENTRY: %s: No fabric connection. "
6259 		    "Dropping...",
6260 		    label);
6261 
6262 		goto done;
6263 	}
6264 
6265 	/* Save the frame data to our seq buffer */
6266 	if (data_size && seq_mp) {
6267 		/* Get the next data rqb */
6268 		data_mp = &data_rq->rqb[host_index];
6269 
6270 		offset = (off_t)((uint64_t)((unsigned long)
6271 		    data_mp->virt) -
6272 		    (uint64_t)((unsigned long)
6273 		    hba->sli.sli4.slim2.virt));
6274 
6275 		EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset,
6276 		    data_size, DDI_DMA_SYNC_FORKERNEL);
6277 
6278 		data = (uint32_t *)data_mp->virt;
6279 
6280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6281 		    "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
6282 		    host_index, data[0], data[1], data[2], data[3],
6283 		    data[4], data[5]);
6284 
6285 		/* Check sequence length */
6286 		if ((seq_len + data_size) > seq_mp->size) {
6287 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6288 			    "RQ ENTRY: %s: Sequence buffer overflow. "
6289 			    "(%d > %d). Dropping...",
6290 			    label, (seq_len + data_size), seq_mp->size);
6291 
6292 			goto done;
6293 		}
6294 
6295 		/* Copy data to local receive buffer */
6296 		bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt +
6297 		    seq_len), data_size);
6298 
6299 		seq_len += data_size;
6300 	}
6301 
6302 	/* If this is not the last frame of sequence, queue it. */
6303 	if (!(fchdr.f_ctl & F_CTL_END_SEQ)) {
6304 		/* Save sequence header */
6305 		if (seq_cnt == 0) {
6306 			bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR,
6307 			    sizeof (fc_frame_hdr_t));
6308 		}
6309 
6310 		/* Update sequence info in iocb */
6311 		iocb->RXSEQCNT = seq_cnt + 1;
6312 		iocb->RXSEQLEN = seq_len;
6313 
6314 		/* Queue iocbq for next frame */
6315 		emlxs_sli4_rxq_put(hba, iocbq);
6316 
6317 		/* Don't free resources */
6318 		iocbq = NULL;
6319 
6320 		/* No need to abort */
6321 		abort = 0;
6322 
6323 		goto done;
6324 	}
6325 
6326 	emlxs_sli4_rq_post(port, hdr_rq->qid);
6327 	posted = 1;
6328 
6329 	/* End of sequence found. Process request now. */
6330 
6331 	if (seq_cnt > 0) {
6332 		/* Retrieve first frame of sequence */
6333 		bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr,
6334 		    sizeof (fc_frame_hdr_t));
6335 
6336 		bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t));
6337 	}
6338 
6339 	/* Build rcv iocb and process it */
6340 	switch (fchdr.type) {
6341 	case 0: /* BLS */
6342 
6343 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6344 		    "RQ ENTRY: %s: oxid:%x rxid %x sid:%x. Sending BLS ACC...",
6345 		    label, fchdr.ox_id, fchdr.rx_id, fchdr.s_id);
6346 
6347 		/* Try to send abort response */
6348 		if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
6349 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6350 			    "RQ ENTRY: %s: Unable to alloc pkt. Dropping...",
6351 			    label);
6352 			goto done;
6353 		}
6354 
6355 		/* Setup sbp / iocb for driver initiated cmd */
6356 		sbp = PKT2PRIV(pkt);
6357 
6358 		/* Free the temporary iocbq */
6359 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
6360 
6361 		iocbq = (emlxs_iocbq_t *)&sbp->iocbq;
6362 		iocbq->port = port;
6363 		iocbq->channel = cp;
6364 		iocbq->node = node;
6365 
6366 		sbp->pkt_flags &= ~PACKET_ULP_OWNED;
6367 
6368 		if (node) {
6369 			sbp->node = node;
6370 			sbp->did  = node->nlp_DID;
6371 		}
6372 
6373 		iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL);
6374 
6375 		/* BLS ACC Response */
6376 		wqe = &iocbq->wqe;
6377 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
6378 
6379 		iocbq->iocb.ULPCOMMAND = CMD_XMIT_BLS_RSP64_CX;
6380 		wqe->Command = CMD_XMIT_BLS_RSP64_CX;
6381 		wqe->CmdType = WQE_TYPE_GEN;
6382 
6383 		wqe->un.BlsRsp.Payload0 = 0x80;
6384 		wqe->un.BlsRsp.Payload1 = fchdr.seq_id;
6385 
6386 		wqe->un.BlsRsp.OXId = fchdr.ox_id;
6387 		wqe->un.BlsRsp.RXId = fchdr.rx_id;
6388 
6389 		wqe->un.BlsRsp.SeqCntLow = 0;
6390 		wqe->un.BlsRsp.SeqCntHigh = 0xFFFF;
6391 
6392 		wqe->un.BlsRsp.XO = ((fchdr.f_ctl & F_CTL_XCHG_CONTEXT)? 1:0);
6393 		wqe->un.BlsRsp.AR = 0;
6394 
6395 		rpip = EMLXS_NODE_TO_RPI(port, node);
6396 
6397 		if (rpip) {
6398 			wqe->ContextType = WQE_RPI_CONTEXT;
6399 			wqe->ContextTag = rpip->RPI;
6400 		} else {
6401 			wqe->ContextType = WQE_VPI_CONTEXT;
6402 			wqe->ContextTag = port->vpip->VPI;
6403 
6404 			rpip = emlxs_rpi_reserve_notify(port, fchdr.s_id, 0);
6405 
6406 			if (!rpip) {
6407 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6408 				    "RQ ENTRY: %s: Unable to alloc "
6409 				    "reserved RPI. Dropping...",
6410 				    label);
6411 
6412 				goto done;
6413 			}
6414 
6415 			/* Store the reserved rpi */
6416 			wqe->CmdSpecific = rpip->RPI;
6417 
6418 			wqe->un.BlsRsp.RemoteId = fchdr.s_id;
6419 			wqe->un.BlsRsp.LocalId = fchdr.d_id;
6420 		}
6421 
6422 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6423 			wqe->CCPE = 1;
6424 			wqe->CCP = fchdr.rsvd;
6425 		}
6426 
6427 		/* Allocate an exchange for this command */
6428 		xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
6429 		    EMLXS_XRI_SOL_BLS_TYPE);
6430 
6431 		if (!xrip) {
6432 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6433 			    "RQ ENTRY: %s: Unable to alloc XRI. Dropping...",
6434 			    label);
6435 			goto done;
6436 		}
6437 
6438 		wqe->XRITag = xrip->XRI;
6439 		wqe->Class = CLASS3;
6440 		wqe->RequestTag = xrip->iotag;
6441 		wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
6442 
6443 		sbp->ticks = hba->timer_tics + 30;
6444 
6445 		emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq);
6446 
6447 		/* The temporary iocbq has been freed already */
6448 		iocbq = NULL;
6449 
6450 		break;
6451 
6452 	case 1: /* ELS */
6453 		cmd = *((uint32_t *)seq_mp->virt);
6454 		cmd &= ELS_CMD_MASK;
6455 
6456 		if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED)) {
6457 			uint32_t dropit = 1;
6458 
6459 			/* Allow for P2P handshaking */
6460 			switch (cmd) {
6461 			case ELS_CMD_FLOGI:
6462 				dropit = 0;
6463 				break;
6464 
6465 			case ELS_CMD_PLOGI:
6466 			case ELS_CMD_PRLI:
6467 				if (hba->flag & FC_PT_TO_PT) {
6468 					dropit = 0;
6469 				}
6470 				break;
6471 			}
6472 
6473 			if (dropit) {
6474 				EMLXS_MSGF(EMLXS_CONTEXT,
6475 				    &emlxs_sli_detail_msg,
6476 				    "RQ ENTRY: %s: Port not yet enabled. "
6477 				    "Dropping...",
6478 				    label);
6479 				goto done;
6480 			}
6481 		}
6482 
6483 		rpip = NULL;
6484 
6485 		if (cmd != ELS_CMD_LOGO) {
6486 			rpip = EMLXS_NODE_TO_RPI(port, node);
6487 		}
6488 
6489 		if (!rpip) {
6490 			/* Use the fabric rpi */
6491 			rpip = port->vpip->fabric_rpip;
6492 		}
6493 
6494 		xrip = emlxs_sli4_reserve_xri(port, rpip,
6495 		    EMLXS_XRI_UNSOL_ELS_TYPE, fchdr.ox_id);
6496 
6497 		if (!xrip) {
6498 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6499 			    "RQ ENTRY: %s: Out of exchange "
6500 			    "resources.  Dropping...",
6501 			    label);
6502 
6503 			goto done;
6504 		}
6505 
6506 		/* Build CMD_RCV_ELS64_CX */
6507 		iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0;
6508 		iocb->un.rcvels64.elsReq.tus.f.bdeSize  = seq_len;
6509 		iocb->un.rcvels64.elsReq.addrLow  = PADDR_LO(seq_mp->phys);
6510 		iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys);
6511 		iocb->ULPBDECOUNT = 1;
6512 
6513 		iocb->un.rcvels64.remoteID = fchdr.s_id;
6514 		iocb->un.rcvels64.parmRo = fchdr.d_id;
6515 
6516 		iocb->ULPPU = 0x3;
6517 		iocb->ULPCONTEXT = xrip->XRI;
6518 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
6519 		iocb->ULPCLASS = CLASS3;
6520 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
6521 
6522 		iocb->unsli3.ext_rcv.seq_len = seq_len;
6523 		iocb->unsli3.ext_rcv.vpi = port->vpip->VPI;
6524 		iocb->unsli3.ext_rcv.oxid = fchdr.ox_id;
6525 
6526 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6527 			iocb->unsli3.ext_rcv.ccpe = 1;
6528 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6529 		}
6530 
6531 		if (port->mode == MODE_INITIATOR) {
6532 			(void) emlxs_els_handle_unsol_req(port, iocbq->channel,
6533 			    iocbq, seq_mp, seq_len);
6534 		}
6535 #ifdef SFCT_SUPPORT
6536 		else if (port->mode == MODE_TARGET) {
6537 			(void) emlxs_fct_handle_unsol_els(port, iocbq->channel,
6538 			    iocbq, seq_mp, seq_len);
6539 		}
6540 #endif /* SFCT_SUPPORT */
6541 		break;
6542 
6543 #ifdef SFCT_SUPPORT
6544 	case 8: /* FCT */
6545 		if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
6546 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6547 			    "RQ ENTRY: %s: Port not yet enabled. "
6548 			    "Dropping...",
6549 			    label);
6550 
6551 			goto done;
6552 		}
6553 
6554 		rpip = EMLXS_NODE_TO_RPI(port, node);
6555 
6556 		if (!rpip) {
6557 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6558 			    "RQ ENTRY: %s: Port not logged in. "
6559 			    "Dropping...",
6560 			    label);
6561 
6562 			goto done;
6563 		}
6564 
6565 		xrip = emlxs_sli4_reserve_xri(port, rpip,
6566 		    EMLXS_XRI_UNSOL_FCP_TYPE, fchdr.ox_id);
6567 
6568 		if (!xrip) {
6569 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6570 			    "RQ ENTRY: %s: Out of exchange "
6571 			    "resources.  Dropping...",
6572 			    label);
6573 
6574 			goto done;
6575 		}
6576 
6577 		/* Build CMD_RCV_SEQUENCE64_CX */
6578 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
6579 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
6580 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
6581 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
6582 		iocb->ULPBDECOUNT = 1;
6583 
6584 		iocb->ULPPU = 0x3;
6585 		iocb->ULPCONTEXT = xrip->XRI;
6586 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
6587 		iocb->ULPCLASS = CLASS3;
6588 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
6589 
6590 		iocb->unsli3.ext_rcv.seq_len = seq_len;
6591 		iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
6592 		iocb->unsli3.ext_rcv.oxid = fchdr.ox_id;
6593 
6594 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6595 			iocb->unsli3.ext_rcv.ccpe = 1;
6596 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6597 		}
6598 
6599 		/* pass xrip to FCT in the iocbq */
6600 		iocbq->sbp = xrip;
6601 
6602 #define	EMLXS_FIX_CISCO_BUG1
6603 #ifdef EMLXS_FIX_CISCO_BUG1
6604 {
6605 uint8_t *ptr;
6606 ptr = ((uint8_t *)seq_mp->virt);
6607 if (((*ptr+12) != 0xa0) && (*(ptr+20) == 0x8) && (*(ptr+21) == 0x8)) {
6608 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6609 	    "RQ ENTRY: Bad CDB fixed");
6610 	*ptr++ = 0;
6611 	*ptr = 0;
6612 }
6613 }
6614 #endif
6615 		(void) emlxs_fct_handle_unsol_req(port, cp, iocbq,
6616 			seq_mp, seq_len);
6617 		break;
6618 #endif /* SFCT_SUPPORT */
6619 
6620 	case 0x20: /* CT */
6621 		if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED) &&
6622 		    !(hba->flag & FC_LOOPBACK_MODE)) {
6623 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6624 			    "RQ ENTRY: %s: Port not yet enabled. "
6625 			    "Dropping...",
6626 			    label);
6627 
6628 			goto done;
6629 		}
6630 
6631 		if (!node) {
6632 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6633 			    "RQ ENTRY: %s: Node not found (did=%x).  "
6634 			    "Dropping...",
6635 			    label, fchdr.d_id);
6636 
6637 			goto done;
6638 		}
6639 
6640 		rpip = EMLXS_NODE_TO_RPI(port, node);
6641 
6642 		if (!rpip) {
6643 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6644 			    "RQ ENTRY: %s: RPI not found (did=%x rpi=%d).  "
6645 			    "Dropping...",
6646 			    label, fchdr.d_id, node->nlp_Rpi);
6647 
6648 			goto done;
6649 		}
6650 
6651 		xrip = emlxs_sli4_reserve_xri(port, rpip,
6652 		    EMLXS_XRI_UNSOL_CT_TYPE, fchdr.ox_id);
6653 
6654 		if (!xrip) {
6655 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6656 			    "RQ ENTRY: %s: Out of exchange "
6657 			    "resources.  Dropping...",
6658 			    label);
6659 
6660 			goto done;
6661 		}
6662 
6663 		/* Build CMD_RCV_SEQ64_CX */
6664 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
6665 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
6666 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
6667 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
6668 		iocb->ULPBDECOUNT = 1;
6669 
6670 		iocb->un.rcvseq64.xrsqRo = 0;
6671 		iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl;
6672 		iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type;
6673 		iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl;
6674 		iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl;
6675 
6676 		iocb->ULPPU = 0x3;
6677 		iocb->ULPCONTEXT = xrip->XRI;
6678 		iocb->ULPIOTAG = rpip->RPI;
6679 		iocb->ULPCLASS = CLASS3;
6680 		iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX;
6681 
6682 		iocb->unsli3.ext_rcv.seq_len = seq_len;
6683 		iocb->unsli3.ext_rcv.vpi = port->vpip->VPI;
6684 
6685 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6686 			iocb->unsli3.ext_rcv.ccpe = 1;
6687 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6688 		}
6689 
6690 		(void) emlxs_ct_handle_unsol_req(port, iocbq->channel,
6691 		    iocbq, seq_mp, seq_len);
6692 
6693 		break;
6694 	}
6695 
6696 	/* Sequence handled, no need to abort */
6697 	abort = 0;
6698 
6699 done:
6700 
6701 	if (!posted) {
6702 		emlxs_sli4_rq_post(port, hdr_rq->qid);
6703 	}
6704 
6705 	if (abort) {
6706 		/* Send ABTS for this exchange */
6707 		/* !!! Currently, we have no implementation for this !!! */
6708 		abort = 0;
6709 	}
6710 
6711 	/* Return memory resources to pools */
6712 	if (iocbq) {
6713 		if (iocbq->bp) {
6714 			emlxs_mem_put(hba, buf_type, (void *)iocbq->bp);
6715 			iocbq->bp = 0;
6716 		}
6717 
6718 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
6719 	}
6720 
6721 #ifdef FMA_SUPPORT
6722 	if (emlxs_fm_check_dma_handle(hba,
6723 	    hba->sli.sli4.slim2.dma_handle)
6724 	    != DDI_FM_OK) {
6725 		EMLXS_MSGF(EMLXS_CONTEXT,
6726 		    &emlxs_invalid_dma_handle_msg,
6727 		    "sli4_process_unsol_rcv: hdl=%p",
6728 		    hba->sli.sli4.slim2.dma_handle);
6729 
6730 		emlxs_thread_spawn(hba, emlxs_restart_thread,
6731 		    0, 0);
6732 	}
6733 #endif
6734 	return;
6735 
6736 } /* emlxs_sli4_process_unsol_rcv() */
6737 
6738 
6739 /*ARGSUSED*/
6740 static void
6741 emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq,
6742     CQE_XRI_Abort_t *cqe)
6743 {
6744 	emlxs_port_t *port = &PPORT;
6745 	XRIobj_t *xrip;
6746 
6747 	mutex_enter(&EMLXS_FCTAB_LOCK);
6748 
6749 	xrip = emlxs_sli4_find_xri(port, cqe->XRI);
6750 	if (xrip == NULL) {
6751 		/* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, */
6752 		/*    "CQ ENTRY: process xri aborted ignored");  */
6753 
6754 		mutex_exit(&EMLXS_FCTAB_LOCK);
6755 		return;
6756 	}
6757 
6758 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6759 	    "CQ ENTRY: XRI Aborted: xri=%d IA=%d EO=%d BR=%d",
6760 	    cqe->XRI, cqe->IA, cqe->EO, cqe->BR);
6761 
6762 	if (!(xrip->flag & EMLXS_XRI_BUSY)) {
6763 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6764 		    "CQ ENTRY: XRI Aborted: xri=%d flag=%x. Bad state.",
6765 		    xrip->XRI, xrip->flag);
6766 
6767 		mutex_exit(&EMLXS_FCTAB_LOCK);
6768 		return;
6769 	}
6770 
6771 	/* Exchange is no longer busy on-chip, free it */
6772 	emlxs_sli4_free_xri(port, 0, xrip, 0);
6773 
6774 	mutex_exit(&EMLXS_FCTAB_LOCK);
6775 
6776 	return;
6777 
6778 } /* emlxs_sli4_process_xri_aborted () */
6779 
6780 
6781 /*ARGSUSED*/
6782 static void
6783 emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq)
6784 {
6785 	emlxs_port_t *port = &PPORT;
6786 	CQE_u *cqe;
6787 	CQE_u cq_entry;
6788 	uint32_t cqdb;
6789 	int num_entries = 0;
6790 	off_t offset;
6791 
6792 	/* EMLXS_PORT_LOCK must be held when entering this routine */
6793 
6794 	cqe = (CQE_u *)cq->addr.virt;
6795 	cqe += cq->host_index;
6796 
6797 	offset = (off_t)((uint64_t)((unsigned long)
6798 	    cq->addr.virt) -
6799 	    (uint64_t)((unsigned long)
6800 	    hba->sli.sli4.slim2.virt));
6801 
6802 	EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset,
6803 	    4096, DDI_DMA_SYNC_FORKERNEL);
6804 
6805 	for (;;) {
6806 		cq_entry.word[3] = BE_SWAP32(cqe->word[3]);
6807 		if (!(cq_entry.word[3] & CQE_VALID)) {
6808 			break;
6809 		}
6810 
6811 		cq_entry.word[2] = BE_SWAP32(cqe->word[2]);
6812 		cq_entry.word[1] = BE_SWAP32(cqe->word[1]);
6813 		cq_entry.word[0] = BE_SWAP32(cqe->word[0]);
6814 
6815 #ifdef	DEBUG_CQE
6816 		emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 6, 0);
6817 #endif /* DEBUG_CQE */
6818 		num_entries++;
6819 		cqe->word[3] = 0;
6820 
6821 		cq->host_index++;
6822 		if (cq->host_index >= cq->max_index) {
6823 			cq->host_index = 0;
6824 			cqe = (CQE_u *)cq->addr.virt;
6825 		} else {
6826 			cqe++;
6827 		}
6828 		mutex_exit(&EMLXS_PORT_LOCK);
6829 
6830 		/* Now handle specific cq type */
6831 		if (cq->type == EMLXS_CQ_TYPE_GROUP1) {
6832 			if (cq_entry.cqAsyncEntry.async_evt) {
6833 				emlxs_sli4_process_async_event(hba,
6834 				    (CQE_ASYNC_t *)&cq_entry);
6835 			} else {
6836 				emlxs_sli4_process_mbox_event(hba,
6837 				    (CQE_MBOX_t *)&cq_entry);
6838 			}
6839 		} else { /* EMLXS_CQ_TYPE_GROUP2 */
6840 			switch (cq_entry.cqCmplEntry.Code) {
6841 			case CQE_TYPE_WQ_COMPLETION:
6842 				if (cq_entry.cqCmplEntry.RequestTag <
6843 				    hba->max_iotag) {
6844 					emlxs_sli4_process_wqe_cmpl(hba, cq,
6845 					    (CQE_CmplWQ_t *)&cq_entry);
6846 				} else {
6847 					emlxs_sli4_process_oor_wqe_cmpl(hba, cq,
6848 					    (CQE_CmplWQ_t *)&cq_entry);
6849 				}
6850 				break;
6851 			case CQE_TYPE_RELEASE_WQE:
6852 				emlxs_sli4_process_release_wqe(hba, cq,
6853 				    (CQE_RelWQ_t *)&cq_entry);
6854 				break;
6855 			case CQE_TYPE_UNSOL_RCV:
6856 			case CQE_TYPE_UNSOL_RCV_V1:
6857 				emlxs_sli4_process_unsol_rcv(hba, cq,
6858 				    (CQE_UnsolRcv_t *)&cq_entry);
6859 				break;
6860 			case CQE_TYPE_XRI_ABORTED:
6861 				emlxs_sli4_process_xri_aborted(hba, cq,
6862 				    (CQE_XRI_Abort_t *)&cq_entry);
6863 				break;
6864 			default:
6865 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6866 				    "Invalid CQ entry %d: %08x %08x %08x %08x",
6867 				    cq_entry.cqCmplEntry.Code, cq_entry.word[0],
6868 				    cq_entry.word[1], cq_entry.word[2],
6869 				    cq_entry.word[3]);
6870 				break;
6871 			}
6872 		}
6873 
6874 		mutex_enter(&EMLXS_PORT_LOCK);
6875 	}
6876 
6877 	/* Number of times this routine gets called for this CQ */
6878 	cq->isr_count++;
6879 
6880 	/* num_entries is the number of CQEs we process in this specific CQ */
6881 	cq->num_proc += num_entries;
6882 	if (cq->max_proc < num_entries)
6883 		cq->max_proc = num_entries;
6884 
6885 	cqdb = cq->qid;
6886 	cqdb |= CQ_DB_REARM;
6887 	if (num_entries != 0) {
6888 		cqdb |= ((num_entries << CQ_DB_POP_SHIFT) & CQ_DB_POP_MASK);
6889 	}
6890 
6891 #ifdef DEBUG_FASTPATH
6892 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6893 	    "CQE: CLEAR cqdb=%08x: pops=%d", cqdb, num_entries);
6894 #endif /* DEBUG_FASTPATH */
6895 
6896 	emlxs_sli4_write_cqdb(hba, cqdb);
6897 
6898 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
6899 
6900 } /* emlxs_sli4_process_cq() */
6901 
6902 
6903 /*ARGSUSED*/
6904 static void
6905 emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
6906 {
6907 	emlxs_port_t *port = &PPORT;
6908 	uint32_t eqdb;
6909 	uint32_t *ptr;
6910 	CHANNEL *cp;
6911 	EQE_u eqe;
6912 	uint32_t i;
6913 	uint16_t cqi;
6914 	int num_entries = 0;
6915 	off_t offset;
6916 
6917 	/* EMLXS_PORT_LOCK must be held when entering this routine */
6918 
6919 	hba->intr_busy_cnt ++;
6920 
6921 	ptr = eq->addr.virt;
6922 	ptr += eq->host_index;
6923 
6924 	offset = (off_t)((uint64_t)((unsigned long)
6925 	    eq->addr.virt) -
6926 	    (uint64_t)((unsigned long)
6927 	    hba->sli.sli4.slim2.virt));
6928 
6929 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
6930 	    4096, DDI_DMA_SYNC_FORKERNEL);
6931 
6932 	for (;;) {
6933 		eqe.word = *ptr;
6934 		eqe.word = BE_SWAP32(eqe.word);
6935 
6936 		if (!(eqe.word & EQE_VALID)) {
6937 			break;
6938 		}
6939 
6940 #ifdef DEBUG_FASTPATH
6941 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6942 		    "EQE00: %08x", eqe.word);
6943 #endif /* DEBUG_FASTPATH */
6944 
6945 		*ptr = 0;
6946 		num_entries++;
6947 		eq->host_index++;
6948 		if (eq->host_index >= eq->max_index) {
6949 			eq->host_index = 0;
6950 			ptr = eq->addr.virt;
6951 		} else {
6952 			ptr++;
6953 		}
6954 
6955 		cqi = emlxs_sli4_cqid_to_index(hba, eqe.entry.CQId);
6956 
6957 		/* Verify CQ index */
6958 		if (cqi == 0xffff) {
6959 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6960 			    "EQE: Invalid CQid: %d. Dropping...",
6961 			    eqe.entry.CQId);
6962 			continue;
6963 		}
6964 
6965 #ifdef DEBUG_FASTPATH
6966 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6967 		    "EQE: CQIndex:%x cqid:%x", cqi, eqe.entry.CQId);
6968 #endif /* DEBUG_FASTPATH */
6969 
6970 		emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[cqi]);
6971 	}
6972 
6973 	/* Number of times the ISR for this EQ gets called */
6974 	eq->isr_count++;
6975 
6976 	/* num_entries is the number of EQEs we process in this specific ISR */
6977 	eq->num_proc += num_entries;
6978 	if (eq->max_proc < num_entries) {
6979 		eq->max_proc = num_entries;
6980 	}
6981 
6982 	eqdb = eq->qid;
6983 	eqdb |= (EQ_DB_CLEAR | EQ_DB_EVENT | EQ_DB_REARM);
6984 
6985 #ifdef DEBUG_FASTPATH
6986 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6987 	    "EQE: CLEAR eqdb=%08x pops=%d", eqdb, num_entries);
6988 #endif /* DEBUG_FASTPATH */
6989 
6990 	if (num_entries != 0) {
6991 		eqdb |= ((num_entries << EQ_DB_POP_SHIFT) & EQ_DB_POP_MASK);
6992 		for (i = 0; i < hba->chan_count; i++) {
6993 			cp = &hba->chan[i];
6994 			if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) {
6995 				cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER;
6996 				emlxs_thread_trigger2(&cp->intr_thread,
6997 				    emlxs_proc_channel, cp);
6998 			}
6999 		}
7000 	}
7001 
7002 	emlxs_sli4_write_cqdb(hba, eqdb);
7003 
7004 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
7005 
7006 	hba->intr_busy_cnt --;
7007 
7008 } /* emlxs_sli4_process_eq() */
7009 
7010 
7011 #ifdef MSI_SUPPORT
7012 /*ARGSUSED*/
7013 static uint32_t
7014 emlxs_sli4_msi_intr(char *arg1, char *arg2)
7015 {
7016 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
7017 #ifdef DEBUG_FASTPATH
7018 	emlxs_port_t *port = &PPORT;
7019 #endif /* DEBUG_FASTPATH */
7020 	uint16_t msgid;
7021 	int rc;
7022 
7023 #ifdef DEBUG_FASTPATH
7024 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7025 	    "msiINTR arg1:%p arg2:%p", arg1, arg2);
7026 #endif /* DEBUG_FASTPATH */
7027 
7028 	/* Check for legacy interrupt handling */
7029 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
7030 		rc = emlxs_sli4_intx_intr(arg1);
7031 		return (rc);
7032 	}
7033 
7034 	/* Get MSI message id */
7035 	msgid = (uint16_t)((unsigned long)arg2);
7036 
7037 	/* Validate the message id */
7038 	if (msgid >= hba->intr_count) {
7039 		msgid = 0;
7040 	}
7041 	mutex_enter(&EMLXS_PORT_LOCK);
7042 
7043 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
7044 		mutex_exit(&EMLXS_PORT_LOCK);
7045 		return (DDI_INTR_UNCLAIMED);
7046 	}
7047 
7048 	/* The eq[] index == the MSI vector number */
7049 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]);
7050 
7051 	mutex_exit(&EMLXS_PORT_LOCK);
7052 	return (DDI_INTR_CLAIMED);
7053 
7054 } /* emlxs_sli4_msi_intr() */
7055 #endif /* MSI_SUPPORT */
7056 
7057 
7058 /*ARGSUSED*/
7059 static int
7060 emlxs_sli4_intx_intr(char *arg)
7061 {
7062 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
7063 #ifdef DEBUG_FASTPATH
7064 	emlxs_port_t *port = &PPORT;
7065 #endif /* DEBUG_FASTPATH */
7066 
7067 #ifdef DEBUG_FASTPATH
7068 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7069 	    "intxINTR arg:%p", arg);
7070 #endif /* DEBUG_FASTPATH */
7071 
7072 	mutex_enter(&EMLXS_PORT_LOCK);
7073 
7074 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
7075 		mutex_exit(&EMLXS_PORT_LOCK);
7076 		return (DDI_INTR_UNCLAIMED);
7077 	}
7078 
7079 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]);
7080 
7081 	mutex_exit(&EMLXS_PORT_LOCK);
7082 	return (DDI_INTR_CLAIMED);
7083 } /* emlxs_sli4_intx_intr() */
7084 
7085 
7086 static void
7087 emlxs_sli4_hba_kill(emlxs_hba_t *hba)
7088 {
7089 	emlxs_port_t *port = &PPORT;
7090 	uint32_t j;
7091 
7092 	mutex_enter(&EMLXS_PORT_LOCK);
7093 	if (hba->flag & FC_INTERLOCKED) {
7094 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
7095 
7096 		mutex_exit(&EMLXS_PORT_LOCK);
7097 
7098 		return;
7099 	}
7100 
7101 	j = 0;
7102 	while (j++ < 10000) {
7103 		if ((hba->mbox_queue_flag == 0) &&
7104 		    (hba->intr_busy_cnt == 0)) {
7105 			break;
7106 		}
7107 
7108 		mutex_exit(&EMLXS_PORT_LOCK);
7109 		BUSYWAIT_US(100);
7110 		mutex_enter(&EMLXS_PORT_LOCK);
7111 	}
7112 
7113 	if ((hba->mbox_queue_flag != 0) || (hba->intr_busy_cnt > 0)) {
7114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
7115 		    "Board kill failed. Adapter busy, %d, %d.",
7116 		    hba->mbox_queue_flag, hba->intr_busy_cnt);
7117 		mutex_exit(&EMLXS_PORT_LOCK);
7118 		return;
7119 	}
7120 
7121 	hba->flag |= FC_INTERLOCKED;
7122 
7123 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
7124 
7125 	mutex_exit(&EMLXS_PORT_LOCK);
7126 
7127 } /* emlxs_sli4_hba_kill() */
7128 
7129 
7130 extern void
7131 emlxs_sli4_hba_reset_all(emlxs_hba_t *hba, uint32_t flag)
7132 {
7133 	emlxs_port_t *port = &PPORT;
7134 	uint32_t value;
7135 
7136 	mutex_enter(&EMLXS_PORT_LOCK);
7137 
7138 	if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) != SLI_INTF_IF_TYPE_2) {
7139 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
7140 		    "Reset All failed. Invalid Operation.");
7141 		mutex_exit(&EMLXS_PORT_LOCK);
7142 		return;
7143 	}
7144 
7145 	/* Issue a Firmware Reset All Request */
7146 	if (flag) {
7147 		value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL | SLI_PHYDEV_DD;
7148 	} else {
7149 		value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL;
7150 	}
7151 
7152 	ddi_put32(hba->sli.sli4.bar0_acc_handle,
7153 	    hba->sli.sli4.PHYSDEV_reg_addr, value);
7154 
7155 	mutex_exit(&EMLXS_PORT_LOCK);
7156 
7157 } /* emlxs_sli4_hba_reset_all() */
7158 
7159 
7160 static void
7161 emlxs_sli4_enable_intr(emlxs_hba_t *hba)
7162 {
7163 	emlxs_config_t *cfg = &CFG;
7164 	int i;
7165 	int num_cq;
7166 	uint32_t data;
7167 
7168 	hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED;
7169 
7170 	num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) +
7171 	    EMLXS_CQ_OFFSET_WQ;
7172 
7173 	/* ARM EQ / CQs */
7174 	for (i = 0; i < num_cq; i++) {
7175 		data = hba->sli.sli4.cq[i].qid;
7176 		data |= CQ_DB_REARM;
7177 		emlxs_sli4_write_cqdb(hba, data);
7178 	}
7179 	for (i = 0; i < hba->intr_count; i++) {
7180 		data = hba->sli.sli4.eq[i].qid;
7181 		data |= (EQ_DB_REARM | EQ_DB_EVENT);
7182 		emlxs_sli4_write_cqdb(hba, data);
7183 	}
7184 } /* emlxs_sli4_enable_intr() */
7185 
7186 
7187 static void
7188 emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att)
7189 {
7190 	if (att) {
7191 		return;
7192 	}
7193 
7194 	hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
7195 
7196 	/* Short of reset, we cannot disable interrupts */
7197 } /* emlxs_sli4_disable_intr() */
7198 
7199 
7200 static void
7201 emlxs_sli4_resource_free(emlxs_hba_t *hba)
7202 {
7203 	emlxs_port_t	*port = &PPORT;
7204 	MBUF_INFO	*buf_info;
7205 	uint32_t	i;
7206 
7207 	buf_info = &hba->sli.sli4.slim2;
7208 	if (buf_info->virt == 0) {
7209 		/* Already free */
7210 		return;
7211 	}
7212 
7213 	emlxs_fcf_fini(hba);
7214 
7215 	buf_info = &hba->sli.sli4.HeaderTmplate;
7216 	if (buf_info->virt) {
7217 		bzero(buf_info, sizeof (MBUF_INFO));
7218 	}
7219 
7220 	if (hba->sli.sli4.XRIp) {
7221 		if ((hba->sli.sli4.XRIinuse_f !=
7222 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
7223 		    (hba->sli.sli4.XRIinuse_b !=
7224 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
7225 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
7226 			    "XRIs in use during free!: %p %p != %p\n",
7227 			    hba->sli.sli4.XRIinuse_f,
7228 			    hba->sli.sli4.XRIinuse_b,
7229 			    &hba->sli.sli4.XRIinuse_f);
7230 		}
7231 		kmem_free(hba->sli.sli4.XRIp,
7232 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
7233 		hba->sli.sli4.XRIp = NULL;
7234 
7235 		hba->sli.sli4.XRIfree_f =
7236 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7237 		hba->sli.sli4.XRIfree_b =
7238 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7239 		hba->sli.sli4.xrif_count = 0;
7240 	}
7241 
7242 	for (i = 0; i < hba->intr_count; i++) {
7243 		mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock);
7244 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
7245 		hba->sli.sli4.eq[i].qid = 0xffff;
7246 	}
7247 	for (i = 0; i < EMLXS_MAX_CQS; i++) {
7248 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
7249 		hba->sli.sli4.cq[i].qid = 0xffff;
7250 	}
7251 	for (i = 0; i < EMLXS_MAX_WQS; i++) {
7252 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
7253 		hba->sli.sli4.wq[i].qid = 0xffff;
7254 	}
7255 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
7256 		mutex_destroy(&hba->sli.sli4.rxq[i].lock);
7257 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
7258 	}
7259 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7260 		mutex_destroy(&hba->sli.sli4.rq[i].lock);
7261 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
7262 		hba->sli.sli4.rq[i].qid = 0xffff;
7263 	}
7264 
7265 	/* Free the MQ */
7266 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
7267 
7268 	buf_info = &hba->sli.sli4.slim2;
7269 	if (buf_info->virt) {
7270 		buf_info->flags = FC_MBUF_DMA;
7271 		emlxs_mem_free(hba, buf_info);
7272 		bzero(buf_info, sizeof (MBUF_INFO));
7273 	}
7274 
7275 } /* emlxs_sli4_resource_free() */
7276 
7277 
7278 static int
7279 emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
7280 {
7281 	emlxs_port_t	*port = &PPORT;
7282 	emlxs_config_t	*cfg = &CFG;
7283 	MBUF_INFO	*buf_info;
7284 	int		num_eq;
7285 	int		num_wq;
7286 	uint16_t	i;
7287 	uint32_t	j;
7288 	uint32_t	k;
7289 	uint16_t	cq_depth;
7290 	uint32_t	cq_size;
7291 	uint32_t	word;
7292 	XRIobj_t	*xrip;
7293 	RQE_t		*rqe;
7294 	MBUF_INFO	*rqb;
7295 	uint64_t	phys;
7296 	uint64_t	tmp_phys;
7297 	char		*virt;
7298 	char		*tmp_virt;
7299 	void		*data_handle;
7300 	void		*dma_handle;
7301 	int32_t		size;
7302 	off_t		offset;
7303 	uint32_t	count = 0;
7304 	uint32_t	hddr_size = 0;
7305 	uint32_t	align;
7306 	uint32_t	iotag;
7307 
7308 	buf_info = &hba->sli.sli4.slim2;
7309 	if (buf_info->virt) {
7310 		/* Already allocated */
7311 		return (0);
7312 	}
7313 
7314 	emlxs_fcf_init(hba);
7315 
7316 	switch (hba->sli.sli4.param.CQV) {
7317 	case 0:
7318 		cq_depth = CQ_DEPTH;
7319 		break;
7320 	case 2:
7321 	default:
7322 		cq_depth = CQ_DEPTH_V2;
7323 		break;
7324 	}
7325 	cq_size = (cq_depth * CQE_SIZE);
7326 
7327 	/* EQs - 1 per Interrupt vector */
7328 	num_eq = hba->intr_count;
7329 
7330 	/* CQs  - number of WQs + 1 for RQs + 1 for mbox/async events */
7331 	num_wq = cfg[CFG_NUM_WQ].current * num_eq;
7332 
7333 	/* Calculate total dmable memory we need */
7334 	/* WARNING: make sure each section is aligned on 4K boundary */
7335 
7336 	/* EQ */
7337 	count += num_eq * 4096;
7338 
7339 	/* CQ */
7340 	count += (num_wq + EMLXS_CQ_OFFSET_WQ) * cq_size;
7341 
7342 	/* WQ */
7343 	count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES);
7344 
7345 	/* MQ */
7346 	count +=  EMLXS_MAX_MQS * 4096;
7347 
7348 	/* RQ */
7349 	count +=  EMLXS_MAX_RQS * 4096;
7350 
7351 	/* RQB/E */
7352 	count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE);
7353 	count += (4096 - (count%4096)); /* Ensure 4K alignment */
7354 
7355 	/* SGL */
7356 	count += hba->sli.sli4.XRIExtSize * hba->sli.sli4.mem_sgl_size;
7357 	count += (4096 - (count%4096)); /* Ensure 4K alignment */
7358 
7359 	/* RPI Header Templates */
7360 	if (hba->sli.sli4.param.HDRR) {
7361 		/* Bytes per extent */
7362 		j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
7363 
7364 		/* Pages required per extent (page == 4096 bytes) */
7365 		k = (j/4096) + ((j%4096)? 1:0);
7366 
7367 		/* Total size */
7368 		hddr_size = (k * hba->sli.sli4.RPIExtCount * 4096);
7369 
7370 		count += hddr_size;
7371 	}
7372 
7373 	/* Allocate slim2 for SLI4 */
7374 	buf_info = &hba->sli.sli4.slim2;
7375 	buf_info->size = count;
7376 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7377 	buf_info->align = ddi_ptob(hba->dip, 1L);
7378 
7379 	(void) emlxs_mem_alloc(hba, buf_info);
7380 
7381 	if (buf_info->virt == NULL) {
7382 		EMLXS_MSGF(EMLXS_CONTEXT,
7383 		    &emlxs_init_failed_msg,
7384 		    "Unable to allocate internal memory for SLI4: %d",
7385 		    count);
7386 		goto failed;
7387 	}
7388 	bzero(buf_info->virt, buf_info->size);
7389 	EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
7390 	    buf_info->size, DDI_DMA_SYNC_FORDEV);
7391 
7392 	/* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
7393 	data_handle = buf_info->data_handle;
7394 	dma_handle = buf_info->dma_handle;
7395 	phys = buf_info->phys;
7396 	virt = (char *)buf_info->virt;
7397 
7398 	/* Allocate space for queues */
7399 
7400 	/* EQ */
7401 	size = 4096;
7402 	for (i = 0; i < num_eq; i++) {
7403 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
7404 
7405 		buf_info = &hba->sli.sli4.eq[i].addr;
7406 		buf_info->size = size;
7407 		buf_info->flags =
7408 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7409 		buf_info->align = ddi_ptob(hba->dip, 1L);
7410 		buf_info->phys = phys;
7411 		buf_info->virt = (void *)virt;
7412 		buf_info->data_handle = data_handle;
7413 		buf_info->dma_handle = dma_handle;
7414 
7415 		phys += size;
7416 		virt += size;
7417 
7418 		hba->sli.sli4.eq[i].max_index = EQ_DEPTH;
7419 		hba->sli.sli4.eq[i].qid = 0xffff;
7420 
7421 		mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, NULL,
7422 		    MUTEX_DRIVER, NULL);
7423 	}
7424 
7425 
7426 	/* CQ */
7427 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
7428 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
7429 
7430 		buf_info = &hba->sli.sli4.cq[i].addr;
7431 		buf_info->size = cq_size;
7432 		buf_info->flags =
7433 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7434 		buf_info->align = ddi_ptob(hba->dip, 1L);
7435 		buf_info->phys = phys;
7436 		buf_info->virt = (void *)virt;
7437 		buf_info->data_handle = data_handle;
7438 		buf_info->dma_handle = dma_handle;
7439 
7440 		phys += cq_size;
7441 		virt += cq_size;
7442 
7443 		hba->sli.sli4.cq[i].max_index = cq_depth;
7444 		hba->sli.sli4.cq[i].qid = 0xffff;
7445 	}
7446 
7447 
7448 	/* WQ */
7449 	size = 4096 * EMLXS_NUM_WQ_PAGES;
7450 	for (i = 0; i < num_wq; i++) {
7451 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
7452 
7453 		buf_info = &hba->sli.sli4.wq[i].addr;
7454 		buf_info->size = size;
7455 		buf_info->flags =
7456 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7457 		buf_info->align = ddi_ptob(hba->dip, 1L);
7458 		buf_info->phys = phys;
7459 		buf_info->virt = (void *)virt;
7460 		buf_info->data_handle = data_handle;
7461 		buf_info->dma_handle = dma_handle;
7462 
7463 		phys += size;
7464 		virt += size;
7465 
7466 		hba->sli.sli4.wq[i].max_index = WQ_DEPTH;
7467 		hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH;
7468 		hba->sli.sli4.wq[i].qid = 0xFFFF;
7469 	}
7470 
7471 
7472 	/* MQ */
7473 	size = 4096;
7474 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
7475 
7476 	buf_info = &hba->sli.sli4.mq.addr;
7477 	buf_info->size = size;
7478 	buf_info->flags =
7479 	    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7480 	buf_info->align = ddi_ptob(hba->dip, 1L);
7481 	buf_info->phys = phys;
7482 	buf_info->virt = (void *)virt;
7483 	buf_info->data_handle = data_handle;
7484 	buf_info->dma_handle = dma_handle;
7485 
7486 	phys += size;
7487 	virt += size;
7488 
7489 	hba->sli.sli4.mq.max_index = MQ_DEPTH;
7490 
7491 
7492 	/* RXQ */
7493 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
7494 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
7495 
7496 		mutex_init(&hba->sli.sli4.rxq[i].lock, NULL, MUTEX_DRIVER,
7497 		    NULL);
7498 	}
7499 
7500 
7501 	/* RQ */
7502 	size = 4096;
7503 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7504 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
7505 
7506 		buf_info = &hba->sli.sli4.rq[i].addr;
7507 		buf_info->size = size;
7508 		buf_info->flags =
7509 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7510 		buf_info->align = ddi_ptob(hba->dip, 1L);
7511 		buf_info->phys = phys;
7512 		buf_info->virt = (void *)virt;
7513 		buf_info->data_handle = data_handle;
7514 		buf_info->dma_handle = dma_handle;
7515 
7516 		phys += size;
7517 		virt += size;
7518 
7519 		hba->sli.sli4.rq[i].max_index = RQ_DEPTH;
7520 		hba->sli.sli4.rq[i].qid = 0xFFFF;
7521 
7522 		mutex_init(&hba->sli.sli4.rq[i].lock, NULL, MUTEX_DRIVER, NULL);
7523 	}
7524 
7525 
7526 	/* RQB/E */
7527 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7528 		size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE;
7529 		tmp_phys = phys;
7530 		tmp_virt = virt;
7531 
7532 		/* Initialize the RQEs */
7533 		rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt;
7534 		for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) {
7535 			phys = tmp_phys;
7536 			virt = tmp_virt;
7537 			for (k = 0; k < RQB_COUNT; k++) {
7538 				word = PADDR_HI(phys);
7539 				rqe->AddrHi = BE_SWAP32(word);
7540 
7541 				word = PADDR_LO(phys);
7542 				rqe->AddrLo = BE_SWAP32(word);
7543 
7544 				rqb = &hba->sli.sli4.rq[i].
7545 				    rqb[k + (j * RQB_COUNT)];
7546 				rqb->size = size;
7547 				rqb->flags = FC_MBUF_DMA |
7548 				    FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7549 				rqb->align = ddi_ptob(hba->dip, 1L);
7550 				rqb->phys = phys;
7551 				rqb->virt = (void *)virt;
7552 				rqb->data_handle = data_handle;
7553 				rqb->dma_handle = dma_handle;
7554 
7555 				phys += size;
7556 				virt += size;
7557 #ifdef DEBUG_RQE
7558 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7559 				    "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p iotag=%d",
7560 				    i, j, k, mp, mp->tag);
7561 #endif /* DEBUG_RQE */
7562 
7563 				rqe++;
7564 			}
7565 		}
7566 
7567 		offset = (off_t)((uint64_t)((unsigned long)
7568 		    hba->sli.sli4.rq[i].addr.virt) -
7569 		    (uint64_t)((unsigned long)
7570 		    hba->sli.sli4.slim2.virt));
7571 
7572 		/* Sync the RQ buffer list */
7573 		EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset,
7574 		    hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV);
7575 	}
7576 
7577 	/* 4K Alignment */
7578 	align = (4096 - (phys%4096));
7579 	phys += align;
7580 	virt += align;
7581 
7582 	/* SGL */
7583 	/* Initialize double linked lists */
7584 	hba->sli.sli4.XRIinuse_f =
7585 	    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7586 	hba->sli.sli4.XRIinuse_b =
7587 	    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7588 	hba->sli.sli4.xria_count = 0;
7589 
7590 	hba->sli.sli4.XRIfree_f =
7591 	    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7592 	hba->sli.sli4.XRIfree_b =
7593 	    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7594 	hba->sli.sli4.xria_count = 0;
7595 
7596 	hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
7597 	    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
7598 
7599 	xrip = hba->sli.sli4.XRIp;
7600 	size = hba->sli.sli4.mem_sgl_size;
7601 	iotag = 1;
7602 	for (i = 0; i < hba->sli.sli4.XRICount; i++) {
7603 		xrip->XRI = emlxs_sli4_index_to_xri(hba, i);
7604 
7605 		/* We don't use XRI==0, since it also represents an */
7606 		/* uninitialized exchange */
7607 		if (xrip->XRI == 0) {
7608 			xrip++;
7609 			continue;
7610 		}
7611 
7612 		xrip->iotag = iotag++;
7613 		xrip->sge_count =
7614 		    (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64));
7615 
7616 		/* Add xrip to end of free list */
7617 		xrip->_b = hba->sli.sli4.XRIfree_b;
7618 		hba->sli.sli4.XRIfree_b->_f = xrip;
7619 		xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7620 		hba->sli.sli4.XRIfree_b = xrip;
7621 		hba->sli.sli4.xrif_count++;
7622 
7623 		/* Allocate SGL for this xrip */
7624 		buf_info = &xrip->SGList;
7625 		buf_info->size = size;
7626 		buf_info->flags =
7627 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7628 		buf_info->align = size;
7629 		buf_info->phys = phys;
7630 		buf_info->virt = (void *)virt;
7631 		buf_info->data_handle = data_handle;
7632 		buf_info->dma_handle = dma_handle;
7633 
7634 		phys += size;
7635 		virt += size;
7636 
7637 		xrip++;
7638 	}
7639 
7640 	/* 4K Alignment */
7641 	align = (4096 - (phys%4096));
7642 	phys += align;
7643 	virt += align;
7644 
7645 	/* RPI Header Templates */
7646 	if (hba->sli.sli4.param.HDRR) {
7647 		buf_info = &hba->sli.sli4.HeaderTmplate;
7648 		bzero(buf_info, sizeof (MBUF_INFO));
7649 		buf_info->size = hddr_size;
7650 		buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
7651 		buf_info->align = ddi_ptob(hba->dip, 1L);
7652 		buf_info->phys = phys;
7653 		buf_info->virt = (void *)virt;
7654 		buf_info->data_handle = data_handle;
7655 		buf_info->dma_handle = dma_handle;
7656 	}
7657 
7658 #ifdef FMA_SUPPORT
7659 	if (hba->sli.sli4.slim2.dma_handle) {
7660 		if (emlxs_fm_check_dma_handle(hba,
7661 		    hba->sli.sli4.slim2.dma_handle)
7662 		    != DDI_FM_OK) {
7663 			EMLXS_MSGF(EMLXS_CONTEXT,
7664 			    &emlxs_invalid_dma_handle_msg,
7665 			    "sli4_resource_alloc: hdl=%p",
7666 			    hba->sli.sli4.slim2.dma_handle);
7667 			goto failed;
7668 		}
7669 	}
7670 #endif /* FMA_SUPPORT */
7671 
7672 	return (0);
7673 
7674 failed:
7675 
7676 	(void) emlxs_sli4_resource_free(hba);
7677 	return (ENOMEM);
7678 
7679 } /* emlxs_sli4_resource_alloc */
7680 
7681 
7682 extern void
7683 emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba)
7684 {
7685 	uint32_t i;
7686 	uint32_t num_wq;
7687 	emlxs_config_t	*cfg = &CFG;
7688 	clock_t		time;
7689 
7690 	/* EQ */
7691 	for (i = 0; i < hba->intr_count; i++) {
7692 		hba->sli.sli4.eq[i].num_proc = 0;
7693 		hba->sli.sli4.eq[i].max_proc = 0;
7694 		hba->sli.sli4.eq[i].isr_count = 0;
7695 	}
7696 	num_wq = cfg[CFG_NUM_WQ].current * hba->intr_count;
7697 	/* CQ */
7698 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
7699 		hba->sli.sli4.cq[i].num_proc = 0;
7700 		hba->sli.sli4.cq[i].max_proc = 0;
7701 		hba->sli.sli4.cq[i].isr_count = 0;
7702 	}
7703 	/* WQ */
7704 	for (i = 0; i < num_wq; i++) {
7705 		hba->sli.sli4.wq[i].num_proc = 0;
7706 		hba->sli.sli4.wq[i].num_busy = 0;
7707 	}
7708 	/* RQ */
7709 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7710 		hba->sli.sli4.rq[i].num_proc = 0;
7711 	}
7712 	(void) drv_getparm(LBOLT, &time);
7713 	hba->sli.sli4.que_stat_timer = (uint32_t)time;
7714 
7715 } /* emlxs_sli4_zero_queue_stat */
7716 
7717 
7718 extern XRIobj_t *
7719 emlxs_sli4_reserve_xri(emlxs_port_t *port,  RPIobj_t *rpip, uint32_t type,
7720     uint16_t rx_id)
7721 {
7722 	emlxs_hba_t *hba = HBA;
7723 	XRIobj_t	*xrip;
7724 	uint16_t	iotag;
7725 
7726 	mutex_enter(&EMLXS_FCTAB_LOCK);
7727 
7728 	xrip = hba->sli.sli4.XRIfree_f;
7729 
7730 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
7731 		mutex_exit(&EMLXS_FCTAB_LOCK);
7732 
7733 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
7734 		    "Unable to reserve XRI. type=%d",
7735 		    type);
7736 
7737 		return (NULL);
7738 	}
7739 
7740 	iotag = xrip->iotag;
7741 
7742 	if ((!iotag) ||
7743 	    ((hba->fc_table[iotag] != NULL) &&
7744 	    (hba->fc_table[iotag] != STALE_PACKET))) {
7745 		/*
7746 		 * No more command slots available, retry later
7747 		 */
7748 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7749 		    "Adapter Busy. Unable to reserve iotag. type=%d",
7750 		    type);
7751 
7752 		mutex_exit(&EMLXS_FCTAB_LOCK);
7753 		return (NULL);
7754 	}
7755 
7756 	xrip->state = XRI_STATE_ALLOCATED;
7757 	xrip->type = type;
7758 	xrip->flag = EMLXS_XRI_RESERVED;
7759 	xrip->sbp = NULL;
7760 
7761 	xrip->rpip = rpip;
7762 	xrip->rx_id = rx_id;
7763 	rpip->xri_count++;
7764 
7765 	/* Take it off free list */
7766 	(xrip->_b)->_f = xrip->_f;
7767 	(xrip->_f)->_b = xrip->_b;
7768 	xrip->_f = NULL;
7769 	xrip->_b = NULL;
7770 	hba->sli.sli4.xrif_count--;
7771 
7772 	/* Add it to end of inuse list */
7773 	xrip->_b = hba->sli.sli4.XRIinuse_b;
7774 	hba->sli.sli4.XRIinuse_b->_f = xrip;
7775 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7776 	hba->sli.sli4.XRIinuse_b = xrip;
7777 	hba->sli.sli4.xria_count++;
7778 
7779 	mutex_exit(&EMLXS_FCTAB_LOCK);
7780 	return (xrip);
7781 
7782 } /* emlxs_sli4_reserve_xri() */
7783 
7784 
7785 extern uint32_t
7786 emlxs_sli4_unreserve_xri(emlxs_port_t *port, uint16_t xri, uint32_t lock)
7787 {
7788 	emlxs_hba_t *hba = HBA;
7789 	XRIobj_t *xrip;
7790 
7791 	if (lock) {
7792 		mutex_enter(&EMLXS_FCTAB_LOCK);
7793 	}
7794 
7795 	xrip = emlxs_sli4_find_xri(port, xri);
7796 
7797 	if (!xrip || xrip->state == XRI_STATE_FREE) {
7798 		if (lock) {
7799 			mutex_exit(&EMLXS_FCTAB_LOCK);
7800 		}
7801 
7802 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7803 		    "sli4_unreserve_xri:%d already freed.", xri);
7804 		return (0);
7805 	}
7806 
7807 	/* Flush this unsolicited ct command */
7808 	if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) {
7809 		(void) emlxs_flush_ct_event(port, xrip->rx_id);
7810 	}
7811 
7812 	if (!(xrip->flag & EMLXS_XRI_RESERVED)) {
7813 		if (lock) {
7814 			mutex_exit(&EMLXS_FCTAB_LOCK);
7815 		}
7816 
7817 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7818 		    "sli4_unreserve_xri:%d in use. type=%d",
7819 		    xrip->XRI, xrip->type);
7820 		return (1);
7821 	}
7822 
7823 	if (xrip->iotag &&
7824 	    (hba->fc_table[xrip->iotag] != NULL) &&
7825 	    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
7826 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
7827 		    "sli4_unreserve_xri:%d  sbp dropped:%p type=%d",
7828 		    xrip->XRI, hba->fc_table[xrip->iotag], xrip->type);
7829 
7830 		hba->fc_table[xrip->iotag] = NULL;
7831 		hba->io_count--;
7832 	}
7833 
7834 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7835 	    "sli4_unreserve_xri:%d unreserved. type=%d",
7836 	    xrip->XRI, xrip->type);
7837 
7838 	xrip->state = XRI_STATE_FREE;
7839 	xrip->type = 0;
7840 
7841 	if (xrip->rpip) {
7842 		xrip->rpip->xri_count--;
7843 		xrip->rpip = NULL;
7844 	}
7845 
7846 	if (xrip->reserved_rpip) {
7847 		xrip->reserved_rpip->xri_count--;
7848 		xrip->reserved_rpip = NULL;
7849 	}
7850 
7851 	/* Take it off inuse list */
7852 	(xrip->_b)->_f = xrip->_f;
7853 	(xrip->_f)->_b = xrip->_b;
7854 	xrip->_f = NULL;
7855 	xrip->_b = NULL;
7856 	hba->sli.sli4.xria_count--;
7857 
7858 	/* Add it to end of free list */
7859 	xrip->_b = hba->sli.sli4.XRIfree_b;
7860 	hba->sli.sli4.XRIfree_b->_f = xrip;
7861 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7862 	hba->sli.sli4.XRIfree_b = xrip;
7863 	hba->sli.sli4.xrif_count++;
7864 
7865 	if (lock) {
7866 		mutex_exit(&EMLXS_FCTAB_LOCK);
7867 	}
7868 
7869 	return (0);
7870 
7871 } /* emlxs_sli4_unreserve_xri() */
7872 
7873 
7874 XRIobj_t *
7875 emlxs_sli4_register_xri(emlxs_port_t *port, emlxs_buf_t *sbp, uint16_t xri,
7876     uint32_t did)
7877 {
7878 	emlxs_hba_t *hba = HBA;
7879 	uint16_t	iotag;
7880 	XRIobj_t	*xrip;
7881 	emlxs_node_t	*node;
7882 	RPIobj_t	*rpip;
7883 
7884 	mutex_enter(&EMLXS_FCTAB_LOCK);
7885 
7886 	xrip = sbp->xrip;
7887 	if (!xrip) {
7888 		xrip = emlxs_sli4_find_xri(port, xri);
7889 
7890 		if (!xrip) {
7891 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7892 			    "sli4_register_xri:%d XRI not found.", xri);
7893 
7894 			mutex_exit(&EMLXS_FCTAB_LOCK);
7895 			return (NULL);
7896 		}
7897 	}
7898 
7899 	if ((xrip->state == XRI_STATE_FREE) ||
7900 	    !(xrip->flag & EMLXS_XRI_RESERVED)) {
7901 
7902 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7903 		    "sli4_register_xri:%d Invalid XRI. xrip=%p "
7904 		    "state=%x flag=%x",
7905 		    xrip->XRI, xrip, xrip->state, xrip->flag);
7906 
7907 		mutex_exit(&EMLXS_FCTAB_LOCK);
7908 		return (NULL);
7909 	}
7910 
7911 	iotag = xrip->iotag;
7912 
7913 	if ((!iotag) ||
7914 	    ((hba->fc_table[iotag] != NULL) &&
7915 	    (hba->fc_table[iotag] != STALE_PACKET))) {
7916 
7917 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7918 		    "sli4_register_xri:%d Invalid fc_table entry. "
7919 		    "iotag=%d entry=%p",
7920 		    xrip->XRI, iotag, hba->fc_table[iotag]);
7921 
7922 		mutex_exit(&EMLXS_FCTAB_LOCK);
7923 		return (NULL);
7924 	}
7925 
7926 	hba->fc_table[iotag] = sbp;
7927 	hba->io_count++;
7928 
7929 	sbp->iotag = iotag;
7930 	sbp->xrip = xrip;
7931 
7932 	xrip->flag &= ~EMLXS_XRI_RESERVED;
7933 	xrip->sbp = sbp;
7934 
7935 	/* If we did not have a registered RPI when we reserved */
7936 	/* this exchange, check again now. */
7937 	if (xrip->rpip && (xrip->rpip->RPI == FABRIC_RPI)) {
7938 		node = emlxs_node_find_did(port, did, 1);
7939 		rpip = EMLXS_NODE_TO_RPI(port, node);
7940 
7941 		if (rpip && (rpip->RPI != FABRIC_RPI)) {
7942 			/* Move the XRI to the new RPI */
7943 			xrip->rpip->xri_count--;
7944 			xrip->rpip = rpip;
7945 			rpip->xri_count++;
7946 		}
7947 	}
7948 
7949 	mutex_exit(&EMLXS_FCTAB_LOCK);
7950 
7951 	return (xrip);
7952 
7953 } /* emlxs_sli4_register_xri() */
7954 
7955 
7956 /* Performs both reserve and register functions for XRI */
7957 static XRIobj_t *
7958 emlxs_sli4_alloc_xri(emlxs_port_t *port, emlxs_buf_t *sbp, RPIobj_t *rpip,
7959     uint32_t type)
7960 {
7961 	emlxs_hba_t *hba = HBA;
7962 	XRIobj_t	*xrip;
7963 	uint16_t	iotag;
7964 
7965 	mutex_enter(&EMLXS_FCTAB_LOCK);
7966 
7967 	xrip = hba->sli.sli4.XRIfree_f;
7968 
7969 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
7970 		mutex_exit(&EMLXS_FCTAB_LOCK);
7971 
7972 		return (NULL);
7973 	}
7974 
7975 	/* Get the iotag by registering the packet */
7976 	iotag = xrip->iotag;
7977 
7978 	if ((!iotag) ||
7979 	    ((hba->fc_table[iotag] != NULL) &&
7980 	    (hba->fc_table[iotag] != STALE_PACKET))) {
7981 		/*
7982 		 * No more command slots available, retry later
7983 		 */
7984 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7985 		    "Adapter Busy. Unable to alloc iotag:(0x%x)(%p) type=%d",
7986 		    iotag, hba->fc_table[iotag], type);
7987 
7988 		mutex_exit(&EMLXS_FCTAB_LOCK);
7989 		return (NULL);
7990 	}
7991 
7992 	hba->fc_table[iotag] = sbp;
7993 	hba->io_count++;
7994 
7995 	sbp->iotag = iotag;
7996 	sbp->xrip = xrip;
7997 
7998 	xrip->state = XRI_STATE_ALLOCATED;
7999 	xrip->type = type;
8000 	xrip->flag = 0;
8001 	xrip->sbp = sbp;
8002 
8003 	xrip->rpip = rpip;
8004 	rpip->xri_count++;
8005 
8006 	/* Take it off free list */
8007 	(xrip->_b)->_f = xrip->_f;
8008 	(xrip->_f)->_b = xrip->_b;
8009 	xrip->_f = NULL;
8010 	xrip->_b = NULL;
8011 	hba->sli.sli4.xrif_count--;
8012 
8013 	/* Add it to end of inuse list */
8014 	xrip->_b = hba->sli.sli4.XRIinuse_b;
8015 	hba->sli.sli4.XRIinuse_b->_f = xrip;
8016 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
8017 	hba->sli.sli4.XRIinuse_b = xrip;
8018 	hba->sli.sli4.xria_count++;
8019 
8020 	mutex_exit(&EMLXS_FCTAB_LOCK);
8021 
8022 	return (xrip);
8023 
8024 } /* emlxs_sli4_alloc_xri() */
8025 
8026 
8027 /* EMLXS_FCTAB_LOCK must be held to enter */
8028 extern XRIobj_t *
8029 emlxs_sli4_find_xri(emlxs_port_t *port, uint16_t xri)
8030 {
8031 	emlxs_hba_t *hba = HBA;
8032 	XRIobj_t	*xrip;
8033 
8034 	xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
8035 	while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
8036 		if ((xrip->state >= XRI_STATE_ALLOCATED) &&
8037 		    (xrip->XRI == xri)) {
8038 			return (xrip);
8039 		}
8040 		xrip = xrip->_f;
8041 	}
8042 
8043 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8044 	    "Unable to find XRI x%x", xri);
8045 
8046 	return (NULL);
8047 
8048 } /* emlxs_sli4_find_xri() */
8049 
8050 
8051 
8052 
8053 extern void
8054 emlxs_sli4_free_xri(emlxs_port_t *port, emlxs_buf_t *sbp, XRIobj_t *xrip,
8055     uint8_t lock)
8056 {
8057 	emlxs_hba_t *hba = HBA;
8058 
8059 	if (lock) {
8060 		mutex_enter(&EMLXS_FCTAB_LOCK);
8061 	}
8062 
8063 	if (xrip) {
8064 		if (xrip->state == XRI_STATE_FREE) {
8065 			if (lock) {
8066 				mutex_exit(&EMLXS_FCTAB_LOCK);
8067 			}
8068 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8069 			    "Free XRI:%x, Already freed. type=%d",
8070 			    xrip->XRI, xrip->type);
8071 			return;
8072 		}
8073 
8074 		if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) {
8075 			(void) emlxs_flush_ct_event(port, xrip->rx_id);
8076 		}
8077 
8078 		if (xrip->iotag &&
8079 		    (hba->fc_table[xrip->iotag] != NULL) &&
8080 		    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
8081 			hba->fc_table[xrip->iotag] = NULL;
8082 			hba->io_count--;
8083 		}
8084 
8085 		xrip->state = XRI_STATE_FREE;
8086 		xrip->type  = 0;
8087 		xrip->flag  = 0;
8088 
8089 		if (xrip->rpip) {
8090 			xrip->rpip->xri_count--;
8091 			xrip->rpip = NULL;
8092 		}
8093 
8094 		if (xrip->reserved_rpip) {
8095 			xrip->reserved_rpip->xri_count--;
8096 			xrip->reserved_rpip = NULL;
8097 		}
8098 
8099 		/* Take it off inuse list */
8100 		(xrip->_b)->_f = xrip->_f;
8101 		(xrip->_f)->_b = xrip->_b;
8102 		xrip->_f = NULL;
8103 		xrip->_b = NULL;
8104 		hba->sli.sli4.xria_count--;
8105 
8106 		/* Add it to end of free list */
8107 		xrip->_b = hba->sli.sli4.XRIfree_b;
8108 		hba->sli.sli4.XRIfree_b->_f = xrip;
8109 		xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
8110 		hba->sli.sli4.XRIfree_b = xrip;
8111 		hba->sli.sli4.xrif_count++;
8112 	}
8113 
8114 	if (sbp) {
8115 		if (!(sbp->pkt_flags & PACKET_VALID) ||
8116 		    (sbp->pkt_flags &
8117 		    (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) {
8118 			if (lock) {
8119 				mutex_exit(&EMLXS_FCTAB_LOCK);
8120 			}
8121 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8122 			    "Free XRI: sbp invalid. sbp=%p flags=%x xri=%d",
8123 			    sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0));
8124 			return;
8125 		}
8126 
8127 		if (xrip && (xrip->iotag != sbp->iotag)) {
8128 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
8129 			    "sbp/iotag mismatch %p iotag:%d %d", sbp,
8130 			    sbp->iotag, xrip->iotag);
8131 		}
8132 
8133 		if (sbp->iotag) {
8134 			if (sbp == hba->fc_table[sbp->iotag]) {
8135 				hba->fc_table[sbp->iotag] = NULL;
8136 				hba->io_count--;
8137 
8138 				if (sbp->xrip) {
8139 					/* Exchange is still reserved */
8140 					sbp->xrip->flag |= EMLXS_XRI_RESERVED;
8141 				}
8142 			}
8143 			sbp->iotag = 0;
8144 		}
8145 
8146 		if (xrip) {
8147 			sbp->xrip = 0;
8148 		}
8149 
8150 		if (lock) {
8151 			mutex_exit(&EMLXS_FCTAB_LOCK);
8152 		}
8153 
8154 		/* Clean up the sbp */
8155 		mutex_enter(&sbp->mtx);
8156 
8157 		if (sbp->pkt_flags & PACKET_IN_TXQ) {
8158 			sbp->pkt_flags &= ~PACKET_IN_TXQ;
8159 			hba->channel_tx_count--;
8160 		}
8161 
8162 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
8163 			sbp->pkt_flags &= ~PACKET_IN_CHIPQ;
8164 		}
8165 
8166 		mutex_exit(&sbp->mtx);
8167 	} else {
8168 		if (lock) {
8169 			mutex_exit(&EMLXS_FCTAB_LOCK);
8170 		}
8171 	}
8172 
8173 } /* emlxs_sli4_free_xri() */
8174 
8175 
8176 static int
8177 emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq)
8178 {
8179 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
8180 	emlxs_port_t	*port = &PPORT;
8181 	XRIobj_t	*xrip;
8182 	MATCHMAP	*mp;
8183 	mbox_req_hdr_t 	*hdr_req;
8184 	uint32_t	i;
8185 	uint32_t	cnt;
8186 	uint32_t	xri_cnt;
8187 	uint32_t	j;
8188 	uint32_t	size;
8189 	IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl;
8190 
8191 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
8192 	mbq->bp = NULL;
8193 	mbq->mbox_cmpl = NULL;
8194 
8195 	if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) {
8196 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8197 		    "Unable to POST_SGL. Mailbox cmd=%x  ",
8198 		    mb->mbxCommand);
8199 		return (EIO);
8200 	}
8201 	mbq->nonembed = (void *)mp;
8202 
8203 	/*
8204 	 * Signifies a non embedded command
8205 	 */
8206 	mb->un.varSLIConfig.be.embedded = 0;
8207 	mb->mbxCommand = MBX_SLI_CONFIG;
8208 	mb->mbxOwner = OWN_HOST;
8209 
8210 	hdr_req = (mbox_req_hdr_t *)mp->virt;
8211 	post_sgl =
8212 	    (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1);
8213 
8214 	xrip = hba->sli.sli4.XRIp;
8215 
8216 	/* For each extent */
8217 	for (j = 0; j < hba->sli.sli4.XRIExtCount; j++) {
8218 		cnt = hba->sli.sli4.XRIExtSize;
8219 		while (cnt) {
8220 			if (xrip->XRI == 0) {
8221 				cnt--;
8222 				xrip++;
8223 				continue;
8224 			}
8225 
8226 			bzero((void *) hdr_req, mp->size);
8227 			size = mp->size - IOCTL_HEADER_SZ;
8228 
8229 			mb->un.varSLIConfig.be.payload_length =
8230 			    mp->size;
8231 			mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
8232 			    IOCTL_SUBSYSTEM_FCOE;
8233 			mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
8234 			    FCOE_OPCODE_CFG_POST_SGL_PAGES;
8235 			mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
8236 			mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size;
8237 
8238 			hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
8239 			hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES;
8240 			hdr_req->timeout = 0;
8241 			hdr_req->req_length = size;
8242 
8243 			post_sgl->params.request.xri_count = 0;
8244 			post_sgl->params.request.xri_start = xrip->XRI;
8245 
8246 			xri_cnt = (size -
8247 			    sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
8248 			    sizeof (FCOE_SGL_PAGES);
8249 
8250 			for (i = 0; (i < xri_cnt) && cnt; i++) {
8251 				post_sgl->params.request.xri_count++;
8252 				post_sgl->params.request.pages[i].\
8253 				    sgl_page0.addrLow =
8254 				    PADDR_LO(xrip->SGList.phys);
8255 				post_sgl->params.request.pages[i].\
8256 				    sgl_page0.addrHigh =
8257 				    PADDR_HI(xrip->SGList.phys);
8258 
8259 				cnt--;
8260 				xrip++;
8261 			}
8262 
8263 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8264 			    MBX_SUCCESS) {
8265 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8266 				    "Unable to POST_SGL. Mailbox cmd=%x "
8267 				    "status=%x XRI cnt:%d start:%d",
8268 				    mb->mbxCommand, mb->mbxStatus,
8269 				    post_sgl->params.request.xri_count,
8270 				    post_sgl->params.request.xri_start);
8271 				emlxs_mem_buf_free(hba, mp);
8272 				mbq->nonembed = NULL;
8273 				return (EIO);
8274 			}
8275 		}
8276 	}
8277 
8278 	emlxs_mem_buf_free(hba, mp);
8279 	mbq->nonembed = NULL;
8280 	return (0);
8281 
8282 } /* emlxs_sli4_post_sgl_pages() */
8283 
8284 
8285 static int
8286 emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq)
8287 {
8288 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
8289 	emlxs_port_t	*port = &PPORT;
8290 	uint32_t 	j;
8291 	uint32_t 	k;
8292 	uint64_t	addr;
8293 	IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr;
8294 	uint16_t	num_pages;
8295 
8296 	if (!(hba->sli.sli4.param.HDRR)) {
8297 		return (0);
8298 	}
8299 
8300 	/* Bytes per extent */
8301 	j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
8302 
8303 	/* Pages required per extent (page == 4096 bytes) */
8304 	num_pages = (j/4096) + ((j%4096)? 1:0);
8305 
8306 	addr = hba->sli.sli4.HeaderTmplate.phys;
8307 
8308 	/* For each extent */
8309 	for (j = 0; j < hba->sli.sli4.RPIExtCount; j++) {
8310 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
8311 		mbq->bp = NULL;
8312 		mbq->mbox_cmpl = NULL;
8313 
8314 		/*
8315 		 * Signifies an embedded command
8316 		 */
8317 		mb->un.varSLIConfig.be.embedded = 1;
8318 
8319 		mb->mbxCommand = MBX_SLI_CONFIG;
8320 		mb->mbxOwner = OWN_HOST;
8321 		mb->un.varSLIConfig.be.payload_length =
8322 		    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
8323 		mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
8324 		    IOCTL_SUBSYSTEM_FCOE;
8325 		mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
8326 		    FCOE_OPCODE_POST_HDR_TEMPLATES;
8327 		mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
8328 		mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
8329 		    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
8330 
8331 		post_hdr =
8332 		    (IOCTL_FCOE_POST_HDR_TEMPLATES *)
8333 		    &mb->un.varSLIConfig.payload;
8334 		post_hdr->params.request.num_pages = num_pages;
8335 		post_hdr->params.request.rpi_offset = hba->sli.sli4.RPIBase[j];
8336 
8337 		for (k = 0; k < num_pages; k++) {
8338 			post_hdr->params.request.pages[k].addrLow =
8339 			    PADDR_LO(addr);
8340 			post_hdr->params.request.pages[k].addrHigh =
8341 			    PADDR_HI(addr);
8342 			addr += 4096;
8343 		}
8344 
8345 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8346 		    MBX_SUCCESS) {
8347 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8348 			    "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x "
8349 			    "status=%x ",
8350 			    mb->mbxCommand, mb->mbxStatus);
8351 			return (EIO);
8352 		}
8353 		emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0);
8354 	}
8355 
8356 	return (0);
8357 
8358 } /* emlxs_sli4_post_hdr_tmplates() */
8359 
8360 
8361 static int
8362 emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq)
8363 {
8364 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
8365 	emlxs_port_t	*port = &PPORT;
8366 	emlxs_config_t	*cfg = &CFG;
8367 	IOCTL_COMMON_EQ_CREATE *eq;
8368 	IOCTL_COMMON_CQ_CREATE *cq;
8369 	IOCTL_FCOE_WQ_CREATE *wq;
8370 	IOCTL_FCOE_RQ_CREATE *rq;
8371 	IOCTL_COMMON_MQ_CREATE *mq;
8372 	IOCTL_COMMON_MQ_CREATE_EXT *mq_ext;
8373 	emlxs_rqdbu_t	rqdb;
8374 	uint16_t i, j;
8375 	uint16_t num_cq, total_cq;
8376 	uint16_t num_wq, total_wq;
8377 
8378 	/*
8379 	 * The first CQ is reserved for ASYNC events,
8380 	 * the second is reserved for unsol rcv, the rest
8381 	 * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
8382 	 */
8383 
8384 	total_cq = 0;
8385 	total_wq = 0;
8386 
8387 	/* Create EQ's */
8388 	for (i = 0; i < hba->intr_count; i++) {
8389 		emlxs_mb_eq_create(hba, mbq, i);
8390 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8391 		    MBX_SUCCESS) {
8392 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8393 			    "Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
8394 			    i, mb->mbxCommand, mb->mbxStatus);
8395 			return (EIO);
8396 		}
8397 		eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
8398 		hba->sli.sli4.eq[i].qid = eq->params.response.EQId;
8399 		hba->sli.sli4.eq[i].lastwq = total_wq;
8400 		hba->sli.sli4.eq[i].msix_vector = i;
8401 
8402 		emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0);
8403 		num_wq = cfg[CFG_NUM_WQ].current;
8404 		num_cq = num_wq;
8405 		if (i == 0) {
8406 			/* One for RQ handling, one for mbox/event handling */
8407 			num_cq += EMLXS_CQ_OFFSET_WQ;
8408 		}
8409 
8410 		/* Create CQ's */
8411 		for (j = 0; j < num_cq; j++) {
8412 			/* Reuse mbq from previous mbox */
8413 			bzero(mbq, sizeof (MAILBOXQ));
8414 
8415 			hba->sli.sli4.cq[total_cq].eqid =
8416 			    hba->sli.sli4.eq[i].qid;
8417 
8418 			emlxs_mb_cq_create(hba, mbq, total_cq);
8419 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8420 			    MBX_SUCCESS) {
8421 				EMLXS_MSGF(EMLXS_CONTEXT,
8422 				    &emlxs_init_failed_msg, "Unable to Create "
8423 				    "CQ %d: Mailbox cmd=%x status=%x ",
8424 				    total_cq, mb->mbxCommand, mb->mbxStatus);
8425 				return (EIO);
8426 			}
8427 			cq = (IOCTL_COMMON_CQ_CREATE *)
8428 			    &mb->un.varSLIConfig.payload;
8429 			hba->sli.sli4.cq[total_cq].qid =
8430 			    cq->params.response.CQId;
8431 
8432 			switch (total_cq) {
8433 			case EMLXS_CQ_MBOX:
8434 				/* First CQ is for async event handling */
8435 				hba->sli.sli4.cq[total_cq].type =
8436 				    EMLXS_CQ_TYPE_GROUP1;
8437 				break;
8438 
8439 			case EMLXS_CQ_RCV:
8440 				/* Second CQ is for unsol receive handling */
8441 				hba->sli.sli4.cq[total_cq].type =
8442 				    EMLXS_CQ_TYPE_GROUP2;
8443 				break;
8444 
8445 			default:
8446 				/* Setup CQ to channel mapping */
8447 				hba->sli.sli4.cq[total_cq].type =
8448 				    EMLXS_CQ_TYPE_GROUP2;
8449 				hba->sli.sli4.cq[total_cq].channelp =
8450 				    &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ];
8451 				break;
8452 			}
8453 			emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb,
8454 			    18, 0);
8455 			total_cq++;
8456 		}
8457 
8458 		/* Create WQ's */
8459 		for (j = 0; j < num_wq; j++) {
8460 			/* Reuse mbq from previous mbox */
8461 			bzero(mbq, sizeof (MAILBOXQ));
8462 
8463 			hba->sli.sli4.wq[total_wq].cqid =
8464 			    hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid;
8465 
8466 			emlxs_mb_wq_create(hba, mbq, total_wq);
8467 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8468 			    MBX_SUCCESS) {
8469 				EMLXS_MSGF(EMLXS_CONTEXT,
8470 				    &emlxs_init_failed_msg, "Unable to Create "
8471 				    "WQ %d: Mailbox cmd=%x status=%x ",
8472 				    total_wq, mb->mbxCommand, mb->mbxStatus);
8473 				return (EIO);
8474 			}
8475 			wq = (IOCTL_FCOE_WQ_CREATE *)
8476 			    &mb->un.varSLIConfig.payload;
8477 			hba->sli.sli4.wq[total_wq].qid =
8478 			    wq->params.response.WQId;
8479 
8480 			hba->sli.sli4.wq[total_wq].cqid =
8481 			    hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid;
8482 			emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb,
8483 			    18, 0);
8484 			total_wq++;
8485 		}
8486 		hba->last_msiid = i;
8487 	}
8488 
8489 	/* We assume 1 RQ pair will handle ALL incoming data */
8490 	/* Create RQs */
8491 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
8492 		/* Personalize the RQ */
8493 		switch (i) {
8494 		case 0:
8495 			hba->sli.sli4.rq[i].cqid =
8496 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
8497 			break;
8498 		case 1:
8499 			hba->sli.sli4.rq[i].cqid =
8500 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
8501 			break;
8502 		default:
8503 			hba->sli.sli4.rq[i].cqid = 0xffff;
8504 		}
8505 
8506 		/* Reuse mbq from previous mbox */
8507 		bzero(mbq, sizeof (MAILBOXQ));
8508 
8509 		emlxs_mb_rq_create(hba, mbq, i);
8510 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8511 		    MBX_SUCCESS) {
8512 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8513 			    "Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
8514 			    i, mb->mbxCommand, mb->mbxStatus);
8515 			return (EIO);
8516 		}
8517 
8518 		rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
8519 		hba->sli.sli4.rq[i].qid = rq->params.response.RQId;
8520 		emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0);
8521 
8522 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8523 		    "RQ CREATE: rq[%d].qid=%d cqid=%d",
8524 		    i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid);
8525 
8526 		/* Initialize the host_index */
8527 		hba->sli.sli4.rq[i].host_index = 0;
8528 
8529 		/* If Data queue was just created, */
8530 		/* then post buffers using the header qid */
8531 		if ((i & 0x1)) {
8532 			/* Ring the RQ doorbell to post buffers */
8533 			rqdb.word = 0;
8534 			rqdb.db.Qid = hba->sli.sli4.rq[i-1].qid;
8535 			rqdb.db.NumPosted = RQB_COUNT;
8536 
8537 			emlxs_sli4_write_rqdb(hba, rqdb.word);
8538 
8539 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8540 			    "RQ CREATE: Doorbell rang: qid=%d count=%d",
8541 			    hba->sli.sli4.rq[i-1].qid, RQB_COUNT);
8542 		}
8543 	}
8544 
8545 	/* Create MQ */
8546 
8547 	/* Personalize the MQ */
8548 	hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid;
8549 
8550 	/* Reuse mbq from previous mbox */
8551 	bzero(mbq, sizeof (MAILBOXQ));
8552 
8553 	emlxs_mb_mq_create_ext(hba, mbq);
8554 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8555 	    MBX_SUCCESS) {
8556 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8557 		    "Unable to Create MQ_EXT %d: Mailbox cmd=%x status=%x ",
8558 		    i, mb->mbxCommand, mb->mbxStatus);
8559 
8560 		/* Reuse mbq from previous mbox */
8561 		bzero(mbq, sizeof (MAILBOXQ));
8562 
8563 		emlxs_mb_mq_create(hba, mbq);
8564 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8565 		    MBX_SUCCESS) {
8566 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8567 			    "Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
8568 			    i, mb->mbxCommand, mb->mbxStatus);
8569 			return (EIO);
8570 		}
8571 
8572 		mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
8573 		hba->sli.sli4.mq.qid = mq->params.response.MQId;
8574 		return (0);
8575 	}
8576 
8577 	mq_ext = (IOCTL_COMMON_MQ_CREATE_EXT *)&mb->un.varSLIConfig.payload;
8578 	hba->sli.sli4.mq.qid = mq_ext->params.response.MQId;
8579 	return (0);
8580 
8581 } /* emlxs_sli4_create_queues() */
8582 
8583 
8584 extern void
8585 emlxs_sli4_timer(emlxs_hba_t *hba)
8586 {
8587 	/* Perform SLI4 level timer checks */
8588 
8589 	emlxs_fcf_timer_notify(hba);
8590 
8591 	emlxs_sli4_timer_check_mbox(hba);
8592 
8593 	return;
8594 
8595 } /* emlxs_sli4_timer() */
8596 
8597 
8598 static void
8599 emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba)
8600 {
8601 	emlxs_port_t *port = &PPORT;
8602 	emlxs_config_t *cfg = &CFG;
8603 	MAILBOX *mb = NULL;
8604 
8605 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
8606 		return;
8607 	}
8608 
8609 	mutex_enter(&EMLXS_PORT_LOCK);
8610 
8611 	/* Return if timer hasn't expired */
8612 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
8613 		mutex_exit(&EMLXS_PORT_LOCK);
8614 		return;
8615 	}
8616 
8617 	/* The first to service the mbox queue will clear the timer */
8618 	hba->mbox_timer = 0;
8619 
8620 	if (hba->mbox_queue_flag) {
8621 		if (hba->mbox_mbq) {
8622 			mb = (MAILBOX *)hba->mbox_mbq;
8623 		}
8624 	}
8625 
8626 	if (mb) {
8627 		switch (hba->mbox_queue_flag) {
8628 		case MBX_NOWAIT:
8629 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8630 			    "%s: Nowait.",
8631 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
8632 			break;
8633 
8634 		case MBX_SLEEP:
8635 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8636 			    "%s: mb=%p Sleep.",
8637 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
8638 			    mb);
8639 			break;
8640 
8641 		case MBX_POLL:
8642 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8643 			    "%s: mb=%p Polled.",
8644 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
8645 			    mb);
8646 			break;
8647 
8648 		default:
8649 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8650 			    "%s: mb=%p (%d).",
8651 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
8652 			    mb, hba->mbox_queue_flag);
8653 			break;
8654 		}
8655 	} else {
8656 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
8657 	}
8658 
8659 	hba->flag |= FC_MBOX_TIMEOUT;
8660 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
8661 
8662 	mutex_exit(&EMLXS_PORT_LOCK);
8663 
8664 	/* Perform mailbox cleanup */
8665 	/* This will wake any sleeping or polling threads */
8666 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
8667 
8668 	/* Trigger adapter shutdown */
8669 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
8670 
8671 	return;
8672 
8673 } /* emlxs_sli4_timer_check_mbox() */
8674 
8675 
8676 extern void
8677 emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err)
8678 {
8679 	void *msg;
8680 
8681 	if (!port || !str || !iptr || !cnt) {
8682 		return;
8683 	}
8684 
8685 	if (err) {
8686 		msg = &emlxs_sli_err_msg;
8687 	} else {
8688 		msg = &emlxs_sli_detail_msg;
8689 	}
8690 
8691 	if (cnt) {
8692 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8693 		    "%s00: %08x %08x %08x %08x %08x %08x", str, *iptr,
8694 		    *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5));
8695 	}
8696 	if (cnt > 6) {
8697 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8698 		    "%s06: %08x %08x %08x %08x %08x %08x", str, *(iptr+6),
8699 		    *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11));
8700 	}
8701 	if (cnt > 12) {
8702 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8703 		    "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12),
8704 		    *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17));
8705 	}
8706 	if (cnt > 18) {
8707 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8708 		    "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18),
8709 		    *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23));
8710 	}
8711 	if (cnt > 24) {
8712 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8713 		    "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24),
8714 		    *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29));
8715 	}
8716 	if (cnt > 30) {
8717 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8718 		    "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30),
8719 		    *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35));
8720 	}
8721 	if (cnt > 36) {
8722 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8723 		    "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36),
8724 		    *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41));
8725 	}
8726 
8727 } /* emlxs_data_dump() */
8728 
8729 
8730 extern void
8731 emlxs_ue_dump(emlxs_hba_t *hba, char *str)
8732 {
8733 	emlxs_port_t *port = &PPORT;
8734 	uint32_t status;
8735 	uint32_t ue_h;
8736 	uint32_t ue_l;
8737 	uint32_t on1;
8738 	uint32_t on2;
8739 
8740 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
8741 	case SLI_INTF_IF_TYPE_0:
8742 		ue_l = ddi_get32(hba->pci_acc_handle,
8743 		    hba->sli.sli4.ERR1_reg_addr);
8744 		ue_h = ddi_get32(hba->pci_acc_handle,
8745 		    hba->sli.sli4.ERR2_reg_addr);
8746 
8747 		on1 = ddi_get32(hba->pci_acc_handle,
8748 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
8749 		on2 = ddi_get32(hba->pci_acc_handle,
8750 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
8751 
8752 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8753 		    "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
8754 		    ue_l, ue_h, on1, on2);
8755 		break;
8756 
8757 	case SLI_INTF_IF_TYPE_2:
8758 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8759 		    hba->sli.sli4.STATUS_reg_addr);
8760 
8761 		ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8762 		    hba->sli.sli4.ERR1_reg_addr);
8763 		ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8764 		    hba->sli.sli4.ERR2_reg_addr);
8765 
8766 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8767 		    "%s: status:%08x err1:%08x err2:%08x", str,
8768 		    status, ue_l, ue_h);
8769 
8770 		break;
8771 	}
8772 
8773 #ifdef FMA_SUPPORT
8774 	/* Access handle validation */
8775 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
8776 #endif  /* FMA_SUPPORT */
8777 
8778 } /* emlxs_ue_dump() */
8779 
8780 
8781 static void
8782 emlxs_sli4_poll_erratt(emlxs_hba_t *hba)
8783 {
8784 	emlxs_port_t *port = &PPORT;
8785 	uint32_t status;
8786 	uint32_t ue_h;
8787 	uint32_t ue_l;
8788 	uint32_t error = 0;
8789 
8790 	if (hba->flag & FC_HARDWARE_ERROR) {
8791 		return;
8792 	}
8793 
8794 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
8795 	case SLI_INTF_IF_TYPE_0:
8796 		ue_l = ddi_get32(hba->pci_acc_handle,
8797 		    hba->sli.sli4.ERR1_reg_addr);
8798 		ue_h = ddi_get32(hba->pci_acc_handle,
8799 		    hba->sli.sli4.ERR2_reg_addr);
8800 
8801 		if ((~hba->sli.sli4.ue_mask_lo & ue_l) ||
8802 		    (~hba->sli.sli4.ue_mask_hi & ue_h) ||
8803 		    (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
8804 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
8805 			    "Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x "
8806 			    "maskHigh:%08x flag:%08x",
8807 			    ue_l, ue_h, hba->sli.sli4.ue_mask_lo,
8808 			    hba->sli.sli4.ue_mask_hi, hba->sli.sli4.flag);
8809 
8810 			error = 2;
8811 		}
8812 		break;
8813 
8814 	case SLI_INTF_IF_TYPE_2:
8815 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8816 		    hba->sli.sli4.STATUS_reg_addr);
8817 
8818 		if ((status & SLI_STATUS_ERROR) ||
8819 		    (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
8820 			ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8821 			    hba->sli.sli4.ERR1_reg_addr);
8822 			ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8823 			    hba->sli.sli4.ERR2_reg_addr);
8824 
8825 			error = (status & SLI_STATUS_RESET_NEEDED)? 1:2;
8826 
8827 			if (error == 1) {
8828 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
8829 				    "Host Error: status:%08x err1:%08x "
8830 				    "err2:%08x flag:%08x",
8831 				    status, ue_l, ue_h, hba->sli.sli4.flag);
8832 			} else {
8833 				EMLXS_MSGF(EMLXS_CONTEXT,
8834 				    &emlxs_hardware_error_msg,
8835 				    "Host Error: status:%08x err1:%08x "
8836 				    "err2:%08x flag:%08x",
8837 				    status, ue_l, ue_h, hba->sli.sli4.flag);
8838 			}
8839 		}
8840 		break;
8841 	}
8842 
8843 	if (error == 2) {
8844 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
8845 
8846 		emlxs_sli4_hba_flush_chipq(hba);
8847 
8848 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
8849 
8850 	} else if (error == 1) {
8851 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
8852 
8853 		emlxs_sli4_hba_flush_chipq(hba);
8854 
8855 		emlxs_thread_spawn(hba, emlxs_restart_thread, 0, 0);
8856 	}
8857 
8858 #ifdef FMA_SUPPORT
8859 	/* Access handle validation */
8860 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
8861 #endif  /* FMA_SUPPORT */
8862 
8863 } /* emlxs_sli4_poll_erratt() */
8864 
8865 
8866 static uint32_t
8867 emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
8868     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
8869 {
8870 	emlxs_hba_t	*hba = HBA;
8871 	NODELIST	*node;
8872 	RPIobj_t	*rpip;
8873 	uint32_t	rval;
8874 
8875 	/* Check for invalid node ids to register */
8876 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
8877 		return (1);
8878 	}
8879 
8880 	if (did & 0xff000000) {
8881 		return (1);
8882 	}
8883 
8884 	/* We don't register our own did */
8885 	if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) {
8886 		return (1);
8887 	}
8888 
8889 	if (did != FABRIC_DID) {
8890 		if ((rval = emlxs_mb_check_sparm(hba, param))) {
8891 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
8892 			    "Invalid service parameters. did=%06x rval=%d", did,
8893 			    rval);
8894 
8895 			return (1);
8896 		}
8897 	}
8898 
8899 	/* Check if the node limit has been reached */
8900 	if (port->node_count >= hba->max_nodes) {
8901 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
8902 		    "Limit reached. did=%06x count=%d", did,
8903 		    port->node_count);
8904 
8905 		return (1);
8906 	}
8907 
8908 	node = emlxs_node_find_did(port, did, 1);
8909 	rpip = EMLXS_NODE_TO_RPI(port, node);
8910 
8911 	rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp,
8912 	    (void *)ubp, (void *)iocbq);
8913 
8914 	return (rval);
8915 
8916 } /* emlxs_sli4_reg_did() */
8917 
8918 
8919 static uint32_t
8920 emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node,
8921     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
8922 {
8923 	RPIobj_t	*rpip;
8924 	uint32_t	rval;
8925 
8926 	if (!node) {
8927 		/* Unreg all nodes */
8928 		(void) emlxs_sli4_unreg_all_nodes(port);
8929 		return (1);
8930 	}
8931 
8932 	/* Check for base node */
8933 	if (node == &port->node_base) {
8934 		/* Just flush base node */
8935 		(void) emlxs_tx_node_flush(port, &port->node_base,
8936 		    0, 0, 0);
8937 
8938 		(void) emlxs_chipq_node_flush(port, 0,
8939 		    &port->node_base, 0);
8940 
8941 		port->did = 0;
8942 
8943 		/* Return now */
8944 		return (1);
8945 	}
8946 
8947 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8948 	    "unreg_node:%p did=%x rpi=%d",
8949 	    node, node->nlp_DID, node->nlp_Rpi);
8950 
8951 	rpip = EMLXS_NODE_TO_RPI(port, node);
8952 
8953 	if (!rpip) {
8954 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8955 		    "unreg_node:%p did=%x rpi=%d. RPI not found.",
8956 		    node, node->nlp_DID, node->nlp_Rpi);
8957 
8958 		emlxs_node_rm(port, node);
8959 		return (1);
8960 	}
8961 
8962 	rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp,
8963 	    (void *)iocbq);
8964 
8965 	return (rval);
8966 
8967 } /* emlxs_sli4_unreg_node() */
8968 
8969 
8970 extern uint32_t
8971 emlxs_sli4_unreg_all_nodes(emlxs_port_t *port)
8972 {
8973 	NODELIST	*nlp;
8974 	int		i;
8975 	uint32_t 	found;
8976 
8977 	/* Set the node tags */
8978 	/* We will process all nodes with this tag */
8979 	rw_enter(&port->node_rwlock, RW_READER);
8980 	found = 0;
8981 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
8982 		nlp = port->node_table[i];
8983 		while (nlp != NULL) {
8984 			found = 1;
8985 			nlp->nlp_tag = 1;
8986 			nlp = nlp->nlp_list_next;
8987 		}
8988 	}
8989 	rw_exit(&port->node_rwlock);
8990 
8991 	if (!found) {
8992 		return (0);
8993 	}
8994 
8995 	for (;;) {
8996 		rw_enter(&port->node_rwlock, RW_READER);
8997 		found = 0;
8998 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
8999 			nlp = port->node_table[i];
9000 			while (nlp != NULL) {
9001 				if (!nlp->nlp_tag) {
9002 					nlp = nlp->nlp_list_next;
9003 					continue;
9004 				}
9005 				nlp->nlp_tag = 0;
9006 				found = 1;
9007 				break;
9008 			}
9009 
9010 			if (found) {
9011 				break;
9012 			}
9013 		}
9014 		rw_exit(&port->node_rwlock);
9015 
9016 		if (!found) {
9017 			break;
9018 		}
9019 
9020 		(void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0);
9021 	}
9022 
9023 	return (0);
9024 
9025 } /* emlxs_sli4_unreg_all_nodes() */
9026 
9027 
9028 static void
9029 emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
9030 {
9031 	emlxs_port_t *port = &PPORT;
9032 
9033 	/* Handle link down */
9034 	if ((cqe->un.link.link_status == ASYNC_EVENT_LOGICAL_LINK_DOWN) ||
9035 	    (cqe->un.link.link_status == ASYNC_EVENT_PHYS_LINK_DOWN)) {
9036 		(void) emlxs_fcf_linkdown_notify(port);
9037 
9038 		mutex_enter(&EMLXS_PORT_LOCK);
9039 		hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9040 		mutex_exit(&EMLXS_PORT_LOCK);
9041 		return;
9042 	}
9043 
9044 	/* Link is up */
9045 
9046 	/* Set linkspeed */
9047 	switch (cqe->un.link.port_speed) {
9048 	case PHY_1GHZ_LINK:
9049 		hba->linkspeed = LA_1GHZ_LINK;
9050 		break;
9051 	case PHY_10GHZ_LINK:
9052 		hba->linkspeed = LA_10GHZ_LINK;
9053 		break;
9054 	default:
9055 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
9056 		    "sli4_handle_fcoe_link_event: Unknown link speed=%x.",
9057 		    cqe->un.link.port_speed);
9058 		hba->linkspeed = 0;
9059 		break;
9060 	}
9061 
9062 	/* Set qos_linkspeed */
9063 	hba->qos_linkspeed = cqe->un.link.qos_link_speed;
9064 
9065 	/* Set topology */
9066 	hba->topology = TOPOLOGY_PT_PT;
9067 
9068 	mutex_enter(&EMLXS_PORT_LOCK);
9069 	hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9070 	mutex_exit(&EMLXS_PORT_LOCK);
9071 
9072 	(void) emlxs_fcf_linkup_notify(port);
9073 
9074 	return;
9075 
9076 } /* emlxs_sli4_handle_fcoe_link_event()  */
9077 
9078 
9079 static void
9080 emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
9081 {
9082 	emlxs_port_t *port = &PPORT;
9083 
9084 	/* Handle link down */
9085 	if (cqe->un.fc.att_type == ATT_TYPE_LINK_DOWN) {
9086 		(void) emlxs_fcf_linkdown_notify(port);
9087 
9088 		mutex_enter(&EMLXS_PORT_LOCK);
9089 		hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9090 		mutex_exit(&EMLXS_PORT_LOCK);
9091 		return;
9092 	}
9093 
9094 	/* Link is up */
9095 
9096 	/* Set linkspeed */
9097 	switch (cqe->un.fc.port_speed) {
9098 	case 1:
9099 		hba->linkspeed = LA_1GHZ_LINK;
9100 		break;
9101 	case 2:
9102 		hba->linkspeed = LA_2GHZ_LINK;
9103 		break;
9104 	case 4:
9105 		hba->linkspeed = LA_4GHZ_LINK;
9106 		break;
9107 	case 8:
9108 		hba->linkspeed = LA_8GHZ_LINK;
9109 		break;
9110 	case 10:
9111 		hba->linkspeed = LA_10GHZ_LINK;
9112 		break;
9113 	case 16:
9114 		hba->linkspeed = LA_16GHZ_LINK;
9115 		break;
9116 	default:
9117 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
9118 		    "sli4_handle_fc_link_att: Unknown link speed=%x.",
9119 		    cqe->un.fc.port_speed);
9120 		hba->linkspeed = 0;
9121 		break;
9122 	}
9123 
9124 	/* Set qos_linkspeed */
9125 	hba->qos_linkspeed = cqe->un.fc.link_speed;
9126 
9127 	/* Set topology */
9128 	hba->topology = cqe->un.fc.topology;
9129 
9130 	mutex_enter(&EMLXS_PORT_LOCK);
9131 	hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9132 	mutex_exit(&EMLXS_PORT_LOCK);
9133 
9134 	(void) emlxs_fcf_linkup_notify(port);
9135 
9136 	return;
9137 
9138 } /* emlxs_sli4_handle_fc_link_att() */
9139 
9140 
9141 static int
9142 emlxs_sli4_init_extents(emlxs_hba_t *hba, MAILBOXQ *mbq)
9143 {
9144 	emlxs_port_t *port = &PPORT;
9145 	MAILBOX4 *mb4;
9146 	IOCTL_COMMON_EXTENTS *ep;
9147 	uint32_t i;
9148 	uint32_t ExtentCnt;
9149 
9150 	if (!(hba->sli.sli4.param.EXT)) {
9151 		return (0);
9152 	}
9153 
9154 	mb4 = (MAILBOX4 *) mbq;
9155 
9156 	/* Discover XRI Extents */
9157 	bzero(mbq, sizeof (MAILBOXQ));
9158 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_XRI);
9159 
9160 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9161 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9162 		    "Unable to discover XRI extents.  Mailbox cmd=%x status=%x",
9163 		    mb4->mbxCommand, mb4->mbxStatus);
9164 
9165 		return (EIO);
9166 	}
9167 
9168 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9169 	hba->sli.sli4.XRIExtSize = ep->params.response.ExtentSize;
9170 	ExtentCnt = ep->params.response.ExtentCnt;
9171 
9172 	/* Allocate XRI Extents */
9173 	bzero(mbq, sizeof (MAILBOXQ));
9174 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_XRI, ExtentCnt);
9175 
9176 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9178 		    "Unable to allocate XRI extents.  Mailbox cmd=%x status=%x",
9179 		    mb4->mbxCommand, mb4->mbxStatus);
9180 
9181 		return (EIO);
9182 	}
9183 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9184 
9185 	bcopy((uint8_t *)ep->params.response.RscId,
9186 	    (uint8_t *)hba->sli.sli4.XRIBase,
9187 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9188 
9189 	hba->sli.sli4.XRIExtCount = ep->params.response.ExtentCnt;
9190 	hba->sli.sli4.XRICount = hba->sli.sli4.XRIExtCount *
9191 	    hba->sli.sli4.XRIExtSize;
9192 
9193 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9194 	    "XRI Ext: size=%d cnt=%d/%d",
9195 	    hba->sli.sli4.XRIExtSize,
9196 	    hba->sli.sli4.XRIExtCount, ExtentCnt);
9197 
9198 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9200 		    "XRI Ext%d: %d, %d, %d, %d", i,
9201 		    hba->sli.sli4.XRIBase[i],
9202 		    hba->sli.sli4.XRIBase[i+1],
9203 		    hba->sli.sli4.XRIBase[i+2],
9204 		    hba->sli.sli4.XRIBase[i+3]);
9205 	}
9206 
9207 
9208 	/* Discover RPI Extents */
9209 	bzero(mbq, sizeof (MAILBOXQ));
9210 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_RPI);
9211 
9212 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9213 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9214 		    "Unable to discover RPI extents.  Mailbox cmd=%x status=%x",
9215 		    mb4->mbxCommand, mb4->mbxStatus);
9216 
9217 		return (EIO);
9218 	}
9219 
9220 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9221 	hba->sli.sli4.RPIExtSize = ep->params.response.ExtentSize;
9222 	ExtentCnt = ep->params.response.ExtentCnt;
9223 
9224 	/* Allocate RPI Extents */
9225 	bzero(mbq, sizeof (MAILBOXQ));
9226 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_RPI, ExtentCnt);
9227 
9228 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9229 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9230 		    "Unable to allocate RPI extents.  Mailbox cmd=%x status=%x",
9231 		    mb4->mbxCommand, mb4->mbxStatus);
9232 
9233 		return (EIO);
9234 	}
9235 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9236 
9237 	bcopy((uint8_t *)ep->params.response.RscId,
9238 	    (uint8_t *)hba->sli.sli4.RPIBase,
9239 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9240 
9241 	hba->sli.sli4.RPIExtCount = ep->params.response.ExtentCnt;
9242 	hba->sli.sli4.RPICount = hba->sli.sli4.RPIExtCount *
9243 	    hba->sli.sli4.RPIExtSize;
9244 
9245 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9246 	    "RPI Ext: size=%d cnt=%d/%d",
9247 	    hba->sli.sli4.RPIExtSize,
9248 	    hba->sli.sli4.RPIExtCount, ExtentCnt);
9249 
9250 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9251 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9252 		    "RPI Ext%d: %d, %d, %d, %d", i,
9253 		    hba->sli.sli4.RPIBase[i],
9254 		    hba->sli.sli4.RPIBase[i+1],
9255 		    hba->sli.sli4.RPIBase[i+2],
9256 		    hba->sli.sli4.RPIBase[i+3]);
9257 	}
9258 
9259 
9260 	/* Discover VPI Extents */
9261 	bzero(mbq, sizeof (MAILBOXQ));
9262 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VPI);
9263 
9264 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9266 		    "Unable to discover VPI extents.  Mailbox cmd=%x status=%x",
9267 		    mb4->mbxCommand, mb4->mbxStatus);
9268 
9269 		return (EIO);
9270 	}
9271 
9272 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9273 	hba->sli.sli4.VPIExtSize = ep->params.response.ExtentSize;
9274 	ExtentCnt = ep->params.response.ExtentCnt;
9275 
9276 	/* Allocate VPI Extents */
9277 	bzero(mbq, sizeof (MAILBOXQ));
9278 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VPI, ExtentCnt);
9279 
9280 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9281 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9282 		    "Unable to allocate VPI extents.  Mailbox cmd=%x status=%x",
9283 		    mb4->mbxCommand, mb4->mbxStatus);
9284 
9285 		return (EIO);
9286 	}
9287 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9288 
9289 	bcopy((uint8_t *)ep->params.response.RscId,
9290 	    (uint8_t *)hba->sli.sli4.VPIBase,
9291 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9292 
9293 	hba->sli.sli4.VPIExtCount = ep->params.response.ExtentCnt;
9294 	hba->sli.sli4.VPICount = hba->sli.sli4.VPIExtCount *
9295 	    hba->sli.sli4.VPIExtSize;
9296 
9297 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9298 	    "VPI Ext: size=%d cnt=%d/%d",
9299 	    hba->sli.sli4.VPIExtSize,
9300 	    hba->sli.sli4.VPIExtCount, ExtentCnt);
9301 
9302 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9303 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9304 		    "VPI Ext%d: %d, %d, %d, %d", i,
9305 		    hba->sli.sli4.VPIBase[i],
9306 		    hba->sli.sli4.VPIBase[i+1],
9307 		    hba->sli.sli4.VPIBase[i+2],
9308 		    hba->sli.sli4.VPIBase[i+3]);
9309 	}
9310 
9311 	/* Discover VFI Extents */
9312 	bzero(mbq, sizeof (MAILBOXQ));
9313 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VFI);
9314 
9315 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9316 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9317 		    "Unable to discover VFI extents.  Mailbox cmd=%x status=%x",
9318 		    mb4->mbxCommand, mb4->mbxStatus);
9319 
9320 		return (EIO);
9321 	}
9322 
9323 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9324 	hba->sli.sli4.VFIExtSize = ep->params.response.ExtentSize;
9325 	ExtentCnt = ep->params.response.ExtentCnt;
9326 
9327 	/* Allocate VFI Extents */
9328 	bzero(mbq, sizeof (MAILBOXQ));
9329 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VFI, ExtentCnt);
9330 
9331 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9332 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9333 		    "Unable to allocate VFI extents.  Mailbox cmd=%x status=%x",
9334 		    mb4->mbxCommand, mb4->mbxStatus);
9335 
9336 		return (EIO);
9337 	}
9338 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9339 
9340 	bcopy((uint8_t *)ep->params.response.RscId,
9341 	    (uint8_t *)hba->sli.sli4.VFIBase,
9342 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9343 
9344 	hba->sli.sli4.VFIExtCount = ep->params.response.ExtentCnt;
9345 	hba->sli.sli4.VFICount = hba->sli.sli4.VFIExtCount *
9346 	    hba->sli.sli4.VFIExtSize;
9347 
9348 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9349 	    "VFI Ext: size=%d cnt=%d/%d",
9350 	    hba->sli.sli4.VFIExtSize,
9351 	    hba->sli.sli4.VFIExtCount, ExtentCnt);
9352 
9353 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9355 		    "VFI Ext%d: %d, %d, %d, %d", i,
9356 		    hba->sli.sli4.VFIBase[i],
9357 		    hba->sli.sli4.VFIBase[i+1],
9358 		    hba->sli.sli4.VFIBase[i+2],
9359 		    hba->sli.sli4.VFIBase[i+3]);
9360 	}
9361 
9362 	return (0);
9363 
9364 } /* emlxs_sli4_init_extents() */
9365 
9366 
9367 extern uint32_t
9368 emlxs_sli4_index_to_rpi(emlxs_hba_t *hba, uint32_t index)
9369 {
9370 	uint32_t i;
9371 	uint32_t j;
9372 	uint32_t rpi;
9373 
9374 	i = index / hba->sli.sli4.RPIExtSize;
9375 	j = index % hba->sli.sli4.RPIExtSize;
9376 	rpi = hba->sli.sli4.RPIBase[i] + j;
9377 
9378 	return (rpi);
9379 
9380 } /* emlxs_sli4_index_to_rpi */
9381 
9382 
9383 extern uint32_t
9384 emlxs_sli4_rpi_to_index(emlxs_hba_t *hba, uint32_t rpi)
9385 {
9386 	uint32_t i;
9387 	uint32_t lo;
9388 	uint32_t hi;
9389 	uint32_t index = hba->sli.sli4.RPICount;
9390 
9391 	for (i = 0; i < hba->sli.sli4.RPIExtCount; i++) {
9392 		lo = hba->sli.sli4.RPIBase[i];
9393 		hi = lo + hba->sli.sli4.RPIExtSize;
9394 
9395 		if ((rpi < hi) && (rpi >= lo)) {
9396 			index = (i * hba->sli.sli4.RPIExtSize) + (rpi - lo);
9397 			break;
9398 		}
9399 	}
9400 
9401 	return (index);
9402 
9403 } /* emlxs_sli4_rpi_to_index */
9404 
9405 
9406 extern uint32_t
9407 emlxs_sli4_index_to_xri(emlxs_hba_t *hba, uint32_t index)
9408 {
9409 	uint32_t i;
9410 	uint32_t j;
9411 	uint32_t xri;
9412 
9413 	i = index / hba->sli.sli4.XRIExtSize;
9414 	j = index % hba->sli.sli4.XRIExtSize;
9415 	xri = hba->sli.sli4.XRIBase[i] + j;
9416 
9417 	return (xri);
9418 
9419 } /* emlxs_sli4_index_to_xri */
9420 
9421 
9422 
9423 
9424 extern uint32_t
9425 emlxs_sli4_index_to_vpi(emlxs_hba_t *hba, uint32_t index)
9426 {
9427 	uint32_t i;
9428 	uint32_t j;
9429 	uint32_t vpi;
9430 
9431 	i = index / hba->sli.sli4.VPIExtSize;
9432 	j = index % hba->sli.sli4.VPIExtSize;
9433 	vpi = hba->sli.sli4.VPIBase[i] + j;
9434 
9435 	return (vpi);
9436 
9437 } /* emlxs_sli4_index_to_vpi */
9438 
9439 
9440 extern uint32_t
9441 emlxs_sli4_vpi_to_index(emlxs_hba_t *hba, uint32_t vpi)
9442 {
9443 	uint32_t i;
9444 	uint32_t lo;
9445 	uint32_t hi;
9446 	uint32_t index = hba->sli.sli4.VPICount;
9447 
9448 	for (i = 0; i < hba->sli.sli4.VPIExtCount; i++) {
9449 		lo = hba->sli.sli4.VPIBase[i];
9450 		hi = lo + hba->sli.sli4.VPIExtSize;
9451 
9452 		if ((vpi < hi) && (vpi >= lo)) {
9453 			index = (i * hba->sli.sli4.VPIExtSize) + (vpi - lo);
9454 			break;
9455 		}
9456 	}
9457 
9458 	return (index);
9459 
9460 } /* emlxs_sli4_vpi_to_index */
9461 
9462 
9463 
9464 
9465 extern uint32_t
9466 emlxs_sli4_index_to_vfi(emlxs_hba_t *hba, uint32_t index)
9467 {
9468 	uint32_t i;
9469 	uint32_t j;
9470 	uint32_t vfi;
9471 
9472 	i = index / hba->sli.sli4.VFIExtSize;
9473 	j = index % hba->sli.sli4.VFIExtSize;
9474 	vfi = hba->sli.sli4.VFIBase[i] + j;
9475 
9476 	return (vfi);
9477 
9478 } /* emlxs_sli4_index_to_vfi */
9479 
9480 
9481 static uint16_t
9482 emlxs_sli4_rqid_to_index(emlxs_hba_t *hba, uint16_t rqid)
9483 {
9484 	uint16_t i;
9485 
9486 	if (rqid < 0xffff) {
9487 		for (i = 0; i < EMLXS_MAX_RQS; i++) {
9488 			if (hba->sli.sli4.rq[i].qid == rqid) {
9489 				return (i);
9490 			}
9491 		}
9492 	}
9493 
9494 	return (0xffff);
9495 
9496 } /* emlxs_sli4_rqid_to_index */
9497 
9498 
9499 static uint16_t
9500 emlxs_sli4_wqid_to_index(emlxs_hba_t *hba, uint16_t wqid)
9501 {
9502 	uint16_t i;
9503 
9504 	if (wqid < 0xffff) {
9505 		for (i = 0; i < EMLXS_MAX_WQS; i++) {
9506 			if (hba->sli.sli4.wq[i].qid == wqid) {
9507 				return (i);
9508 			}
9509 		}
9510 	}
9511 
9512 	return (0xffff);
9513 
9514 } /* emlxs_sli4_wqid_to_index */
9515 
9516 
9517 static uint16_t
9518 emlxs_sli4_cqid_to_index(emlxs_hba_t *hba, uint16_t cqid)
9519 {
9520 	uint16_t i;
9521 
9522 	if (cqid < 0xffff) {
9523 		for (i = 0; i < EMLXS_MAX_CQS; i++) {
9524 			if (hba->sli.sli4.cq[i].qid == cqid) {
9525 				return (i);
9526 			}
9527 		}
9528 	}
9529 
9530 	return (0xffff);
9531 
9532 } /* emlxs_sli4_cqid_to_index */
9533