1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <emlxs.h>
29 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_SLI4_C);
32 
33 static int		emlxs_sli4_create_queues(emlxs_hba_t *hba,
34 				MAILBOXQ *mbq);
35 static int		emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba,
36 				MAILBOXQ *mbq);
37 static int		emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba,
38 				MAILBOXQ *mbq);
39 
40 static int		emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq);
41 
42 extern void		emlxs_parse_prog_types(emlxs_hba_t *hba, char *types);
43 
44 extern int32_t		emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd,
45 				uint32_t size);
46 extern void		emlxs_decode_label(char *label, char *buffer, int bige);
47 
48 extern void		emlxs_build_prog_types(emlxs_hba_t *hba,
49 				char *prog_types);
50 
51 extern int		emlxs_pci_model_count;
52 
53 extern emlxs_model_t	emlxs_pci_model[];
54 
55 static int		emlxs_sli4_map_hdw(emlxs_hba_t *hba);
56 
57 static void		emlxs_sli4_unmap_hdw(emlxs_hba_t *hba);
58 
59 static int32_t		emlxs_sli4_online(emlxs_hba_t *hba);
60 
61 static void		emlxs_sli4_offline(emlxs_hba_t *hba);
62 
63 static uint32_t		emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart,
64 				uint32_t skip_post, uint32_t quiesce);
65 static void		emlxs_sli4_hba_kill(emlxs_hba_t *hba);
66 
67 static uint32_t		emlxs_sli4_hba_init(emlxs_hba_t *hba);
68 
69 static uint32_t		emlxs_sli4_bde_setup(emlxs_port_t *port,
70 				emlxs_buf_t *sbp);
71 
72 
73 static void		emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba,
74 				CHANNEL *cp, IOCBQ *iocb_cmd);
75 static uint32_t		emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba,
76 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
77 static uint32_t		emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba,
78 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
79 #ifdef SFCT_SUPPORT
80 static uint32_t		emlxs_sli4_prep_fct_iocb(emlxs_port_t *port,
81 				emlxs_buf_t *cmd_sbp, int channel);
82 #endif /* SFCT_SUPPORT */
83 
84 static uint32_t		emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port,
85 				emlxs_buf_t *sbp, int ring);
86 static uint32_t		emlxs_sli4_prep_ip_iocb(emlxs_port_t *port,
87 				emlxs_buf_t *sbp);
88 static uint32_t		emlxs_sli4_prep_els_iocb(emlxs_port_t *port,
89 				emlxs_buf_t *sbp);
90 static uint32_t		emlxs_sli4_prep_ct_iocb(emlxs_port_t *port,
91 				emlxs_buf_t *sbp);
92 static void		emlxs_sli4_poll_intr(emlxs_hba_t *hba,
93 				uint32_t att_bit);
94 static int32_t		emlxs_sli4_intx_intr(char *arg);
95 
96 #ifdef MSI_SUPPORT
97 static uint32_t		emlxs_sli4_msi_intr(char *arg1, char *arg2);
98 #endif /* MSI_SUPPORT */
99 
100 static void		emlxs_sli4_resource_free(emlxs_hba_t *hba);
101 
102 static int		emlxs_sli4_resource_alloc(emlxs_hba_t *hba);
103 
104 static XRIobj_t		*emlxs_sli4_alloc_xri(emlxs_hba_t *hba,
105 				emlxs_buf_t *sbp, RPIobj_t *rpip);
106 static void		emlxs_sli4_enable_intr(emlxs_hba_t *hba);
107 
108 static void		emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att);
109 
110 extern void		emlxs_sli4_timer(emlxs_hba_t *hba);
111 
112 static void		emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
113 
114 static void		emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
115 
116 static XRIobj_t 	*emlxs_sli4_register_xri(emlxs_hba_t *hba,
117 				emlxs_buf_t *sbp, uint16_t xri);
118 
119 static XRIobj_t 	*emlxs_sli4_reserve_xri(emlxs_hba_t *hba,
120 				RPIobj_t *rpip);
121 static int		emlxs_check_hdw_ready(emlxs_hba_t *);
122 
123 
124 /* Define SLI4 API functions */
125 emlxs_sli_api_t emlxs_sli4_api = {
126 	emlxs_sli4_map_hdw,
127 	emlxs_sli4_unmap_hdw,
128 	emlxs_sli4_online,
129 	emlxs_sli4_offline,
130 	emlxs_sli4_hba_reset,
131 	emlxs_sli4_hba_kill,
132 	emlxs_sli4_issue_iocb_cmd,
133 	emlxs_sli4_issue_mbox_cmd,
134 #ifdef SFCT_SUPPORT
135 	emlxs_sli4_prep_fct_iocb,
136 #else
137 	NULL,
138 #endif /* SFCT_SUPPORT */
139 	emlxs_sli4_prep_fcp_iocb,
140 	emlxs_sli4_prep_ip_iocb,
141 	emlxs_sli4_prep_els_iocb,
142 	emlxs_sli4_prep_ct_iocb,
143 	emlxs_sli4_poll_intr,
144 	emlxs_sli4_intx_intr,
145 	emlxs_sli4_msi_intr,
146 	emlxs_sli4_disable_intr,
147 	emlxs_sli4_timer,
148 	emlxs_sli4_poll_erratt
149 };
150 
151 
152 /* ************************************************************************** */
153 
154 
155 /*
156  * emlxs_sli4_online()
157  *
158  * This routine will start initialization of the SLI4 HBA.
159  */
160 static int32_t
161 emlxs_sli4_online(emlxs_hba_t *hba)
162 {
163 	emlxs_port_t *port = &PPORT;
164 	emlxs_config_t *cfg;
165 	emlxs_vpd_t *vpd;
166 	MAILBOXQ *mbq = NULL;
167 	MAILBOX4 *mb  = NULL;
168 	MATCHMAP *mp  = NULL;
169 	uint32_t i;
170 	uint32_t j;
171 	uint32_t rval = 0;
172 	uint8_t *vpd_data;
173 	uint32_t sli_mode;
174 	uint8_t *outptr;
175 	uint32_t status;
176 	uint32_t fw_check;
177 	uint32_t kern_update = 0;
178 	emlxs_firmware_t hba_fw;
179 	emlxs_firmware_t *fw;
180 	uint16_t ssvid;
181 
182 	cfg = &CFG;
183 	vpd = &VPD;
184 
185 	sli_mode = EMLXS_HBA_SLI4_MODE;
186 	hba->sli_mode = sli_mode;
187 
188 	/* Set the fw_check flag */
189 	fw_check = cfg[CFG_FW_CHECK].current;
190 
191 	if ((fw_check & 0x04) ||
192 	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
193 		kern_update = 1;
194 	}
195 
196 	hba->mbox_queue_flag = 0;
197 	hba->fc_edtov = FF_DEF_EDTOV;
198 	hba->fc_ratov = FF_DEF_RATOV;
199 	hba->fc_altov = FF_DEF_ALTOV;
200 	hba->fc_arbtov = FF_DEF_ARBTOV;
201 
202 	/* Target mode not supported */
203 	if (hba->tgt_mode) {
204 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
205 		    "Target mode not supported in SLI4.");
206 
207 		return (ENOMEM);
208 	}
209 
210 	/* Networking not supported */
211 	if (cfg[CFG_NETWORK_ON].current) {
212 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
213 		    "Networking not supported in SLI4, turning it off");
214 		cfg[CFG_NETWORK_ON].current = 0;
215 	}
216 
217 	hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
218 	if (hba->chan_count > MAX_CHANNEL) {
219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
220 		    "Max channels exceeded, dropping num-wq from %d to 1",
221 		    cfg[CFG_NUM_WQ].current);
222 		cfg[CFG_NUM_WQ].current = 1;
223 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
224 	}
225 	hba->channel_fcp = 0; /* First channel */
226 
227 	/* Default channel for everything else is the last channel */
228 	hba->channel_ip = hba->chan_count - 1;
229 	hba->channel_els = hba->chan_count - 1;
230 	hba->channel_ct = hba->chan_count - 1;
231 
232 	hba->fc_iotag = 1;
233 	hba->io_count = 0;
234 	hba->channel_tx_count = 0;
235 
236 	/* Initialize the local dump region buffer */
237 	bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
238 	hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
239 	hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
240 	    | FC_MBUF_DMA32;
241 	hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L);
242 
243 	(void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region);
244 
245 	if (hba->sli.sli4.dump_region.virt == NULL) {
246 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
247 		    "Unable to allocate dump region buffer.");
248 
249 		return (ENOMEM);
250 	}
251 
252 	/*
253 	 * Get a buffer which will be used repeatedly for mailbox commands
254 	 */
255 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
256 
257 	mb = (MAILBOX4 *)mbq;
258 
259 reset:
260 	/* Reset & Initialize the adapter */
261 	if (emlxs_sli4_hba_init(hba)) {
262 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
263 		    "Unable to init hba.");
264 
265 		rval = EIO;
266 		goto failed1;
267 	}
268 
269 #ifdef FMA_SUPPORT
270 	/* Access handle validation */
271 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
272 	    != DDI_FM_OK) ||
273 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli4.bar1_acc_handle)
274 	    != DDI_FM_OK) ||
275 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli4.bar2_acc_handle)
276 	    != DDI_FM_OK)) {
277 		EMLXS_MSGF(EMLXS_CONTEXT,
278 		    &emlxs_invalid_access_handle_msg, NULL);
279 
280 		rval = EIO;
281 		goto failed1;
282 	}
283 #endif	/* FMA_SUPPORT */
284 
285 	/*
286 	 * Setup and issue mailbox READ REV command
287 	 */
288 	vpd->opFwRev = 0;
289 	vpd->postKernRev = 0;
290 	vpd->sli1FwRev = 0;
291 	vpd->sli2FwRev = 0;
292 	vpd->sli3FwRev = 0;
293 	vpd->sli4FwRev = 0;
294 
295 	vpd->postKernName[0] = 0;
296 	vpd->opFwName[0] = 0;
297 	vpd->sli1FwName[0] = 0;
298 	vpd->sli2FwName[0] = 0;
299 	vpd->sli3FwName[0] = 0;
300 	vpd->sli4FwName[0] = 0;
301 
302 	vpd->opFwLabel[0] = 0;
303 	vpd->sli1FwLabel[0] = 0;
304 	vpd->sli2FwLabel[0] = 0;
305 	vpd->sli3FwLabel[0] = 0;
306 	vpd->sli4FwLabel[0] = 0;
307 
308 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
309 
310 	emlxs_mb_read_rev(hba, mbq, 0);
311 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
312 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
313 		    "Unable to read rev. Mailbox cmd=%x status=%x",
314 		    mb->mbxCommand, mb->mbxStatus);
315 
316 		rval = EIO;
317 		goto failed1;
318 
319 	}
320 
321 emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0);
322 	if (mb->un.varRdRev4.sliLevel != 4) {
323 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
324 		    "Invalid read rev Version for SLI4: 0x%x",
325 		    mb->un.varRdRev4.sliLevel);
326 
327 		rval = EIO;
328 		goto failed1;
329 	}
330 
331 	switch (mb->un.varRdRev4.dcbxMode) {
332 	case EMLXS_DCBX_MODE_CIN:	/* Mapped to nonFIP mode */
333 		hba->flag &= ~FC_FIP_SUPPORTED;
334 		break;
335 
336 	case EMLXS_DCBX_MODE_CEE:	/* Mapped to FIP mode */
337 		hba->flag |= FC_FIP_SUPPORTED;
338 		break;
339 
340 	default:
341 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
342 		    "Invalid read rev dcbx mode for SLI4: 0x%x",
343 		    mb->un.varRdRev4.dcbxMode);
344 
345 		rval = EIO;
346 		goto failed1;
347 	}
348 
349 
350 	/* Save information as VPD data */
351 	vpd->rBit = 1;
352 
353 	vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId);
354 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16);
355 
356 	vpd->opFwRev = (mb->un.varRdRev4.ULPFwId);
357 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16);
358 
359 	vpd->postKernRev = (mb->un.varRdRev4.ARMFwId);
360 	bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16);
361 
362 	vpd->fcphHigh = mb->un.varRdRev4.fcphHigh;
363 	vpd->fcphLow = mb->un.varRdRev4.fcphLow;
364 	vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh;
365 	vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow;
366 
367 	/* Decode FW labels */
368 	emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0);
369 	emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0);
370 	emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0);
371 
372 	if (hba->model_info.chip == EMLXS_BE2_CHIP) {
373 		(void) strcpy(vpd->sli4FwLabel, "be2.ufi");
374 	} else if (hba->model_info.chip == EMLXS_BE3_CHIP) {
375 		(void) strcpy(vpd->sli4FwLabel, "be3.ufi");
376 	} else {
377 		(void) strcpy(vpd->sli4FwLabel, "sli4.fw");
378 	}
379 
380 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
381 	    "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
382 	    vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName,
383 	    vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow,
384 	    mb->un.varRdRev4.dcbxMode);
385 
386 	/* No key information is needed for SLI4 products */
387 
388 	/* Get adapter VPD information */
389 	vpd->port_index = (uint32_t)-1;
390 
391 	/* Reuse mbq from previous mbox */
392 	bzero(mbq, sizeof (MAILBOXQ));
393 
394 	emlxs_mb_dump_vpd(hba, mbq, 0);
395 	vpd_data = hba->sli.sli4.dump_region.virt;
396 
397 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
398 	    MBX_SUCCESS) {
399 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
400 		    "No VPD found. status=%x", mb->mbxStatus);
401 	} else {
402 		EMLXS_MSGF(EMLXS_CONTEXT,
403 		    &emlxs_init_debug_msg,
404 		    "VPD dumped. rsp_cnt=%d status=%x",
405 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
406 
407 		if (mb->un.varDmp4.rsp_cnt) {
408 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
409 			    0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL);
410 
411 #ifdef FMA_SUPPORT
412 			if (hba->sli.sli4.dump_region.dma_handle) {
413 				if (emlxs_fm_check_dma_handle(hba,
414 				    hba->sli.sli4.dump_region.dma_handle)
415 				    != DDI_FM_OK) {
416 					EMLXS_MSGF(EMLXS_CONTEXT,
417 					    &emlxs_invalid_dma_handle_msg,
418 					    "emlxs_sli4_online: hdl=%p",
419 					    hba->sli.sli4.dump_region.
420 					    dma_handle);
421 					rval = EIO;
422 					goto failed1;
423 				}
424 			}
425 #endif /* FMA_SUPPORT */
426 
427 		}
428 	}
429 
430 	if (vpd_data[0]) {
431 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data,
432 		    mb->un.varDmp4.rsp_cnt);
433 
434 		/*
435 		 * If there is a VPD part number, and it does not
436 		 * match the current default HBA model info,
437 		 * replace the default data with an entry that
438 		 * does match.
439 		 *
440 		 * After emlxs_parse_vpd model holds the VPD value
441 		 * for V2 and part_num hold the value for PN. These
442 		 * 2 values are NOT necessarily the same.
443 		 */
444 
445 		rval = 0;
446 		if ((vpd->model[0] != 0) &&
447 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
448 
449 			/* First scan for a V2 match */
450 
451 			for (i = 1; i < emlxs_pci_model_count; i++) {
452 				if (strcmp(&vpd->model[0],
453 				    emlxs_pci_model[i].model) == 0) {
454 					bcopy(&emlxs_pci_model[i],
455 					    &hba->model_info,
456 					    sizeof (emlxs_model_t));
457 					rval = 1;
458 					break;
459 				}
460 			}
461 		}
462 
463 		if (!rval && (vpd->part_num[0] != 0) &&
464 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
465 
466 			/* Next scan for a PN match */
467 
468 			for (i = 1; i < emlxs_pci_model_count; i++) {
469 				if (strcmp(&vpd->part_num[0],
470 				    emlxs_pci_model[i].model) == 0) {
471 					bcopy(&emlxs_pci_model[i],
472 					    &hba->model_info,
473 					    sizeof (emlxs_model_t));
474 					break;
475 				}
476 			}
477 		}
478 
479 		/* HP CNA port indices start at 1 instead of 0 */
480 		if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
481 		    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
482 
483 			ssvid = ddi_get16(hba->pci_acc_handle,
484 			    (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER));
485 
486 			if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) {
487 				vpd->port_index--;
488 			}
489 		}
490 
491 		/*
492 		 * Now lets update hba->model_info with the real
493 		 * VPD data, if any.
494 		 */
495 
496 		/*
497 		 * Replace the default model description with vpd data
498 		 */
499 		if (vpd->model_desc[0] != 0) {
500 			(void) strcpy(hba->model_info.model_desc,
501 			    vpd->model_desc);
502 		}
503 
504 		/* Replace the default model with vpd data */
505 		if (vpd->model[0] != 0) {
506 			(void) strcpy(hba->model_info.model, vpd->model);
507 		}
508 
509 		/* Replace the default program types with vpd data */
510 		if (vpd->prog_types[0] != 0) {
511 			emlxs_parse_prog_types(hba, vpd->prog_types);
512 		}
513 	}
514 
515 	/*
516 	 * Since the adapter model may have changed with the vpd data
517 	 * lets double check if adapter is not supported
518 	 */
519 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
520 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
521 		    "Unsupported adapter found.  "
522 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
523 		    hba->model_info.id, hba->model_info.device_id,
524 		    hba->model_info.ssdid, hba->model_info.model);
525 
526 		rval = EIO;
527 		goto failed1;
528 	}
529 
530 	(void) strcpy(vpd->boot_version, vpd->sli4FwName);
531 
532 	/* Get fcode version property */
533 	emlxs_get_fcode_version(hba);
534 
535 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
536 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
537 	    vpd->opFwRev, vpd->sli1FwRev);
538 
539 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
540 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
541 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
542 
543 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
544 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
545 
546 	/*
547 	 * If firmware checking is enabled and the adapter model indicates
548 	 * a firmware image, then perform firmware version check
549 	 */
550 	hba->fw_flag = 0;
551 	hba->fw_timer = 0;
552 
553 	if (((fw_check & 0x1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
554 	    hba->model_info.fwid) || ((fw_check & 0x2) &&
555 	    hba->model_info.fwid)) {
556 
557 		/* Find firmware image indicated by adapter model */
558 		fw = NULL;
559 		for (i = 0; i < emlxs_fw_count; i++) {
560 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
561 				fw = &emlxs_fw_table[i];
562 				break;
563 			}
564 		}
565 
566 		/*
567 		 * If the image was found, then verify current firmware
568 		 * versions of adapter
569 		 */
570 		if (fw) {
571 
572 			/* Obtain current firmware version info */
573 			if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
574 			    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
575 				(void) emlxs_sli4_read_fw_version(hba, &hba_fw);
576 			} else {
577 				hba_fw.kern = vpd->postKernRev;
578 				hba_fw.stub = vpd->opFwRev;
579 				hba_fw.sli1 = vpd->sli1FwRev;
580 				hba_fw.sli2 = vpd->sli2FwRev;
581 				hba_fw.sli3 = vpd->sli3FwRev;
582 				hba_fw.sli4 = vpd->sli4FwRev;
583 			}
584 
585 			if (!kern_update &&
586 			    ((fw->kern && (hba_fw.kern != fw->kern)) ||
587 			    (fw->stub && (hba_fw.stub != fw->stub)))) {
588 
589 				hba->fw_flag |= FW_UPDATE_NEEDED;
590 
591 			} else if ((fw->kern && (hba_fw.kern != fw->kern)) ||
592 			    (fw->stub && (hba_fw.stub != fw->stub)) ||
593 			    (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
594 			    (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
595 			    (fw->sli3 && (hba_fw.sli3 != fw->sli3)) ||
596 			    (fw->sli4 && (hba_fw.sli4 != fw->sli4))) {
597 
598 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
599 				    "Firmware update needed. "
600 				    "Updating. id=%d fw=%d",
601 				    hba->model_info.id, hba->model_info.fwid);
602 
603 #ifdef MODFW_SUPPORT
604 				/*
605 				 * Load the firmware image now
606 				 * If MODFW_SUPPORT is not defined, the
607 				 * firmware image will already be defined
608 				 * in the emlxs_fw_table
609 				 */
610 				emlxs_fw_load(hba, fw);
611 #endif /* MODFW_SUPPORT */
612 
613 				if (fw->image && fw->size) {
614 					if (emlxs_fw_download(hba,
615 					    (char *)fw->image, fw->size, 0)) {
616 						EMLXS_MSGF(EMLXS_CONTEXT,
617 						    &emlxs_init_msg,
618 						    "Firmware update failed.");
619 
620 						hba->fw_flag |=
621 						    FW_UPDATE_NEEDED;
622 					}
623 #ifdef MODFW_SUPPORT
624 					/*
625 					 * Unload the firmware image from
626 					 * kernel memory
627 					 */
628 					emlxs_fw_unload(hba, fw);
629 #endif /* MODFW_SUPPORT */
630 
631 					fw_check = 0;
632 
633 					goto reset;
634 				}
635 
636 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
637 				    "Firmware image unavailable.");
638 			} else {
639 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
640 				    "Firmware update not needed.");
641 			}
642 		} else {
643 			/*
644 			 * This means either the adapter database is not
645 			 * correct or a firmware image is missing from the
646 			 * compile
647 			 */
648 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
649 			    "Firmware image unavailable. id=%d fw=%d",
650 			    hba->model_info.id, hba->model_info.fwid);
651 		}
652 	}
653 
654 	/* Reuse mbq from previous mbox */
655 	bzero(mbq, sizeof (MAILBOXQ));
656 
657 	emlxs_mb_dump_fcoe(hba, mbq, 0);
658 
659 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
660 	    MBX_SUCCESS) {
661 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
662 		    "No FCOE info found. status=%x", mb->mbxStatus);
663 	} else {
664 		EMLXS_MSGF(EMLXS_CONTEXT,
665 		    &emlxs_init_debug_msg,
666 		    "FCOE info dumped. rsp_cnt=%d status=%x",
667 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
668 		(void) emlxs_parse_fcoe(hba,
669 		    (uint8_t *)hba->sli.sli4.dump_region.virt,
670 		    mb->un.varDmp4.rsp_cnt);
671 	}
672 
673 	/* Reuse mbq from previous mbox */
674 	bzero(mbq, sizeof (MAILBOXQ));
675 
676 	emlxs_mb_request_features(hba, mbq);
677 
678 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
679 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
680 		    "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
681 		    mb->mbxCommand, mb->mbxStatus);
682 
683 		rval = EIO;
684 		goto failed1;
685 	}
686 emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0);
687 
688 	/* Make sure we get the features we requested */
689 	if (mb->un.varReqFeatures.featuresRequested !=
690 	    mb->un.varReqFeatures.featuresEnabled) {
691 
692 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
693 		    "Unable to get REQUESTed_FEATURES. want:x%x  got:x%x",
694 		    mb->un.varReqFeatures.featuresRequested,
695 		    mb->un.varReqFeatures.featuresEnabled);
696 
697 		rval = EIO;
698 		goto failed1;
699 	}
700 
701 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) {
702 		hba->flag |= FC_NPIV_ENABLED;
703 	}
704 
705 	/* Check enable-npiv driver parameter for now */
706 	if (cfg[CFG_NPIV_ENABLE].current) {
707 		hba->flag |= FC_NPIV_ENABLED;
708 	}
709 
710 	/* Reuse mbq from previous mbox */
711 	bzero(mbq, sizeof (MAILBOXQ));
712 
713 	emlxs_mb_read_config(hba, mbq);
714 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
715 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
716 		    "Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
717 		    mb->mbxCommand, mb->mbxStatus);
718 
719 		rval = EIO;
720 		goto failed1;
721 	}
722 emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0);
723 
724 	hba->sli.sli4.XRICount = (mb->un.varRdConfig4.XRICount);
725 	hba->sli.sli4.XRIBase = (mb->un.varRdConfig4.XRIBase);
726 	hba->sli.sli4.RPICount = (mb->un.varRdConfig4.RPICount);
727 	hba->sli.sli4.RPIBase = (mb->un.varRdConfig4.RPIBase);
728 	hba->sli.sli4.VPICount = (mb->un.varRdConfig4.VPICount);
729 	hba->sli.sli4.VPIBase = (mb->un.varRdConfig4.VPIBase);
730 	hba->sli.sli4.VFICount = (mb->un.varRdConfig4.VFICount);
731 	hba->sli.sli4.VFIBase = (mb->un.varRdConfig4.VFIBase);
732 	hba->sli.sli4.FCFICount = (mb->un.varRdConfig4.FCFICount);
733 
734 	if (hba->sli.sli4.VPICount) {
735 		hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
736 	}
737 	hba->vpi_base = mb->un.varRdConfig4.VPIBase;
738 
739 	/* Set the max node count */
740 	if (cfg[CFG_NUM_NODES].current > 0) {
741 		hba->max_nodes =
742 		    min(cfg[CFG_NUM_NODES].current,
743 		    hba->sli.sli4.RPICount);
744 	} else {
745 		hba->max_nodes = hba->sli.sli4.RPICount;
746 	}
747 
748 	/* Set the io throttle */
749 	hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE;
750 	hba->max_iotag = hba->sli.sli4.XRICount;
751 
752 	/* Save the link speed capabilities */
753 	vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt;
754 	emlxs_process_link_speed(hba);
755 
756 	/*
757 	 * Allocate some memory for buffers
758 	 */
759 	if (emlxs_mem_alloc_buffer(hba) == 0) {
760 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
761 		    "Unable to allocate memory buffers.");
762 
763 		rval = ENOMEM;
764 		goto failed1;
765 	}
766 
767 	/*
768 	 * OutOfRange (oor) iotags are used for abort or close
769 	 * XRI commands or any WQE that does not require a SGL
770 	 */
771 	hba->fc_oor_iotag = hba->max_iotag;
772 
773 	if (emlxs_sli4_resource_alloc(hba)) {
774 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
775 		    "Unable to allocate resources.");
776 
777 		rval = ENOMEM;
778 		goto failed2;
779 	}
780 emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0);
781 
782 #if (EMLXS_MODREV >= EMLXS_MODREV5)
783 	if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) {
784 		hba->fca_tran->fca_num_npivports = hba->vpi_max;
785 	}
786 #endif /* >= EMLXS_MODREV5 */
787 
788 	/* Reuse mbq from previous mbox */
789 	bzero(mbq, sizeof (MAILBOXQ));
790 
791 	if (emlxs_sli4_post_sgl_pages(hba, mbq)) {
792 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
793 		    "Unable to post sgl pages.");
794 
795 		rval = EIO;
796 		goto failed3;
797 	}
798 
799 	/* Reuse mbq from previous mbox */
800 	bzero(mbq, sizeof (MAILBOXQ));
801 
802 	if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) {
803 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
804 		    "Unable to post header templates.");
805 
806 		rval = EIO;
807 		goto failed3;
808 	}
809 
810 	/*
811 	 * Add our interrupt routine to kernel's interrupt chain & enable it
812 	 * If MSI is enabled this will cause Solaris to program the MSI address
813 	 * and data registers in PCI config space
814 	 */
815 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
816 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
817 		    "Unable to add interrupt(s).");
818 
819 		rval = EIO;
820 		goto failed3;
821 	}
822 
823 	/* Reuse mbq from previous mbox */
824 	bzero(mbq, sizeof (MAILBOXQ));
825 
826 	/* This MUST be done after EMLXS_INTR_ADD */
827 	if (emlxs_sli4_create_queues(hba, mbq)) {
828 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
829 		    "Unable to create queues.");
830 
831 		rval = EIO;
832 		goto failed3;
833 	}
834 
835 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
836 
837 	/* Get and save the current firmware version (based on sli_mode) */
838 	emlxs_decode_firmware_rev(hba, vpd);
839 
840 
841 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
842 
843 	/* Reuse mbq from previous mbox */
844 	bzero(mbq, sizeof (MAILBOXQ));
845 
846 	/*
847 	 * We need to get login parameters for NID
848 	 */
849 	(void) emlxs_mb_read_sparam(hba, mbq);
850 	mp = (MATCHMAP *)mbq->bp;
851 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
852 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
853 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
854 		    mb->mbxCommand, mb->mbxStatus);
855 
856 		rval = EIO;
857 		goto failed3;
858 	}
859 
860 	/* Free the buffer since we were polling */
861 	emlxs_mem_put(hba, MEM_BUF, (void *)mp);
862 	mp = NULL;
863 
864 	/* If no serial number in VPD data, then use the WWPN */
865 	if (vpd->serial_num[0] == 0) {
866 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
867 		for (i = 0; i < 12; i++) {
868 			status = *outptr++;
869 			j = ((status & 0xf0) >> 4);
870 			if (j <= 9) {
871 				vpd->serial_num[i] =
872 				    (char)((uint8_t)'0' + (uint8_t)j);
873 			} else {
874 				vpd->serial_num[i] =
875 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
876 			}
877 
878 			i++;
879 			j = (status & 0xf);
880 			if (j <= 9) {
881 				vpd->serial_num[i] =
882 				    (char)((uint8_t)'0' + (uint8_t)j);
883 			} else {
884 				vpd->serial_num[i] =
885 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
886 			}
887 		}
888 
889 		/*
890 		 * Set port number and port index to zero
891 		 * The WWN's are unique to each port and therefore port_num
892 		 * must equal zero. This effects the hba_fru_details structure
893 		 * in fca_bind_port()
894 		 */
895 		vpd->port_num[0] = 0;
896 		vpd->port_index = 0;
897 	}
898 
899 	/* Make attempt to set a port index */
900 	if (vpd->port_index == (uint32_t)-1) {
901 		dev_info_t *p_dip;
902 		dev_info_t *c_dip;
903 
904 		p_dip = ddi_get_parent(hba->dip);
905 		c_dip = ddi_get_child(p_dip);
906 
907 		vpd->port_index = 0;
908 		while (c_dip && (hba->dip != c_dip)) {
909 			c_dip = ddi_get_next_sibling(c_dip);
910 
911 			if (strcmp(ddi_get_name(c_dip), "ethernet")) {
912 				vpd->port_index++;
913 			}
914 		}
915 	}
916 
917 	if (vpd->port_num[0] == 0) {
918 		if (hba->model_info.channels > 1) {
919 			(void) sprintf(vpd->port_num, "%d", vpd->port_index);
920 		}
921 	}
922 
923 	if (vpd->id[0] == 0) {
924 		(void) sprintf(vpd->id, "%s %d",
925 		    hba->model_info.model_desc, vpd->port_index);
926 
927 	}
928 
929 	if (vpd->manufacturer[0] == 0) {
930 		(void) strcpy(vpd->manufacturer, hba->model_info.manufacturer);
931 	}
932 
933 	if (vpd->part_num[0] == 0) {
934 		(void) strcpy(vpd->part_num, hba->model_info.model);
935 	}
936 
937 	if (vpd->model_desc[0] == 0) {
938 		(void) sprintf(vpd->model_desc, "%s %d",
939 		    hba->model_info.model_desc, vpd->port_index);
940 	}
941 
942 	if (vpd->model[0] == 0) {
943 		(void) strcpy(vpd->model, hba->model_info.model);
944 	}
945 
946 	if (vpd->prog_types[0] == 0) {
947 		emlxs_build_prog_types(hba, vpd->prog_types);
948 	}
949 
950 	/* Create the symbolic names */
951 	(void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s",
952 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
953 	    (char *)utsname.nodename);
954 
955 	(void) sprintf(hba->spn,
956 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
957 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
958 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
959 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
960 
961 
962 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
963 	emlxs_sli4_enable_intr(hba);
964 
965 	/* Reuse mbq from previous mbox */
966 	bzero(mbq, sizeof (MAILBOXQ));
967 
968 	/*
969 	 * Setup and issue mailbox INITIALIZE LINK command
970 	 * At this point, the interrupt will be generated by the HW
971 	 * Do this only if persist-linkdown is not set
972 	 */
973 	if (cfg[CFG_PERSIST_LINKDOWN].current == 0) {
974 		emlxs_mb_init_link(hba, mbq,
975 		    cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
976 
977 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0)
978 		    != MBX_SUCCESS) {
979 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
980 			    "Unable to initialize link. "
981 			    "Mailbox cmd=%x status=%x",
982 			    mb->mbxCommand, mb->mbxStatus);
983 
984 			rval = EIO;
985 			goto failed3;
986 		}
987 
988 		/* Wait for link to come up */
989 		i = cfg[CFG_LINKUP_DELAY].current;
990 		while (i && (hba->state < FC_LINK_UP)) {
991 			/* Check for hardware error */
992 			if (hba->state == FC_ERROR) {
993 				EMLXS_MSGF(EMLXS_CONTEXT,
994 				    &emlxs_init_failed_msg,
995 				    "Adapter error.", mb->mbxCommand,
996 				    mb->mbxStatus);
997 
998 				rval = EIO;
999 				goto failed3;
1000 			}
1001 
1002 			DELAYMS(1000);
1003 			i--;
1004 		}
1005 	} else {
1006 		EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1007 	}
1008 
1009 	/*
1010 	 * The leadvile driver will now handle the FLOGI at the driver level
1011 	 */
1012 
1013 	if (mbq) {
1014 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1015 		mbq = NULL;
1016 		mb = NULL;
1017 	}
1018 	return (0);
1019 
1020 failed3:
1021 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1022 
1023 	if (mp) {
1024 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1025 		mp = NULL;
1026 	}
1027 
1028 
1029 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
1030 		(void) EMLXS_INTR_REMOVE(hba);
1031 	}
1032 
1033 	emlxs_sli4_resource_free(hba);
1034 
1035 failed2:
1036 	(void) emlxs_mem_free_buffer(hba);
1037 
1038 failed1:
1039 	if (mbq) {
1040 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1041 		mbq = NULL;
1042 		mb = NULL;
1043 	}
1044 
1045 	if (hba->sli.sli4.dump_region.virt) {
1046 		(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1047 	}
1048 
1049 	if (rval == 0) {
1050 		rval = EIO;
1051 	}
1052 
1053 	return (rval);
1054 
1055 } /* emlxs_sli4_online() */
1056 
1057 
1058 static void
1059 emlxs_sli4_offline(emlxs_hba_t *hba)
1060 {
1061 	emlxs_port_t		*port = &PPORT;
1062 	MAILBOXQ mboxq;
1063 
1064 	/* Reverse emlxs_sli4_online */
1065 
1066 	mutex_enter(&EMLXS_PORT_LOCK);
1067 	if (!(hba->flag & FC_INTERLOCKED)) {
1068 		mutex_exit(&EMLXS_PORT_LOCK);
1069 
1070 		/* This is the only way to disable interupts */
1071 		bzero((void *)&mboxq, sizeof (MAILBOXQ));
1072 		emlxs_mb_resetport(hba, &mboxq);
1073 		if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
1074 		    MBX_WAIT, 0) != MBX_SUCCESS) {
1075 			/* Timeout occurred */
1076 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1077 			    "Timeout: Offline RESET");
1078 		}
1079 		(void) emlxs_check_hdw_ready(hba);
1080 	} else {
1081 		mutex_exit(&EMLXS_PORT_LOCK);
1082 	}
1083 
1084 	/* Shutdown the adapter interface */
1085 	emlxs_sli4_hba_kill(hba);
1086 
1087 	/* Free SLI shared memory */
1088 	emlxs_sli4_resource_free(hba);
1089 
1090 	/* Free driver shared memory */
1091 	(void) emlxs_mem_free_buffer(hba);
1092 
1093 	/* Free the host dump region buffer */
1094 	(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1095 
1096 } /* emlxs_sli4_offline() */
1097 
1098 
1099 /*ARGSUSED*/
1100 static int
1101 emlxs_sli4_map_hdw(emlxs_hba_t *hba)
1102 {
1103 	emlxs_port_t		*port = &PPORT;
1104 	dev_info_t		*dip;
1105 	ddi_device_acc_attr_t	dev_attr;
1106 	int			status;
1107 
1108 	dip = (dev_info_t *)hba->dip;
1109 	dev_attr = emlxs_dev_acc_attr;
1110 
1111 	/*
1112 	 * Map in Hardware BAR pages that will be used for
1113 	 * communication with HBA.
1114 	 */
1115 	if (hba->sli.sli4.bar1_acc_handle == 0) {
1116 		status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX,
1117 		    (caddr_t *)&hba->sli.sli4.bar1_addr,
1118 		    0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle);
1119 		if (status != DDI_SUCCESS) {
1120 			EMLXS_MSGF(EMLXS_CONTEXT,
1121 			    &emlxs_attach_failed_msg,
1122 			    "(PCI) ddi_regs_map_setup BAR1 failed. "
1123 			    "stat=%d mem=%p attr=%p hdl=%p",
1124 			    status, &hba->sli.sli4.bar1_addr, &dev_attr,
1125 			    &hba->sli.sli4.bar1_acc_handle);
1126 			goto failed;
1127 		}
1128 	}
1129 
1130 	if (hba->sli.sli4.bar2_acc_handle == 0) {
1131 		status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX,
1132 		    (caddr_t *)&hba->sli.sli4.bar2_addr,
1133 		    0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle);
1134 		if (status != DDI_SUCCESS) {
1135 			EMLXS_MSGF(EMLXS_CONTEXT,
1136 			    &emlxs_attach_failed_msg,
1137 			    "ddi_regs_map_setup BAR2 failed. status=%x",
1138 			    status);
1139 			goto failed;
1140 		}
1141 	}
1142 
1143 	if (hba->sli.sli4.bootstrapmb.virt == 0) {
1144 		MBUF_INFO	*buf_info;
1145 		MBUF_INFO	bufinfo;
1146 
1147 		buf_info = &bufinfo;
1148 
1149 		bzero(buf_info, sizeof (MBUF_INFO));
1150 		buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE;
1151 		buf_info->flags =
1152 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1153 		buf_info->align = ddi_ptob(dip, 1L);
1154 
1155 		(void) emlxs_mem_alloc(hba, buf_info);
1156 
1157 		if (buf_info->virt == NULL) {
1158 			goto failed;
1159 		}
1160 
1161 		hba->sli.sli4.bootstrapmb.virt = buf_info->virt;
1162 		hba->sli.sli4.bootstrapmb.phys = buf_info->phys;
1163 		hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE +
1164 		    MBOX_EXTENSION_SIZE;
1165 		hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle;
1166 		hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle;
1167 		bzero((char *)hba->sli.sli4.bootstrapmb.virt,
1168 		    EMLXS_BOOTSTRAP_MB_SIZE);
1169 	}
1170 
1171 	/* offset from beginning of register space */
1172 	hba->sli.sli4.MPUEPSemaphore_reg_addr =
1173 	    (uint32_t *)(hba->sli.sli4.bar1_addr + CSR_MPU_EP_SEMAPHORE_OFFSET);
1174 	hba->sli.sli4.MBDB_reg_addr =
1175 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET);
1176 	hba->sli.sli4.CQDB_reg_addr =
1177 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET);
1178 	hba->sli.sli4.MQDB_reg_addr =
1179 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET);
1180 	hba->sli.sli4.WQDB_reg_addr =
1181 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET);
1182 	hba->sli.sli4.RQDB_reg_addr =
1183 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET);
1184 	hba->chan_count = MAX_CHANNEL;
1185 
1186 	return (0);
1187 
1188 failed:
1189 
1190 	emlxs_sli4_unmap_hdw(hba);
1191 	return (ENOMEM);
1192 
1193 
1194 } /* emlxs_sli4_map_hdw() */
1195 
1196 
1197 /*ARGSUSED*/
1198 static void
1199 emlxs_sli4_unmap_hdw(emlxs_hba_t *hba)
1200 {
1201 	MBUF_INFO	bufinfo;
1202 	MBUF_INFO	*buf_info = &bufinfo;
1203 
1204 	/*
1205 	 * Free map for Hardware BAR pages that were used for
1206 	 * communication with HBA.
1207 	 */
1208 	if (hba->sli.sli4.bar1_acc_handle) {
1209 		ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle);
1210 		hba->sli.sli4.bar1_acc_handle = 0;
1211 	}
1212 
1213 	if (hba->sli.sli4.bar2_acc_handle) {
1214 		ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle);
1215 		hba->sli.sli4.bar2_acc_handle = 0;
1216 	}
1217 	if (hba->sli.sli4.bootstrapmb.virt) {
1218 		bzero(buf_info, sizeof (MBUF_INFO));
1219 
1220 		if (hba->sli.sli4.bootstrapmb.phys) {
1221 			buf_info->phys = hba->sli.sli4.bootstrapmb.phys;
1222 			buf_info->data_handle =
1223 			    hba->sli.sli4.bootstrapmb.data_handle;
1224 			buf_info->dma_handle =
1225 			    hba->sli.sli4.bootstrapmb.dma_handle;
1226 			buf_info->flags = FC_MBUF_DMA;
1227 		}
1228 
1229 		buf_info->virt = hba->sli.sli4.bootstrapmb.virt;
1230 		buf_info->size = hba->sli.sli4.bootstrapmb.size;
1231 		emlxs_mem_free(hba, buf_info);
1232 
1233 		hba->sli.sli4.bootstrapmb.virt = NULL;
1234 	}
1235 
1236 	return;
1237 
1238 } /* emlxs_sli4_unmap_hdw() */
1239 
1240 
1241 static int
1242 emlxs_check_hdw_ready(emlxs_hba_t *hba)
1243 {
1244 	emlxs_port_t *port = &PPORT;
1245 	uint32_t status;
1246 	uint32_t i = 0;
1247 
1248 	/* Wait for reset completion */
1249 	while (i < 30) {
1250 		/* Check Semaphore register to see what the ARM state is */
1251 		status = READ_BAR1_REG(hba, FC_SEMA_REG(hba));
1252 
1253 		/* Check to see if any errors occurred during init */
1254 		if (status & ARM_POST_FATAL) {
1255 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1256 			    "SEMA Error: status=0x%x", status);
1257 
1258 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1259 #ifdef FMA_SUPPORT
1260 			/* Access handle validation */
1261 			EMLXS_CHK_ACC_HANDLE(hba,
1262 			    hba->sli.sli4.bar1_acc_handle);
1263 #endif  /* FMA_SUPPORT */
1264 			return (1);
1265 		}
1266 		if ((status & ARM_POST_MASK) == ARM_POST_READY) {
1267 			/* ARM Ready !! */
1268 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
1269 			    "ARM Ready: status=0x%x", status);
1270 #ifdef FMA_SUPPORT
1271 			/* Access handle validation */
1272 			EMLXS_CHK_ACC_HANDLE(hba,
1273 			    hba->sli.sli4.bar1_acc_handle);
1274 #endif  /* FMA_SUPPORT */
1275 			return (0);
1276 		}
1277 
1278 		DELAYMS(1000);
1279 		i++;
1280 	}
1281 
1282 	/* Timeout occurred */
1283 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1284 	    "Timeout waiting for READY: status=0x%x", status);
1285 
1286 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1287 
1288 #ifdef FMA_SUPPORT
1289 	/* Access handle validation */
1290 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle);
1291 #endif  /* FMA_SUPPORT */
1292 
1293 	/* Log a dump event - not supported */
1294 
1295 	return (2);
1296 
1297 } /* emlxs_check_hdw_ready() */
1298 
1299 
1300 static uint32_t
1301 emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo)
1302 {
1303 	emlxs_port_t *port = &PPORT;
1304 	uint32_t status;
1305 
1306 	/* Wait for reset completion, tmo is in 10ms ticks */
1307 	while (tmo) {
1308 		/* Check Semaphore register to see what the ARM state is */
1309 		status = READ_BAR2_REG(hba, FC_MBDB_REG(hba));
1310 
1311 		/* Check to see if any errors occurred during init */
1312 		if (status & BMBX_READY) {
1313 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
1314 			    "BMBX Ready: status=0x%x", status);
1315 #ifdef FMA_SUPPORT
1316 			/* Access handle validation */
1317 			EMLXS_CHK_ACC_HANDLE(hba,
1318 			    hba->sli.sli4.bar2_acc_handle);
1319 #endif  /* FMA_SUPPORT */
1320 			return (tmo);
1321 		}
1322 
1323 		DELAYMS(10);
1324 		tmo--;
1325 	}
1326 
1327 	/* Timeout occurred */
1328 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1329 	    "Timeout waiting for BMailbox: status=0x%x", status);
1330 
1331 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1332 
1333 #ifdef FMA_SUPPORT
1334 	/* Access handle validation */
1335 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle);
1336 #endif  /* FMA_SUPPORT */
1337 
1338 	/* Log a dump event - not supported */
1339 
1340 	return (0);
1341 
1342 } /* emlxs_check_bootstrap_ready() */
1343 
1344 
1345 static uint32_t
1346 emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo)
1347 {
1348 	emlxs_port_t *port = &PPORT;
1349 	uint32_t *iptr;
1350 	uint32_t addr30;
1351 
1352 	/*
1353 	 * This routine assumes the bootstrap mbox is loaded
1354 	 * with the mailbox command to be executed.
1355 	 *
1356 	 * First, load the high 30 bits of bootstrap mailbox
1357 	 */
1358 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>32) & 0xfffffffc);
1359 	addr30 |= BMBX_ADDR_HI;
1360 	WRITE_BAR2_REG(hba, FC_MBDB_REG(hba), addr30);
1361 
1362 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
1363 	if (tmo == 0) {
1364 		return (0);
1365 	}
1366 
1367 	/* Load the low 30 bits of bootstrap mailbox */
1368 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>2) & 0xfffffffc);
1369 	WRITE_BAR2_REG(hba, FC_MBDB_REG(hba), addr30);
1370 
1371 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
1372 	if (tmo == 0) {
1373 		return (0);
1374 	}
1375 
1376 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
1377 
1378 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
1379 	    "BootstrapMB: %p Completed %08x %08x %08x",
1380 	    hba->sli.sli4.bootstrapmb.virt,
1381 	    *iptr, *(iptr+1), *(iptr+2));
1382 
1383 	return (tmo);
1384 
1385 } /* emlxs_issue_bootstrap_mb() */
1386 
1387 
1388 static int
1389 emlxs_init_bootstrap_mb(emlxs_hba_t *hba)
1390 {
1391 #ifdef FMA_SUPPORT
1392 	emlxs_port_t *port = &PPORT;
1393 #endif /* FMA_SUPPORT */
1394 	uint32_t *iptr;
1395 	uint32_t tmo;
1396 
1397 	if (emlxs_check_hdw_ready(hba)) {
1398 		return (1);
1399 	}
1400 
1401 	if (hba->flag & FC_BOOTSTRAPMB_INIT) {
1402 		return (0);  /* Already initialized */
1403 	}
1404 
1405 	/* NOTE: tmo is in 10ms ticks */
1406 	tmo = emlxs_check_bootstrap_ready(hba, 3000);
1407 	if (tmo == 0) {
1408 		return (1);
1409 	}
1410 
1411 	/* Special words to initialize bootstrap mbox MUST be little endian */
1412 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
1413 	*iptr++ = LE_SWAP32(MQE_SPECIAL_WORD0);
1414 	*iptr = LE_SWAP32(MQE_SPECIAL_WORD1);
1415 
1416 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
1417 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
1418 
1419 emlxs_data_dump(port, "EndianIN", (uint32_t *)iptr, 6, 0);
1420 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
1421 		return (1);
1422 	}
1423 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
1424 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
1425 emlxs_data_dump(port, "EndianOUT", (uint32_t *)iptr, 6, 0);
1426 
1427 #ifdef FMA_SUPPORT
1428 	if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle)
1429 	    != DDI_FM_OK) {
1430 		EMLXS_MSGF(EMLXS_CONTEXT,
1431 		    &emlxs_invalid_dma_handle_msg,
1432 		    "emlxs_init_bootstrap_mb: hdl=%p",
1433 		    hba->sli.sli4.bootstrapmb.dma_handle);
1434 		return (1);
1435 	}
1436 #endif
1437 	hba->flag |= FC_BOOTSTRAPMB_INIT;
1438 	return (0);
1439 
1440 } /* emlxs_init_bootstrap_mb() */
1441 
1442 
1443 static uint32_t
1444 emlxs_sli4_hba_init(emlxs_hba_t *hba)
1445 {
1446 	int rc;
1447 	uint16_t i;
1448 	emlxs_port_t *vport;
1449 	emlxs_config_t *cfg = &CFG;
1450 	CHANNEL *cp;
1451 
1452 	/* Restart the adapter */
1453 	if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) {
1454 		return (1);
1455 	}
1456 
1457 	for (i = 0; i < hba->chan_count; i++) {
1458 		cp = &hba->chan[i];
1459 		cp->iopath = (void *)&hba->sli.sli4.wq[i];
1460 	}
1461 
1462 	/* Initialize all the port objects */
1463 	hba->vpi_base = 0;
1464 	hba->vpi_max  = 0;
1465 	for (i = 0; i < MAX_VPORTS; i++) {
1466 		vport = &VPORT(i);
1467 		vport->hba = hba;
1468 		vport->vpi = i;
1469 
1470 		vport->VPIobj.index = i;
1471 		vport->VPIobj.VPI = i;
1472 		vport->VPIobj.port = vport;
1473 	}
1474 
1475 	/* Set the max node count */
1476 	if (hba->max_nodes == 0) {
1477 		if (cfg[CFG_NUM_NODES].current > 0) {
1478 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
1479 		} else {
1480 			hba->max_nodes = 4096;
1481 		}
1482 	}
1483 
1484 	rc = emlxs_init_bootstrap_mb(hba);
1485 	if (rc) {
1486 		return (rc);
1487 	}
1488 
1489 	hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0;
1490 	hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1;
1491 	hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2;
1492 
1493 	/* Cache the UE MASK registers value for UE error detection */
1494 	hba->sli.sli4.ue_mask_lo = ddi_get32(hba->pci_acc_handle,
1495 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_LO_OFFSET));
1496 	hba->sli.sli4.ue_mask_hi = ddi_get32(hba->pci_acc_handle,
1497 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_HI_OFFSET));
1498 
1499 	return (0);
1500 
1501 } /* emlxs_sli4_hba_init() */
1502 
1503 
1504 /*ARGSUSED*/
1505 static uint32_t
1506 emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
1507 		uint32_t quiesce)
1508 {
1509 	emlxs_port_t *port = &PPORT;
1510 	emlxs_port_t *vport;
1511 	CHANNEL *cp;
1512 	emlxs_config_t *cfg = &CFG;
1513 	MAILBOXQ mboxq;
1514 	uint32_t i;
1515 	uint32_t rc;
1516 	uint16_t channelno;
1517 
1518 	if (!cfg[CFG_RESET_ENABLE].current) {
1519 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1520 		    "Adapter reset disabled.");
1521 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
1522 
1523 		return (1);
1524 	}
1525 
1526 	if (quiesce == 0) {
1527 		emlxs_sli4_hba_kill(hba);
1528 
1529 		/*
1530 		 * Initalize Hardware that will be used to bring
1531 		 * SLI4 online.
1532 		 */
1533 		rc = emlxs_init_bootstrap_mb(hba);
1534 		if (rc) {
1535 			return (rc);
1536 		}
1537 	}
1538 
1539 	bzero((void *)&mboxq, sizeof (MAILBOXQ));
1540 	emlxs_mb_resetport(hba, &mboxq);
1541 
1542 	if (quiesce == 0) {
1543 		if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
1544 		    MBX_POLL, 0) != MBX_SUCCESS) {
1545 			/* Timeout occurred */
1546 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1547 			    "Timeout: RESET");
1548 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1549 			/* Log a dump event - not supported */
1550 			return (1);
1551 		}
1552 	} else {
1553 		if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq,
1554 		    MBX_POLL, 0) != MBX_SUCCESS) {
1555 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1556 			/* Log a dump event - not supported */
1557 			return (1);
1558 		}
1559 	}
1560 emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0);
1561 
1562 	/* Reset the hba structure */
1563 	hba->flag &= FC_RESET_MASK;
1564 
1565 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
1566 		cp = &hba->chan[channelno];
1567 		cp->hba = hba;
1568 		cp->channelno = channelno;
1569 	}
1570 
1571 	hba->channel_tx_count = 0;
1572 	hba->io_count = 0;
1573 	hba->iodone_count = 0;
1574 	hba->topology = 0;
1575 	hba->linkspeed = 0;
1576 	hba->heartbeat_active = 0;
1577 	hba->discovery_timer = 0;
1578 	hba->linkup_timer = 0;
1579 	hba->loopback_tics = 0;
1580 
1581 	/* Reset the port objects */
1582 	for (i = 0; i < MAX_VPORTS; i++) {
1583 		vport = &VPORT(i);
1584 
1585 		vport->flag &= EMLXS_PORT_RESET_MASK;
1586 		vport->did = 0;
1587 		vport->prev_did = 0;
1588 		vport->lip_type = 0;
1589 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
1590 		bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
1591 
1592 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
1593 		vport->node_base.nlp_Rpi = 0;
1594 		vport->node_base.nlp_DID = 0xffffff;
1595 		vport->node_base.nlp_list_next = NULL;
1596 		vport->node_base.nlp_list_prev = NULL;
1597 		vport->node_base.nlp_active = 1;
1598 		vport->node_count = 0;
1599 
1600 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
1601 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
1602 		}
1603 	}
1604 
1605 	if (emlxs_check_hdw_ready(hba)) {
1606 		return (1);
1607 	}
1608 
1609 	return (0);
1610 
1611 } /* emlxs_sli4_hba_reset */
1612 
1613 
1614 #define	SGL_CMD		0
1615 #define	SGL_RESP	1
1616 #define	SGL_DATA	2
1617 #define	SGL_LAST	0x80
1618 
1619 /*ARGSUSED*/
1620 ULP_SGE64 *
1621 emlxs_pkt_to_sgl(emlxs_port_t *port, ULP_SGE64 *sge, fc_packet_t *pkt,
1622     uint32_t sgl_type, uint32_t *pcnt)
1623 {
1624 #ifdef DEBUG_SGE
1625 	emlxs_hba_t *hba = HBA;
1626 #endif
1627 	ddi_dma_cookie_t *cp;
1628 	uint_t i;
1629 	uint_t last;
1630 	int32_t	size;
1631 	int32_t	sge_size;
1632 	uint64_t sge_addr;
1633 	int32_t	len;
1634 	uint32_t cnt;
1635 	uint_t cookie_cnt;
1636 	ULP_SGE64 stage_sge;
1637 
1638 	last = sgl_type & SGL_LAST;
1639 	sgl_type &= ~SGL_LAST;
1640 
1641 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1642 	switch (sgl_type) {
1643 	case SGL_CMD:
1644 		cp = pkt->pkt_cmd_cookie;
1645 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
1646 		size = (int32_t)pkt->pkt_cmdlen;
1647 		break;
1648 
1649 	case SGL_RESP:
1650 		cp = pkt->pkt_resp_cookie;
1651 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
1652 		size = (int32_t)pkt->pkt_rsplen;
1653 		break;
1654 
1655 
1656 	case SGL_DATA:
1657 		cp = pkt->pkt_data_cookie;
1658 		cookie_cnt = pkt->pkt_data_cookie_cnt;
1659 		size = (int32_t)pkt->pkt_datalen;
1660 		break;
1661 	}
1662 
1663 #else
1664 	switch (sgl_type) {
1665 	case SGL_CMD:
1666 		cp = &pkt->pkt_cmd_cookie;
1667 		cookie_cnt = 1;
1668 		size = (int32_t)pkt->pkt_cmdlen;
1669 		break;
1670 
1671 	case SGL_RESP:
1672 		cp = &pkt->pkt_resp_cookie;
1673 		cookie_cnt = 1;
1674 		size = (int32_t)pkt->pkt_rsplen;
1675 		break;
1676 
1677 
1678 	case SGL_DATA:
1679 		cp = &pkt->pkt_data_cookie;
1680 		cookie_cnt = 1;
1681 		size = (int32_t)pkt->pkt_datalen;
1682 		break;
1683 	}
1684 #endif	/* >= EMLXS_MODREV3 */
1685 
1686 	stage_sge.offset = 0;
1687 	stage_sge.reserved = 0;
1688 	stage_sge.last = 0;
1689 	cnt = 0;
1690 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
1691 
1692 		sge_size = cp->dmac_size;
1693 		sge_addr = cp->dmac_laddress;
1694 		while (sge_size && size) {
1695 			if (cnt) {
1696 				/* Copy staged SGE before we build next one */
1697 				BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
1698 				    (uint8_t *)sge, sizeof (ULP_SGE64));
1699 				sge++;
1700 			}
1701 			len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
1702 			len = MIN(size, len);
1703 
1704 			stage_sge.addrHigh =
1705 			    PADDR_HI(sge_addr);
1706 			stage_sge.addrLow =
1707 			    PADDR_LO(sge_addr);
1708 			stage_sge.length = len;
1709 			if (sgl_type == SGL_DATA) {
1710 				stage_sge.offset = cnt;
1711 			}
1712 #ifdef DEBUG_SGE
1713 			emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge,
1714 			    4, 0);
1715 #endif
1716 			sge_addr += len;
1717 			sge_size -= len;
1718 
1719 			cnt += len;
1720 			size -= len;
1721 		}
1722 	}
1723 
1724 	if (last) {
1725 		stage_sge.last = 1;
1726 	}
1727 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
1728 	    sizeof (ULP_SGE64));
1729 
1730 	sge++;
1731 
1732 	*pcnt = cnt;
1733 	return (sge);
1734 
1735 } /* emlxs_pkt_to_sgl */
1736 
1737 
1738 /*ARGSUSED*/
1739 uint32_t
1740 emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
1741 {
1742 	fc_packet_t *pkt;
1743 	XRIobj_t *xrip;
1744 	ULP_SGE64 *sge;
1745 	emlxs_wqe_t *wqe;
1746 	IOCBQ *iocbq;
1747 	ddi_dma_cookie_t *cp_cmd;
1748 	uint32_t cmd_cnt;
1749 	uint32_t resp_cnt;
1750 	uint32_t cnt;
1751 
1752 	iocbq = (IOCBQ *) &sbp->iocbq;
1753 	wqe = &iocbq->wqe;
1754 	pkt = PRIV2PKT(sbp);
1755 	xrip = sbp->xrip;
1756 	sge = xrip->SGList.virt;
1757 
1758 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1759 	cp_cmd = pkt->pkt_cmd_cookie;
1760 #else
1761 	cp_cmd  = &pkt->pkt_cmd_cookie;
1762 #endif	/* >= EMLXS_MODREV3 */
1763 
1764 	iocbq = &sbp->iocbq;
1765 	if (iocbq->flag & IOCB_FCP_CMD) {
1766 
1767 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
1768 			return (1);
1769 		}
1770 
1771 		/* CMD payload */
1772 		sge = emlxs_pkt_to_sgl(port, sge, pkt, SGL_CMD, &cmd_cnt);
1773 
1774 		/* DATA payload */
1775 		if (pkt->pkt_datalen != 0) {
1776 			/* RSP payload */
1777 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1778 			    SGL_RESP, &resp_cnt);
1779 
1780 			/* Data portion */
1781 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1782 			    SGL_DATA | SGL_LAST, &cnt);
1783 		} else {
1784 			/* RSP payload */
1785 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1786 			    SGL_RESP | SGL_LAST, &resp_cnt);
1787 		}
1788 
1789 		wqe->un.FcpCmd.Payload.addrHigh =
1790 		    PADDR_HI(cp_cmd->dmac_laddress);
1791 		wqe->un.FcpCmd.Payload.addrLow =
1792 		    PADDR_LO(cp_cmd->dmac_laddress);
1793 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt;
1794 		wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt;
1795 
1796 	} else {
1797 
1798 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
1799 			/* CMD payload */
1800 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1801 			    SGL_CMD | SGL_LAST, &cmd_cnt);
1802 		} else {
1803 			/* CMD payload */
1804 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1805 			    SGL_CMD, &cmd_cnt);
1806 
1807 			/* RSP payload */
1808 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1809 			    SGL_RESP | SGL_LAST, &resp_cnt);
1810 			wqe->un.GenReq.PayloadLength = cmd_cnt;
1811 		}
1812 
1813 		wqe->un.GenReq.Payload.addrHigh =
1814 		    PADDR_HI(cp_cmd->dmac_laddress);
1815 		wqe->un.GenReq.Payload.addrLow =
1816 		    PADDR_LO(cp_cmd->dmac_laddress);
1817 		wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt;
1818 	}
1819 	return (0);
1820 } /* emlxs_sli4_bde_setup */
1821 
1822 
1823 
1824 
1825 static void
1826 emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
1827 {
1828 	emlxs_port_t *port = &PPORT;
1829 	emlxs_buf_t *sbp;
1830 	uint32_t channelno;
1831 	int32_t throttle;
1832 	emlxs_wqe_t *wqe;
1833 	emlxs_wqe_t *wqeslot;
1834 	WQ_DESC_t *wq;
1835 	uint32_t flag;
1836 	uint32_t wqdb;
1837 	uint16_t next_wqe;
1838 	off_t offset;
1839 
1840 
1841 	channelno = cp->channelno;
1842 	wq = (WQ_DESC_t *)cp->iopath;
1843 
1844 #ifdef SLI4_FASTPATH_DEBUG
1845 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
1846 	    "ISSUE WQE channel: %x  %p", channelno, wq);
1847 #endif
1848 
1849 	throttle = 0;
1850 
1851 	/* Check if FCP ring and adapter is not ready */
1852 	/* We may use any ring for FCP_CMD */
1853 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
1854 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
1855 		    !(((emlxs_port_t *)iocbq->port)->tgt_mode)) {
1856 			emlxs_tx_put(iocbq, 1);
1857 			return;
1858 		}
1859 	}
1860 
1861 	/* Attempt to acquire CMD_RING lock */
1862 	if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) {
1863 		/* Queue it for later */
1864 		if (iocbq) {
1865 			if ((hba->io_count -
1866 			    hba->channel_tx_count) > 10) {
1867 				emlxs_tx_put(iocbq, 1);
1868 				return;
1869 			} else {
1870 
1871 				mutex_enter(&EMLXS_QUE_LOCK(channelno));
1872 			}
1873 		} else {
1874 			return;
1875 		}
1876 	}
1877 	/* EMLXS_QUE_LOCK acquired */
1878 
1879 	/* Throttle check only applies to non special iocb */
1880 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
1881 		/* Check if HBA is full */
1882 		throttle = hba->io_throttle - hba->io_active;
1883 		if (throttle <= 0) {
1884 			/* Hitting adapter throttle limit */
1885 			/* Queue it for later */
1886 			if (iocbq) {
1887 				emlxs_tx_put(iocbq, 1);
1888 			}
1889 
1890 			goto busy;
1891 		}
1892 	}
1893 
1894 	/* Check to see if we have room for this WQE */
1895 	next_wqe = wq->host_index + 1;
1896 	if (next_wqe >= wq->max_index) {
1897 		next_wqe = 0;
1898 	}
1899 
1900 	if (next_wqe == wq->port_index) {
1901 		/* Queue it for later */
1902 		if (iocbq) {
1903 			emlxs_tx_put(iocbq, 1);
1904 		}
1905 		goto busy;
1906 	}
1907 
1908 	/*
1909 	 * We have a command ring slot available
1910 	 * Make sure we have an iocb to send
1911 	 */
1912 	if (iocbq) {
1913 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
1914 
1915 		/* Check if the ring already has iocb's waiting */
1916 		if (cp->nodeq.q_first != NULL) {
1917 			/* Put the current iocbq on the tx queue */
1918 			emlxs_tx_put(iocbq, 0);
1919 
1920 			/*
1921 			 * Attempt to replace it with the next iocbq
1922 			 * in the tx queue
1923 			 */
1924 			iocbq = emlxs_tx_get(cp, 0);
1925 		}
1926 
1927 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
1928 	} else {
1929 		iocbq = emlxs_tx_get(cp, 1);
1930 	}
1931 
1932 sendit:
1933 	/* Process each iocbq */
1934 	while (iocbq) {
1935 
1936 		wqe = &iocbq->wqe;
1937 #ifdef SLI4_FASTPATH_DEBUG
1938 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
1939 		    "ISSUE QID %d WQE iotag: %x xri: %x", wq->qid,
1940 		    wqe->RequestTag, wqe->XRITag);
1941 #endif
1942 
1943 		sbp = iocbq->sbp;
1944 		if (sbp) {
1945 			/* If exchange removed after wqe was prep'ed, drop it */
1946 			if (!(sbp->xrip)) {
1947 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
1948 				    "Xmit WQE iotag: %x xri: %x aborted",
1949 				    wqe->RequestTag, wqe->XRITag);
1950 
1951 				/* Get next iocb from the tx queue */
1952 				iocbq = emlxs_tx_get(cp, 1);
1953 				continue;
1954 			}
1955 
1956 			if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) {
1957 
1958 				/* Perform delay */
1959 				if ((channelno == hba->channel_els) &&
1960 				    !(iocbq->flag & IOCB_FCP_CMD)) {
1961 					drv_usecwait(100000);
1962 				} else {
1963 					drv_usecwait(20000);
1964 				}
1965 			}
1966 		}
1967 
1968 		/*
1969 		 * At this point, we have a command ring slot available
1970 		 * and an iocb to send
1971 		 */
1972 		wq->release_depth--;
1973 		if (wq->release_depth == 0) {
1974 			wq->release_depth = WQE_RELEASE_DEPTH;
1975 			wqe->WQEC = 1;
1976 		}
1977 
1978 
1979 		HBASTATS.IocbIssued[channelno]++;
1980 
1981 		/* Check for ULP pkt request */
1982 		if (sbp) {
1983 			mutex_enter(&sbp->mtx);
1984 
1985 			if (sbp->node == NULL) {
1986 				/* Set node to base node by default */
1987 				iocbq->node = (void *)&port->node_base;
1988 				sbp->node = (void *)&port->node_base;
1989 			}
1990 
1991 			sbp->pkt_flags |= PACKET_IN_CHIPQ;
1992 			mutex_exit(&sbp->mtx);
1993 
1994 			atomic_add_32(&hba->io_active, 1);
1995 			sbp->xrip->flag |= EMLXS_XRI_PENDING_IO;
1996 		}
1997 
1998 
1999 		/* Free the local iocb if there is no sbp tracking it */
2000 		if (sbp) {
2001 #ifdef SFCT_SUPPORT
2002 #ifdef FCT_IO_TRACE
2003 			if (sbp->fct_cmd) {
2004 				emlxs_fct_io_trace(port, sbp->fct_cmd,
2005 				    EMLXS_FCT_IOCB_ISSUED);
2006 				emlxs_fct_io_trace(port, sbp->fct_cmd,
2007 				    icmd->ULPCOMMAND);
2008 			}
2009 #endif /* FCT_IO_TRACE */
2010 #endif /* SFCT_SUPPORT */
2011 			cp->hbaSendCmd_sbp++;
2012 			iocbq->channel = cp;
2013 		} else {
2014 			cp->hbaSendCmd++;
2015 		}
2016 
2017 		flag = iocbq->flag;
2018 
2019 		/* Send the iocb */
2020 		wqeslot = (emlxs_wqe_t *)wq->addr.virt;
2021 		wqeslot += wq->host_index;
2022 
2023 		wqe->CQId = wq->cqid;
2024 		BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot,
2025 		    sizeof (emlxs_wqe_t));
2026 #ifdef DEBUG_WQE
2027 		emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0);
2028 #endif
2029 		offset = (off_t)((uint64_t)((unsigned long)
2030 		    wq->addr.virt) -
2031 		    (uint64_t)((unsigned long)
2032 		    hba->sli.sli4.slim2.virt));
2033 
2034 		EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset,
2035 		    4096, DDI_DMA_SYNC_FORDEV);
2036 
2037 		/* Ring the WQ Doorbell */
2038 		wqdb = wq->qid;
2039 		wqdb |= ((1 << 24) | (wq->host_index << 16));
2040 
2041 
2042 		WRITE_BAR2_REG(hba, FC_WQDB_REG(hba), wqdb);
2043 		wq->host_index = next_wqe;
2044 
2045 #ifdef SLI4_FASTPATH_DEBUG
2046 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2047 		    "WQ RING: %08x", wqdb);
2048 #endif
2049 
2050 		/*
2051 		 * After this, the sbp / iocb / wqe should not be
2052 		 * accessed in the xmit path.
2053 		 */
2054 
2055 		if (!sbp) {
2056 			emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
2057 		}
2058 
2059 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
2060 			/* Check if HBA is full */
2061 			throttle = hba->io_throttle - hba->io_active;
2062 			if (throttle <= 0) {
2063 				goto busy;
2064 			}
2065 		}
2066 
2067 		/* Check to see if we have room for another WQE */
2068 		next_wqe++;
2069 		if (next_wqe >= wq->max_index) {
2070 			next_wqe = 0;
2071 		}
2072 
2073 		if (next_wqe == wq->port_index) {
2074 			/* Queue it for later */
2075 			goto busy;
2076 		}
2077 
2078 
2079 		/* Get the next iocb from the tx queue if there is one */
2080 		iocbq = emlxs_tx_get(cp, 1);
2081 	}
2082 
2083 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
2084 
2085 	return;
2086 
2087 busy:
2088 	if (throttle <= 0) {
2089 		HBASTATS.IocbThrottled++;
2090 	} else {
2091 		HBASTATS.IocbRingFull[channelno]++;
2092 	}
2093 
2094 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
2095 
2096 	return;
2097 
2098 } /* emlxs_sli4_issue_iocb_cmd() */
2099 
2100 
2101 /*ARGSUSED*/
2102 static uint32_t
2103 emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb,
2104     uint32_t tmo)
2105 {
2106 	emlxs_hba_t *hba = HBA;
2107 	MAILBOXQ	*mbq;
2108 	MAILBOX4	*mb4;
2109 	MATCHMAP	*mp;
2110 	uint32_t	*iptr;
2111 	uint32_t	mqdb;
2112 	off_t		offset;
2113 
2114 	mbq = (MAILBOXQ *)mb;
2115 	mb4 = (MAILBOX4 *)mb;
2116 	mp = (MATCHMAP *) mbq->nonembed;
2117 	hba->mbox_mqe = (void *)mqe;
2118 
2119 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
2120 	    (mb4->un.varSLIConfig.be.embedded)) {
2121 		/*
2122 		 * If this is an embedded mbox, everything should fit
2123 		 * into the mailbox area.
2124 		 */
2125 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
2126 		    MAILBOX_CMD_SLI4_BSIZE);
2127 
2128 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
2129 		    4096, DDI_DMA_SYNC_FORDEV);
2130 
2131 		if (mb->mbxCommand != MBX_HEARTBEAT) {
2132 			emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe,
2133 			    18, 0);
2134 		}
2135 	} else {
2136 		/* SLI_CONFIG and non-embedded */
2137 
2138 		/*
2139 		 * If this is not embedded, the MQ area
2140 		 * MUST contain a SGE pointer to a larger area for the
2141 		 * non-embedded mailbox command.
2142 		 * mp will point to the actual mailbox command which
2143 		 * should be copied into the non-embedded area.
2144 		 */
2145 		mb4->un.varSLIConfig.be.sge_cnt = 1;
2146 		mb4->un.varSLIConfig.be.payload_length = mp->size;
2147 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
2148 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
2149 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
2150 		*iptr = mp->size;
2151 
2152 		BE_SWAP32_BUFFER(mp->virt, mp->size);
2153 
2154 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2155 		    DDI_DMA_SYNC_FORDEV);
2156 
2157 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
2158 		    MAILBOX_CMD_SLI4_BSIZE);
2159 
2160 		offset = (off_t)((uint64_t)((unsigned long)
2161 		    hba->sli.sli4.mq.addr.virt) -
2162 		    (uint64_t)((unsigned long)
2163 		    hba->sli.sli4.slim2.virt));
2164 
2165 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
2166 		    4096, DDI_DMA_SYNC_FORDEV);
2167 
2168 		emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0);
2169 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2170 		    "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt));
2171 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
2172 	}
2173 
2174 	/* Ring the MQ Doorbell */
2175 	mqdb = hba->sli.sli4.mq.qid;
2176 	mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK);
2177 
2178 	if (mb->mbxCommand != MBX_HEARTBEAT) {
2179 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2180 		    "MQ RING: %08x", mqdb);
2181 	}
2182 
2183 	WRITE_BAR2_REG(hba, FC_MQDB_REG(hba), mqdb);
2184 	return (MBX_SUCCESS);
2185 
2186 } /* emlxs_sli4_issue_mq() */
2187 
2188 
2189 /*ARGSUSED*/
2190 static uint32_t
2191 emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo)
2192 {
2193 	emlxs_port_t	*port = &PPORT;
2194 	MAILBOXQ	*mbq;
2195 	MAILBOX4	*mb4;
2196 	MATCHMAP	*mp = NULL;
2197 	uint32_t	*iptr;
2198 	int		nonembed = 0;
2199 
2200 	mbq = (MAILBOXQ *)mb;
2201 	mb4 = (MAILBOX4 *)mb;
2202 	mp = (MATCHMAP *) mbq->nonembed;
2203 	hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt;
2204 
2205 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
2206 	    (mb4->un.varSLIConfig.be.embedded)) {
2207 		/*
2208 		 * If this is an embedded mbox, everything should fit
2209 		 * into the bootstrap mailbox area.
2210 		 */
2211 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2212 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
2213 		    MAILBOX_CMD_SLI4_BSIZE);
2214 
2215 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2216 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV);
2217 		emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0);
2218 	} else {
2219 		/*
2220 		 * If this is not embedded, the bootstrap mailbox area
2221 		 * MUST contain a SGE pointer to a larger area for the
2222 		 * non-embedded mailbox command.
2223 		 * mp will point to the actual mailbox command which
2224 		 * should be copied into the non-embedded area.
2225 		 */
2226 		nonembed = 1;
2227 		mb4->un.varSLIConfig.be.sge_cnt = 1;
2228 		mb4->un.varSLIConfig.be.payload_length = mp->size;
2229 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
2230 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
2231 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
2232 		*iptr = mp->size;
2233 
2234 		BE_SWAP32_BUFFER(mp->virt, mp->size);
2235 
2236 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2237 		    DDI_DMA_SYNC_FORDEV);
2238 
2239 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2240 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
2241 		    MAILBOX_CMD_SLI4_BSIZE);
2242 
2243 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2244 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
2245 		    DDI_DMA_SYNC_FORDEV);
2246 
2247 		emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0);
2248 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2249 		    "Extension Addr %p %p", mp->phys,
2250 		    (uint32_t *)((uint8_t *)mp->virt));
2251 		iptr = (uint32_t *)((uint8_t *)mp->virt);
2252 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
2253 	}
2254 
2255 
2256 	/* NOTE: tmo is in 10ms ticks */
2257 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
2258 		return (MBX_TIMEOUT);
2259 	}
2260 
2261 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
2262 	    (mb4->un.varSLIConfig.be.embedded)) {
2263 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2264 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL);
2265 
2266 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2267 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
2268 		    MAILBOX_CMD_SLI4_BSIZE);
2269 
2270 		emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0);
2271 
2272 	} else {
2273 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2274 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
2275 		    DDI_DMA_SYNC_FORKERNEL);
2276 
2277 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2278 		    DDI_DMA_SYNC_FORKERNEL);
2279 
2280 		BE_SWAP32_BUFFER(mp->virt, mp->size);
2281 
2282 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2283 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
2284 		    MAILBOX_CMD_SLI4_BSIZE);
2285 
2286 		emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0);
2287 		iptr = (uint32_t *)((uint8_t *)mp->virt);
2288 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
2289 	}
2290 
2291 #ifdef FMA_SUPPORT
2292 	if (nonembed && mp) {
2293 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
2294 		    != DDI_FM_OK) {
2295 			EMLXS_MSGF(EMLXS_CONTEXT,
2296 			    &emlxs_invalid_dma_handle_msg,
2297 			    "emlxs_sli4_issue_bootstrap: mp_hdl=%p",
2298 			    mp->dma_handle);
2299 			return (MBXERR_DMA_ERROR);
2300 		}
2301 	}
2302 
2303 	if (emlxs_fm_check_dma_handle(hba,
2304 	    hba->sli.sli4.bootstrapmb.dma_handle)
2305 	    != DDI_FM_OK) {
2306 		EMLXS_MSGF(EMLXS_CONTEXT,
2307 		    &emlxs_invalid_dma_handle_msg,
2308 		    "emlxs_sli4_issue_bootstrap: hdl=%p",
2309 		    hba->sli.sli4.bootstrapmb.dma_handle);
2310 		return (MBXERR_DMA_ERROR);
2311 	}
2312 #endif
2313 
2314 	return (MBX_SUCCESS);
2315 
2316 } /* emlxs_sli4_issue_bootstrap() */
2317 
2318 
2319 /*ARGSUSED*/
2320 static uint32_t
2321 emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
2322     uint32_t tmo)
2323 {
2324 	emlxs_port_t	*port;
2325 	MAILBOX4	*mb4;
2326 	MAILBOX		*mb;
2327 	mbox_rsp_hdr_t	*hdr_rsp;
2328 	MATCHMAP	*mp;
2329 	uint32_t	*iptr;
2330 	uint32_t	rc;
2331 	uint32_t	i;
2332 	uint32_t	tmo_local;
2333 
2334 	if (!mbq->port) {
2335 		mbq->port = &PPORT;
2336 	}
2337 
2338 	port = (emlxs_port_t *)mbq->port;
2339 
2340 	mb4 = (MAILBOX4 *)mbq;
2341 	mb = (MAILBOX *)mbq;
2342 
2343 	mb->mbxStatus = MBX_SUCCESS;
2344 	rc = MBX_SUCCESS;
2345 
2346 	/* Check for minimum timeouts */
2347 	switch (mb->mbxCommand) {
2348 	/* Mailbox commands that erase/write flash */
2349 	case MBX_DOWN_LOAD:
2350 	case MBX_UPDATE_CFG:
2351 	case MBX_LOAD_AREA:
2352 	case MBX_LOAD_EXP_ROM:
2353 	case MBX_WRITE_NV:
2354 	case MBX_FLASH_WR_ULA:
2355 	case MBX_DEL_LD_ENTRY:
2356 	case MBX_LOAD_SM:
2357 		if (tmo < 300) {
2358 			tmo = 300;
2359 		}
2360 		break;
2361 
2362 	default:
2363 		if (tmo < 30) {
2364 			tmo = 30;
2365 		}
2366 		break;
2367 	}
2368 
2369 	/* Convert tmo seconds to 10 millisecond tics */
2370 	tmo_local = tmo * 100;
2371 
2372 	mutex_enter(&EMLXS_PORT_LOCK);
2373 
2374 	/* Adjust wait flag */
2375 	if (flag != MBX_NOWAIT) {
2376 		if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) {
2377 			flag = MBX_SLEEP;
2378 		} else {
2379 			flag = MBX_POLL;
2380 		}
2381 	} else {
2382 		/* Must have interrupts enabled to perform MBX_NOWAIT */
2383 		if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) {
2384 
2385 			mb->mbxStatus = MBX_HARDWARE_ERROR;
2386 			mutex_exit(&EMLXS_PORT_LOCK);
2387 
2388 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2389 			    "Interrupts disabled. %s failed.",
2390 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
2391 
2392 			return (MBX_HARDWARE_ERROR);
2393 		}
2394 	}
2395 
2396 	/* Check for hardware error ; special case SLI_CONFIG */
2397 	if ((hba->flag & FC_HARDWARE_ERROR) &&
2398 	    ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
2399 	    (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
2400 	    COMMON_OPCODE_RESET))) {
2401 		mb->mbxStatus = MBX_HARDWARE_ERROR;
2402 
2403 		mutex_exit(&EMLXS_PORT_LOCK);
2404 
2405 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2406 		    "Hardware error reported. %s failed. status=%x mb=%p",
2407 		    emlxs_mb_cmd_xlate(mb->mbxCommand),  mb->mbxStatus, mb);
2408 
2409 		return (MBX_HARDWARE_ERROR);
2410 	}
2411 
2412 	if (hba->mbox_queue_flag) {
2413 		/* If we are not polling, then queue it for later */
2414 		if (flag == MBX_NOWAIT) {
2415 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2416 			    "Busy.      %s: mb=%p NoWait.",
2417 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
2418 
2419 			emlxs_mb_put(hba, mbq);
2420 
2421 			HBASTATS.MboxBusy++;
2422 
2423 			mutex_exit(&EMLXS_PORT_LOCK);
2424 
2425 			return (MBX_BUSY);
2426 		}
2427 
2428 		while (hba->mbox_queue_flag) {
2429 			mutex_exit(&EMLXS_PORT_LOCK);
2430 
2431 			if (tmo_local-- == 0) {
2432 				EMLXS_MSGF(EMLXS_CONTEXT,
2433 				    &emlxs_mbox_event_msg,
2434 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
2435 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2436 				    tmo);
2437 
2438 				/* Non-lethalStatus mailbox timeout */
2439 				/* Does not indicate a hardware error */
2440 				mb->mbxStatus = MBX_TIMEOUT;
2441 				return (MBX_TIMEOUT);
2442 			}
2443 
2444 			DELAYMS(10);
2445 			mutex_enter(&EMLXS_PORT_LOCK);
2446 		}
2447 	}
2448 
2449 	/* Initialize mailbox area */
2450 	emlxs_mb_init(hba, mbq, flag, tmo);
2451 
2452 	if (mb->mbxCommand == MBX_DOWN_LINK) {
2453 		hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK;
2454 	}
2455 
2456 	mutex_exit(&EMLXS_PORT_LOCK);
2457 	switch (flag) {
2458 
2459 	case MBX_NOWAIT:
2460 		if (mb->mbxCommand != MBX_HEARTBEAT) {
2461 			if (mb->mbxCommand != MBX_DOWN_LOAD
2462 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2463 				EMLXS_MSGF(EMLXS_CONTEXT,
2464 				    &emlxs_mbox_detail_msg,
2465 				    "Sending.   %s: mb=%p NoWait. embedded %d",
2466 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2467 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2468 				    (mb4->un.varSLIConfig.be.embedded)));
2469 			}
2470 		}
2471 
2472 		iptr = hba->sli.sli4.mq.addr.virt;
2473 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
2474 		hba->sli.sli4.mq.host_index++;
2475 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
2476 			hba->sli.sli4.mq.host_index = 0;
2477 		}
2478 
2479 		if (mbq->bp) {
2480 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2481 			    "BDE virt %p phys %p size x%x",
2482 			    ((MATCHMAP *)mbq->bp)->virt,
2483 			    ((MATCHMAP *)mbq->bp)->phys,
2484 			    ((MATCHMAP *)mbq->bp)->size);
2485 			emlxs_data_dump(port, "DATA",
2486 			    (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0);
2487 		}
2488 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
2489 		break;
2490 
2491 	case MBX_POLL:
2492 		if (mb->mbxCommand != MBX_DOWN_LOAD
2493 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2494 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2495 			    "Sending.   %s: mb=%p Poll. embedded %d",
2496 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2497 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2498 			    (mb4->un.varSLIConfig.be.embedded)));
2499 		}
2500 
2501 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
2502 
2503 		/* Clean up the mailbox area */
2504 		if (rc == MBX_TIMEOUT) {
2505 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2506 			    "Timeout.   %s: mb=%p tmo=%x Poll. embedded %d",
2507 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
2508 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2509 			    (mb4->un.varSLIConfig.be.embedded)));
2510 
2511 			hba->flag |= FC_MBOX_TIMEOUT;
2512 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
2513 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
2514 
2515 		} else {
2516 			if (mb->mbxCommand != MBX_DOWN_LOAD
2517 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2518 				EMLXS_MSGF(EMLXS_CONTEXT,
2519 				    &emlxs_mbox_detail_msg,
2520 				    "Completed.   %s: mb=%p status=%x Poll. "
2521 				    "embedded %d",
2522 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
2523 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2524 				    (mb4->un.varSLIConfig.be.embedded)));
2525 			}
2526 
2527 			/* Process the result */
2528 			if (!(mbq->flag & MBQ_PASSTHRU)) {
2529 				if (mbq->mbox_cmpl) {
2530 					(void) (mbq->mbox_cmpl)(hba, mbq);
2531 				}
2532 			}
2533 
2534 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
2535 		}
2536 
2537 		mp = (MATCHMAP *)mbq->nonembed;
2538 		if (mp) {
2539 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2540 			if (hdr_rsp->status) {
2541 				EMLXS_MSGF(EMLXS_CONTEXT,
2542 				    &emlxs_mbox_detail_msg,
2543 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
2544 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2545 				    hdr_rsp->status, hdr_rsp->extra_status);
2546 
2547 				mb->mbxStatus = MBX_NONEMBED_ERROR;
2548 			}
2549 		}
2550 		rc = mb->mbxStatus;
2551 
2552 		/* Attempt to send pending mailboxes */
2553 		mbq = (MAILBOXQ *)emlxs_mb_get(hba);
2554 		if (mbq) {
2555 			/* Attempt to send pending mailboxes */
2556 			i =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
2557 			if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
2558 				emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2559 			}
2560 		}
2561 		break;
2562 
2563 	case MBX_SLEEP:
2564 		if (mb->mbxCommand != MBX_DOWN_LOAD
2565 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2566 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2567 			    "Sending.   %s: mb=%p Sleep. embedded %d",
2568 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2569 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2570 			    (mb4->un.varSLIConfig.be.embedded)));
2571 		}
2572 
2573 		iptr = hba->sli.sli4.mq.addr.virt;
2574 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
2575 		hba->sli.sli4.mq.host_index++;
2576 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
2577 			hba->sli.sli4.mq.host_index = 0;
2578 		}
2579 
2580 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
2581 
2582 		if (rc != MBX_SUCCESS) {
2583 			break;
2584 		}
2585 
2586 		/* Wait for completion */
2587 		/* The driver clock is timing the mailbox. */
2588 
2589 		mutex_enter(&EMLXS_MBOX_LOCK);
2590 		while (!(mbq->flag & MBQ_COMPLETED)) {
2591 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
2592 		}
2593 		mutex_exit(&EMLXS_MBOX_LOCK);
2594 
2595 		mp = (MATCHMAP *)mbq->nonembed;
2596 		if (mp) {
2597 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2598 			if (hdr_rsp->status) {
2599 				EMLXS_MSGF(EMLXS_CONTEXT,
2600 				    &emlxs_mbox_detail_msg,
2601 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
2602 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2603 				    hdr_rsp->status, hdr_rsp->extra_status);
2604 
2605 				mb->mbxStatus = MBX_NONEMBED_ERROR;
2606 			}
2607 		}
2608 		rc = mb->mbxStatus;
2609 
2610 		if (rc == MBX_TIMEOUT) {
2611 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2612 			    "Timeout.   %s: mb=%p tmo=%x Sleep. embedded %d",
2613 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
2614 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2615 			    (mb4->un.varSLIConfig.be.embedded)));
2616 		} else {
2617 			if (mb->mbxCommand != MBX_DOWN_LOAD
2618 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2619 				EMLXS_MSGF(EMLXS_CONTEXT,
2620 				    &emlxs_mbox_detail_msg,
2621 				    "Completed.   %s: mb=%p status=%x Sleep. "
2622 				    "embedded %d",
2623 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
2624 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2625 				    (mb4->un.varSLIConfig.be.embedded)));
2626 			}
2627 		}
2628 		break;
2629 	}
2630 
2631 	return (rc);
2632 
2633 } /* emlxs_sli4_issue_mbox_cmd() */
2634 
2635 
2636 
2637 /*ARGSUSED*/
2638 static uint32_t
2639 emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
2640     uint32_t tmo)
2641 {
2642 	emlxs_port_t	*port = &PPORT;
2643 	MAILBOX		*mb;
2644 	mbox_rsp_hdr_t	*hdr_rsp;
2645 	MATCHMAP	*mp;
2646 	uint32_t	rc;
2647 	uint32_t	tmo_local;
2648 
2649 	mb = (MAILBOX *)mbq;
2650 
2651 	mb->mbxStatus = MBX_SUCCESS;
2652 	rc = MBX_SUCCESS;
2653 
2654 	if (tmo < 30) {
2655 		tmo = 30;
2656 	}
2657 
2658 	/* Convert tmo seconds to 10 millisecond tics */
2659 	tmo_local = tmo * 100;
2660 
2661 	flag = MBX_POLL;
2662 
2663 	/* Check for hardware error */
2664 	if (hba->flag & FC_HARDWARE_ERROR) {
2665 		mb->mbxStatus = MBX_HARDWARE_ERROR;
2666 		return (MBX_HARDWARE_ERROR);
2667 	}
2668 
2669 	/* Initialize mailbox area */
2670 	emlxs_mb_init(hba, mbq, flag, tmo);
2671 
2672 	switch (flag) {
2673 
2674 	case MBX_POLL:
2675 
2676 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
2677 
2678 		/* Clean up the mailbox area */
2679 		if (rc == MBX_TIMEOUT) {
2680 			hba->flag |= FC_MBOX_TIMEOUT;
2681 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
2682 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
2683 
2684 		} else {
2685 			/* Process the result */
2686 			if (!(mbq->flag & MBQ_PASSTHRU)) {
2687 				if (mbq->mbox_cmpl) {
2688 					(void) (mbq->mbox_cmpl)(hba, mbq);
2689 				}
2690 			}
2691 
2692 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
2693 		}
2694 
2695 		mp = (MATCHMAP *)mbq->nonembed;
2696 		if (mp) {
2697 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2698 			if (hdr_rsp->status) {
2699 				EMLXS_MSGF(EMLXS_CONTEXT,
2700 				    &emlxs_mbox_detail_msg,
2701 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
2702 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2703 				    hdr_rsp->status, hdr_rsp->extra_status);
2704 
2705 				mb->mbxStatus = MBX_NONEMBED_ERROR;
2706 			}
2707 		}
2708 		rc = mb->mbxStatus;
2709 
2710 		break;
2711 	}
2712 
2713 	return (rc);
2714 
2715 } /* emlxs_sli4_issue_mbox_cmd4quiesce() */
2716 
2717 
2718 
2719 #ifdef SFCT_SUPPORT
2720 /*ARGSUSED*/
2721 static uint32_t
2722 emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel)
2723 {
2724 	return (IOERR_NO_RESOURCES);
2725 
2726 } /* emlxs_sli4_prep_fct_iocb() */
2727 #endif /* SFCT_SUPPORT */
2728 
2729 
2730 /*ARGSUSED*/
2731 extern uint32_t
2732 emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
2733 {
2734 	emlxs_hba_t *hba = HBA;
2735 	fc_packet_t *pkt;
2736 	CHANNEL *cp;
2737 	RPIobj_t *rpip;
2738 	XRIobj_t *xrip;
2739 	emlxs_wqe_t *wqe;
2740 	IOCBQ *iocbq;
2741 	NODELIST *node;
2742 	uint16_t iotag;
2743 	uint32_t did;
2744 	off_t offset;
2745 
2746 	pkt = PRIV2PKT(sbp);
2747 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2748 	cp = &hba->chan[channel];
2749 
2750 	iocbq = &sbp->iocbq;
2751 	iocbq->channel = (void *) cp;
2752 	iocbq->port = (void *) port;
2753 
2754 	wqe = &iocbq->wqe;
2755 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
2756 
2757 	/* Find target node object */
2758 	node = (NODELIST *)iocbq->node;
2759 	rpip = EMLXS_NODE_TO_RPI(port, node);
2760 
2761 	if (!rpip) {
2762 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2763 		    "Unable to find rpi. did=0x%x", did);
2764 
2765 		emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
2766 		    IOERR_INVALID_RPI, 0);
2767 		return (0xff);
2768 	}
2769 
2770 	sbp->channel = cp;
2771 	/* Next allocate an Exchange for this command */
2772 	xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip);
2773 
2774 	if (!xrip) {
2775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2776 		    "Adapter Busy. Unable to allocate exchange. did=0x%x", did);
2777 
2778 		return (FC_TRAN_BUSY);
2779 	}
2780 	sbp->bmp = NULL;
2781 	iotag = sbp->iotag;
2782 
2783 #ifdef SLI4_FASTPATH_DEBUG
2784 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,  /* DEBUG */
2785 	    "Prep FCP iotag: %x xri: %x", iotag, xrip->XRI);
2786 #endif
2787 
2788 	/* Indicate this is a FCP cmd */
2789 	iocbq->flag |= IOCB_FCP_CMD;
2790 
2791 	if (emlxs_sli4_bde_setup(port, sbp)) {
2792 		emlxs_sli4_free_xri(hba, sbp, xrip, 1);
2793 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2794 		    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
2795 
2796 		return (FC_TRAN_BUSY);
2797 	}
2798 
2799 
2800 	/* DEBUG */
2801 #ifdef DEBUG_FCP
2802 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2803 	    "SGLaddr virt %p phys %p size %d", xrip->SGList.virt,
2804 	    xrip->SGList.phys, pkt->pkt_datalen);
2805 	emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt, 20, 0);
2806 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2807 	    "CMD virt %p len %d:%d:%d",
2808 	    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
2809 	emlxs_data_dump(port, "FCP CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
2810 #endif
2811 
2812 	offset = (off_t)((uint64_t)((unsigned long)
2813 	    xrip->SGList.virt) -
2814 	    (uint64_t)((unsigned long)
2815 	    hba->sli.sli4.slim2.virt));
2816 
2817 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
2818 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
2819 
2820 	/* if device is FCP-2 device, set the following bit */
2821 	/* that says to run the FC-TAPE protocol. */
2822 	if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
2823 		wqe->ERP = 1;
2824 	}
2825 
2826 	if (pkt->pkt_datalen == 0) {
2827 		wqe->Command = CMD_FCP_ICMND64_CR;
2828 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
2829 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
2830 		wqe->Command = CMD_FCP_IREAD64_CR;
2831 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
2832 		wqe->PU = PARM_READ_CHECK;
2833 	} else {
2834 		wqe->Command = CMD_FCP_IWRITE64_CR;
2835 		wqe->CmdType = WQE_TYPE_FCP_DATA_OUT;
2836 	}
2837 	wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen;
2838 
2839 	wqe->ContextTag = rpip->RPI;
2840 	wqe->ContextType = WQE_RPI_CONTEXT;
2841 	wqe->XRITag = xrip->XRI;
2842 	wqe->Timer =
2843 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
2844 
2845 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
2846 		wqe->CCPE = 1;
2847 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
2848 	}
2849 
2850 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
2851 	case FC_TRAN_CLASS2:
2852 		wqe->Class = CLASS2;
2853 		break;
2854 	case FC_TRAN_CLASS3:
2855 	default:
2856 		wqe->Class = CLASS3;
2857 		break;
2858 	}
2859 	sbp->class = wqe->Class;
2860 	wqe->RequestTag = iotag;
2861 	wqe->CQId = 0x3ff;  /* default CQ for response */
2862 	return (FC_SUCCESS);
2863 } /* emlxs_sli4_prep_fcp_iocb() */
2864 
2865 
2866 /*ARGSUSED*/
2867 static uint32_t
2868 emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
2869 {
2870 	return (FC_TRAN_BUSY);
2871 
2872 } /* emlxs_sli4_prep_ip_iocb() */
2873 
2874 
2875 /*ARGSUSED*/
2876 static uint32_t
2877 emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
2878 {
2879 	emlxs_hba_t *hba = HBA;
2880 	fc_packet_t *pkt;
2881 	IOCBQ *iocbq;
2882 	IOCB *iocb;
2883 	emlxs_wqe_t *wqe;
2884 	FCFIobj_t *fcfp;
2885 	RPIobj_t *rpip = NULL;
2886 	XRIobj_t *xrip;
2887 	CHANNEL *cp;
2888 	uint32_t did;
2889 	uint32_t cmd;
2890 	ULP_SGE64 stage_sge;
2891 	ULP_SGE64 *sge;
2892 	ddi_dma_cookie_t *cp_cmd;
2893 	ddi_dma_cookie_t *cp_resp;
2894 	emlxs_node_t *node;
2895 	off_t offset;
2896 
2897 	pkt = PRIV2PKT(sbp);
2898 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2899 
2900 	iocbq = &sbp->iocbq;
2901 	wqe = &iocbq->wqe;
2902 	iocb = &iocbq->iocb;
2903 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
2904 	bzero((void *)iocb, sizeof (IOCB));
2905 	cp = &hba->chan[hba->channel_els];
2906 
2907 	/* Initalize iocbq */
2908 	iocbq->port = (void *) port;
2909 	iocbq->channel = (void *) cp;
2910 
2911 	sbp->channel = cp;
2912 	sbp->bmp = NULL;
2913 
2914 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2915 	cp_cmd = pkt->pkt_cmd_cookie;
2916 	cp_resp = pkt->pkt_resp_cookie;
2917 #else
2918 	cp_cmd  = &pkt->pkt_cmd_cookie;
2919 	cp_resp = &pkt->pkt_resp_cookie;
2920 #endif	/* >= EMLXS_MODREV3 */
2921 
2922 	/* CMD payload */
2923 	sge = &stage_sge;
2924 	sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
2925 	sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress);
2926 	sge->length = pkt->pkt_cmdlen;
2927 	sge->offset = 0;
2928 	sge->reserved = 0;
2929 
2930 	/* Initalize iocb */
2931 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2932 		/* ELS Response */
2933 
2934 		xrip = emlxs_sli4_register_xri(hba, sbp,
2935 		    pkt->pkt_cmd_fhdr.rx_id);
2936 
2937 		if (!xrip) {
2938 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
2939 			    "Unable to find XRI. rxid=%x",
2940 			    pkt->pkt_cmd_fhdr.rx_id);
2941 
2942 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
2943 			    IOERR_NO_XRI, 0);
2944 			return (0xff);
2945 		}
2946 
2947 		rpip = xrip->rpip;
2948 
2949 		if (!rpip) {
2950 			/* This means that we had a node registered */
2951 			/* when the unsol request came in but the node */
2952 			/* has since been unregistered. */
2953 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
2954 			    "Unable to find RPI. rxid=%x",
2955 			    pkt->pkt_cmd_fhdr.rx_id);
2956 
2957 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
2958 			    IOERR_INVALID_RPI, 0);
2959 			return (0xff);
2960 		}
2961 
2962 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2963 		    "Prep ELS XRI: xri=%x iotag=%x oxid=%x rpi=%x",
2964 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
2965 
2966 		wqe->Command = CMD_XMIT_ELS_RSP64_CX;
2967 		wqe->CmdType = WQE_TYPE_GEN;
2968 
2969 		wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh;
2970 		wqe->un.ElsRsp.Payload.addrLow = sge->addrLow;
2971 		wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
2972 
2973 		wqe->un.ElsRsp.RemoteId = did;
2974 		wqe->PU = 0x3;
2975 
2976 		sge->last = 1;
2977 		/* Now sge is fully staged */
2978 
2979 		sge = xrip->SGList.virt;
2980 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
2981 		    sizeof (ULP_SGE64));
2982 
2983 		wqe->ContextTag = port->VPIobj.VPI;
2984 		wqe->ContextType = WQE_VPI_CONTEXT;
2985 		wqe->OXId = xrip->rx_id;
2986 
2987 	} else {
2988 		/* ELS Request */
2989 
2990 		node = (emlxs_node_t *)iocbq->node;
2991 		rpip = EMLXS_NODE_TO_RPI(port, node);
2992 		fcfp = port->VPIobj.vfip->fcfp;
2993 
2994 		if (!rpip) {
2995 			rpip = port->VPIobj.rpip;
2996 		}
2997 
2998 		/* Next allocate an Exchange for this command */
2999 		xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip);
3000 
3001 		if (!xrip) {
3002 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3003 			    "Adapter Busy. Unable to allocate exchange. "
3004 			    "did=0x%x", did);
3005 
3006 			return (FC_TRAN_BUSY);
3007 		}
3008 
3009 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3010 		    "Prep ELS XRI: xri=%x iotag=%x rpi=%x", xrip->XRI,
3011 		    xrip->iotag, rpip->RPI);
3012 
3013 		wqe->Command = CMD_ELS_REQUEST64_CR;
3014 		wqe->CmdType = WQE_TYPE_ELS;
3015 
3016 		wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh;
3017 		wqe->un.ElsCmd.Payload.addrLow = sge->addrLow;
3018 		wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
3019 
3020 		/* setup for rsp */
3021 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
3022 		iocb->ULPPU = 1;	/* Wd4 is relative offset */
3023 
3024 		sge->last = 0;
3025 
3026 		sge = xrip->SGList.virt;
3027 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
3028 		    sizeof (ULP_SGE64));
3029 
3030 		wqe->un.ElsCmd.PayloadLength =
3031 		    pkt->pkt_cmdlen; /* Byte offset of rsp data */
3032 
3033 		/* RSP payload */
3034 		sge = &stage_sge;
3035 		sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress);
3036 		sge->addrLow = PADDR_LO(cp_resp->dmac_laddress);
3037 		sge->length = pkt->pkt_rsplen;
3038 		sge->offset = 0;
3039 		sge->last = 1;
3040 		/* Now sge is fully staged */
3041 
3042 		sge = xrip->SGList.virt;
3043 		sge++;
3044 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
3045 		    sizeof (ULP_SGE64));
3046 #ifdef DEBUG_ELS
3047 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3048 		    "SGLaddr virt %p phys %p",
3049 		    xrip->SGList.virt, xrip->SGList.phys);
3050 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3051 		    "PAYLOAD virt %p phys %p",
3052 		    pkt->pkt_cmd, cp_cmd->dmac_laddress);
3053 		emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt,
3054 		    12, 0);
3055 #endif
3056 
3057 		cmd = *((uint32_t *)pkt->pkt_cmd);
3058 		cmd &= ELS_CMD_MASK;
3059 
3060 		switch (cmd) {
3061 		case ELS_CMD_FLOGI:
3062 			wqe->un.ElsCmd.SP = 1;
3063 			wqe->ContextTag = fcfp->FCFI;
3064 			wqe->ContextType = WQE_FCFI_CONTEXT;
3065 			if (hba->flag & FC_FIP_SUPPORTED) {
3066 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
3067 				wqe->ELSId |= WQE_ELSID_FLOGI;
3068 			}
3069 			break;
3070 		case ELS_CMD_FDISC:
3071 			wqe->un.ElsCmd.SP = 1;
3072 			wqe->ContextTag = port->VPIobj.VPI;
3073 			wqe->ContextType = WQE_VPI_CONTEXT;
3074 			if (hba->flag & FC_FIP_SUPPORTED) {
3075 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
3076 				wqe->ELSId |= WQE_ELSID_FDISC;
3077 			}
3078 			break;
3079 		case ELS_CMD_LOGO:
3080 			if (did == FABRIC_DID) {
3081 				wqe->ContextTag = fcfp->FCFI;
3082 				wqe->ContextType = WQE_FCFI_CONTEXT;
3083 				if (hba->flag & FC_FIP_SUPPORTED) {
3084 					wqe->CmdType |= WQE_TYPE_MASK_FIP;
3085 					wqe->ELSId |= WQE_ELSID_LOGO;
3086 				}
3087 			} else {
3088 				wqe->ContextTag = port->VPIobj.VPI;
3089 				wqe->ContextType = WQE_VPI_CONTEXT;
3090 			}
3091 			break;
3092 
3093 		case ELS_CMD_SCR:
3094 		case ELS_CMD_PLOGI:
3095 		case ELS_CMD_PRLI:
3096 		default:
3097 			wqe->ContextTag = port->VPIobj.VPI;
3098 			wqe->ContextType = WQE_VPI_CONTEXT;
3099 			break;
3100 		}
3101 		wqe->un.ElsCmd.RemoteId = did;
3102 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3103 	}
3104 
3105 	offset = (off_t)((uint64_t)((unsigned long)
3106 	    xrip->SGList.virt) -
3107 	    (uint64_t)((unsigned long)
3108 	    hba->sli.sli4.slim2.virt));
3109 
3110 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
3111 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
3112 
3113 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
3114 		wqe->CCPE = 1;
3115 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
3116 	}
3117 
3118 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3119 	case FC_TRAN_CLASS2:
3120 		wqe->Class = CLASS2;
3121 		break;
3122 	case FC_TRAN_CLASS3:
3123 	default:
3124 		wqe->Class = CLASS3;
3125 		break;
3126 	}
3127 	sbp->class = wqe->Class;
3128 	wqe->XRITag = xrip->XRI;
3129 	wqe->RequestTag = xrip->iotag;
3130 	wqe->CQId = 0x3ff;
3131 	return (FC_SUCCESS);
3132 
3133 } /* emlxs_sli4_prep_els_iocb() */
3134 
3135 
3136 /*ARGSUSED*/
3137 static uint32_t
3138 emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3139 {
3140 	emlxs_hba_t *hba = HBA;
3141 	fc_packet_t *pkt;
3142 	IOCBQ *iocbq;
3143 	IOCB *iocb;
3144 	emlxs_wqe_t *wqe;
3145 	NODELIST *node = NULL;
3146 	CHANNEL *cp;
3147 	RPIobj_t *rpip;
3148 	XRIobj_t *xrip;
3149 	uint32_t did;
3150 	off_t offset;
3151 
3152 	pkt = PRIV2PKT(sbp);
3153 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3154 
3155 	iocbq = &sbp->iocbq;
3156 	wqe = &iocbq->wqe;
3157 	iocb = &iocbq->iocb;
3158 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
3159 	bzero((void *)iocb, sizeof (IOCB));
3160 
3161 	cp = &hba->chan[hba->channel_ct];
3162 
3163 	iocbq->port = (void *) port;
3164 	iocbq->channel = (void *) cp;
3165 
3166 	sbp->bmp = NULL;
3167 	sbp->channel = cp;
3168 
3169 	/* Initalize wqe */
3170 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
3171 		/* CT Response */
3172 
3173 		xrip = emlxs_sli4_register_xri(hba, sbp,
3174 		    pkt->pkt_cmd_fhdr.rx_id);
3175 
3176 		if (!xrip) {
3177 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3178 			    "Unable to find XRI. rxid=%x",
3179 			    pkt->pkt_cmd_fhdr.rx_id);
3180 
3181 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3182 			    IOERR_NO_XRI, 0);
3183 			return (0xff);
3184 		}
3185 
3186 		rpip = xrip->rpip;
3187 
3188 		if (!rpip) {
3189 			/* This means that we had a node registered */
3190 			/* when the unsol request came in but the node */
3191 			/* has since been unregistered. */
3192 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3193 			    "Unable to find RPI. rxid=%x",
3194 			    pkt->pkt_cmd_fhdr.rx_id);
3195 
3196 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3197 			    IOERR_INVALID_RPI, 0);
3198 			return (0xff);
3199 		}
3200 
3201 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3202 		    "Prep CT XRI: xri=%x iotag=%x oxid=%x", xrip->XRI,
3203 		    xrip->iotag, xrip->rx_id);
3204 
3205 		if (emlxs_sli4_bde_setup(port, sbp)) {
3206 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3207 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
3208 
3209 			return (FC_TRAN_BUSY);
3210 		}
3211 
3212 		wqe->CmdType = WQE_TYPE_GEN;
3213 		wqe->Command = CMD_XMIT_SEQUENCE64_CR;
3214 		wqe->un.XmitSeq.la = 1;
3215 
3216 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
3217 			wqe->un.XmitSeq.ls = 1;
3218 		}
3219 
3220 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
3221 			wqe->un.XmitSeq.si = 1;
3222 		}
3223 
3224 		wqe->un.XmitSeq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
3225 		wqe->un.XmitSeq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3226 		wqe->un.XmitSeq.Type  = pkt->pkt_cmd_fhdr.type;
3227 		wqe->OXId = xrip->rx_id;
3228 		wqe->XC = 0; /* xri_tag is a new exchange */
3229 		wqe->CmdSpecific[0] = wqe->un.GenReq.Payload.tus.f.bdeSize;
3230 
3231 	} else {
3232 		/* CT Request */
3233 
3234 		node = (emlxs_node_t *)iocbq->node;
3235 		rpip = EMLXS_NODE_TO_RPI(port, node);
3236 
3237 		if (!rpip) {
3238 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3239 			    "Unable to find rpi. did=0x%x rpi=%x",
3240 			    did, node->nlp_Rpi);
3241 
3242 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3243 			    IOERR_INVALID_RPI, 0);
3244 			return (0xff);
3245 		}
3246 
3247 		/* Next allocate an Exchange for this command */
3248 		xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip);
3249 
3250 		if (!xrip) {
3251 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3252 			    "Adapter Busy. Unable to allocate exchange. "
3253 			    "did=0x%x", did);
3254 
3255 			return (FC_TRAN_BUSY);
3256 		}
3257 
3258 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3259 		    "Prep CT XRI: %x iotag %x", xrip->XRI, xrip->iotag);
3260 
3261 		if (emlxs_sli4_bde_setup(port, sbp)) {
3262 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3263 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
3264 
3265 			emlxs_sli4_free_xri(hba, sbp, xrip, 1);
3266 			return (FC_TRAN_BUSY);
3267 		}
3268 
3269 		wqe->CmdType = WQE_TYPE_GEN;
3270 		wqe->Command = CMD_GEN_REQUEST64_CR;
3271 		wqe->un.GenReq.la = 1;
3272 		wqe->un.GenReq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
3273 		wqe->un.GenReq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3274 		wqe->un.GenReq.Type  = pkt->pkt_cmd_fhdr.type;
3275 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3276 
3277 #ifdef DEBUG_CT
3278 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3279 		    "SGLaddr virt %p phys %p", xrip->SGList.virt,
3280 		    xrip->SGList.phys);
3281 		emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt,
3282 		    12, 0);
3283 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3284 		    "CMD virt %p len %d:%d",
3285 		    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
3286 		emlxs_data_dump(port, "DATA", (uint32_t *)pkt->pkt_cmd, 20, 0);
3287 #endif /* DEBUG_CT */
3288 	}
3289 
3290 	/* Setup for rsp */
3291 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3292 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
3293 	iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
3294 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
3295 
3296 	offset = (off_t)((uint64_t)((unsigned long)
3297 	    xrip->SGList.virt) -
3298 	    (uint64_t)((unsigned long)
3299 	    hba->sli.sli4.slim2.virt));
3300 
3301 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
3302 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
3303 
3304 	wqe->ContextTag = rpip->RPI;
3305 	wqe->ContextType = WQE_RPI_CONTEXT;
3306 	wqe->XRITag = xrip->XRI;
3307 
3308 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
3309 		wqe->CCPE = 1;
3310 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
3311 	}
3312 
3313 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3314 	case FC_TRAN_CLASS2:
3315 		wqe->Class = CLASS2;
3316 		break;
3317 	case FC_TRAN_CLASS3:
3318 	default:
3319 		wqe->Class = CLASS3;
3320 		break;
3321 	}
3322 	sbp->class = wqe->Class;
3323 	wqe->RequestTag = xrip->iotag;
3324 	wqe->CQId = 0x3ff;
3325 	return (FC_SUCCESS);
3326 
3327 } /* emlxs_sli4_prep_ct_iocb() */
3328 
3329 
3330 /*ARGSUSED*/
3331 static int
3332 emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
3333 {
3334 	uint32_t *ptr;
3335 	EQE_u eqe;
3336 	int rc = 0;
3337 	off_t offset;
3338 
3339 	/* EMLXS_PORT_LOCK must be held when entering this routine */
3340 	ptr = eq->addr.virt;
3341 	ptr += eq->host_index;
3342 
3343 	offset = (off_t)((uint64_t)((unsigned long)
3344 	    eq->addr.virt) -
3345 	    (uint64_t)((unsigned long)
3346 	    hba->sli.sli4.slim2.virt));
3347 
3348 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
3349 	    4096, DDI_DMA_SYNC_FORKERNEL);
3350 
3351 	mutex_enter(&EMLXS_PORT_LOCK);
3352 
3353 	eqe.word = *ptr;
3354 	eqe.word = BE_SWAP32(eqe.word);
3355 
3356 	if (eqe.word & EQE_VALID) {
3357 		rc = 1;
3358 	}
3359 
3360 	mutex_exit(&EMLXS_PORT_LOCK);
3361 
3362 	return (rc);
3363 
3364 } /* emlxs_sli4_read_eq */
3365 
3366 
3367 /*ARGSUSED*/
3368 static void
3369 emlxs_sli4_poll_intr(emlxs_hba_t *hba, uint32_t att_bit)
3370 {
3371 	int rc = 0;
3372 	int i;
3373 	char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
3374 	char arg2;
3375 
3376 	/*
3377 	 * Poll the eqe to see if the valid bit is set or not
3378 	 */
3379 
3380 	for (;;) {
3381 		if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
3382 			/* only poll eqe0 */
3383 			rc = emlxs_sli4_read_eq(hba,
3384 			    &hba->sli.sli4.eq[0]);
3385 			if (rc == 1) {
3386 				(void) bcopy((char *)&arg[0],
3387 				    (char *)&arg2, sizeof (char));
3388 				break;
3389 			}
3390 		} else {
3391 			/* poll every msi vector */
3392 			for (i = 0; i < hba->intr_count; i++) {
3393 				rc = emlxs_sli4_read_eq(hba,
3394 				    &hba->sli.sli4.eq[i]);
3395 
3396 				if (rc == 1) {
3397 					break;
3398 				}
3399 			}
3400 			if ((i != hba->intr_count) && (rc == 1)) {
3401 				(void) bcopy((char *)&arg[i],
3402 				    (char *)&arg2, sizeof (char));
3403 				break;
3404 			}
3405 		}
3406 	}
3407 
3408 	/* process it here */
3409 	rc = emlxs_sli4_msi_intr((char *)hba, (char *)&arg2);
3410 
3411 	return;
3412 
3413 } /* emlxs_sli4_poll_intr() */
3414 
3415 
3416 /*ARGSUSED*/
3417 static void
3418 emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
3419 {
3420 	emlxs_port_t *port = &PPORT;
3421 
3422 	/* Save the event tag */
3423 	hba->link_event_tag = cqe->un.link.event_tag;
3424 
3425 	switch (cqe->event_code) {
3426 	case ASYNC_EVENT_CODE_LINK_STATE:
3427 		switch (cqe->un.link.link_status) {
3428 		case ASYNC_EVENT_PHYS_LINK_UP:
3429 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3430 			    "Link Async Event: PHYS_LINK_UP. val=%d type=%x",
3431 			    cqe->valid, cqe->event_type);
3432 			break;
3433 
3434 		case ASYNC_EVENT_PHYS_LINK_DOWN:
3435 		case ASYNC_EVENT_LOGICAL_LINK_DOWN:
3436 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3437 			    "Link Async Event: LINK_DOWN. val=%d type=%x",
3438 			    cqe->valid, cqe->event_type);
3439 
3440 			(void) emlxs_fcf_linkdown_notify(port);
3441 
3442 			mutex_enter(&EMLXS_PORT_LOCK);
3443 			hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
3444 			mutex_exit(&EMLXS_PORT_LOCK);
3445 			break;
3446 
3447 		case ASYNC_EVENT_LOGICAL_LINK_UP:
3448 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3449 			    "Link Async Event: LOGICAL_LINK_UP. val=%d type=%x",
3450 			    cqe->valid, cqe->event_type);
3451 
3452 			if (cqe->un.link.port_speed == PHY_1GHZ_LINK) {
3453 				hba->linkspeed = LA_1GHZ_LINK;
3454 			} else {
3455 				hba->linkspeed = LA_10GHZ_LINK;
3456 			}
3457 			hba->topology = TOPOLOGY_PT_PT;
3458 			hba->qos_linkspeed = cqe->un.link.qos_link_speed;
3459 
3460 			(void) emlxs_fcf_linkup_notify(port);
3461 			break;
3462 		}
3463 		break;
3464 	case ASYNC_EVENT_CODE_FCOE_FIP:
3465 		switch (cqe->un.fcoe.evt_type) {
3466 		case ASYNC_EVENT_NEW_FCF_DISC:
3467 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3468 			    "FCOE Async Event: FCF_FOUND %d:%d",
3469 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
3470 
3471 			(void) emlxs_fcf_found_notify(port,
3472 			    cqe->un.fcoe.ref_index);
3473 			break;
3474 		case ASYNC_EVENT_FCF_TABLE_FULL:
3475 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3476 			    "FCOE Async Event: FCFTAB_FULL %d:%d",
3477 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
3478 
3479 			(void) emlxs_fcf_full_notify(port);
3480 			break;
3481 		case ASYNC_EVENT_FCF_DEAD:
3482 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3483 			    "FCOE Async Event: FCF_LOST %d:%d",
3484 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
3485 
3486 			(void) emlxs_fcf_lost_notify(port,
3487 			    cqe->un.fcoe.ref_index);
3488 			break;
3489 		case ASYNC_EVENT_VIRT_LINK_CLEAR:
3490 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3491 			    "FCOE Async Event: CVL %d",
3492 			    cqe->un.fcoe.ref_index);
3493 
3494 			(void) emlxs_fcf_cvl_notify(port,
3495 			    (cqe->un.fcoe.ref_index - hba->vpi_base));
3496 			break;
3497 
3498 		case ASYNC_EVENT_FCF_MODIFIED:
3499 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3500 			    "FCOE Async Event: FCF_CHANGED %d",
3501 			    cqe->un.fcoe.ref_index);
3502 
3503 			(void) emlxs_fcf_changed_notify(port,
3504 			    cqe->un.fcoe.ref_index);
3505 			break;
3506 		}
3507 		break;
3508 	case ASYNC_EVENT_CODE_DCBX:
3509 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3510 		    "DCBX Async Event Code %d: Not supported",
3511 		    cqe->event_code);
3512 		break;
3513 	case ASYNC_EVENT_CODE_GRP_5:
3514 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3515 		    "Group 5 Async Event type %d", cqe->event_type);
3516 		if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) {
3517 			hba->qos_linkspeed = cqe->un.qos.qos_link_speed;
3518 		}
3519 		break;
3520 	default:
3521 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3522 		    "Unknown Async Event Code %d", cqe->event_code);
3523 		break;
3524 	}
3525 
3526 } /* emlxs_sli4_process_async_event() */
3527 
3528 
3529 /*ARGSUSED*/
3530 static void
3531 emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe)
3532 {
3533 	emlxs_port_t *port = &PPORT;
3534 	MAILBOX4 *mb;
3535 	MATCHMAP *mbox_bp;
3536 	MATCHMAP *mbox_nonembed;
3537 	MAILBOXQ *mbq = NULL;
3538 	uint32_t size;
3539 	uint32_t *iptr;
3540 	int rc;
3541 	off_t offset;
3542 
3543 	if (cqe->consumed && !cqe->completed) {
3544 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3545 		    "CQ ENTRY: Mbox event. Entry consumed but not completed");
3546 		return;
3547 	}
3548 
3549 	mutex_enter(&EMLXS_PORT_LOCK);
3550 	switch (hba->mbox_queue_flag) {
3551 	case 0:
3552 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
3553 		    "CQ ENTRY: Mbox event. No mailbox active.");
3554 
3555 		mutex_exit(&EMLXS_PORT_LOCK);
3556 		return;
3557 
3558 	case MBX_POLL:
3559 
3560 		/* Mark mailbox complete, this should wake up any polling */
3561 		/* threads. This can happen if interrupts are enabled while */
3562 		/* a polled mailbox command is outstanding. If we don't set */
3563 		/* MBQ_COMPLETED here, the polling thread may wait until */
3564 		/* timeout error occurs */
3565 
3566 		mutex_enter(&EMLXS_MBOX_LOCK);
3567 		mbq = (MAILBOXQ *)hba->mbox_mbq;
3568 		if (mbq) {
3569 			port = (emlxs_port_t *)mbq->port;
3570 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3571 			    "CQ ENTRY: Mbox event. Completing Polled command.");
3572 			mbq->flag |= MBQ_COMPLETED;
3573 		}
3574 		mutex_exit(&EMLXS_MBOX_LOCK);
3575 
3576 		mutex_exit(&EMLXS_PORT_LOCK);
3577 		return;
3578 
3579 	case MBX_SLEEP:
3580 	case MBX_NOWAIT:
3581 		/* Check mbox_timer, it acts as a service flag too */
3582 		/* The first to service the mbox queue will clear the timer */
3583 		if (hba->mbox_timer) {
3584 			hba->mbox_timer = 0;
3585 
3586 			mutex_enter(&EMLXS_MBOX_LOCK);
3587 			mbq = (MAILBOXQ *)hba->mbox_mbq;
3588 			mutex_exit(&EMLXS_MBOX_LOCK);
3589 		}
3590 
3591 		if (!mbq) {
3592 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3593 			    "Mailbox event. No service required.");
3594 			mutex_exit(&EMLXS_PORT_LOCK);
3595 			return;
3596 		}
3597 
3598 		mb = (MAILBOX4 *)mbq;
3599 		mutex_exit(&EMLXS_PORT_LOCK);
3600 		break;
3601 
3602 	default:
3603 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
3604 		    "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).",
3605 		    hba->mbox_queue_flag);
3606 
3607 		mutex_exit(&EMLXS_PORT_LOCK);
3608 		return;
3609 	}
3610 
3611 	/* Set port context */
3612 	port = (emlxs_port_t *)mbq->port;
3613 
3614 	offset = (off_t)((uint64_t)((unsigned long)
3615 	    hba->sli.sli4.mq.addr.virt) -
3616 	    (uint64_t)((unsigned long)
3617 	    hba->sli.sli4.slim2.virt));
3618 
3619 	/* Now that we are the owner, DMA Sync entire MQ if needed */
3620 	EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
3621 	    4096, DDI_DMA_SYNC_FORDEV);
3622 
3623 	BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb,
3624 	    MAILBOX_CMD_SLI4_BSIZE);
3625 
3626 	if (mb->mbxCommand != MBX_HEARTBEAT) {
3627 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3628 		    "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x",
3629 		    mb->mbxStatus, mb->mbxCommand);
3630 
3631 		emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe,
3632 		    12, 0);
3633 	}
3634 
3635 	if (mb->mbxCommand == MBX_SLI_CONFIG) {
3636 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3637 		    "Mbox sge_cnt: %d length: %d embed: %d",
3638 		    mb->un.varSLIConfig.be.sge_cnt,
3639 		    mb->un.varSLIConfig.be.payload_length,
3640 		    mb->un.varSLIConfig.be.embedded);
3641 	}
3642 
3643 	/* Now sync the memory buffer if one was used */
3644 	if (mbq->bp) {
3645 		mbox_bp = (MATCHMAP *)mbq->bp;
3646 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
3647 		    DDI_DMA_SYNC_FORKERNEL);
3648 #ifdef FMA_SUPPORT
3649 		if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle)
3650 		    != DDI_FM_OK) {
3651 			EMLXS_MSGF(EMLXS_CONTEXT,
3652 			    &emlxs_invalid_dma_handle_msg,
3653 			    "emlxs_sli4_process_mbox_event: hdl=%p",
3654 			    mbox_bp->dma_handle);
3655 
3656 			mb->mbxStatus = MBXERR_DMA_ERROR;
3657 }
3658 #endif
3659 	}
3660 
3661 	/* Now sync the memory buffer if one was used */
3662 	if (mbq->nonembed) {
3663 		mbox_nonembed = (MATCHMAP *)mbq->nonembed;
3664 		size = mbox_nonembed->size;
3665 		EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size,
3666 		    DDI_DMA_SYNC_FORKERNEL);
3667 		iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt);
3668 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size);
3669 
3670 #ifdef FMA_SUPPORT
3671 		if (emlxs_fm_check_dma_handle(hba,
3672 		    mbox_nonembed->dma_handle) != DDI_FM_OK) {
3673 			EMLXS_MSGF(EMLXS_CONTEXT,
3674 			    &emlxs_invalid_dma_handle_msg,
3675 			    "emlxs_sli4_process_mbox_event: hdl=%p",
3676 			    mbox_nonembed->dma_handle);
3677 
3678 			mb->mbxStatus = MBXERR_DMA_ERROR;
3679 		}
3680 #endif
3681 emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
3682 	}
3683 
3684 	/* Mailbox has been completely received at this point */
3685 
3686 	if (mb->mbxCommand == MBX_HEARTBEAT) {
3687 		hba->heartbeat_active = 0;
3688 		goto done;
3689 	}
3690 
3691 	if (hba->mbox_queue_flag == MBX_SLEEP) {
3692 		if (mb->mbxCommand != MBX_DOWN_LOAD
3693 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3694 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3695 			    "Received.  %s: status=%x Sleep.",
3696 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
3697 			    mb->mbxStatus);
3698 		}
3699 	} else {
3700 		if (mb->mbxCommand != MBX_DOWN_LOAD
3701 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3702 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3703 			    "Completed. %s: status=%x",
3704 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
3705 			    mb->mbxStatus);
3706 		}
3707 	}
3708 
3709 	/* Filter out passthru mailbox */
3710 	if (mbq->flag & MBQ_PASSTHRU) {
3711 		goto done;
3712 	}
3713 
3714 	if (mb->mbxStatus) {
3715 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3716 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
3717 		    (uint32_t)mb->mbxStatus);
3718 	}
3719 
3720 	if (mbq->mbox_cmpl) {
3721 		rc = (mbq->mbox_cmpl)(hba, mbq);
3722 
3723 		/* If mbox was retried, return immediately */
3724 		if (rc) {
3725 			return;
3726 		}
3727 	}
3728 
3729 done:
3730 
3731 	/* Clean up the mailbox area */
3732 	emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus);
3733 
3734 	/* Attempt to send pending mailboxes */
3735 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
3736 	if (mbq) {
3737 		/* Attempt to send pending mailboxes */
3738 		rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
3739 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
3740 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3741 		}
3742 	}
3743 	return;
3744 
3745 } /* emlxs_sli4_process_mbox_event() */
3746 
3747 
3748 /*ARGSUSED*/
3749 static void
3750 emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp)
3751 {
3752 #ifdef SLI4_FASTPATH_DEBUG
3753 	emlxs_port_t *port = &PPORT;
3754 #endif
3755 	IOCBQ *iocbq;
3756 	IOCB *iocb;
3757 	uint32_t *iptr;
3758 	fc_packet_t *pkt;
3759 	emlxs_wqe_t *wqe;
3760 
3761 	iocbq = &sbp->iocbq;
3762 	wqe = &iocbq->wqe;
3763 	iocb = &iocbq->iocb;
3764 
3765 #ifdef SLI4_FASTPATH_DEBUG
3766 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3767 	    "CQE to IOCB: cmd:x%x tag:x%x xri:x%x", wqe->Command,
3768 	    wqe->RequestTag, wqe->XRITag);
3769 #endif
3770 
3771 	iocb->ULPSTATUS = cqe->Status;
3772 	iocb->un.ulpWord[4] = cqe->Parameter;
3773 	iocb->ULPIOTAG = cqe->RequestTag;
3774 	iocb->ULPCONTEXT = wqe->XRITag;
3775 
3776 	switch (wqe->Command) {
3777 
3778 	case CMD_FCP_ICMND64_CR:
3779 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX;
3780 		break;
3781 
3782 	case CMD_FCP_IREAD64_CR:
3783 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX;
3784 		iocb->ULPPU = PARM_READ_CHECK;
3785 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
3786 			iocb->un.fcpi64.fcpi_parm =
3787 			    wqe->un.FcpCmd.TotalTransferCount -
3788 			    cqe->CmdSpecific;
3789 		}
3790 		break;
3791 
3792 	case CMD_FCP_IWRITE64_CR:
3793 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX;
3794 		break;
3795 
3796 	case CMD_ELS_REQUEST64_CR:
3797 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX;
3798 		iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific;
3799 		if (iocb->ULPSTATUS == 0) {
3800 			iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
3801 		}
3802 		if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
3803 			/* For LS_RJT, the driver populates the rsp buffer */
3804 			pkt = PRIV2PKT(sbp);
3805 			iptr = (uint32_t *)pkt->pkt_resp;
3806 			*iptr++ = ELS_CMD_LS_RJT;
3807 			*iptr = cqe->Parameter;
3808 		}
3809 		break;
3810 
3811 	case CMD_GEN_REQUEST64_CR:
3812 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
3813 		iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
3814 		break;
3815 
3816 	case CMD_XMIT_SEQUENCE64_CR:
3817 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
3818 		break;
3819 
3820 	default:
3821 		iocb->ULPCOMMAND = wqe->Command;
3822 
3823 	}
3824 
3825 } /* emlxs_CQE_to_IOCB() */
3826 
3827 
3828 /*ARGSUSED*/
3829 static void
3830 emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba)
3831 {
3832 #ifdef SFCT_SUPPORT
3833 #ifdef FCT_IO_TRACE
3834 	emlxs_port_t *port = &PPORT;
3835 #endif /* FCT_IO_TRACE */
3836 #endif /* SFCT_SUPPORT */
3837 	CHANNEL *cp;
3838 	emlxs_buf_t *sbp;
3839 	IOCBQ *iocbq;
3840 	uint16_t i;
3841 	uint32_t trigger;
3842 	CQE_CmplWQ_t cqe;
3843 
3844 	mutex_enter(&EMLXS_FCTAB_LOCK);
3845 	for (i = 0; i < hba->max_iotag; i++) {
3846 		sbp = hba->fc_table[i];
3847 		if (sbp == NULL || sbp == STALE_PACKET) {
3848 			continue;
3849 		}
3850 		hba->fc_table[i] = STALE_PACKET;
3851 		hba->io_count--;
3852 		sbp->iotag = 0;
3853 		mutex_exit(&EMLXS_FCTAB_LOCK);
3854 
3855 		cp = sbp->channel;
3856 		bzero(&cqe, sizeof (CQE_CmplWQ_t));
3857 		cqe.RequestTag = i;
3858 		cqe.Status = IOSTAT_LOCAL_REJECT;
3859 		cqe.Parameter = IOERR_SEQUENCE_TIMEOUT;
3860 
3861 		cp->hbaCmplCmd_sbp++;
3862 
3863 #ifdef SFCT_SUPPORT
3864 #ifdef FCT_IO_TRACE
3865 		if (sbp->fct_cmd) {
3866 			emlxs_fct_io_trace(port, sbp->fct_cmd,
3867 			    EMLXS_FCT_IOCB_COMPLETE);
3868 		}
3869 #endif /* FCT_IO_TRACE */
3870 #endif /* SFCT_SUPPORT */
3871 
3872 		atomic_add_32(&hba->io_active, -1);
3873 
3874 		/* Copy entry to sbp's iocbq */
3875 		iocbq = &sbp->iocbq;
3876 		emlxs_CQE_to_IOCB(hba, &cqe, sbp);
3877 
3878 		iocbq->next = NULL;
3879 
3880 		/* Exchange is no longer busy on-chip, free it */
3881 		emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1);
3882 
3883 		if (!(sbp->pkt_flags &
3884 		    (PACKET_POLLED | PACKET_ALLOCATED))) {
3885 			/* Add the IOCB to the channel list */
3886 			mutex_enter(&cp->rsp_lock);
3887 			if (cp->rsp_head == NULL) {
3888 				cp->rsp_head = iocbq;
3889 				cp->rsp_tail = iocbq;
3890 			} else {
3891 				cp->rsp_tail->next = iocbq;
3892 				cp->rsp_tail = iocbq;
3893 			}
3894 			mutex_exit(&cp->rsp_lock);
3895 			trigger = 1;
3896 		} else {
3897 			emlxs_proc_channel_event(hba, cp, iocbq);
3898 		}
3899 		mutex_enter(&EMLXS_FCTAB_LOCK);
3900 	}
3901 	mutex_exit(&EMLXS_FCTAB_LOCK);
3902 
3903 	if (trigger) {
3904 		for (i = 0; i < hba->chan_count; i++) {
3905 			cp = &hba->chan[i];
3906 			if (cp->rsp_head != NULL) {
3907 				emlxs_thread_trigger2(&cp->intr_thread,
3908 				    emlxs_proc_channel, cp);
3909 			}
3910 		}
3911 	}
3912 
3913 } /* emlxs_sli4_hba_flush_chipq() */
3914 
3915 
3916 /*ARGSUSED*/
3917 static void
3918 emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba,
3919     CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
3920 {
3921 	emlxs_port_t *port = &PPORT;
3922 	CHANNEL *cp;
3923 	uint16_t request_tag;
3924 	CQE_u	*cq_entry;
3925 
3926 	request_tag = cqe->RequestTag;
3927 
3928 	cq_entry = (CQE_u *)cqe;
3929 
3930 	/* 1 to 1 mapping between CQ and channel */
3931 	cp = cq->channelp;
3932 
3933 	cp->hbaCmplCmd++;
3934 
3935 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3936 	    "CQ ENTRY: OOR Cmpl: tag=%x", request_tag);
3937 
3938 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3939 	    "CQ ENTRY: %08x %08x %08x %08x", cq_entry->word[0],
3940 	    cq_entry->word[1], cq_entry->word[2], cq_entry->word[3]);
3941 
3942 } /* emlxs_sli4_process_oor_wqe_cmpl() */
3943 
3944 
3945 /*ARGSUSED*/
3946 static void
3947 emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
3948 {
3949 	emlxs_port_t *port = &PPORT;
3950 	CHANNEL *cp;
3951 	emlxs_buf_t *sbp;
3952 	IOCBQ *iocbq;
3953 	uint16_t request_tag;
3954 #ifdef SFCT_SUPPORT
3955 	fct_cmd_t *fct_cmd;
3956 	emlxs_buf_t *cmd_sbp;
3957 #endif /* SFCT_SUPPORT */
3958 
3959 	request_tag = cqe->RequestTag;
3960 
3961 	/* 1 to 1 mapping between CQ and channel */
3962 	cp = cq->channelp;
3963 
3964 	mutex_enter(&EMLXS_FCTAB_LOCK);
3965 	sbp = hba->fc_table[request_tag];
3966 	atomic_add_32(&hba->io_active, -1);
3967 
3968 	if (sbp == STALE_PACKET) {
3969 		cp->hbaCmplCmd_sbp++;
3970 		mutex_exit(&EMLXS_FCTAB_LOCK);
3971 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3972 		    "CQ ENTRY: Stale sbp. tag=%x. Dropping...", request_tag);
3973 		return;
3974 	}
3975 
3976 	if (!sbp || !(sbp->xrip)) {
3977 		cp->hbaCmplCmd++;
3978 		mutex_exit(&EMLXS_FCTAB_LOCK);
3979 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3980 		    "CQ ENTRY: NULL sbp %p. tag=%x. Dropping...",
3981 		    sbp, request_tag);
3982 		return;
3983 	}
3984 
3985 #ifdef SLI4_FASTPATH_DEBUG
3986 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3987 	    "CQ ENTRY: process wqe compl");
3988 #endif
3989 
3990 	cp->hbaCmplCmd_sbp++;
3991 
3992 	/* Copy entry to sbp's iocbq */
3993 	iocbq = &sbp->iocbq;
3994 	emlxs_CQE_to_IOCB(hba, cqe, sbp);
3995 
3996 	iocbq->next = NULL;
3997 
3998 	if (cqe->XB) {
3999 		/* Mark exchange as ABORT in progress */
4000 		sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO;
4001 		sbp->xrip->flag |= EMLXS_XRI_ABORT_INP;
4002 
4003 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4004 		    "CQ ENTRY: ABORT INP: tag=%x xri=%x", request_tag,
4005 		    sbp->xrip->XRI);
4006 
4007 		emlxs_sli4_free_xri(hba, sbp, 0, 0);
4008 	} else {
4009 		/* Exchange is no longer busy on-chip, free it */
4010 		emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 0);
4011 	}
4012 
4013 	mutex_exit(&EMLXS_FCTAB_LOCK);
4014 
4015 #ifdef SFCT_SUPPORT
4016 	fct_cmd = sbp->fct_cmd;
4017 	if (fct_cmd) {
4018 		cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4019 		mutex_enter(&cmd_sbp->fct_mtx);
4020 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE);
4021 		mutex_exit(&cmd_sbp->fct_mtx);
4022 	}
4023 #endif /* SFCT_SUPPORT */
4024 
4025 	/*
4026 	 * If this is NOT a polled command completion
4027 	 * or a driver allocated pkt, then defer pkt
4028 	 * completion.
4029 	 */
4030 	if (!(sbp->pkt_flags &
4031 	    (PACKET_POLLED | PACKET_ALLOCATED))) {
4032 		/* Add the IOCB to the channel list */
4033 		mutex_enter(&cp->rsp_lock);
4034 		if (cp->rsp_head == NULL) {
4035 			cp->rsp_head = iocbq;
4036 			cp->rsp_tail = iocbq;
4037 		} else {
4038 			cp->rsp_tail->next = iocbq;
4039 			cp->rsp_tail = iocbq;
4040 		}
4041 		mutex_exit(&cp->rsp_lock);
4042 
4043 		/* Delay triggering thread till end of ISR */
4044 		cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
4045 	} else {
4046 		emlxs_proc_channel_event(hba, cp, iocbq);
4047 	}
4048 
4049 } /* emlxs_sli4_process_wqe_cmpl() */
4050 
4051 
4052 /*ARGSUSED*/
4053 static void
4054 emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq,
4055     CQE_RelWQ_t *cqe)
4056 {
4057 #ifdef SLI4_FASTPATH_DEBUG
4058 	emlxs_port_t *port = &PPORT;
4059 #endif
4060 	WQ_DESC_t *wq;
4061 	CHANNEL *cp;
4062 	uint32_t i;
4063 
4064 	i = cqe->WQid;
4065 	wq = &hba->sli.sli4.wq[hba->sli.sli4.wq_map[i]];
4066 
4067 #ifdef SLI4_FASTPATH_DEBUG
4068 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4069 	    "CQ ENTRY: process release wqe: old %d new %d", wq->port_index,
4070 	    cqe->WQindex);
4071 #endif
4072 
4073 	wq->port_index = cqe->WQindex;
4074 
4075 	/* Cmd ring may be available. Try sending more iocbs */
4076 	for (i = 0; i < hba->chan_count; i++) {
4077 		cp = &hba->chan[i];
4078 		if (wq == (WQ_DESC_t *)cp->iopath) {
4079 			emlxs_sli4_issue_iocb_cmd(hba, cp, 0);
4080 		}
4081 	}
4082 
4083 } /* emlxs_sli4_process_release_wqe() */
4084 
4085 
4086 /*ARGSUSED*/
4087 emlxs_iocbq_t *
4088 emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr)
4089 {
4090 	emlxs_queue_t *q;
4091 	emlxs_iocbq_t *iocbq;
4092 	emlxs_iocbq_t *prev;
4093 	fc_frame_hdr_t *fchdr2;
4094 	RXQ_DESC_t *rxq;
4095 
4096 	switch (fchdr->type) {
4097 	case 1: /* ELS */
4098 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
4099 		break;
4100 	case 0x20: /* CT */
4101 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
4102 		break;
4103 	default:
4104 		return (NULL);
4105 	}
4106 
4107 	mutex_enter(&rxq->lock);
4108 
4109 	q = &rxq->active;
4110 	iocbq  = (emlxs_iocbq_t *)q->q_first;
4111 	prev = NULL;
4112 
4113 	while (iocbq) {
4114 
4115 		fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord;
4116 
4117 		if ((fchdr2->s_id == fchdr->s_id) &&
4118 		    (fchdr2->ox_id == fchdr->ox_id) &&
4119 		    (fchdr2->seq_id == fchdr->seq_id)) {
4120 			/* Remove iocbq */
4121 			if (prev) {
4122 				prev->next = iocbq->next;
4123 			}
4124 			if (q->q_first == (uint8_t *)iocbq) {
4125 				q->q_first = (uint8_t *)iocbq->next;
4126 			}
4127 			if (q->q_last == (uint8_t *)iocbq) {
4128 				q->q_last = (uint8_t *)prev;
4129 			}
4130 			q->q_cnt--;
4131 
4132 			break;
4133 		}
4134 
4135 		prev  = iocbq;
4136 		iocbq = iocbq->next;
4137 	}
4138 
4139 	mutex_exit(&rxq->lock);
4140 
4141 	return (iocbq);
4142 
4143 } /* emlxs_sli4_rxq_get() */
4144 
4145 
4146 /*ARGSUSED*/
4147 void
4148 emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq)
4149 {
4150 	emlxs_queue_t *q;
4151 	fc_frame_hdr_t *fchdr;
4152 	RXQ_DESC_t *rxq;
4153 
4154 	fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR;
4155 
4156 	switch (fchdr->type) {
4157 	case 1: /* ELS */
4158 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
4159 		break;
4160 	case 0x20: /* CT */
4161 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
4162 		break;
4163 	default:
4164 		return;
4165 	}
4166 
4167 	mutex_enter(&rxq->lock);
4168 
4169 	q = &rxq->active;
4170 
4171 	if (q->q_last) {
4172 		((emlxs_iocbq_t *)q->q_last)->next = iocbq;
4173 		q->q_cnt++;
4174 	} else {
4175 		q->q_first = (uint8_t *)iocbq;
4176 		q->q_cnt = 1;
4177 	}
4178 
4179 	q->q_last = (uint8_t *)iocbq;
4180 	iocbq->next = NULL;
4181 
4182 	mutex_exit(&rxq->lock);
4183 
4184 	return;
4185 
4186 } /* emlxs_sli4_rxq_put() */
4187 
4188 
4189 static void
4190 emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid)
4191 {
4192 	emlxs_hba_t *hba = HBA;
4193 	emlxs_rqdbu_t rqdb;
4194 
4195 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4196 	    "RQ POST: rqid=%d count=1", rqid);
4197 
4198 	/* Ring the RQ doorbell once to repost the RQ buffer */
4199 	rqdb.word = 0;
4200 	rqdb.db.Qid = rqid;
4201 	rqdb.db.NumPosted = 1;
4202 
4203 	WRITE_BAR2_REG(hba, FC_RQDB_REG(hba), rqdb.word);
4204 
4205 } /* emlxs_sli4_rq_post() */
4206 
4207 
4208 /*ARGSUSED*/
4209 static void
4210 emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq,
4211     CQE_UnsolRcv_t *cqe)
4212 {
4213 	emlxs_port_t *port = &PPORT;
4214 	emlxs_port_t *vport;
4215 	RQ_DESC_t *hdr_rq;
4216 	RQ_DESC_t *data_rq;
4217 	MBUF_INFO *hdr_mp;
4218 	MBUF_INFO *data_mp;
4219 	MATCHMAP *seq_mp;
4220 	uint32_t *data;
4221 	fc_frame_hdr_t fchdr;
4222 	uint32_t hdr_rqi;
4223 	uint32_t host_index;
4224 	emlxs_iocbq_t *iocbq = NULL;
4225 	emlxs_iocb_t *iocb;
4226 	emlxs_node_t *node;
4227 	uint32_t i;
4228 	uint32_t seq_len;
4229 	uint32_t seq_cnt;
4230 	uint32_t buf_type;
4231 	char label[32];
4232 	emlxs_wqe_t *wqe;
4233 	CHANNEL *cp;
4234 	uint16_t iotag;
4235 	XRIobj_t *xrip;
4236 	RPIobj_t *rpip = NULL;
4237 	uint32_t	cmd;
4238 	uint32_t posted = 0;
4239 	uint32_t abort = 1;
4240 	off_t offset;
4241 
4242 	hdr_rqi = hba->sli.sli4.rq_map[cqe->RQid];
4243 	hdr_rq  = &hba->sli.sli4.rq[hdr_rqi];
4244 	data_rq = &hba->sli.sli4.rq[hdr_rqi + 1];
4245 
4246 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4247 	    "CQ ENTRY: Unsol Rcv: RQid=%d,%d index=%d status=%x "
4248 	    "hdr_size=%d data_size=%d",
4249 	    cqe->RQid, hdr_rqi, hdr_rq->host_index, cqe->Status, cqe->hdr_size,
4250 	    cqe->data_size);
4251 
4252 	/* Validate the CQE */
4253 
4254 	/* Check status */
4255 	switch (cqe->Status) {
4256 	case RQ_STATUS_SUCCESS: /* 0x10 */
4257 		break;
4258 
4259 	case RQ_STATUS_BUFLEN_EXCEEDED:  /* 0x11 */
4260 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4261 		    "CQ ENTRY: Unsol Rcv: Payload truncated.");
4262 		break;
4263 
4264 	case RQ_STATUS_NEED_BUFFER: /* 0x12 */
4265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4266 		    "CQ ENTRY: Unsol Rcv: Payload buffer needed.");
4267 		return;
4268 
4269 	case RQ_STATUS_FRAME_DISCARDED:  /* 0x13 */
4270 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4271 		    "CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
4272 		return;
4273 
4274 	default:
4275 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4276 		    "CQ ENTRY: Unsol Rcv: Unknown status=%x.",
4277 		    cqe->Status);
4278 		break;
4279 	}
4280 
4281 	/* Make sure there is a frame header */
4282 	if (cqe->hdr_size < sizeof (fc_frame_hdr_t)) {
4283 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4284 		    "CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
4285 		return;
4286 	}
4287 
4288 	/* Update host index */
4289 	mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock);
4290 	host_index = hdr_rq->host_index;
4291 	hdr_rq->host_index++;
4292 	if (hdr_rq->host_index >= hdr_rq->max_index) {
4293 		hdr_rq->host_index = 0;
4294 	}
4295 	data_rq->host_index = hdr_rq->host_index;
4296 	mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock);
4297 
4298 	/* Get the next header rqb */
4299 	hdr_mp  = &hdr_rq->rqb[host_index];
4300 
4301 	offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) -
4302 	    (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt));
4303 
4304 	EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset,
4305 	    sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
4306 
4307 	LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr,
4308 	    sizeof (fc_frame_hdr_t));
4309 
4310 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4311 	    "RQ HDR[%d]: rctl:%x type:%x "
4312 	    "sid:%x did:%x oxid:%x rxid:%x",
4313 	    host_index, fchdr.r_ctl, fchdr.type,
4314 	    fchdr.s_id,  fchdr.d_id, fchdr.ox_id, fchdr.rx_id);
4315 
4316 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4317 	    "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
4318 	    host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt,
4319 	    fchdr.df_ctl, fchdr.ro);
4320 
4321 	/* Verify fc header type */
4322 	switch (fchdr.type) {
4323 	case 0: /* BLS */
4324 		if (fchdr.r_ctl != 0x81) {
4325 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4326 			    "RQ ENTRY: Unexpected FC rctl (0x%x) "
4327 			    "received. Dropping...",
4328 			    fchdr.r_ctl);
4329 
4330 			goto done;
4331 		}
4332 
4333 		/* Make sure there is no payload */
4334 		if (cqe->data_size != 0) {
4335 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4336 			    "RQ ENTRY: ABTS payload provided. Dropping...");
4337 
4338 			goto done;
4339 		}
4340 
4341 		buf_type = 0xFFFFFFFF;
4342 		(void) strcpy(label, "ABTS");
4343 		cp = &hba->chan[hba->channel_els];
4344 		break;
4345 
4346 	case 0x01: /* ELS */
4347 		/* Make sure there is a payload */
4348 		if (cqe->data_size == 0) {
4349 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4350 			    "RQ ENTRY: Unsol Rcv: No ELS payload provided. "
4351 			    "Dropping...");
4352 
4353 			goto done;
4354 		}
4355 
4356 		buf_type = MEM_ELSBUF;
4357 		(void) strcpy(label, "Unsol ELS");
4358 		cp = &hba->chan[hba->channel_els];
4359 		break;
4360 
4361 	case 0x20: /* CT */
4362 		/* Make sure there is a payload */
4363 		if (cqe->data_size == 0) {
4364 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4365 			    "RQ ENTRY: Unsol Rcv: No CT payload provided. "
4366 			    "Dropping...");
4367 
4368 			goto done;
4369 		}
4370 
4371 		buf_type = MEM_CTBUF;
4372 		(void) strcpy(label, "Unsol CT");
4373 		cp = &hba->chan[hba->channel_ct];
4374 		break;
4375 
4376 	default:
4377 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4378 		    "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
4379 		    fchdr.type);
4380 
4381 		goto done;
4382 	}
4383 	/* Fc Header is valid */
4384 
4385 	/* Check if this is an active sequence */
4386 	iocbq = emlxs_sli4_rxq_get(hba, &fchdr);
4387 
4388 	if (!iocbq) {
4389 		if (fchdr.type != 0) {
4390 			if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) {
4391 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4392 				    "RQ ENTRY: %s: First of sequence not"
4393 				    " set.  Dropping...",
4394 				    label);
4395 
4396 				goto done;
4397 			}
4398 		}
4399 
4400 		if (fchdr.seq_cnt != 0) {
4401 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4402 			    "RQ ENTRY: %s: Sequence count not zero (%d).  "
4403 			    "Dropping...",
4404 			    label, fchdr.seq_cnt);
4405 
4406 			goto done;
4407 		}
4408 
4409 		/* Find vport (defaults to physical port) */
4410 		for (i = 0; i < MAX_VPORTS; i++) {
4411 			vport = &VPORT(i);
4412 
4413 			if (vport->did == fchdr.d_id) {
4414 				port = vport;
4415 				break;
4416 			}
4417 		}
4418 
4419 		/* Allocate an IOCBQ */
4420 		iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba,
4421 		    MEM_IOCB, 1);
4422 
4423 		if (!iocbq) {
4424 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4425 			    "RQ ENTRY: %s: Out of IOCB "
4426 			    "resources.  Dropping...",
4427 			    label);
4428 
4429 			goto done;
4430 		}
4431 
4432 		seq_mp = NULL;
4433 		if (fchdr.type != 0) {
4434 			/* Allocate a buffer */
4435 			seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type, 1);
4436 
4437 			if (!seq_mp) {
4438 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4439 				    "RQ ENTRY: %s: Out of buffer "
4440 				    "resources.  Dropping...",
4441 				    label);
4442 
4443 				goto done;
4444 			}
4445 
4446 			iocbq->bp = (uint8_t *)seq_mp;
4447 		}
4448 
4449 		node = (void *)emlxs_node_find_did(port, fchdr.s_id);
4450 		if (node == NULL) {
4451 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4452 			    "RQ ENTRY: %s: Node not found. sid=%x",
4453 			    label, fchdr.s_id);
4454 		}
4455 
4456 		/* Initialize the iocbq */
4457 		iocbq->port = port;
4458 		iocbq->channel = cp;
4459 		iocbq->node = node;
4460 
4461 		iocb = &iocbq->iocb;
4462 		iocb->RXSEQCNT = 0;
4463 		iocb->RXSEQLEN = 0;
4464 
4465 		seq_len = 0;
4466 		seq_cnt = 0;
4467 
4468 	} else {
4469 
4470 		iocb = &iocbq->iocb;
4471 		port = iocbq->port;
4472 		node = (emlxs_node_t *)iocbq->node;
4473 
4474 		seq_mp = (MATCHMAP *)iocbq->bp;
4475 		seq_len = iocb->RXSEQLEN;
4476 		seq_cnt = iocb->RXSEQCNT;
4477 
4478 		/* Check sequence order */
4479 		if (fchdr.seq_cnt != seq_cnt) {
4480 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4481 			    "RQ ENTRY: %s: Out of order frame received "
4482 			    "(%d != %d).  Dropping...",
4483 			    label, fchdr.seq_cnt, seq_cnt);
4484 
4485 			goto done;
4486 		}
4487 	}
4488 
4489 	/* We now have an iocbq */
4490 
4491 	if (!port->VPIobj.vfip) {
4492 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4493 		    "RQ ENTRY: %s: No fabric connection. "
4494 		    "Dropping...",
4495 		    label);
4496 
4497 		goto done;
4498 	}
4499 
4500 	/* Save the frame data to our seq buffer */
4501 	if (cqe->data_size && seq_mp) {
4502 		/* Get the next data rqb */
4503 		data_mp = &data_rq->rqb[host_index];
4504 
4505 		offset = (off_t)((uint64_t)((unsigned long)
4506 		    data_mp->virt) -
4507 		    (uint64_t)((unsigned long)
4508 		    hba->sli.sli4.slim2.virt));
4509 
4510 		EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset,
4511 		    cqe->data_size, DDI_DMA_SYNC_FORKERNEL);
4512 
4513 		data = (uint32_t *)data_mp->virt;
4514 
4515 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4516 		    "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
4517 		    host_index, data[0], data[1], data[2], data[3],
4518 		    data[4], data[5]);
4519 
4520 		/* Check sequence length */
4521 		if ((seq_len + cqe->data_size) > seq_mp->size) {
4522 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4523 			    "RQ ENTRY: %s: Sequence buffer overflow. "
4524 			    "(%d > %d). Dropping...",
4525 			    label, (seq_len + cqe->data_size), seq_mp->size);
4526 
4527 			goto done;
4528 		}
4529 
4530 		/* Copy data to local receive buffer */
4531 		bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt +
4532 		    seq_len), cqe->data_size);
4533 
4534 		seq_len += cqe->data_size;
4535 	}
4536 
4537 	/* If this is not the last frame of sequence, queue it. */
4538 	if (!(fchdr.f_ctl & F_CTL_END_SEQ)) {
4539 		/* Save sequence header */
4540 		if (seq_cnt == 0) {
4541 			bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR,
4542 			    sizeof (fc_frame_hdr_t));
4543 		}
4544 
4545 		/* Update sequence info in iocb */
4546 		iocb->RXSEQCNT = seq_cnt + 1;
4547 		iocb->RXSEQLEN = seq_len;
4548 
4549 		/* Queue iocbq for next frame */
4550 		emlxs_sli4_rxq_put(hba, iocbq);
4551 
4552 		/* Don't free resources */
4553 		iocbq = NULL;
4554 
4555 		/* No need to abort */
4556 		abort = 0;
4557 
4558 		goto done;
4559 	}
4560 
4561 	emlxs_sli4_rq_post(port, hdr_rq->qid);
4562 	posted = 1;
4563 
4564 	/* End of sequence found. Process request now. */
4565 
4566 	if (seq_cnt > 0) {
4567 		/* Retrieve first frame of sequence */
4568 		bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr,
4569 		    sizeof (fc_frame_hdr_t));
4570 
4571 		bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t));
4572 	}
4573 
4574 	/* Build rcv iocb and process it */
4575 	switch (fchdr.type) {
4576 	case 0: /* BLS */
4577 
4578 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4579 		    "RQ ENTRY: %s: xid:%x sid:%x. Sending BLS ACC...",
4580 		    label, fchdr.ox_id, fchdr.s_id);
4581 
4582 		iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL);
4583 
4584 		/* Set up an iotag using special Abort iotags */
4585 		mutex_enter(&EMLXS_FCTAB_LOCK);
4586 		if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) {
4587 			hba->fc_oor_iotag = hba->max_iotag;
4588 		}
4589 		iotag = hba->fc_oor_iotag++;
4590 		mutex_exit(&EMLXS_FCTAB_LOCK);
4591 
4592 		/* BLS ACC Response */
4593 		wqe = &iocbq->wqe;
4594 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
4595 
4596 		wqe->Command = CMD_XMIT_BLS_RSP64_CX;
4597 		wqe->CmdType = WQE_TYPE_GEN;
4598 
4599 		wqe->un.BlsRsp.Payload0 = 0x80;
4600 		wqe->un.BlsRsp.Payload1 = fchdr.seq_id;
4601 
4602 		wqe->un.BlsRsp.OXId = fchdr.ox_id;
4603 		wqe->un.BlsRsp.RXId = fchdr.rx_id;
4604 
4605 		wqe->un.BlsRsp.SeqCntLow = 0;
4606 		wqe->un.BlsRsp.SeqCntHigh = 0xFFFF;
4607 
4608 		wqe->un.BlsRsp.XO = 0;
4609 		wqe->un.BlsRsp.AR = 0;
4610 		wqe->un.BlsRsp.PT = 1;
4611 		wqe->un.BlsRsp.RemoteId = fchdr.s_id;
4612 
4613 		wqe->PU = 0x3;
4614 		wqe->ContextTag = port->VPIobj.VPI;
4615 		wqe->ContextType = WQE_VPI_CONTEXT;
4616 		wqe->OXId = (volatile uint16_t) fchdr.ox_id;
4617 		wqe->XRITag = 0xffff;
4618 
4619 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
4620 			wqe->CCPE = 1;
4621 			wqe->CCP = fchdr.rsvd;
4622 		}
4623 
4624 		wqe->Class = CLASS3;
4625 		wqe->RequestTag = iotag;
4626 		wqe->CQId = 0x3ff;
4627 
4628 		emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq);
4629 
4630 		break;
4631 
4632 	case 1: /* ELS */
4633 		if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
4634 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4635 			    "RQ ENTRY: %s: Port not yet enabled. "
4636 			    "Dropping...",
4637 			    label);
4638 
4639 			goto done;
4640 		}
4641 
4642 		cmd = *((uint32_t *)seq_mp->virt);
4643 		cmd &= ELS_CMD_MASK;
4644 		rpip = NULL;
4645 
4646 		if (cmd != ELS_CMD_LOGO) {
4647 			rpip = EMLXS_NODE_TO_RPI(port, node);
4648 		}
4649 
4650 		if (!rpip) {
4651 			rpip = port->VPIobj.rpip;
4652 		}
4653 
4654 		xrip = emlxs_sli4_reserve_xri(hba, rpip);
4655 
4656 		if (!xrip) {
4657 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4658 			    "RQ ENTRY: %s: Out of exchange "
4659 			    "resources.  Dropping...",
4660 			    label);
4661 
4662 			goto done;
4663 		}
4664 
4665 		xrip->rx_id = fchdr.ox_id;
4666 
4667 		/* Build CMD_RCV_ELS64_CX */
4668 		iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0;
4669 		iocb->un.rcvels64.elsReq.tus.f.bdeSize  = seq_len;
4670 		iocb->un.rcvels64.elsReq.addrLow  = PADDR_LO(seq_mp->phys);
4671 		iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys);
4672 		iocb->ULPBDECOUNT = 1;
4673 
4674 		iocb->un.rcvels64.remoteID = fchdr.s_id;
4675 		iocb->un.rcvels64.parmRo = fchdr.d_id;
4676 
4677 		iocb->ULPPU = 0x3;
4678 		iocb->ULPCONTEXT = xrip->XRI;
4679 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
4680 		iocb->ULPCLASS = CLASS3;
4681 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
4682 
4683 		iocb->unsli3.ext_rcv.seq_len = seq_len;
4684 		iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
4685 
4686 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
4687 			iocb->unsli3.ext_rcv.ccpe = 1;
4688 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
4689 		}
4690 
4691 		(void) emlxs_els_handle_unsol_req(port, iocbq->channel,
4692 		    iocbq, seq_mp, seq_len);
4693 
4694 		break;
4695 
4696 	case 0x20: /* CT */
4697 		if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
4698 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4699 			    "RQ ENTRY: %s: Port not yet enabled. "
4700 			    "Dropping...",
4701 			    label);
4702 
4703 			goto done;
4704 		}
4705 
4706 		if (!node) {
4707 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4708 			    "RQ ENTRY: %s: Node not found (did=%x).  "
4709 			    "Dropping...",
4710 			    label, fchdr.d_id);
4711 
4712 			goto done;
4713 		}
4714 
4715 		rpip = EMLXS_NODE_TO_RPI(port, node);
4716 
4717 		if (!rpip) {
4718 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4719 			    "RQ ENTRY: %s: RPI not found (did=%x rpi=%x).  "
4720 			    "Dropping...",
4721 			    label, fchdr.d_id, node->nlp_Rpi);
4722 
4723 			goto done;
4724 		}
4725 
4726 		xrip = emlxs_sli4_reserve_xri(hba, rpip);
4727 
4728 		if (!xrip) {
4729 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4730 			    "RQ ENTRY: %s: Out of exchange "
4731 			    "resources.  Dropping...",
4732 			    label);
4733 
4734 			goto done;
4735 		}
4736 
4737 		xrip->rx_id = fchdr.ox_id;
4738 
4739 		/* Build CMD_RCV_SEQ64_CX */
4740 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
4741 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
4742 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
4743 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
4744 		iocb->ULPBDECOUNT = 1;
4745 
4746 		iocb->un.rcvseq64.xrsqRo = 0;
4747 		iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl;
4748 		iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type;
4749 		iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl;
4750 		iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl;
4751 
4752 		iocb->ULPPU = 0x3;
4753 		iocb->ULPCONTEXT = xrip->XRI;
4754 		iocb->ULPIOTAG = rpip->RPI;
4755 		iocb->ULPCLASS = CLASS3;
4756 		iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX;
4757 
4758 		iocb->unsli3.ext_rcv.seq_len = seq_len;
4759 		iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
4760 
4761 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
4762 			iocb->unsli3.ext_rcv.ccpe = 1;
4763 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
4764 		}
4765 
4766 		(void) emlxs_ct_handle_unsol_req(port, iocbq->channel,
4767 		    iocbq, seq_mp, seq_len);
4768 
4769 		break;
4770 	}
4771 
4772 	/* Sequence handled, no need to abort */
4773 	abort = 0;
4774 
4775 done:
4776 
4777 	if (!posted) {
4778 		emlxs_sli4_rq_post(port, hdr_rq->qid);
4779 	}
4780 
4781 	if (abort) {
4782 		/* Send ABTS for this exchange */
4783 		/* !!! Currently, we have no implementation for this !!! */
4784 		abort = 0;
4785 	}
4786 
4787 	/* Return memory resources to pools */
4788 	if (iocbq) {
4789 		if (iocbq->bp) {
4790 			emlxs_mem_put(hba, buf_type, (void *)iocbq->bp);
4791 		}
4792 
4793 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
4794 	}
4795 
4796 #ifdef FMA_SUPPORT
4797 	if (emlxs_fm_check_dma_handle(hba,
4798 	    hba->sli.sli4.slim2.dma_handle)
4799 	    != DDI_FM_OK) {
4800 		EMLXS_MSGF(EMLXS_CONTEXT,
4801 		    &emlxs_invalid_dma_handle_msg,
4802 		    "emlxs_sli4_process_unsol_rcv: hdl=%p",
4803 		    hba->sli.sli4.slim2.dma_handle);
4804 
4805 		emlxs_thread_spawn(hba, emlxs_restart_thread,
4806 		    0, 0);
4807 	}
4808 #endif
4809 	return;
4810 
4811 } /* emlxs_sli4_process_unsol_rcv() */
4812 
4813 
4814 /*ARGSUSED*/
4815 static void
4816 emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq,
4817     CQE_XRI_Abort_t *cqe)
4818 {
4819 	emlxs_port_t *port = &PPORT;
4820 	XRIobj_t *xrip;
4821 
4822 	mutex_enter(&EMLXS_FCTAB_LOCK);
4823 
4824 	xrip = emlxs_sli4_find_xri(hba, cqe->XRI);
4825 	if (xrip == NULL) {
4826 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4827 		    "CQ ENTRY: process xri aborted ignored");
4828 
4829 		mutex_exit(&EMLXS_FCTAB_LOCK);
4830 		return;
4831 	}
4832 
4833 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4834 	    "CQ ENTRY: process xri x%x aborted: IA %d EO %d BR %d",
4835 	    cqe->XRI, cqe->IA, cqe->EO, cqe->BR);
4836 
4837 	if (!(xrip->flag & EMLXS_XRI_ABORT_INP)) {
4838 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4839 		    "XRI Aborted: Bad state: x%x xri x%x",
4840 		    xrip->flag, xrip->XRI);
4841 
4842 		mutex_exit(&EMLXS_FCTAB_LOCK);
4843 		return;
4844 	}
4845 
4846 	/* Exchange is no longer busy on-chip, free it */
4847 	emlxs_sli4_free_xri(hba, 0, xrip, 0);
4848 
4849 	mutex_exit(&EMLXS_FCTAB_LOCK);
4850 
4851 	return;
4852 
4853 } /* emlxs_sli4_process_xri_aborted () */
4854 
4855 
4856 /*ARGSUSED*/
4857 static void
4858 emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq)
4859 {
4860 	emlxs_port_t *port = &PPORT;
4861 	CQE_u *cqe;
4862 	CQE_u cq_entry;
4863 	uint32_t cqdb;
4864 	int num_entries = 0;
4865 	off_t offset;
4866 
4867 	/* EMLXS_PORT_LOCK must be held when entering this routine */
4868 
4869 	cqe = (CQE_u *)cq->addr.virt;
4870 	cqe += cq->host_index;
4871 
4872 	offset = (off_t)((uint64_t)((unsigned long)
4873 	    cq->addr.virt) -
4874 	    (uint64_t)((unsigned long)
4875 	    hba->sli.sli4.slim2.virt));
4876 
4877 	EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset,
4878 	    4096, DDI_DMA_SYNC_FORKERNEL);
4879 
4880 	for (;;) {
4881 		cq_entry.word[3] = BE_SWAP32(cqe->word[3]);
4882 		if (!(cq_entry.word[3] & CQE_VALID))
4883 			break;
4884 
4885 		cq_entry.word[2] = BE_SWAP32(cqe->word[2]);
4886 		cq_entry.word[1] = BE_SWAP32(cqe->word[1]);
4887 		cq_entry.word[0] = BE_SWAP32(cqe->word[0]);
4888 
4889 #ifdef SLI4_FASTPATH_DEBUG
4890 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4891 		    "CQ ENTRY: %08x %08x %08x %08x", cq_entry.word[0],
4892 		    cq_entry.word[1], cq_entry.word[2], cq_entry.word[3]);
4893 #endif
4894 
4895 		num_entries++;
4896 		cqe->word[3] = 0;
4897 
4898 		cq->host_index++;
4899 		if (cq->host_index >= cq->max_index) {
4900 			cq->host_index = 0;
4901 			cqe = (CQE_u *)cq->addr.virt;
4902 		} else {
4903 			cqe++;
4904 		}
4905 		mutex_exit(&EMLXS_PORT_LOCK);
4906 
4907 		/* Now handle specific cq type */
4908 		if (cq->type == EMLXS_CQ_TYPE_GROUP1) {
4909 			if (cq_entry.cqAsyncEntry.async_evt) {
4910 				emlxs_sli4_process_async_event(hba,
4911 				    (CQE_ASYNC_t *)&cq_entry);
4912 			} else {
4913 				emlxs_sli4_process_mbox_event(hba,
4914 				    (CQE_MBOX_t *)&cq_entry);
4915 			}
4916 		} else { /* EMLXS_CQ_TYPE_GROUP2 */
4917 			switch (cq_entry.cqCmplEntry.Code) {
4918 			case CQE_TYPE_WQ_COMPLETION:
4919 				if (cq_entry.cqCmplEntry.RequestTag <
4920 				    hba->max_iotag) {
4921 					emlxs_sli4_process_wqe_cmpl(hba, cq,
4922 					    (CQE_CmplWQ_t *)&cq_entry);
4923 				} else {
4924 					emlxs_sli4_process_oor_wqe_cmpl(hba, cq,
4925 					    (CQE_CmplWQ_t *)&cq_entry);
4926 				}
4927 				break;
4928 			case CQE_TYPE_RELEASE_WQE:
4929 				emlxs_sli4_process_release_wqe(hba, cq,
4930 				    (CQE_RelWQ_t *)&cq_entry);
4931 				break;
4932 			case CQE_TYPE_UNSOL_RCV:
4933 				emlxs_sli4_process_unsol_rcv(hba, cq,
4934 				    (CQE_UnsolRcv_t *)&cq_entry);
4935 				break;
4936 			case CQE_TYPE_XRI_ABORTED:
4937 				emlxs_sli4_process_xri_aborted(hba, cq,
4938 				    (CQE_XRI_Abort_t *)&cq_entry);
4939 				break;
4940 			default:
4941 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4942 				    "Invalid CQ entry %d: %08x %08x %08x %08x",
4943 				    cq_entry.cqCmplEntry.Code, cq_entry.word[0],
4944 				    cq_entry.word[1], cq_entry.word[2],
4945 				    cq_entry.word[3]);
4946 				break;
4947 			}
4948 		}
4949 
4950 		mutex_enter(&EMLXS_PORT_LOCK);
4951 	}
4952 
4953 	cqdb = cq->qid;
4954 	cqdb |= CQ_DB_REARM;
4955 	if (num_entries != 0) {
4956 		cqdb |= ((num_entries << CQ_DB_POP_SHIFT) & CQ_DB_POP_MASK);
4957 	}
4958 
4959 #ifdef SLI4_FASTPATH_DEBUG
4960 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4961 	    "CQ CLEAR: %08x: pops:x%x", cqdb, num_entries);
4962 #endif
4963 
4964 	WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), cqdb);
4965 
4966 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
4967 
4968 } /* emlxs_sli4_process_cq() */
4969 
4970 
4971 /*ARGSUSED*/
4972 static void
4973 emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
4974 {
4975 #ifdef SLI4_FASTPATH_DEBUG
4976 	emlxs_port_t *port = &PPORT;
4977 #endif
4978 	uint32_t eqdb;
4979 	uint32_t *ptr;
4980 	CHANNEL *cp;
4981 	EQE_u eqe;
4982 	uint32_t i;
4983 	uint32_t value;
4984 	int num_entries = 0;
4985 	off_t offset;
4986 
4987 	/* EMLXS_PORT_LOCK must be held when entering this routine */
4988 
4989 	ptr = eq->addr.virt;
4990 	ptr += eq->host_index;
4991 
4992 	offset = (off_t)((uint64_t)((unsigned long)
4993 	    eq->addr.virt) -
4994 	    (uint64_t)((unsigned long)
4995 	    hba->sli.sli4.slim2.virt));
4996 
4997 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
4998 	    4096, DDI_DMA_SYNC_FORKERNEL);
4999 
5000 	for (;;) {
5001 		eqe.word = *ptr;
5002 		eqe.word = BE_SWAP32(eqe.word);
5003 
5004 		if (!(eqe.word & EQE_VALID))
5005 			break;
5006 
5007 #ifdef SLI4_FASTPATH_DEBUG
5008 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5009 		    "EQ ENTRY: %08x", eqe.word);
5010 #endif
5011 
5012 		*ptr = 0;
5013 		num_entries++;
5014 		eq->host_index++;
5015 		if (eq->host_index >= eq->max_index) {
5016 			eq->host_index = 0;
5017 			ptr = eq->addr.virt;
5018 		} else {
5019 			ptr++;
5020 		}
5021 
5022 		value = hba->sli.sli4.cq_map[eqe.entry.CQId];
5023 
5024 #ifdef SLI4_FASTPATH_DEBUG
5025 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5026 		    "EQ ENTRY:  CQIndex:x%x: cqid:x%x", value, eqe.entry.CQId);
5027 #endif
5028 
5029 		emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[value]);
5030 	}
5031 
5032 	eqdb = eq->qid;
5033 	eqdb |= (EQ_DB_CLEAR | EQ_DB_EVENT | EQ_DB_REARM);
5034 
5035 #ifdef SLI4_FASTPATH_DEBUG
5036 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5037 	    "EQ CLEAR: %08x: pops:x%x", eqdb, num_entries);
5038 #endif
5039 
5040 	if (num_entries != 0) {
5041 		eqdb |= ((num_entries << EQ_DB_POP_SHIFT) & EQ_DB_POP_MASK);
5042 		for (i = 0; i < hba->chan_count; i++) {
5043 			cp = &hba->chan[i];
5044 			if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) {
5045 				cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER;
5046 				emlxs_thread_trigger2(&cp->intr_thread,
5047 				    emlxs_proc_channel, cp);
5048 			}
5049 		}
5050 	}
5051 
5052 	WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), eqdb);
5053 
5054 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
5055 
5056 } /* emlxs_sli4_process_eq() */
5057 
5058 
5059 #ifdef MSI_SUPPORT
5060 /*ARGSUSED*/
5061 static uint32_t
5062 emlxs_sli4_msi_intr(char *arg1, char *arg2)
5063 {
5064 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
5065 #ifdef SLI4_FASTPATH_DEBUG
5066 	emlxs_port_t *port = &PPORT;
5067 #endif
5068 	uint16_t msgid;
5069 	int rc;
5070 
5071 #ifdef SLI4_FASTPATH_DEBUG
5072 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5073 	    "msiINTR arg1:%p arg2:%p", arg1, arg2);
5074 #endif
5075 
5076 	/* Check for legacy interrupt handling */
5077 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
5078 		rc = emlxs_sli4_intx_intr(arg1);
5079 		return (rc);
5080 	}
5081 
5082 	/* Get MSI message id */
5083 	msgid = (uint16_t)((unsigned long)arg2);
5084 
5085 	/* Validate the message id */
5086 	if (msgid >= hba->intr_count) {
5087 		msgid = 0;
5088 	}
5089 	mutex_enter(&EMLXS_PORT_LOCK);
5090 
5091 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
5092 		mutex_exit(&EMLXS_PORT_LOCK);
5093 		return (DDI_INTR_UNCLAIMED);
5094 	}
5095 
5096 	/* The eq[] index == the MSI vector number */
5097 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]);
5098 
5099 	mutex_exit(&EMLXS_PORT_LOCK);
5100 	return (DDI_INTR_CLAIMED);
5101 
5102 } /* emlxs_sli4_msi_intr() */
5103 #endif /* MSI_SUPPORT */
5104 
5105 
5106 /*ARGSUSED*/
5107 static int
5108 emlxs_sli4_intx_intr(char *arg)
5109 {
5110 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
5111 #ifdef SLI4_FASTPATH_DEBUG
5112 	emlxs_port_t *port = &PPORT;
5113 #endif
5114 
5115 #ifdef SLI4_FASTPATH_DEBUG
5116 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5117 	    "intxINTR arg:%p", arg);
5118 #endif
5119 
5120 	mutex_enter(&EMLXS_PORT_LOCK);
5121 
5122 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
5123 		mutex_exit(&EMLXS_PORT_LOCK);
5124 		return (DDI_INTR_UNCLAIMED);
5125 	}
5126 
5127 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]);
5128 
5129 	mutex_exit(&EMLXS_PORT_LOCK);
5130 	return (DDI_INTR_CLAIMED);
5131 } /* emlxs_sli4_intx_intr() */
5132 
5133 
5134 static void
5135 emlxs_sli4_hba_kill(emlxs_hba_t *hba)
5136 {
5137 	emlxs_port_t *port = &PPORT;
5138 	uint32_t j;
5139 
5140 	mutex_enter(&EMLXS_PORT_LOCK);
5141 	if (hba->flag & FC_INTERLOCKED) {
5142 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5143 
5144 		mutex_exit(&EMLXS_PORT_LOCK);
5145 
5146 		return;
5147 	}
5148 
5149 	j = 0;
5150 	while (j++ < 10000) {
5151 		if (hba->mbox_queue_flag == 0) {
5152 			break;
5153 		}
5154 
5155 		mutex_exit(&EMLXS_PORT_LOCK);
5156 		DELAYUS(100);
5157 		mutex_enter(&EMLXS_PORT_LOCK);
5158 	}
5159 
5160 	if (hba->mbox_queue_flag != 0) {
5161 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5162 		    "Board kill failed. Mailbox busy.");
5163 		mutex_exit(&EMLXS_PORT_LOCK);
5164 		return;
5165 	}
5166 
5167 	hba->flag |= FC_INTERLOCKED;
5168 
5169 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5170 
5171 	mutex_exit(&EMLXS_PORT_LOCK);
5172 
5173 } /* emlxs_sli4_hba_kill() */
5174 
5175 
5176 static void
5177 emlxs_sli4_enable_intr(emlxs_hba_t *hba)
5178 {
5179 	emlxs_config_t *cfg = &CFG;
5180 	int i;
5181 	int num_cq;
5182 	uint32_t data;
5183 
5184 	hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED;
5185 
5186 	num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) +
5187 	    EMLXS_CQ_OFFSET_WQ;
5188 
5189 	/* ARM EQ / CQs */
5190 	for (i = 0; i < num_cq; i++) {
5191 		data = hba->sli.sli4.cq[i].qid;
5192 		data |= CQ_DB_REARM;
5193 		WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), data);
5194 	}
5195 	for (i = 0; i < hba->intr_count; i++) {
5196 		data = hba->sli.sli4.eq[i].qid;
5197 		data |= (EQ_DB_REARM | EQ_DB_EVENT);
5198 		WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), data);
5199 	}
5200 } /* emlxs_sli4_enable_intr() */
5201 
5202 
5203 static void
5204 emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att)
5205 {
5206 	if (att) {
5207 		return;
5208 	}
5209 
5210 	hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
5211 
5212 	/* Short of reset, we cannot disable interrupts */
5213 } /* emlxs_sli4_disable_intr() */
5214 
5215 
5216 static void
5217 emlxs_sli4_resource_free(emlxs_hba_t *hba)
5218 {
5219 	emlxs_port_t	*port = &PPORT;
5220 	MBUF_INFO	*buf_info;
5221 	uint32_t	i;
5222 
5223 	emlxs_fcf_fini(hba);
5224 
5225 	buf_info = &hba->sli.sli4.HeaderTmplate;
5226 	if (buf_info->virt) {
5227 		bzero(buf_info, sizeof (MBUF_INFO));
5228 	}
5229 
5230 	if (hba->sli.sli4.XRIp) {
5231 		if ((hba->sli.sli4.XRIinuse_f !=
5232 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
5233 		    (hba->sli.sli4.XRIinuse_b !=
5234 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
5235 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
5236 			    "XRIs inuse during free!: %p %p != %p\n",
5237 			    hba->sli.sli4.XRIinuse_f,
5238 			    hba->sli.sli4.XRIinuse_b,
5239 			    &hba->sli.sli4.XRIinuse_f);
5240 		}
5241 		kmem_free(hba->sli.sli4.XRIp,
5242 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
5243 		hba->sli.sli4.XRIp = NULL;
5244 
5245 		hba->sli.sli4.XRIfree_f =
5246 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5247 		hba->sli.sli4.XRIfree_b =
5248 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5249 		hba->sli.sli4.xrif_count = 0;
5250 	}
5251 
5252 	for (i = 0; i < EMLXS_MAX_EQS; i++) {
5253 		mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock);
5254 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
5255 	}
5256 	for (i = 0; i < EMLXS_MAX_CQS; i++) {
5257 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
5258 	}
5259 	for (i = 0; i < EMLXS_MAX_WQS; i++) {
5260 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
5261 	}
5262 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5263 		mutex_destroy(&hba->sli.sli4.rq[i].lock);
5264 		mutex_destroy(&hba->sli.sli4.rxq[i].lock);
5265 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
5266 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
5267 	}
5268 
5269 	/* Free the MQ */
5270 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
5271 
5272 	buf_info = &hba->sli.sli4.slim2;
5273 	if (buf_info->virt) {
5274 		buf_info->flags = FC_MBUF_DMA;
5275 		emlxs_mem_free(hba, buf_info);
5276 		bzero(buf_info, sizeof (MBUF_INFO));
5277 	}
5278 
5279 	/* Cleanup queue ordinal mapping */
5280 	for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) {
5281 		hba->sli.sli4.eq_map[i] = 0xffff;
5282 	}
5283 	for (i = 0; i < EMLXS_MAX_CQ_IDS; i++) {
5284 		hba->sli.sli4.cq_map[i] = 0xffff;
5285 	}
5286 	for (i = 0; i < EMLXS_MAX_WQ_IDS; i++) {
5287 		hba->sli.sli4.wq_map[i] = 0xffff;
5288 	}
5289 
5290 } /* emlxs_sli4_resource_free() */
5291 
5292 
5293 static int
5294 emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
5295 {
5296 	emlxs_port_t	*port = &PPORT;
5297 	emlxs_config_t	*cfg = &CFG;
5298 	MBUF_INFO	*buf_info;
5299 	uint16_t	index;
5300 	int		num_eq;
5301 	int		num_wq;
5302 	uint16_t	i;
5303 	uint32_t	j;
5304 	uint32_t	k;
5305 	uint32_t	word;
5306 	XRIobj_t	*xrip;
5307 	char		buf[64];
5308 	RQE_t		*rqe;
5309 	MBUF_INFO	*rqb;
5310 	uint64_t	phys;
5311 	uint64_t	tmp_phys;
5312 	char		*virt;
5313 	char		*tmp_virt;
5314 	void		*data_handle;
5315 	void		*dma_handle;
5316 	int32_t		size;
5317 	off_t		offset;
5318 	uint32_t	count = 0;
5319 
5320 	emlxs_fcf_init(hba);
5321 
5322 	/* EQs - 1 per Interrupt vector */
5323 	num_eq = hba->intr_count;
5324 	/* CQs  - number of WQs + 1 for RQs + 1 for mbox/async events */
5325 	num_wq = cfg[CFG_NUM_WQ].current * num_eq;
5326 
5327 	/* Calculate total dmable memory we need */
5328 	/* EQ */
5329 	count += num_eq * 4096;
5330 	/* CQ */
5331 	count += (num_wq + EMLXS_CQ_OFFSET_WQ) * 4096;
5332 	/* WQ */
5333 	count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES);
5334 	/* MQ */
5335 	count +=  EMLXS_MAX_MQS * 4096;
5336 	/* RQ */
5337 	count +=  EMLXS_MAX_RQS * 4096;
5338 	/* RQB/E */
5339 	count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE);
5340 	/* SGL */
5341 	count += hba->sli.sli4.XRICount * hba->sli.sli4.mem_sgl_size;
5342 	/* RPI Head Template */
5343 	count += hba->sli.sli4.RPICount * sizeof (RPIHdrTmplate_t);
5344 
5345 	/* Allocate slim2 for SLI4 */
5346 	buf_info = &hba->sli.sli4.slim2;
5347 	buf_info->size = count;
5348 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5349 	buf_info->align = ddi_ptob(hba->dip, 1L);
5350 
5351 	(void) emlxs_mem_alloc(hba, buf_info);
5352 
5353 	if (buf_info->virt == NULL) {
5354 		EMLXS_MSGF(EMLXS_CONTEXT,
5355 		    &emlxs_init_failed_msg,
5356 		    "Unable to allocate internal memory for SLI4: %d",
5357 		    count);
5358 		goto failed;
5359 	}
5360 	bzero(buf_info->virt, buf_info->size);
5361 	EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
5362 	    buf_info->size, DDI_DMA_SYNC_FORDEV);
5363 
5364 	/* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
5365 	data_handle = buf_info->data_handle;
5366 	dma_handle = buf_info->dma_handle;
5367 	phys = buf_info->phys;
5368 	virt = (char *)buf_info->virt;
5369 
5370 	/* Allocate space for queues */
5371 	size = 4096;
5372 	for (i = 0; i < num_eq; i++) {
5373 		buf_info = &hba->sli.sli4.eq[i].addr;
5374 		if (buf_info->virt == NULL) {
5375 			bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
5376 			buf_info->size = size;
5377 			buf_info->flags =
5378 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5379 			buf_info->align = ddi_ptob(hba->dip, 1L);
5380 			buf_info->phys = phys;
5381 			buf_info->virt = (void *)virt;
5382 			buf_info->data_handle = data_handle;
5383 			buf_info->dma_handle = dma_handle;
5384 
5385 			phys += size;
5386 			virt += size;
5387 
5388 			hba->sli.sli4.eq[i].max_index = EQ_DEPTH;
5389 		}
5390 
5391 		(void) sprintf(buf, "%s_eq%d_lastwq_lock mutex",
5392 		    DRIVER_NAME, i);
5393 		mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, buf,
5394 		    MUTEX_DRIVER, NULL);
5395 	}
5396 
5397 	size = 4096;
5398 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
5399 		buf_info = &hba->sli.sli4.cq[i].addr;
5400 		if (buf_info->virt == NULL) {
5401 			bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
5402 			buf_info->size = size;
5403 			buf_info->flags =
5404 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5405 			buf_info->align = ddi_ptob(hba->dip, 1L);
5406 			buf_info->phys = phys;
5407 			buf_info->virt = (void *)virt;
5408 			buf_info->data_handle = data_handle;
5409 			buf_info->dma_handle = dma_handle;
5410 
5411 			phys += size;
5412 			virt += size;
5413 
5414 			hba->sli.sli4.cq[i].max_index = CQ_DEPTH;
5415 		}
5416 	}
5417 
5418 	/* WQs - NUM_WQ config parameter * number of EQs */
5419 	size = 4096 * EMLXS_NUM_WQ_PAGES;
5420 	for (i = 0; i < num_wq; i++) {
5421 		buf_info = &hba->sli.sli4.wq[i].addr;
5422 		if (buf_info->virt == NULL) {
5423 			bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
5424 			buf_info->size = size;
5425 			buf_info->flags =
5426 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5427 			buf_info->align = ddi_ptob(hba->dip, 1L);
5428 			buf_info->phys = phys;
5429 			buf_info->virt = (void *)virt;
5430 			buf_info->data_handle = data_handle;
5431 			buf_info->dma_handle = dma_handle;
5432 
5433 			phys += size;
5434 			virt += size;
5435 
5436 			hba->sli.sli4.wq[i].max_index = WQ_DEPTH;
5437 			hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH;
5438 		}
5439 	}
5440 
5441 	/* MQ */
5442 	size = 4096;
5443 	buf_info = &hba->sli.sli4.mq.addr;
5444 	if (!buf_info->virt) {
5445 		bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
5446 		buf_info->size = size;
5447 		buf_info->flags =
5448 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5449 		buf_info->align = ddi_ptob(hba->dip, 1L);
5450 		buf_info->phys = phys;
5451 		buf_info->virt = (void *)virt;
5452 		buf_info->data_handle = data_handle;
5453 		buf_info->dma_handle = dma_handle;
5454 
5455 		phys += size;
5456 		virt += size;
5457 
5458 		hba->sli.sli4.mq.max_index = MQ_DEPTH;
5459 	}
5460 
5461 	/* RXQs */
5462 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
5463 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
5464 
5465 		(void) sprintf(buf, "%s_rxq%d_lock mutex", DRIVER_NAME, i);
5466 		mutex_init(&hba->sli.sli4.rxq[i].lock, buf, MUTEX_DRIVER, NULL);
5467 	}
5468 
5469 	/* RQs */
5470 	size = 4096;
5471 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5472 		buf_info = &hba->sli.sli4.rq[i].addr;
5473 		if (buf_info->virt) {
5474 			continue;
5475 		}
5476 
5477 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
5478 		buf_info->size = size;
5479 		buf_info->flags =
5480 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5481 		buf_info->align = ddi_ptob(hba->dip, 1L);
5482 		buf_info->phys = phys;
5483 		buf_info->virt = (void *)virt;
5484 		buf_info->data_handle = data_handle;
5485 		buf_info->dma_handle = dma_handle;
5486 
5487 		phys += size;
5488 		virt += size;
5489 
5490 		hba->sli.sli4.rq[i].max_index = RQ_DEPTH;
5491 
5492 		(void) sprintf(buf, "%s_rq%d_lock mutex", DRIVER_NAME, i);
5493 		mutex_init(&hba->sli.sli4.rq[i].lock, buf, MUTEX_DRIVER, NULL);
5494 	}
5495 
5496 	/* Setup RQE */
5497 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5498 		size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE;
5499 		tmp_phys = phys;
5500 		tmp_virt = virt;
5501 
5502 		/* Initialize the RQEs */
5503 		rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt;
5504 		for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) {
5505 			phys = tmp_phys;
5506 			virt = tmp_virt;
5507 			for (k = 0; k < RQB_COUNT; k++) {
5508 				word = PADDR_HI(phys);
5509 				rqe->AddrHi = BE_SWAP32(word);
5510 
5511 				word = PADDR_LO(phys);
5512 				rqe->AddrLo = BE_SWAP32(word);
5513 
5514 				rqb = &hba->sli.sli4.rq[i].
5515 				    rqb[k + (j * RQB_COUNT)];
5516 				rqb->size = size;
5517 				rqb->flags = FC_MBUF_DMA |
5518 				    FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5519 				rqb->align = ddi_ptob(hba->dip, 1L);
5520 				rqb->phys = phys;
5521 				rqb->virt = (void *)virt;
5522 				rqb->data_handle = data_handle;
5523 				rqb->dma_handle = dma_handle;
5524 
5525 				phys += size;
5526 				virt += size;
5527 #ifdef RQ_DEBUG
5528 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5529 				    "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p tag=%08x",
5530 				    i, j, k, mp, mp->tag);
5531 #endif
5532 
5533 				rqe++;
5534 			}
5535 		}
5536 
5537 		offset = (off_t)((uint64_t)((unsigned long)
5538 		    hba->sli.sli4.rq[i].addr.virt) -
5539 		    (uint64_t)((unsigned long)
5540 		    hba->sli.sli4.slim2.virt));
5541 
5542 		/* Sync the RQ buffer list */
5543 		EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset,
5544 		    hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV);
5545 	}
5546 
5547 	if ((!hba->sli.sli4.XRIp) && (hba->sli.sli4.XRICount)) {
5548 		/* Initialize double linked lists */
5549 		hba->sli.sli4.XRIinuse_f =
5550 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5551 		hba->sli.sli4.XRIinuse_b =
5552 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5553 		hba->sli.sli4.xria_count = 0;
5554 
5555 		hba->sli.sli4.XRIfree_f =
5556 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5557 		hba->sli.sli4.XRIfree_b =
5558 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5559 		hba->sli.sli4.xria_count = 0;
5560 
5561 		hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
5562 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
5563 
5564 		xrip = hba->sli.sli4.XRIp;
5565 		index = hba->sli.sli4.XRIBase;
5566 		size = hba->sli.sli4.mem_sgl_size;
5567 		for (i = 0; i < hba->sli.sli4.XRICount; i++) {
5568 			xrip->sge_count =
5569 			    (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64));
5570 			xrip->XRI = index;
5571 			xrip->iotag = i;
5572 			if ((xrip->XRI == 0) || (xrip->iotag == 0)) {
5573 				index++; /* Skip XRI 0 or IOTag 0 */
5574 				xrip++;
5575 				continue;
5576 			}
5577 			/* Add xrip to end of free list */
5578 			xrip->_b = hba->sli.sli4.XRIfree_b;
5579 			hba->sli.sli4.XRIfree_b->_f = xrip;
5580 			xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5581 			hba->sli.sli4.XRIfree_b = xrip;
5582 			hba->sli.sli4.xrif_count++;
5583 
5584 			/* Allocate SGL for this xrip */
5585 			buf_info = &xrip->SGList;
5586 			buf_info->size = size;
5587 			buf_info->flags =
5588 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5589 			buf_info->align = size;
5590 			buf_info->phys = phys;
5591 			buf_info->virt = (void *)virt;
5592 			buf_info->data_handle = data_handle;
5593 			buf_info->dma_handle = dma_handle;
5594 
5595 			phys += size;
5596 			virt += size;
5597 
5598 			xrip++;
5599 			index++;
5600 		}
5601 	}
5602 
5603 	size = sizeof (RPIHdrTmplate_t) * hba->sli.sli4.RPICount;
5604 	buf_info = &hba->sli.sli4.HeaderTmplate;
5605 	if ((buf_info->virt == NULL) && (hba->sli.sli4.RPICount)) {
5606 		bzero(buf_info, sizeof (MBUF_INFO));
5607 		buf_info->size = size;
5608 		buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
5609 		buf_info->align = ddi_ptob(hba->dip, 1L);
5610 		buf_info->phys = phys;
5611 		buf_info->virt = (void *)virt;
5612 		buf_info->data_handle = data_handle;
5613 		buf_info->dma_handle = dma_handle;
5614 	}
5615 
5616 #ifdef FMA_SUPPORT
5617 	if (hba->sli.sli4.slim2.dma_handle) {
5618 		if (emlxs_fm_check_dma_handle(hba,
5619 		    hba->sli.sli4.slim2.dma_handle)
5620 		    != DDI_FM_OK) {
5621 			EMLXS_MSGF(EMLXS_CONTEXT,
5622 			    &emlxs_invalid_dma_handle_msg,
5623 			    "emlxs_sli4_resource_alloc: hdl=%p",
5624 			    hba->sli.sli4.slim2.dma_handle);
5625 			goto failed;
5626 		}
5627 	}
5628 #endif
5629 
5630 	return (0);
5631 
5632 failed:
5633 
5634 	(void) emlxs_sli4_resource_free(hba);
5635 	return (ENOMEM);
5636 
5637 } /* emlxs_sli4_resource_alloc */
5638 
5639 
5640 static XRIobj_t *
5641 emlxs_sli4_reserve_xri(emlxs_hba_t *hba,  RPIobj_t *rpip)
5642 {
5643 	emlxs_port_t	*port = &PPORT;
5644 	XRIobj_t	*xrip;
5645 	uint16_t	iotag;
5646 
5647 	mutex_enter(&EMLXS_FCTAB_LOCK);
5648 
5649 	xrip = hba->sli.sli4.XRIfree_f;
5650 
5651 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
5652 		mutex_exit(&EMLXS_FCTAB_LOCK);
5653 
5654 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5655 		    "Unable to reserve XRI");
5656 
5657 		return (NULL);
5658 	}
5659 
5660 	iotag = xrip->iotag;
5661 
5662 	if ((!iotag) ||
5663 	    ((hba->fc_table[iotag] != NULL) &&
5664 	    (hba->fc_table[iotag] != STALE_PACKET))) {
5665 		/*
5666 		 * No more command slots available, retry later
5667 		 */
5668 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5669 		    "Adapter Busy. Unable to reserve iotag");
5670 
5671 		mutex_exit(&EMLXS_FCTAB_LOCK);
5672 		return (NULL);
5673 	}
5674 
5675 	xrip->state = XRI_STATE_ALLOCATED;
5676 	xrip->flag = EMLXS_XRI_RESERVED;
5677 	xrip->rpip = rpip;
5678 	xrip->sbp = NULL;
5679 
5680 	if (rpip) {
5681 		rpip->xri_count++;
5682 	}
5683 
5684 	/* Take it off free list */
5685 	(xrip->_b)->_f = xrip->_f;
5686 	(xrip->_f)->_b = xrip->_b;
5687 	xrip->_f = NULL;
5688 	xrip->_b = NULL;
5689 	hba->sli.sli4.xrif_count--;
5690 
5691 	/* Add it to end of inuse list */
5692 	xrip->_b = hba->sli.sli4.XRIinuse_b;
5693 	hba->sli.sli4.XRIinuse_b->_f = xrip;
5694 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5695 	hba->sli.sli4.XRIinuse_b = xrip;
5696 	hba->sli.sli4.xria_count++;
5697 
5698 	mutex_exit(&EMLXS_FCTAB_LOCK);
5699 	return (xrip);
5700 
5701 } /* emlxs_sli4_reserve_xri() */
5702 
5703 
5704 extern uint32_t
5705 emlxs_sli4_unreserve_xri(emlxs_hba_t *hba, uint16_t xri, uint32_t lock)
5706 {
5707 	emlxs_port_t	*port = &PPORT;
5708 	XRIobj_t *xrip;
5709 
5710 	if (lock) {
5711 		mutex_enter(&EMLXS_FCTAB_LOCK);
5712 	}
5713 
5714 	xrip = emlxs_sli4_find_xri(hba, xri);
5715 
5716 	if (!xrip || xrip->state == XRI_STATE_FREE) {
5717 		if (lock) {
5718 			mutex_exit(&EMLXS_FCTAB_LOCK);
5719 		}
5720 
5721 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5722 		    "emlxs_sli4_unreserve_xri: xri=%x already freed.",
5723 		    xrip->XRI);
5724 		return (0);
5725 	}
5726 
5727 	if (!(xrip->flag & EMLXS_XRI_RESERVED)) {
5728 		if (lock) {
5729 			mutex_exit(&EMLXS_FCTAB_LOCK);
5730 		}
5731 
5732 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5733 		    "emlxs_sli4_unreserve_xri: xri=%x in use.", xrip->XRI);
5734 		return (1);
5735 	}
5736 
5737 	if (xrip->iotag &&
5738 	    (hba->fc_table[xrip->iotag] != NULL) &&
5739 	    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
5740 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5741 		    "emlxs_sli4_unreserve_xri:%x  sbp dropped:%p",
5742 		    xrip->XRI, hba->fc_table[xrip->iotag]);
5743 
5744 		hba->fc_table[xrip->iotag] = NULL;
5745 		hba->io_count--;
5746 	}
5747 
5748 	xrip->state = XRI_STATE_FREE;
5749 
5750 	if (xrip->rpip) {
5751 		xrip->rpip->xri_count--;
5752 		xrip->rpip = NULL;
5753 	}
5754 
5755 	/* Take it off inuse list */
5756 	(xrip->_b)->_f = xrip->_f;
5757 	(xrip->_f)->_b = xrip->_b;
5758 	xrip->_f = NULL;
5759 	xrip->_b = NULL;
5760 	hba->sli.sli4.xria_count--;
5761 
5762 	/* Add it to end of free list */
5763 	xrip->_b = hba->sli.sli4.XRIfree_b;
5764 	hba->sli.sli4.XRIfree_b->_f = xrip;
5765 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5766 	hba->sli.sli4.XRIfree_b = xrip;
5767 	hba->sli.sli4.xrif_count++;
5768 
5769 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5770 	    "emlxs_sli4_unreserve_xri: xri=%x unreserved.", xrip->XRI);
5771 
5772 	if (lock) {
5773 		mutex_exit(&EMLXS_FCTAB_LOCK);
5774 	}
5775 
5776 	return (0);
5777 
5778 } /* emlxs_sli4_unreserve_xri() */
5779 
5780 
5781 static XRIobj_t *
5782 emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri)
5783 {
5784 	emlxs_port_t	*port = &PPORT;
5785 	uint16_t	iotag;
5786 	XRIobj_t	*xrip;
5787 
5788 	mutex_enter(&EMLXS_FCTAB_LOCK);
5789 
5790 	xrip = emlxs_sli4_find_xri(hba, xri);
5791 
5792 	if (!xrip) {
5793 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5794 		    "emlxs_sli4_register_xri: XRI not found.");
5795 
5796 
5797 		mutex_exit(&EMLXS_FCTAB_LOCK);
5798 		return (NULL);
5799 	}
5800 
5801 	if ((xrip->state == XRI_STATE_FREE) ||
5802 	    !(xrip->flag & EMLXS_XRI_RESERVED)) {
5803 
5804 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5805 		    "emlxs_sli4_register_xri: Invalid XRI. xrip=%p "
5806 		    "state=%x flag=%x",
5807 		    xrip, xrip->state, xrip->flag);
5808 
5809 		mutex_exit(&EMLXS_FCTAB_LOCK);
5810 		return (NULL);
5811 	}
5812 
5813 	iotag = xrip->iotag;
5814 
5815 	if ((!iotag) ||
5816 	    ((hba->fc_table[iotag] != NULL) &&
5817 	    (hba->fc_table[iotag] != STALE_PACKET))) {
5818 
5819 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5820 		    "emlxs_sli4_register_xri: Invalid fc_table entry. "
5821 		    "iotag=%x entry=%p",
5822 		    iotag, hba->fc_table[iotag]);
5823 
5824 		mutex_exit(&EMLXS_FCTAB_LOCK);
5825 		return (NULL);
5826 	}
5827 
5828 	hba->fc_table[iotag] = sbp;
5829 	hba->io_count++;
5830 
5831 	sbp->iotag = iotag;
5832 	sbp->xrip = xrip;
5833 
5834 	xrip->flag &= ~EMLXS_XRI_RESERVED;
5835 	xrip->sbp = sbp;
5836 
5837 	mutex_exit(&EMLXS_FCTAB_LOCK);
5838 
5839 	return (xrip);
5840 
5841 } /* emlxs_sli4_register_xri() */
5842 
5843 
5844 /* Performs both reserve and register functions for XRI */
5845 static XRIobj_t *
5846 emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rpip)
5847 {
5848 	emlxs_port_t	*port = &PPORT;
5849 	XRIobj_t	*xrip;
5850 	uint16_t	iotag;
5851 
5852 	mutex_enter(&EMLXS_FCTAB_LOCK);
5853 
5854 	xrip = hba->sli.sli4.XRIfree_f;
5855 
5856 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
5857 		mutex_exit(&EMLXS_FCTAB_LOCK);
5858 
5859 		return (NULL);
5860 	}
5861 
5862 	/* Get the iotag by registering the packet */
5863 	iotag = xrip->iotag;
5864 
5865 	if ((!iotag) ||
5866 	    ((hba->fc_table[iotag] != NULL) &&
5867 	    (hba->fc_table[iotag] != STALE_PACKET))) {
5868 		/*
5869 		 * No more command slots available, retry later
5870 		 */
5871 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5872 		    "Adapter Busy. Unable to alloc iotag:(0x%x)(%p)",
5873 		    iotag, hba->fc_table[iotag]);
5874 
5875 		mutex_exit(&EMLXS_FCTAB_LOCK);
5876 		return (NULL);
5877 	}
5878 
5879 	hba->fc_table[iotag] = sbp;
5880 	hba->io_count++;
5881 
5882 	sbp->iotag = iotag;
5883 	sbp->xrip = xrip;
5884 
5885 	xrip->state = XRI_STATE_ALLOCATED;
5886 	xrip->flag = 0;
5887 	xrip->rpip = rpip;
5888 	xrip->sbp = sbp;
5889 
5890 	if (rpip) {
5891 		rpip->xri_count++;
5892 	}
5893 
5894 	/* Take it off free list */
5895 	(xrip->_b)->_f = xrip->_f;
5896 	(xrip->_f)->_b = xrip->_b;
5897 	xrip->_f = NULL;
5898 	xrip->_b = NULL;
5899 	hba->sli.sli4.xrif_count--;
5900 
5901 	/* Add it to end of inuse list */
5902 	xrip->_b = hba->sli.sli4.XRIinuse_b;
5903 	hba->sli.sli4.XRIinuse_b->_f = xrip;
5904 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5905 	hba->sli.sli4.XRIinuse_b = xrip;
5906 	hba->sli.sli4.xria_count++;
5907 
5908 	mutex_exit(&EMLXS_FCTAB_LOCK);
5909 
5910 	return (xrip);
5911 
5912 } /* emlxs_sli4_alloc_xri() */
5913 
5914 
5915 /* EMLXS_FCTAB_LOCK must be held to enter */
5916 extern XRIobj_t *
5917 emlxs_sli4_find_xri(emlxs_hba_t *hba, uint16_t xri)
5918 {
5919 	emlxs_port_t	*port = &PPORT;
5920 	XRIobj_t	*xrip;
5921 
5922 	xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
5923 	while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
5924 		if ((xrip->state >= XRI_STATE_ALLOCATED) &&
5925 		    (xrip->XRI == xri)) {
5926 			return (xrip);
5927 		}
5928 		xrip = xrip->_f;
5929 	}
5930 
5931 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5932 	    "Unable to find XRI x%x", xri);
5933 
5934 	return (NULL);
5935 
5936 } /* emlxs_sli4_find_xri() */
5937 
5938 
5939 
5940 
5941 extern void
5942 emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xrip,
5943     uint8_t lock)
5944 {
5945 	emlxs_port_t	*port = &PPORT;
5946 
5947 	if (lock) {
5948 		mutex_enter(&EMLXS_FCTAB_LOCK);
5949 	}
5950 
5951 	if (xrip) {
5952 		if (xrip->state == XRI_STATE_FREE) {
5953 			if (lock) {
5954 				mutex_exit(&EMLXS_FCTAB_LOCK);
5955 			}
5956 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5957 			    "Free XRI:%x, Already freed", xrip->XRI);
5958 			return;
5959 		}
5960 
5961 		if (xrip->iotag &&
5962 		    (hba->fc_table[xrip->iotag] != NULL) &&
5963 		    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
5964 			hba->fc_table[xrip->iotag] = NULL;
5965 			hba->io_count--;
5966 		}
5967 
5968 		xrip->state = XRI_STATE_FREE;
5969 		xrip->flag  = 0;
5970 
5971 		if (xrip->rpip) {
5972 			xrip->rpip->xri_count--;
5973 			xrip->rpip = NULL;
5974 		}
5975 
5976 		/* Take it off inuse list */
5977 		(xrip->_b)->_f = xrip->_f;
5978 		(xrip->_f)->_b = xrip->_b;
5979 		xrip->_f = NULL;
5980 		xrip->_b = NULL;
5981 		hba->sli.sli4.xria_count--;
5982 
5983 		/* Add it to end of free list */
5984 		xrip->_b = hba->sli.sli4.XRIfree_b;
5985 		hba->sli.sli4.XRIfree_b->_f = xrip;
5986 		xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5987 		hba->sli.sli4.XRIfree_b = xrip;
5988 		hba->sli.sli4.xrif_count++;
5989 	}
5990 
5991 	if (sbp) {
5992 		if (!(sbp->pkt_flags & PACKET_VALID) ||
5993 		    (sbp->pkt_flags &
5994 		    (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) {
5995 			if (lock) {
5996 				mutex_exit(&EMLXS_FCTAB_LOCK);
5997 			}
5998 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5999 			    "Free XRI: sbp invalid. sbp=%p flags=%x xri=%x",
6000 			    sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0));
6001 			return;
6002 		}
6003 
6004 		sbp->xrip = 0;
6005 
6006 		if (xrip && (xrip->iotag != sbp->iotag)) {
6007 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
6008 			    "sbp / iotag mismatch %p iotag:%d %d", sbp,
6009 			    sbp->iotag, xrip->iotag);
6010 		}
6011 
6012 		if (sbp->iotag) {
6013 			if (sbp == hba->fc_table[sbp->iotag]) {
6014 				hba->fc_table[sbp->iotag] = NULL;
6015 				hba->io_count--;
6016 			}
6017 			sbp->iotag = 0;
6018 		}
6019 
6020 		if (lock) {
6021 			mutex_exit(&EMLXS_FCTAB_LOCK);
6022 		}
6023 
6024 		/* Clean up the sbp */
6025 		mutex_enter(&sbp->mtx);
6026 
6027 		if (sbp->pkt_flags & PACKET_IN_TXQ) {
6028 			sbp->pkt_flags &= ~PACKET_IN_TXQ;
6029 			hba->channel_tx_count--;
6030 		}
6031 
6032 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
6033 			sbp->pkt_flags &= ~PACKET_IN_CHIPQ;
6034 		}
6035 
6036 		mutex_exit(&sbp->mtx);
6037 	} else {
6038 		if (lock) {
6039 			mutex_exit(&EMLXS_FCTAB_LOCK);
6040 		}
6041 	}
6042 
6043 } /* emlxs_sli4_free_xri() */
6044 
6045 
6046 static int
6047 emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq)
6048 {
6049 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
6050 	emlxs_port_t	*port = &PPORT;
6051 	XRIobj_t	*xrip;
6052 	MATCHMAP	*mp;
6053 	mbox_req_hdr_t 	*hdr_req;
6054 	uint32_t	i, cnt, xri_cnt;
6055 	uint32_t	size;
6056 	IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl;
6057 
6058 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
6059 	mbq->bp = NULL;
6060 	mbq->mbox_cmpl = NULL;
6061 
6062 	if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) {
6063 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6064 		    "Unable to POST_SGL. Mailbox cmd=%x  ",
6065 		    mb->mbxCommand);
6066 		return (EIO);
6067 	}
6068 	mbq->nonembed = (void *)mp;
6069 
6070 	/*
6071 	 * Signifies a non embedded command
6072 	 */
6073 	mb->un.varSLIConfig.be.embedded = 0;
6074 	mb->mbxCommand = MBX_SLI_CONFIG;
6075 	mb->mbxOwner = OWN_HOST;
6076 
6077 	hdr_req = (mbox_req_hdr_t *)mp->virt;
6078 	post_sgl =
6079 	    (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1);
6080 
6081 
6082 	xrip = hba->sli.sli4.XRIp;
6083 	cnt = hba->sli.sli4.XRICount;
6084 	while (cnt) {
6085 		bzero((void *) hdr_req, mp->size);
6086 		size = mp->size - IOCTL_HEADER_SZ;
6087 
6088 		mb->un.varSLIConfig.be.payload_length =
6089 		    mp->size;
6090 		mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
6091 		    IOCTL_SUBSYSTEM_FCOE;
6092 		mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
6093 		    FCOE_OPCODE_CFG_POST_SGL_PAGES;
6094 		mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
6095 		mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size;
6096 
6097 		hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
6098 		hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES;
6099 		hdr_req->timeout = 0;
6100 		hdr_req->req_length = size;
6101 
6102 		post_sgl->params.request.xri_count = 0;
6103 		post_sgl->params.request.xri_start = xrip->XRI;
6104 		xri_cnt = (size - sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
6105 		    sizeof (FCOE_SGL_PAGES);
6106 		for (i = 0; i < xri_cnt; i++) {
6107 
6108 			post_sgl->params.request.xri_count++;
6109 			post_sgl->params.request.pages[i].sgl_page0.addrLow =
6110 			    PADDR_LO(xrip->SGList.phys);
6111 			post_sgl->params.request.pages[i].sgl_page0.addrHigh =
6112 			    PADDR_HI(xrip->SGList.phys);
6113 			cnt--;
6114 			xrip++;
6115 			if (cnt == 0) {
6116 				break;
6117 			}
6118 		}
6119 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6120 		    MBX_SUCCESS) {
6121 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6122 			    "Unable to POST_SGL. Mailbox cmd=%x status=%x "
6123 			    "XRI cnt:%d start:%d",
6124 			    mb->mbxCommand, mb->mbxStatus,
6125 			    post_sgl->params.request.xri_count,
6126 			    post_sgl->params.request.xri_start);
6127 			emlxs_mem_buf_free(hba, mp);
6128 			mbq->nonembed = NULL;
6129 			return (EIO);
6130 		}
6131 	}
6132 	emlxs_mem_buf_free(hba, mp);
6133 	mbq->nonembed = NULL;
6134 	return (0);
6135 
6136 } /* emlxs_sli4_post_sgl_pages() */
6137 
6138 
6139 static int
6140 emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq)
6141 {
6142 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
6143 	emlxs_port_t	*port = &PPORT;
6144 	int		i, cnt;
6145 	uint64_t	addr;
6146 	IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr;
6147 
6148 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
6149 	mbq->bp = NULL;
6150 	mbq->mbox_cmpl = NULL;
6151 
6152 	/*
6153 	 * Signifies an embedded command
6154 	 */
6155 	mb->un.varSLIConfig.be.embedded = 1;
6156 
6157 	mb->mbxCommand = MBX_SLI_CONFIG;
6158 	mb->mbxOwner = OWN_HOST;
6159 	mb->un.varSLIConfig.be.payload_length =
6160 	    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
6161 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
6162 	    IOCTL_SUBSYSTEM_FCOE;
6163 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
6164 	    FCOE_OPCODE_POST_HDR_TEMPLATES;
6165 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
6166 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
6167 	    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
6168 	post_hdr =
6169 	    (IOCTL_FCOE_POST_HDR_TEMPLATES *)&mb->un.varSLIConfig.payload;
6170 	addr = hba->sli.sli4.HeaderTmplate.phys;
6171 	post_hdr->params.request.num_pages = 0;
6172 	i = 0;
6173 	cnt = hba->sli.sli4.HeaderTmplate.size;
6174 	while (cnt > 0) {
6175 		post_hdr->params.request.num_pages++;
6176 		post_hdr->params.request.pages[i].addrLow = PADDR_LO(addr);
6177 		post_hdr->params.request.pages[i].addrHigh = PADDR_HI(addr);
6178 		i++;
6179 		addr += 4096;
6180 		cnt -= 4096;
6181 	}
6182 	post_hdr->params.request.starting_rpi_index = hba->sli.sli4.RPIBase;
6183 
6184 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6185 	    MBX_SUCCESS) {
6186 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6187 		    "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x status=%x ",
6188 		    mb->mbxCommand, mb->mbxStatus);
6189 		return (EIO);
6190 	}
6191 emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0);
6192 	return (0);
6193 
6194 } /* emlxs_sli4_post_hdr_tmplates() */
6195 
6196 
6197 static int
6198 emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq)
6199 {
6200 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
6201 	emlxs_port_t	*port = &PPORT;
6202 	emlxs_config_t	*cfg = &CFG;
6203 	IOCTL_COMMON_EQ_CREATE *eq;
6204 	IOCTL_COMMON_CQ_CREATE *cq;
6205 	IOCTL_FCOE_WQ_CREATE *wq;
6206 	IOCTL_FCOE_RQ_CREATE *rq;
6207 	IOCTL_COMMON_MQ_CREATE *mq;
6208 	IOCTL_COMMON_MCC_CREATE_EXT *mcc_ext;
6209 	emlxs_rqdbu_t	rqdb;
6210 	uint16_t i, j;
6211 	uint16_t num_cq, total_cq;
6212 	uint16_t num_wq, total_wq;
6213 
6214 	/*
6215 	 * The first CQ is reserved for ASYNC events,
6216 	 * the second is reserved for unsol rcv, the rest
6217 	 * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
6218 	 */
6219 
6220 	/* First initialize queue ordinal mapping */
6221 	for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) {
6222 		hba->sli.sli4.eq_map[i] = 0xffff;
6223 	}
6224 	for (i = 0; i < EMLXS_MAX_CQ_IDS; i++) {
6225 		hba->sli.sli4.cq_map[i] = 0xffff;
6226 	}
6227 	for (i = 0; i < EMLXS_MAX_WQ_IDS; i++) {
6228 		hba->sli.sli4.wq_map[i] = 0xffff;
6229 	}
6230 	for (i = 0; i < EMLXS_MAX_RQ_IDS; i++) {
6231 		hba->sli.sli4.rq_map[i] = 0xffff;
6232 	}
6233 
6234 	total_cq = 0;
6235 	total_wq = 0;
6236 
6237 	/* Create EQ's */
6238 	for (i = 0; i < hba->intr_count; i++) {
6239 		emlxs_mb_eq_create(hba, mbq, i);
6240 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6241 		    MBX_SUCCESS) {
6242 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6243 			    "Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
6244 			    i, mb->mbxCommand, mb->mbxStatus);
6245 			return (EIO);
6246 		}
6247 		eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
6248 		hba->sli.sli4.eq[i].qid = eq->params.response.EQId;
6249 		hba->sli.sli4.eq_map[eq->params.response.EQId] = i;
6250 		hba->sli.sli4.eq[i].lastwq = total_wq;
6251 
6252 emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0);
6253 		num_wq = cfg[CFG_NUM_WQ].current;
6254 		num_cq = num_wq;
6255 		if (i == 0) {
6256 			/* One for RQ handling, one for mbox/event handling */
6257 			num_cq += EMLXS_CQ_OFFSET_WQ;
6258 		}
6259 
6260 		for (j = 0; j < num_cq; j++) {
6261 			/* Reuse mbq from previous mbox */
6262 			bzero(mbq, sizeof (MAILBOXQ));
6263 
6264 			hba->sli.sli4.cq[total_cq].eqid =
6265 			    hba->sli.sli4.eq[i].qid;
6266 
6267 			emlxs_mb_cq_create(hba, mbq, total_cq);
6268 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6269 			    MBX_SUCCESS) {
6270 				EMLXS_MSGF(EMLXS_CONTEXT,
6271 				    &emlxs_init_failed_msg, "Unable to Create "
6272 				    "CQ %d: Mailbox cmd=%x status=%x ",
6273 				    total_cq, mb->mbxCommand, mb->mbxStatus);
6274 				return (EIO);
6275 			}
6276 			cq = (IOCTL_COMMON_CQ_CREATE *)
6277 			    &mb->un.varSLIConfig.payload;
6278 			hba->sli.sli4.cq[total_cq].qid =
6279 			    cq->params.response.CQId;
6280 			hba->sli.sli4.cq_map[cq->params.response.CQId] =
6281 			    total_cq;
6282 
6283 			switch (total_cq) {
6284 			case EMLXS_CQ_MBOX:
6285 				/* First CQ is for async event handling */
6286 				hba->sli.sli4.cq[total_cq].type =
6287 				    EMLXS_CQ_TYPE_GROUP1;
6288 				break;
6289 
6290 			case EMLXS_CQ_RCV:
6291 				/* Second CQ is for unsol receive handling */
6292 				hba->sli.sli4.cq[total_cq].type =
6293 				    EMLXS_CQ_TYPE_GROUP2;
6294 				break;
6295 
6296 			default:
6297 				/* Setup CQ to channel mapping */
6298 				hba->sli.sli4.cq[total_cq].type =
6299 				    EMLXS_CQ_TYPE_GROUP2;
6300 				hba->sli.sli4.cq[total_cq].channelp =
6301 				    &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ];
6302 				break;
6303 			}
6304 emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb, 18, 0);
6305 			total_cq++;
6306 		}
6307 
6308 		for (j = 0; j < num_wq; j++) {
6309 			/* Reuse mbq from previous mbox */
6310 			bzero(mbq, sizeof (MAILBOXQ));
6311 
6312 			hba->sli.sli4.wq[total_wq].cqid =
6313 			    hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid;
6314 
6315 			emlxs_mb_wq_create(hba, mbq, total_wq);
6316 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6317 			    MBX_SUCCESS) {
6318 				EMLXS_MSGF(EMLXS_CONTEXT,
6319 				    &emlxs_init_failed_msg, "Unable to Create "
6320 				    "WQ %d: Mailbox cmd=%x status=%x ",
6321 				    total_wq, mb->mbxCommand, mb->mbxStatus);
6322 				return (EIO);
6323 			}
6324 			wq = (IOCTL_FCOE_WQ_CREATE *)
6325 			    &mb->un.varSLIConfig.payload;
6326 			hba->sli.sli4.wq[total_wq].qid =
6327 			    wq->params.response.WQId;
6328 			hba->sli.sli4.wq_map[wq->params.response.WQId] =
6329 			    total_wq;
6330 
6331 			hba->sli.sli4.wq[total_wq].cqid =
6332 			    hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid;
6333 emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb, 18, 0);
6334 			total_wq++;
6335 		}
6336 		hba->last_msiid = i;
6337 	}
6338 
6339 	/* We assume 1 RQ pair will handle ALL incoming data */
6340 	/* Create RQs */
6341 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
6342 		/* Personalize the RQ */
6343 		switch (i) {
6344 		case 0:
6345 			hba->sli.sli4.rq[i].cqid =
6346 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
6347 			break;
6348 		case 1:
6349 			hba->sli.sli4.rq[i].cqid =
6350 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
6351 			break;
6352 		default:
6353 			hba->sli.sli4.rq[i].cqid = 0xffff;
6354 		}
6355 
6356 		/* Reuse mbq from previous mbox */
6357 		bzero(mbq, sizeof (MAILBOXQ));
6358 
6359 		emlxs_mb_rq_create(hba, mbq, i);
6360 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6361 		    MBX_SUCCESS) {
6362 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6363 			    "Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
6364 			    i, mb->mbxCommand, mb->mbxStatus);
6365 			return (EIO);
6366 		}
6367 		rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
6368 		hba->sli.sli4.rq[i].qid = rq->params.response.RQId;
6369 		hba->sli.sli4.rq_map[rq->params.response.RQId] = i;
6370 emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0);
6371 
6372 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6373 		    "RQ CREATE: rq[%d].qid=%d cqid=%d",
6374 		    i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid);
6375 
6376 		/* Initialize the host_index */
6377 		hba->sli.sli4.rq[i].host_index = 0;
6378 
6379 		/* If Data queue was just created, */
6380 		/* then post buffers using the header qid */
6381 		if ((i & 0x1)) {
6382 			/* Ring the RQ doorbell to post buffers */
6383 			rqdb.word = 0;
6384 			rqdb.db.Qid = hba->sli.sli4.rq[i-1].qid;
6385 			rqdb.db.NumPosted = RQB_COUNT;
6386 
6387 			WRITE_BAR2_REG(hba, FC_RQDB_REG(hba), rqdb.word);
6388 
6389 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6390 			    "RQ CREATE: Doorbell rang: qid=%d count=%d",
6391 			    hba->sli.sli4.rq[i-1].qid, RQB_COUNT);
6392 		}
6393 	}
6394 
6395 	/* Create MQ */
6396 
6397 	/* Personalize the MQ */
6398 	hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid;
6399 
6400 	/* Reuse mbq from previous mbox */
6401 	bzero(mbq, sizeof (MAILBOXQ));
6402 
6403 	emlxs_mb_mcc_create_ext(hba, mbq);
6404 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6405 	    MBX_SUCCESS) {
6406 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6407 		    "Unable to Create MCC_EXT %d: Mailbox cmd=%x status=%x ",
6408 		    i, mb->mbxCommand, mb->mbxStatus);
6409 
6410 		/* Reuse mbq from previous mbox */
6411 		bzero(mbq, sizeof (MAILBOXQ));
6412 
6413 		emlxs_mb_mq_create(hba, mbq);
6414 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6415 		    MBX_SUCCESS) {
6416 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6417 			    "Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
6418 			    i, mb->mbxCommand, mb->mbxStatus);
6419 			return (EIO);
6420 		}
6421 
6422 		mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
6423 		hba->sli.sli4.mq.qid = mq->params.response.MQId;
6424 		return (0);
6425 	}
6426 
6427 	mcc_ext = (IOCTL_COMMON_MCC_CREATE_EXT *)&mb->un.varSLIConfig.payload;
6428 	hba->sli.sli4.mq.qid = mcc_ext->params.response.id;
6429 	return (0);
6430 
6431 } /* emlxs_sli4_create_queues() */
6432 
6433 
6434 /*ARGSUSED*/
6435 extern int
6436 emlxs_sli4_check_fcf_config(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec)
6437 {
6438 	int i;
6439 
6440 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
6441 		if (!hba->sli.sli4.cfgFCOE.length) {
6442 			/* Nothing specified, so everything matches */
6443 			/* For nonFIP only use index 0 */
6444 			if (fcfrec->fcf_index == 0) {
6445 				return (1);  /* success */
6446 			}
6447 			return (0);
6448 		}
6449 
6450 		/* Just check FCMap for now */
6451 		if (bcmp((char *)fcfrec->fc_map,
6452 		    hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) {
6453 			return (1);  /* success */
6454 		}
6455 		return (0);
6456 	}
6457 
6458 	/* For FIP mode, the FCF record must match Config Region 23 */
6459 
6460 	if (!hba->sli.sli4.cfgFCF.length) {
6461 		/* Nothing specified, so everything matches */
6462 		return (1);  /* success */
6463 	}
6464 
6465 	/* Just check FabricName for now */
6466 	for (i = 0; i < MAX_FCFCONNECTLIST_ENTRIES; i++) {
6467 		if ((hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) &&
6468 		    (bcmp((char *)fcfrec->fabric_name_identifier,
6469 		    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0)) {
6470 			return (1);  /* success */
6471 		}
6472 	}
6473 	return (0);
6474 
6475 } /* emlxs_sli4_check_fcf_config() */
6476 
6477 
6478 extern void
6479 emlxs_sli4_timer(emlxs_hba_t *hba)
6480 {
6481 	/* Perform SLI4 level timer checks */
6482 
6483 	emlxs_fcf_timer_notify(hba);
6484 
6485 	emlxs_sli4_timer_check_mbox(hba);
6486 
6487 	return;
6488 
6489 } /* emlxs_sli4_timer() */
6490 
6491 
6492 static void
6493 emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba)
6494 {
6495 	emlxs_port_t *port = &PPORT;
6496 	emlxs_config_t *cfg = &CFG;
6497 	MAILBOX *mb = NULL;
6498 
6499 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
6500 		return;
6501 	}
6502 
6503 	mutex_enter(&EMLXS_PORT_LOCK);
6504 
6505 	/* Return if timer hasn't expired */
6506 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
6507 		mutex_exit(&EMLXS_PORT_LOCK);
6508 		return;
6509 	}
6510 
6511 	/* The first to service the mbox queue will clear the timer */
6512 	hba->mbox_timer = 0;
6513 
6514 	if (hba->mbox_queue_flag) {
6515 		if (hba->mbox_mbq) {
6516 			mb = (MAILBOX *)hba->mbox_mbq;
6517 		}
6518 	}
6519 
6520 	if (mb) {
6521 		switch (hba->mbox_queue_flag) {
6522 		case MBX_NOWAIT:
6523 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6524 			    "%s: Nowait.",
6525 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
6526 			break;
6527 
6528 		case MBX_SLEEP:
6529 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6530 			    "%s: mb=%p Sleep.",
6531 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
6532 			    mb);
6533 			break;
6534 
6535 		case MBX_POLL:
6536 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6537 			    "%s: mb=%p Polled.",
6538 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
6539 			    mb);
6540 			break;
6541 
6542 		default:
6543 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6544 			    "%s: mb=%p (%d).",
6545 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
6546 			    mb, hba->mbox_queue_flag);
6547 			break;
6548 		}
6549 	} else {
6550 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
6551 	}
6552 
6553 	hba->flag |= FC_MBOX_TIMEOUT;
6554 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
6555 
6556 	mutex_exit(&EMLXS_PORT_LOCK);
6557 
6558 	/* Perform mailbox cleanup */
6559 	/* This will wake any sleeping or polling threads */
6560 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
6561 
6562 	/* Trigger adapter shutdown */
6563 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
6564 
6565 	return;
6566 
6567 } /* emlxs_sli4_timer_check_mbox() */
6568 
6569 
6570 extern void
6571 emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err)
6572 {
6573 	void *msg;
6574 
6575 	if (err) {
6576 		msg = &emlxs_sli_err_msg;
6577 	} else {
6578 		msg = &emlxs_sli_detail_msg;
6579 	}
6580 
6581 	if (cnt) {
6582 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6583 		    "%s00:  %08x %08x %08x %08x %08x %08x", str, *iptr,
6584 		    *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5));
6585 	}
6586 	if (cnt > 6) {
6587 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6588 		    "%s06:  %08x %08x %08x %08x %08x %08x", str, *(iptr+6),
6589 		    *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11));
6590 	}
6591 	if (cnt > 12) {
6592 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6593 		    "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12),
6594 		    *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17));
6595 	}
6596 	if (cnt > 18) {
6597 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6598 		    "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18),
6599 		    *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23));
6600 	}
6601 	if (cnt > 24) {
6602 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6603 		    "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24),
6604 		    *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29));
6605 	}
6606 	if (cnt > 30) {
6607 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6608 		    "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30),
6609 		    *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35));
6610 	}
6611 	if (cnt > 36) {
6612 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6613 		    "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36),
6614 		    *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41));
6615 	}
6616 
6617 } /* emlxs_data_dump() */
6618 
6619 
6620 extern void
6621 emlxs_ue_dump(emlxs_hba_t *hba, char *str)
6622 {
6623 	emlxs_port_t *port = &PPORT;
6624 	uint32_t ue_h;
6625 	uint32_t ue_l;
6626 	uint32_t on1;
6627 	uint32_t on2;
6628 
6629 	ue_l = ddi_get32(hba->pci_acc_handle,
6630 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET));
6631 	ue_h = ddi_get32(hba->pci_acc_handle,
6632 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET));
6633 	on1 = ddi_get32(hba->pci_acc_handle,
6634 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
6635 	on2 = ddi_get32(hba->pci_acc_handle,
6636 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
6637 
6638 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6639 	    "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
6640 	    ue_l, ue_h, on1, on2);
6641 
6642 #ifdef FMA_SUPPORT
6643 	/* Access handle validation */
6644 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
6645 #endif  /* FMA_SUPPORT */
6646 
6647 } /* emlxs_ue_dump() */
6648 
6649 
6650 static void
6651 emlxs_sli4_poll_erratt(emlxs_hba_t *hba)
6652 {
6653 	emlxs_port_t *port = &PPORT;
6654 	uint32_t ue_h;
6655 	uint32_t ue_l;
6656 
6657 	if (hba->flag & FC_HARDWARE_ERROR) {
6658 		return;
6659 	}
6660 
6661 	ue_l = ddi_get32(hba->pci_acc_handle,
6662 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET));
6663 	ue_h = ddi_get32(hba->pci_acc_handle,
6664 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET));
6665 
6666 	if ((~hba->sli.sli4.ue_mask_lo & ue_l) ||
6667 	    (~hba->sli.sli4.ue_mask_hi & ue_h) ||
6668 	    (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
6669 		/* Unrecoverable error detected */
6670 		/* Shut the HBA down */
6671 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
6672 		    "Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x "
6673 		    "maskHigh:%08x",
6674 		    ue_l, ue_h, hba->sli.sli4.ue_mask_lo,
6675 		    hba->sli.sli4.ue_mask_hi);
6676 
6677 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
6678 
6679 		emlxs_sli4_hba_flush_chipq(hba);
6680 
6681 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
6682 	}
6683 
6684 } /* emlxs_sli4_poll_erratt() */
6685 
6686 
6687 extern uint32_t
6688 emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
6689     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
6690 {
6691 	emlxs_hba_t	*hba = HBA;
6692 	NODELIST	*node;
6693 	RPIobj_t	*rpip;
6694 	uint32_t	rval;
6695 
6696 	/* Check for invalid node ids to register */
6697 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
6698 		return (1);
6699 	}
6700 
6701 	if (did & 0xff000000) {
6702 		return (1);
6703 	}
6704 
6705 	if ((rval = emlxs_mb_check_sparm(hba, param))) {
6706 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6707 		    "Invalid service parameters. did=%06x rval=%d", did,
6708 		    rval);
6709 
6710 		return (1);
6711 	}
6712 
6713 	/* Check if the node limit has been reached */
6714 	if (port->node_count >= hba->max_nodes) {
6715 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6716 		    "Limit reached. did=%06x count=%d", did,
6717 		    port->node_count);
6718 
6719 		return (1);
6720 	}
6721 
6722 	node = emlxs_node_find_did(port, did);
6723 	rpip = EMLXS_NODE_TO_RPI(port, node);
6724 
6725 	rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp,
6726 	    (void *)ubp, (void *)iocbq);
6727 
6728 	return (rval);
6729 
6730 } /* emlxs_sli4_reg_did() */
6731 
6732 
6733 extern uint32_t
6734 emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node,
6735     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
6736 {
6737 	RPIobj_t	*rpip;
6738 	uint32_t	rval;
6739 
6740 	if (!node) {
6741 		/* Unreg all nodes */
6742 		(void) emlxs_sli4_unreg_all_nodes(port);
6743 		return (1);
6744 	}
6745 
6746 	/* Check for base node */
6747 	if (node == &port->node_base) {
6748 		/* Just flush base node */
6749 		(void) emlxs_tx_node_flush(port, &port->node_base,
6750 		    0, 0, 0);
6751 
6752 		(void) emlxs_chipq_node_flush(port, 0,
6753 		    &port->node_base, 0);
6754 
6755 		port->did = 0;
6756 
6757 		/* Return now */
6758 		return (1);
6759 	}
6760 
6761 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6762 	    "unreg_node:%p did=%x rpi=%d",
6763 	    node, node->nlp_DID, node->nlp_Rpi);
6764 
6765 	rpip = EMLXS_NODE_TO_RPI(port, node);
6766 
6767 	if (!rpip) {
6768 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6769 		    "unreg_node:%p did=%x rpi=%d. RPI not found.",
6770 		    node, node->nlp_DID, node->nlp_Rpi);
6771 
6772 		emlxs_node_rm(port, node);
6773 		return (1);
6774 	}
6775 
6776 	rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp,
6777 	    (void *)iocbq);
6778 
6779 	return (rval);
6780 
6781 } /* emlxs_sli4_unreg_node() */
6782 
6783 
6784 extern uint32_t
6785 emlxs_sli4_unreg_all_nodes(emlxs_port_t *port)
6786 {
6787 	NODELIST	*nlp;
6788 	int		i;
6789 	uint32_t 	found;
6790 
6791 	/* Set the node tags */
6792 	/* We will process all nodes with this tag */
6793 	rw_enter(&port->node_rwlock, RW_READER);
6794 	found = 0;
6795 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6796 		nlp = port->node_table[i];
6797 		while (nlp != NULL) {
6798 			found = 1;
6799 			nlp->nlp_tag = 1;
6800 			nlp = nlp->nlp_list_next;
6801 		}
6802 	}
6803 	rw_exit(&port->node_rwlock);
6804 
6805 	if (!found) {
6806 		return (0);
6807 	}
6808 
6809 	for (;;) {
6810 		rw_enter(&port->node_rwlock, RW_READER);
6811 		found = 0;
6812 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6813 			nlp = port->node_table[i];
6814 			while (nlp != NULL) {
6815 				if (!nlp->nlp_tag) {
6816 					nlp = nlp->nlp_list_next;
6817 					continue;
6818 				}
6819 				nlp->nlp_tag = 0;
6820 				found = 1;
6821 				break;
6822 			}
6823 
6824 			if (found) {
6825 				break;
6826 			}
6827 		}
6828 		rw_exit(&port->node_rwlock);
6829 
6830 		if (!found) {
6831 			break;
6832 		}
6833 
6834 		(void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0);
6835 	}
6836 
6837 	return (0);
6838 
6839 } /* emlxs_sli4_unreg_all_nodes() */
6840