182527734SSukumar Swaminathan /*
282527734SSukumar Swaminathan  * CDDL HEADER START
382527734SSukumar Swaminathan  *
482527734SSukumar Swaminathan  * The contents of this file are subject to the terms of the
582527734SSukumar Swaminathan  * Common Development and Distribution License (the "License").
682527734SSukumar Swaminathan  * You may not use this file except in compliance with the License.
782527734SSukumar Swaminathan  *
882527734SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
982527734SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
1082527734SSukumar Swaminathan  * See the License for the specific language governing permissions
1182527734SSukumar Swaminathan  * and limitations under the License.
1282527734SSukumar Swaminathan  *
1382527734SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
1482527734SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1582527734SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
1682527734SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
1782527734SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
1882527734SSukumar Swaminathan  *
1982527734SSukumar Swaminathan  * CDDL HEADER END
2082527734SSukumar Swaminathan  */
2182527734SSukumar Swaminathan 
2282527734SSukumar Swaminathan /*
23bce54adfSSukumar Swaminathan  * Copyright 2010 Emulex.  All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
2582527734SSukumar Swaminathan  */
2682527734SSukumar Swaminathan 
2782527734SSukumar Swaminathan 
2882527734SSukumar Swaminathan #include <emlxs.h>
2982527734SSukumar Swaminathan 
3082527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
3182527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI4_C);
3282527734SSukumar Swaminathan 
3382527734SSukumar Swaminathan static int		emlxs_sli4_create_queues(emlxs_hba_t *hba,
3482527734SSukumar Swaminathan 				MAILBOXQ *mbq);
3582527734SSukumar Swaminathan static int		emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba,
3682527734SSukumar Swaminathan 				MAILBOXQ *mbq);
3782527734SSukumar Swaminathan static int		emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba,
3882527734SSukumar Swaminathan 				MAILBOXQ *mbq);
3982527734SSukumar Swaminathan 
40*a9800bebSGarrett D'Amore static int		emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq);
4182527734SSukumar Swaminathan 
4282527734SSukumar Swaminathan extern void		emlxs_parse_prog_types(emlxs_hba_t *hba, char *types);
4382527734SSukumar Swaminathan 
4482527734SSukumar Swaminathan extern int32_t		emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd,
4582527734SSukumar Swaminathan 				uint32_t size);
4682527734SSukumar Swaminathan extern void		emlxs_decode_label(char *label, char *buffer, int bige);
4782527734SSukumar Swaminathan 
4882527734SSukumar Swaminathan extern void		emlxs_build_prog_types(emlxs_hba_t *hba,
4982527734SSukumar Swaminathan 				char *prog_types);
5082527734SSukumar Swaminathan 
5182527734SSukumar Swaminathan extern int		emlxs_pci_model_count;
5282527734SSukumar Swaminathan 
5382527734SSukumar Swaminathan extern emlxs_model_t	emlxs_pci_model[];
5482527734SSukumar Swaminathan 
5582527734SSukumar Swaminathan static int		emlxs_sli4_map_hdw(emlxs_hba_t *hba);
5682527734SSukumar Swaminathan 
5782527734SSukumar Swaminathan static void		emlxs_sli4_unmap_hdw(emlxs_hba_t *hba);
5882527734SSukumar Swaminathan 
5982527734SSukumar Swaminathan static int32_t		emlxs_sli4_online(emlxs_hba_t *hba);
6082527734SSukumar Swaminathan 
6182527734SSukumar Swaminathan static void		emlxs_sli4_offline(emlxs_hba_t *hba);
6282527734SSukumar Swaminathan 
6382527734SSukumar Swaminathan static uint32_t		emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart,
6482527734SSukumar Swaminathan 				uint32_t skip_post, uint32_t quiesce);
6582527734SSukumar Swaminathan static void		emlxs_sli4_hba_kill(emlxs_hba_t *hba);
6682527734SSukumar Swaminathan 
6782527734SSukumar Swaminathan static uint32_t		emlxs_sli4_hba_init(emlxs_hba_t *hba);
6882527734SSukumar Swaminathan 
6982527734SSukumar Swaminathan static uint32_t		emlxs_sli4_bde_setup(emlxs_port_t *port,
7082527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
71*a9800bebSGarrett D'Amore 
72*a9800bebSGarrett D'Amore 
7382527734SSukumar Swaminathan static void		emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba,
74*a9800bebSGarrett D'Amore 				CHANNEL *cp, IOCBQ *iocb_cmd);
7582527734SSukumar Swaminathan static uint32_t		emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba,
7682527734SSukumar Swaminathan 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
7782527734SSukumar Swaminathan static uint32_t		emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba,
7882527734SSukumar Swaminathan 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
7982527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
8082527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_fct_iocb(emlxs_port_t *port,
8182527734SSukumar Swaminathan 				emlxs_buf_t *cmd_sbp, int channel);
8282527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
8382527734SSukumar Swaminathan 
8482527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port,
8582527734SSukumar Swaminathan 				emlxs_buf_t *sbp, int ring);
8682527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_ip_iocb(emlxs_port_t *port,
8782527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
8882527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_els_iocb(emlxs_port_t *port,
8982527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
9082527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_ct_iocb(emlxs_port_t *port,
9182527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
9282527734SSukumar Swaminathan static void		emlxs_sli4_poll_intr(emlxs_hba_t *hba,
9382527734SSukumar Swaminathan 				uint32_t att_bit);
9482527734SSukumar Swaminathan static int32_t		emlxs_sli4_intx_intr(char *arg);
9582527734SSukumar Swaminathan 
9682527734SSukumar Swaminathan #ifdef MSI_SUPPORT
9782527734SSukumar Swaminathan static uint32_t		emlxs_sli4_msi_intr(char *arg1, char *arg2);
9882527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
9982527734SSukumar Swaminathan 
10082527734SSukumar Swaminathan static void		emlxs_sli4_resource_free(emlxs_hba_t *hba);
10182527734SSukumar Swaminathan 
10282527734SSukumar Swaminathan static int		emlxs_sli4_resource_alloc(emlxs_hba_t *hba);
10382527734SSukumar Swaminathan 
10482527734SSukumar Swaminathan static XRIobj_t		*emlxs_sli4_alloc_xri(emlxs_hba_t *hba,
105*a9800bebSGarrett D'Amore 				emlxs_buf_t *sbp, RPIobj_t *rpip);
10682527734SSukumar Swaminathan static void		emlxs_sli4_enable_intr(emlxs_hba_t *hba);
10782527734SSukumar Swaminathan 
10882527734SSukumar Swaminathan static void		emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att);
10982527734SSukumar Swaminathan 
11082527734SSukumar Swaminathan extern void		emlxs_sli4_timer(emlxs_hba_t *hba);
11182527734SSukumar Swaminathan 
11282527734SSukumar Swaminathan static void		emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
11382527734SSukumar Swaminathan 
114*a9800bebSGarrett D'Amore static void		emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
11582527734SSukumar Swaminathan 
11682527734SSukumar Swaminathan static XRIobj_t 	*emlxs_sli4_register_xri(emlxs_hba_t *hba,
11782527734SSukumar Swaminathan 				emlxs_buf_t *sbp, uint16_t xri);
11882527734SSukumar Swaminathan 
119*a9800bebSGarrett D'Amore static XRIobj_t 	*emlxs_sli4_reserve_xri(emlxs_hba_t *hba,
120*a9800bebSGarrett D'Amore 				RPIobj_t *rpip);
12182527734SSukumar Swaminathan static int		emlxs_check_hdw_ready(emlxs_hba_t *);
12282527734SSukumar Swaminathan 
123*a9800bebSGarrett D'Amore 
12482527734SSukumar Swaminathan /* Define SLI4 API functions */
12582527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli4_api = {
12682527734SSukumar Swaminathan 	emlxs_sli4_map_hdw,
12782527734SSukumar Swaminathan 	emlxs_sli4_unmap_hdw,
12882527734SSukumar Swaminathan 	emlxs_sli4_online,
12982527734SSukumar Swaminathan 	emlxs_sli4_offline,
13082527734SSukumar Swaminathan 	emlxs_sli4_hba_reset,
13182527734SSukumar Swaminathan 	emlxs_sli4_hba_kill,
13282527734SSukumar Swaminathan 	emlxs_sli4_issue_iocb_cmd,
13382527734SSukumar Swaminathan 	emlxs_sli4_issue_mbox_cmd,
13482527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
13582527734SSukumar Swaminathan 	emlxs_sli4_prep_fct_iocb,
13682527734SSukumar Swaminathan #else
13782527734SSukumar Swaminathan 	NULL,
13882527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
13982527734SSukumar Swaminathan 	emlxs_sli4_prep_fcp_iocb,
14082527734SSukumar Swaminathan 	emlxs_sli4_prep_ip_iocb,
14182527734SSukumar Swaminathan 	emlxs_sli4_prep_els_iocb,
14282527734SSukumar Swaminathan 	emlxs_sli4_prep_ct_iocb,
14382527734SSukumar Swaminathan 	emlxs_sli4_poll_intr,
14482527734SSukumar Swaminathan 	emlxs_sli4_intx_intr,
14582527734SSukumar Swaminathan 	emlxs_sli4_msi_intr,
14682527734SSukumar Swaminathan 	emlxs_sli4_disable_intr,
14782527734SSukumar Swaminathan 	emlxs_sli4_timer,
14882527734SSukumar Swaminathan 	emlxs_sli4_poll_erratt
14982527734SSukumar Swaminathan };
15082527734SSukumar Swaminathan 
15182527734SSukumar Swaminathan 
15282527734SSukumar Swaminathan /* ************************************************************************** */
15382527734SSukumar Swaminathan 
15482527734SSukumar Swaminathan 
15582527734SSukumar Swaminathan /*
15682527734SSukumar Swaminathan  * emlxs_sli4_online()
15782527734SSukumar Swaminathan  *
15882527734SSukumar Swaminathan  * This routine will start initialization of the SLI4 HBA.
15982527734SSukumar Swaminathan  */
16082527734SSukumar Swaminathan static int32_t
16182527734SSukumar Swaminathan emlxs_sli4_online(emlxs_hba_t *hba)
16282527734SSukumar Swaminathan {
16382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
16482527734SSukumar Swaminathan 	emlxs_config_t *cfg;
16582527734SSukumar Swaminathan 	emlxs_vpd_t *vpd;
16682527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
16782527734SSukumar Swaminathan 	MAILBOX4 *mb  = NULL;
16882527734SSukumar Swaminathan 	MATCHMAP *mp  = NULL;
16982527734SSukumar Swaminathan 	uint32_t i;
17082527734SSukumar Swaminathan 	uint32_t j;
17182527734SSukumar Swaminathan 	uint32_t rval = 0;
17282527734SSukumar Swaminathan 	uint8_t *vpd_data;
17382527734SSukumar Swaminathan 	uint32_t sli_mode;
17482527734SSukumar Swaminathan 	uint8_t *outptr;
17582527734SSukumar Swaminathan 	uint32_t status;
17682527734SSukumar Swaminathan 	uint32_t fw_check;
1776a573d82SSukumar Swaminathan 	uint32_t kern_update = 0;
17882527734SSukumar Swaminathan 	emlxs_firmware_t hba_fw;
17982527734SSukumar Swaminathan 	emlxs_firmware_t *fw;
180*a9800bebSGarrett D'Amore 	uint16_t ssvid;
18182527734SSukumar Swaminathan 
18282527734SSukumar Swaminathan 	cfg = &CFG;
18382527734SSukumar Swaminathan 	vpd = &VPD;
18482527734SSukumar Swaminathan 
18582527734SSukumar Swaminathan 	sli_mode = EMLXS_HBA_SLI4_MODE;
18682527734SSukumar Swaminathan 	hba->sli_mode = sli_mode;
18782527734SSukumar Swaminathan 
18882527734SSukumar Swaminathan 	/* Set the fw_check flag */
18982527734SSukumar Swaminathan 	fw_check = cfg[CFG_FW_CHECK].current;
19082527734SSukumar Swaminathan 
1916a573d82SSukumar Swaminathan 	if ((fw_check & 0x04) ||
1926a573d82SSukumar Swaminathan 	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
1936a573d82SSukumar Swaminathan 		kern_update = 1;
1946a573d82SSukumar Swaminathan 	}
1956a573d82SSukumar Swaminathan 
19682527734SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
19782527734SSukumar Swaminathan 	hba->fc_edtov = FF_DEF_EDTOV;
19882527734SSukumar Swaminathan 	hba->fc_ratov = FF_DEF_RATOV;
19982527734SSukumar Swaminathan 	hba->fc_altov = FF_DEF_ALTOV;
20082527734SSukumar Swaminathan 	hba->fc_arbtov = FF_DEF_ARBTOV;
20182527734SSukumar Swaminathan 
20282527734SSukumar Swaminathan 	/* Target mode not supported */
20382527734SSukumar Swaminathan 	if (hba->tgt_mode) {
20482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
20582527734SSukumar Swaminathan 		    "Target mode not supported in SLI4.");
20682527734SSukumar Swaminathan 
20782527734SSukumar Swaminathan 		return (ENOMEM);
20882527734SSukumar Swaminathan 	}
20982527734SSukumar Swaminathan 
21082527734SSukumar Swaminathan 	/* Networking not supported */
21182527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
21282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
21382527734SSukumar Swaminathan 		    "Networking not supported in SLI4, turning it off");
21482527734SSukumar Swaminathan 		cfg[CFG_NETWORK_ON].current = 0;
21582527734SSukumar Swaminathan 	}
21682527734SSukumar Swaminathan 
21782527734SSukumar Swaminathan 	hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
21882527734SSukumar Swaminathan 	if (hba->chan_count > MAX_CHANNEL) {
21982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
22082527734SSukumar Swaminathan 		    "Max channels exceeded, dropping num-wq from %d to 1",
22182527734SSukumar Swaminathan 		    cfg[CFG_NUM_WQ].current);
22282527734SSukumar Swaminathan 		cfg[CFG_NUM_WQ].current = 1;
22382527734SSukumar Swaminathan 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
22482527734SSukumar Swaminathan 	}
22582527734SSukumar Swaminathan 	hba->channel_fcp = 0; /* First channel */
22682527734SSukumar Swaminathan 
22782527734SSukumar Swaminathan 	/* Default channel for everything else is the last channel */
22882527734SSukumar Swaminathan 	hba->channel_ip = hba->chan_count - 1;
22982527734SSukumar Swaminathan 	hba->channel_els = hba->chan_count - 1;
23082527734SSukumar Swaminathan 	hba->channel_ct = hba->chan_count - 1;
23182527734SSukumar Swaminathan 
23282527734SSukumar Swaminathan 	hba->fc_iotag = 1;
23382527734SSukumar Swaminathan 	hba->io_count = 0;
23482527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
23582527734SSukumar Swaminathan 
23682527734SSukumar Swaminathan 	/* Initialize the local dump region buffer */
23782527734SSukumar Swaminathan 	bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
23882527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
23982527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
24082527734SSukumar Swaminathan 	    | FC_MBUF_DMA32;
24182527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L);
24282527734SSukumar Swaminathan 
24382527734SSukumar Swaminathan 	(void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region);
24482527734SSukumar Swaminathan 
24582527734SSukumar Swaminathan 	if (hba->sli.sli4.dump_region.virt == NULL) {
24682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
24782527734SSukumar Swaminathan 		    "Unable to allocate dump region buffer.");
24882527734SSukumar Swaminathan 
24982527734SSukumar Swaminathan 		return (ENOMEM);
25082527734SSukumar Swaminathan 	}
25182527734SSukumar Swaminathan 
25282527734SSukumar Swaminathan 	/*
25382527734SSukumar Swaminathan 	 * Get a buffer which will be used repeatedly for mailbox commands
25482527734SSukumar Swaminathan 	 */
25582527734SSukumar Swaminathan 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
25682527734SSukumar Swaminathan 
25782527734SSukumar Swaminathan 	mb = (MAILBOX4 *)mbq;
25882527734SSukumar Swaminathan 
25982527734SSukumar Swaminathan reset:
26082527734SSukumar Swaminathan 	/* Reset & Initialize the adapter */
26182527734SSukumar Swaminathan 	if (emlxs_sli4_hba_init(hba)) {
26282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
26382527734SSukumar Swaminathan 		    "Unable to init hba.");
26482527734SSukumar Swaminathan 
26582527734SSukumar Swaminathan 		rval = EIO;
26682527734SSukumar Swaminathan 		goto failed1;
26782527734SSukumar Swaminathan 	}
26882527734SSukumar Swaminathan 
26982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
27082527734SSukumar Swaminathan 	/* Access handle validation */
27182527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
27282527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
27382527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli4.bar1_acc_handle)
27482527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
27582527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli4.bar2_acc_handle)
27682527734SSukumar Swaminathan 	    != DDI_FM_OK)) {
27782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
27882527734SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
27982527734SSukumar Swaminathan 
28082527734SSukumar Swaminathan 		rval = EIO;
28182527734SSukumar Swaminathan 		goto failed1;
28282527734SSukumar Swaminathan 	}
28382527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
28482527734SSukumar Swaminathan 
28582527734SSukumar Swaminathan 	/*
28682527734SSukumar Swaminathan 	 * Setup and issue mailbox READ REV command
28782527734SSukumar Swaminathan 	 */
28882527734SSukumar Swaminathan 	vpd->opFwRev = 0;
28982527734SSukumar Swaminathan 	vpd->postKernRev = 0;
29082527734SSukumar Swaminathan 	vpd->sli1FwRev = 0;
29182527734SSukumar Swaminathan 	vpd->sli2FwRev = 0;
29282527734SSukumar Swaminathan 	vpd->sli3FwRev = 0;
29382527734SSukumar Swaminathan 	vpd->sli4FwRev = 0;
29482527734SSukumar Swaminathan 
29582527734SSukumar Swaminathan 	vpd->postKernName[0] = 0;
29682527734SSukumar Swaminathan 	vpd->opFwName[0] = 0;
29782527734SSukumar Swaminathan 	vpd->sli1FwName[0] = 0;
29882527734SSukumar Swaminathan 	vpd->sli2FwName[0] = 0;
29982527734SSukumar Swaminathan 	vpd->sli3FwName[0] = 0;
30082527734SSukumar Swaminathan 	vpd->sli4FwName[0] = 0;
30182527734SSukumar Swaminathan 
30282527734SSukumar Swaminathan 	vpd->opFwLabel[0] = 0;
30382527734SSukumar Swaminathan 	vpd->sli1FwLabel[0] = 0;
30482527734SSukumar Swaminathan 	vpd->sli2FwLabel[0] = 0;
30582527734SSukumar Swaminathan 	vpd->sli3FwLabel[0] = 0;
30682527734SSukumar Swaminathan 	vpd->sli4FwLabel[0] = 0;
30782527734SSukumar Swaminathan 
30882527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
30982527734SSukumar Swaminathan 
31082527734SSukumar Swaminathan 	emlxs_mb_read_rev(hba, mbq, 0);
31182527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
31282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
31382527734SSukumar Swaminathan 		    "Unable to read rev. Mailbox cmd=%x status=%x",
31482527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
31582527734SSukumar Swaminathan 
31682527734SSukumar Swaminathan 		rval = EIO;
31782527734SSukumar Swaminathan 		goto failed1;
31882527734SSukumar Swaminathan 
31982527734SSukumar Swaminathan 	}
32082527734SSukumar Swaminathan 
321*a9800bebSGarrett D'Amore emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0);
32282527734SSukumar Swaminathan 	if (mb->un.varRdRev4.sliLevel != 4) {
32382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
32482527734SSukumar Swaminathan 		    "Invalid read rev Version for SLI4: 0x%x",
32582527734SSukumar Swaminathan 		    mb->un.varRdRev4.sliLevel);
32682527734SSukumar Swaminathan 
32782527734SSukumar Swaminathan 		rval = EIO;
32882527734SSukumar Swaminathan 		goto failed1;
32982527734SSukumar Swaminathan 	}
33082527734SSukumar Swaminathan 
33182527734SSukumar Swaminathan 	switch (mb->un.varRdRev4.dcbxMode) {
33282527734SSukumar Swaminathan 	case EMLXS_DCBX_MODE_CIN:	/* Mapped to nonFIP mode */
33382527734SSukumar Swaminathan 		hba->flag &= ~FC_FIP_SUPPORTED;
33482527734SSukumar Swaminathan 		break;
33582527734SSukumar Swaminathan 
33682527734SSukumar Swaminathan 	case EMLXS_DCBX_MODE_CEE:	/* Mapped to FIP mode */
33782527734SSukumar Swaminathan 		hba->flag |= FC_FIP_SUPPORTED;
33882527734SSukumar Swaminathan 		break;
33982527734SSukumar Swaminathan 
34082527734SSukumar Swaminathan 	default:
34182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
34282527734SSukumar Swaminathan 		    "Invalid read rev dcbx mode for SLI4: 0x%x",
34382527734SSukumar Swaminathan 		    mb->un.varRdRev4.dcbxMode);
34482527734SSukumar Swaminathan 
34582527734SSukumar Swaminathan 		rval = EIO;
34682527734SSukumar Swaminathan 		goto failed1;
34782527734SSukumar Swaminathan 	}
34882527734SSukumar Swaminathan 
34982527734SSukumar Swaminathan 
35082527734SSukumar Swaminathan 	/* Save information as VPD data */
35182527734SSukumar Swaminathan 	vpd->rBit = 1;
35282527734SSukumar Swaminathan 
35382527734SSukumar Swaminathan 	vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId);
35482527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16);
35582527734SSukumar Swaminathan 
35682527734SSukumar Swaminathan 	vpd->opFwRev = (mb->un.varRdRev4.ULPFwId);
35782527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16);
35882527734SSukumar Swaminathan 
35982527734SSukumar Swaminathan 	vpd->postKernRev = (mb->un.varRdRev4.ARMFwId);
36082527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16);
36182527734SSukumar Swaminathan 
36282527734SSukumar Swaminathan 	vpd->fcphHigh = mb->un.varRdRev4.fcphHigh;
36382527734SSukumar Swaminathan 	vpd->fcphLow = mb->un.varRdRev4.fcphLow;
36482527734SSukumar Swaminathan 	vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh;
36582527734SSukumar Swaminathan 	vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow;
36682527734SSukumar Swaminathan 
36782527734SSukumar Swaminathan 	/* Decode FW labels */
36882527734SSukumar Swaminathan 	emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0);
36982527734SSukumar Swaminathan 	emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0);
37082527734SSukumar Swaminathan 	emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0);
37182527734SSukumar Swaminathan 
372*a9800bebSGarrett D'Amore 	if (hba->model_info.chip == EMLXS_BE2_CHIP) {
37382527734SSukumar Swaminathan 		(void) strcpy(vpd->sli4FwLabel, "be2.ufi");
374*a9800bebSGarrett D'Amore 	} else if (hba->model_info.chip == EMLXS_BE3_CHIP) {
375*a9800bebSGarrett D'Amore 		(void) strcpy(vpd->sli4FwLabel, "be3.ufi");
37682527734SSukumar Swaminathan 	} else {
37782527734SSukumar Swaminathan 		(void) strcpy(vpd->sli4FwLabel, "sli4.fw");
37882527734SSukumar Swaminathan 	}
37982527734SSukumar Swaminathan 
38082527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
38182527734SSukumar Swaminathan 	    "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
38282527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName,
38382527734SSukumar Swaminathan 	    vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow,
38482527734SSukumar Swaminathan 	    mb->un.varRdRev4.dcbxMode);
38582527734SSukumar Swaminathan 
38682527734SSukumar Swaminathan 	/* No key information is needed for SLI4 products */
38782527734SSukumar Swaminathan 
38882527734SSukumar Swaminathan 	/* Get adapter VPD information */
38982527734SSukumar Swaminathan 	vpd->port_index = (uint32_t)-1;
39082527734SSukumar Swaminathan 
39182527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
39282527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
39382527734SSukumar Swaminathan 
39482527734SSukumar Swaminathan 	emlxs_mb_dump_vpd(hba, mbq, 0);
39582527734SSukumar Swaminathan 	vpd_data = hba->sli.sli4.dump_region.virt;
39682527734SSukumar Swaminathan 
39782527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
39882527734SSukumar Swaminathan 	    MBX_SUCCESS) {
39982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
40082527734SSukumar Swaminathan 		    "No VPD found. status=%x", mb->mbxStatus);
40182527734SSukumar Swaminathan 	} else {
40282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
40382527734SSukumar Swaminathan 		    &emlxs_init_debug_msg,
40482527734SSukumar Swaminathan 		    "VPD dumped. rsp_cnt=%d status=%x",
40582527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
40682527734SSukumar Swaminathan 
40782527734SSukumar Swaminathan 		if (mb->un.varDmp4.rsp_cnt) {
40882527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
40982527734SSukumar Swaminathan 			    0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL);
41082527734SSukumar Swaminathan 
411b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
412b3660a96SSukumar Swaminathan 			if (hba->sli.sli4.dump_region.dma_handle) {
413b3660a96SSukumar Swaminathan 				if (emlxs_fm_check_dma_handle(hba,
414b3660a96SSukumar Swaminathan 				    hba->sli.sli4.dump_region.dma_handle)
415b3660a96SSukumar Swaminathan 				    != DDI_FM_OK) {
416b3660a96SSukumar Swaminathan 					EMLXS_MSGF(EMLXS_CONTEXT,
417b3660a96SSukumar Swaminathan 					    &emlxs_invalid_dma_handle_msg,
418b3660a96SSukumar Swaminathan 					    "emlxs_sli4_online: hdl=%p",
419b3660a96SSukumar Swaminathan 					    hba->sli.sli4.dump_region.
420b3660a96SSukumar Swaminathan 					    dma_handle);
421b3660a96SSukumar Swaminathan 					rval = EIO;
422b3660a96SSukumar Swaminathan 					goto failed1;
423b3660a96SSukumar Swaminathan 				}
424b3660a96SSukumar Swaminathan 			}
425b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
426b3660a96SSukumar Swaminathan 
42782527734SSukumar Swaminathan 		}
42882527734SSukumar Swaminathan 	}
42982527734SSukumar Swaminathan 
43082527734SSukumar Swaminathan 	if (vpd_data[0]) {
43182527734SSukumar Swaminathan 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data,
43282527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt);
43382527734SSukumar Swaminathan 
43482527734SSukumar Swaminathan 		/*
43582527734SSukumar Swaminathan 		 * If there is a VPD part number, and it does not
43682527734SSukumar Swaminathan 		 * match the current default HBA model info,
43782527734SSukumar Swaminathan 		 * replace the default data with an entry that
43882527734SSukumar Swaminathan 		 * does match.
43982527734SSukumar Swaminathan 		 *
44082527734SSukumar Swaminathan 		 * After emlxs_parse_vpd model holds the VPD value
44182527734SSukumar Swaminathan 		 * for V2 and part_num hold the value for PN. These
44282527734SSukumar Swaminathan 		 * 2 values are NOT necessarily the same.
44382527734SSukumar Swaminathan 		 */
44482527734SSukumar Swaminathan 
44582527734SSukumar Swaminathan 		rval = 0;
44682527734SSukumar Swaminathan 		if ((vpd->model[0] != 0) &&
44782527734SSukumar Swaminathan 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
44882527734SSukumar Swaminathan 
44982527734SSukumar Swaminathan 			/* First scan for a V2 match */
45082527734SSukumar Swaminathan 
45182527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
45282527734SSukumar Swaminathan 				if (strcmp(&vpd->model[0],
45382527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
45482527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
45582527734SSukumar Swaminathan 					    &hba->model_info,
45682527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
45782527734SSukumar Swaminathan 					rval = 1;
45882527734SSukumar Swaminathan 					break;
45982527734SSukumar Swaminathan 				}
46082527734SSukumar Swaminathan 			}
46182527734SSukumar Swaminathan 		}
46282527734SSukumar Swaminathan 
46382527734SSukumar Swaminathan 		if (!rval && (vpd->part_num[0] != 0) &&
46482527734SSukumar Swaminathan 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
46582527734SSukumar Swaminathan 
46682527734SSukumar Swaminathan 			/* Next scan for a PN match */
46782527734SSukumar Swaminathan 
46882527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
46982527734SSukumar Swaminathan 				if (strcmp(&vpd->part_num[0],
47082527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
47182527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
47282527734SSukumar Swaminathan 					    &hba->model_info,
47382527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
47482527734SSukumar Swaminathan 					break;
47582527734SSukumar Swaminathan 				}
47682527734SSukumar Swaminathan 			}
47782527734SSukumar Swaminathan 		}
47882527734SSukumar Swaminathan 
479*a9800bebSGarrett D'Amore 		/* HP CNA port indices start at 1 instead of 0 */
480*a9800bebSGarrett D'Amore 		if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
481*a9800bebSGarrett D'Amore 		    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
482*a9800bebSGarrett D'Amore 
483*a9800bebSGarrett D'Amore 			ssvid = ddi_get16(hba->pci_acc_handle,
484*a9800bebSGarrett D'Amore 			    (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER));
485*a9800bebSGarrett D'Amore 
486*a9800bebSGarrett D'Amore 			if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) {
487*a9800bebSGarrett D'Amore 				vpd->port_index--;
488*a9800bebSGarrett D'Amore 			}
489*a9800bebSGarrett D'Amore 		}
490*a9800bebSGarrett D'Amore 
49182527734SSukumar Swaminathan 		/*
49282527734SSukumar Swaminathan 		 * Now lets update hba->model_info with the real
49382527734SSukumar Swaminathan 		 * VPD data, if any.
49482527734SSukumar Swaminathan 		 */
49582527734SSukumar Swaminathan 
49682527734SSukumar Swaminathan 		/*
49782527734SSukumar Swaminathan 		 * Replace the default model description with vpd data
49882527734SSukumar Swaminathan 		 */
49982527734SSukumar Swaminathan 		if (vpd->model_desc[0] != 0) {
50082527734SSukumar Swaminathan 			(void) strcpy(hba->model_info.model_desc,
50182527734SSukumar Swaminathan 			    vpd->model_desc);
50282527734SSukumar Swaminathan 		}
50382527734SSukumar Swaminathan 
50482527734SSukumar Swaminathan 		/* Replace the default model with vpd data */
50582527734SSukumar Swaminathan 		if (vpd->model[0] != 0) {
50682527734SSukumar Swaminathan 			(void) strcpy(hba->model_info.model, vpd->model);
50782527734SSukumar Swaminathan 		}
50882527734SSukumar Swaminathan 
50982527734SSukumar Swaminathan 		/* Replace the default program types with vpd data */
51082527734SSukumar Swaminathan 		if (vpd->prog_types[0] != 0) {
51182527734SSukumar Swaminathan 			emlxs_parse_prog_types(hba, vpd->prog_types);
51282527734SSukumar Swaminathan 		}
51382527734SSukumar Swaminathan 	}
51482527734SSukumar Swaminathan 
51582527734SSukumar Swaminathan 	/*
51682527734SSukumar Swaminathan 	 * Since the adapter model may have changed with the vpd data
51782527734SSukumar Swaminathan 	 * lets double check if adapter is not supported
51882527734SSukumar Swaminathan 	 */
51982527734SSukumar Swaminathan 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
52082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
52182527734SSukumar Swaminathan 		    "Unsupported adapter found.  "
52282527734SSukumar Swaminathan 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
52382527734SSukumar Swaminathan 		    hba->model_info.id, hba->model_info.device_id,
52482527734SSukumar Swaminathan 		    hba->model_info.ssdid, hba->model_info.model);
52582527734SSukumar Swaminathan 
52682527734SSukumar Swaminathan 		rval = EIO;
52782527734SSukumar Swaminathan 		goto failed1;
52882527734SSukumar Swaminathan 	}
52982527734SSukumar Swaminathan 
53082527734SSukumar Swaminathan 	(void) strcpy(vpd->boot_version, vpd->sli4FwName);
53182527734SSukumar Swaminathan 
53282527734SSukumar Swaminathan 	/* Get fcode version property */
53382527734SSukumar Swaminathan 	emlxs_get_fcode_version(hba);
53482527734SSukumar Swaminathan 
53582527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
53682527734SSukumar Swaminathan 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
53782527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->sli1FwRev);
53882527734SSukumar Swaminathan 
53982527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
54082527734SSukumar Swaminathan 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
54182527734SSukumar Swaminathan 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
54282527734SSukumar Swaminathan 
54382527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
54482527734SSukumar Swaminathan 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
54582527734SSukumar Swaminathan 
54682527734SSukumar Swaminathan 	/*
54782527734SSukumar Swaminathan 	 * If firmware checking is enabled and the adapter model indicates
54882527734SSukumar Swaminathan 	 * a firmware image, then perform firmware version check
54982527734SSukumar Swaminathan 	 */
5506a573d82SSukumar Swaminathan 	hba->fw_flag = 0;
5516a573d82SSukumar Swaminathan 	hba->fw_timer = 0;
5526a573d82SSukumar Swaminathan 
5536a573d82SSukumar Swaminathan 	if (((fw_check & 0x1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
5546a573d82SSukumar Swaminathan 	    hba->model_info.fwid) || ((fw_check & 0x2) &&
55582527734SSukumar Swaminathan 	    hba->model_info.fwid)) {
55682527734SSukumar Swaminathan 
55782527734SSukumar Swaminathan 		/* Find firmware image indicated by adapter model */
55882527734SSukumar Swaminathan 		fw = NULL;
55982527734SSukumar Swaminathan 		for (i = 0; i < emlxs_fw_count; i++) {
56082527734SSukumar Swaminathan 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
56182527734SSukumar Swaminathan 				fw = &emlxs_fw_table[i];
56282527734SSukumar Swaminathan 				break;
56382527734SSukumar Swaminathan 			}
56482527734SSukumar Swaminathan 		}
56582527734SSukumar Swaminathan 
56682527734SSukumar Swaminathan 		/*
56782527734SSukumar Swaminathan 		 * If the image was found, then verify current firmware
56882527734SSukumar Swaminathan 		 * versions of adapter
56982527734SSukumar Swaminathan 		 */
57082527734SSukumar Swaminathan 		if (fw) {
57182527734SSukumar Swaminathan 
57282527734SSukumar Swaminathan 			/* Obtain current firmware version info */
573*a9800bebSGarrett D'Amore 			if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
574*a9800bebSGarrett D'Amore 			    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
57582527734SSukumar Swaminathan 				(void) emlxs_sli4_read_fw_version(hba, &hba_fw);
57682527734SSukumar Swaminathan 			} else {
57782527734SSukumar Swaminathan 				hba_fw.kern = vpd->postKernRev;
57882527734SSukumar Swaminathan 				hba_fw.stub = vpd->opFwRev;
57982527734SSukumar Swaminathan 				hba_fw.sli1 = vpd->sli1FwRev;
58082527734SSukumar Swaminathan 				hba_fw.sli2 = vpd->sli2FwRev;
58182527734SSukumar Swaminathan 				hba_fw.sli3 = vpd->sli3FwRev;
58282527734SSukumar Swaminathan 				hba_fw.sli4 = vpd->sli4FwRev;
58382527734SSukumar Swaminathan 			}
58482527734SSukumar Swaminathan 
5856a573d82SSukumar Swaminathan 			if (!kern_update &&
5866a573d82SSukumar Swaminathan 			    ((fw->kern && (hba_fw.kern != fw->kern)) ||
5876a573d82SSukumar Swaminathan 			    (fw->stub && (hba_fw.stub != fw->stub)))) {
5886a573d82SSukumar Swaminathan 
5896a573d82SSukumar Swaminathan 				hba->fw_flag |= FW_UPDATE_NEEDED;
5906a573d82SSukumar Swaminathan 
5916a573d82SSukumar Swaminathan 			} else if ((fw->kern && (hba_fw.kern != fw->kern)) ||
59282527734SSukumar Swaminathan 			    (fw->stub && (hba_fw.stub != fw->stub)) ||
59382527734SSukumar Swaminathan 			    (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
59482527734SSukumar Swaminathan 			    (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
59582527734SSukumar Swaminathan 			    (fw->sli3 && (hba_fw.sli3 != fw->sli3)) ||
59682527734SSukumar Swaminathan 			    (fw->sli4 && (hba_fw.sli4 != fw->sli4))) {
59782527734SSukumar Swaminathan 
59882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
59982527734SSukumar Swaminathan 				    "Firmware update needed. "
60082527734SSukumar Swaminathan 				    "Updating. id=%d fw=%d",
60182527734SSukumar Swaminathan 				    hba->model_info.id, hba->model_info.fwid);
60282527734SSukumar Swaminathan 
60382527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
60482527734SSukumar Swaminathan 				/*
60582527734SSukumar Swaminathan 				 * Load the firmware image now
60682527734SSukumar Swaminathan 				 * If MODFW_SUPPORT is not defined, the
60782527734SSukumar Swaminathan 				 * firmware image will already be defined
60882527734SSukumar Swaminathan 				 * in the emlxs_fw_table
60982527734SSukumar Swaminathan 				 */
61082527734SSukumar Swaminathan 				emlxs_fw_load(hba, fw);
61182527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
61282527734SSukumar Swaminathan 
61382527734SSukumar Swaminathan 				if (fw->image && fw->size) {
61482527734SSukumar Swaminathan 					if (emlxs_fw_download(hba,
61582527734SSukumar Swaminathan 					    (char *)fw->image, fw->size, 0)) {
61682527734SSukumar Swaminathan 						EMLXS_MSGF(EMLXS_CONTEXT,
61782527734SSukumar Swaminathan 						    &emlxs_init_msg,
61882527734SSukumar Swaminathan 						    "Firmware update failed.");
6196a573d82SSukumar Swaminathan 
6206a573d82SSukumar Swaminathan 						hba->fw_flag |=
6216a573d82SSukumar Swaminathan 						    FW_UPDATE_NEEDED;
62282527734SSukumar Swaminathan 					}
62382527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
62482527734SSukumar Swaminathan 					/*
62582527734SSukumar Swaminathan 					 * Unload the firmware image from
62682527734SSukumar Swaminathan 					 * kernel memory
62782527734SSukumar Swaminathan 					 */
62882527734SSukumar Swaminathan 					emlxs_fw_unload(hba, fw);
62982527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
63082527734SSukumar Swaminathan 
63182527734SSukumar Swaminathan 					fw_check = 0;
63282527734SSukumar Swaminathan 
63382527734SSukumar Swaminathan 					goto reset;
63482527734SSukumar Swaminathan 				}
63582527734SSukumar Swaminathan 
63682527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
63782527734SSukumar Swaminathan 				    "Firmware image unavailable.");
63882527734SSukumar Swaminathan 			} else {
63982527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
64082527734SSukumar Swaminathan 				    "Firmware update not needed.");
64182527734SSukumar Swaminathan 			}
64282527734SSukumar Swaminathan 		} else {
64382527734SSukumar Swaminathan 			/*
64482527734SSukumar Swaminathan 			 * This means either the adapter database is not
64582527734SSukumar Swaminathan 			 * correct or a firmware image is missing from the
64682527734SSukumar Swaminathan 			 * compile
64782527734SSukumar Swaminathan 			 */
64882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
64982527734SSukumar Swaminathan 			    "Firmware image unavailable. id=%d fw=%d",
65082527734SSukumar Swaminathan 			    hba->model_info.id, hba->model_info.fwid);
65182527734SSukumar Swaminathan 		}
65282527734SSukumar Swaminathan 	}
65382527734SSukumar Swaminathan 
65482527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
65582527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
65682527734SSukumar Swaminathan 
65782527734SSukumar Swaminathan 	emlxs_mb_dump_fcoe(hba, mbq, 0);
65882527734SSukumar Swaminathan 
65982527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
66082527734SSukumar Swaminathan 	    MBX_SUCCESS) {
66182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
66282527734SSukumar Swaminathan 		    "No FCOE info found. status=%x", mb->mbxStatus);
66382527734SSukumar Swaminathan 	} else {
66482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
66582527734SSukumar Swaminathan 		    &emlxs_init_debug_msg,
66682527734SSukumar Swaminathan 		    "FCOE info dumped. rsp_cnt=%d status=%x",
66782527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
66882527734SSukumar Swaminathan 		(void) emlxs_parse_fcoe(hba,
669fe199829SSukumar Swaminathan 		    (uint8_t *)hba->sli.sli4.dump_region.virt,
670fe199829SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt);
67182527734SSukumar Swaminathan 	}
67282527734SSukumar Swaminathan 
67382527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
67482527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
67582527734SSukumar Swaminathan 
67682527734SSukumar Swaminathan 	emlxs_mb_request_features(hba, mbq);
67782527734SSukumar Swaminathan 
67882527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
67982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
68082527734SSukumar Swaminathan 		    "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
68182527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
68282527734SSukumar Swaminathan 
68382527734SSukumar Swaminathan 		rval = EIO;
68482527734SSukumar Swaminathan 		goto failed1;
68582527734SSukumar Swaminathan 	}
686*a9800bebSGarrett D'Amore emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0);
68782527734SSukumar Swaminathan 
68882527734SSukumar Swaminathan 	/* Make sure we get the features we requested */
68982527734SSukumar Swaminathan 	if (mb->un.varReqFeatures.featuresRequested !=
69082527734SSukumar Swaminathan 	    mb->un.varReqFeatures.featuresEnabled) {
69182527734SSukumar Swaminathan 
69282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
69382527734SSukumar Swaminathan 		    "Unable to get REQUESTed_FEATURES. want:x%x  got:x%x",
69482527734SSukumar Swaminathan 		    mb->un.varReqFeatures.featuresRequested,
69582527734SSukumar Swaminathan 		    mb->un.varReqFeatures.featuresEnabled);
69682527734SSukumar Swaminathan 
69782527734SSukumar Swaminathan 		rval = EIO;
69882527734SSukumar Swaminathan 		goto failed1;
69982527734SSukumar Swaminathan 	}
70082527734SSukumar Swaminathan 
70182527734SSukumar Swaminathan 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) {
70282527734SSukumar Swaminathan 		hba->flag |= FC_NPIV_ENABLED;
70382527734SSukumar Swaminathan 	}
70482527734SSukumar Swaminathan 
70582527734SSukumar Swaminathan 	/* Check enable-npiv driver parameter for now */
70682527734SSukumar Swaminathan 	if (cfg[CFG_NPIV_ENABLE].current) {
70782527734SSukumar Swaminathan 		hba->flag |= FC_NPIV_ENABLED;
70882527734SSukumar Swaminathan 	}
70982527734SSukumar Swaminathan 
71082527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
71182527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
71282527734SSukumar Swaminathan 
71382527734SSukumar Swaminathan 	emlxs_mb_read_config(hba, mbq);
71482527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
71582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
71682527734SSukumar Swaminathan 		    "Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
71782527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
71882527734SSukumar Swaminathan 
71982527734SSukumar Swaminathan 		rval = EIO;
72082527734SSukumar Swaminathan 		goto failed1;
72182527734SSukumar Swaminathan 	}
722*a9800bebSGarrett D'Amore emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0);
72382527734SSukumar Swaminathan 
72482527734SSukumar Swaminathan 	hba->sli.sli4.XRICount = (mb->un.varRdConfig4.XRICount);
72582527734SSukumar Swaminathan 	hba->sli.sli4.XRIBase = (mb->un.varRdConfig4.XRIBase);
72682527734SSukumar Swaminathan 	hba->sli.sli4.RPICount = (mb->un.varRdConfig4.RPICount);
72782527734SSukumar Swaminathan 	hba->sli.sli4.RPIBase = (mb->un.varRdConfig4.RPIBase);
72882527734SSukumar Swaminathan 	hba->sli.sli4.VPICount = (mb->un.varRdConfig4.VPICount);
72982527734SSukumar Swaminathan 	hba->sli.sli4.VPIBase = (mb->un.varRdConfig4.VPIBase);
73082527734SSukumar Swaminathan 	hba->sli.sli4.VFICount = (mb->un.varRdConfig4.VFICount);
73182527734SSukumar Swaminathan 	hba->sli.sli4.VFIBase = (mb->un.varRdConfig4.VFIBase);
73282527734SSukumar Swaminathan 	hba->sli.sli4.FCFICount = (mb->un.varRdConfig4.FCFICount);
73382527734SSukumar Swaminathan 
73482527734SSukumar Swaminathan 	if (hba->sli.sli4.VPICount) {
73582527734SSukumar Swaminathan 		hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
73682527734SSukumar Swaminathan 	}
73782527734SSukumar Swaminathan 	hba->vpi_base = mb->un.varRdConfig4.VPIBase;
73882527734SSukumar Swaminathan 
73982527734SSukumar Swaminathan 	/* Set the max node count */
74082527734SSukumar Swaminathan 	if (cfg[CFG_NUM_NODES].current > 0) {
74182527734SSukumar Swaminathan 		hba->max_nodes =
74282527734SSukumar Swaminathan 		    min(cfg[CFG_NUM_NODES].current,
74382527734SSukumar Swaminathan 		    hba->sli.sli4.RPICount);
74482527734SSukumar Swaminathan 	} else {
74582527734SSukumar Swaminathan 		hba->max_nodes = hba->sli.sli4.RPICount;
74682527734SSukumar Swaminathan 	}
74782527734SSukumar Swaminathan 
74882527734SSukumar Swaminathan 	/* Set the io throttle */
74982527734SSukumar Swaminathan 	hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE;
75082527734SSukumar Swaminathan 	hba->max_iotag = hba->sli.sli4.XRICount;
75182527734SSukumar Swaminathan 
75282527734SSukumar Swaminathan 	/* Save the link speed capabilities */
753*a9800bebSGarrett D'Amore 	vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt;
75482527734SSukumar Swaminathan 	emlxs_process_link_speed(hba);
75582527734SSukumar Swaminathan 
75682527734SSukumar Swaminathan 	/*
75782527734SSukumar Swaminathan 	 * Allocate some memory for buffers
75882527734SSukumar Swaminathan 	 */
75982527734SSukumar Swaminathan 	if (emlxs_mem_alloc_buffer(hba) == 0) {
76082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
76182527734SSukumar Swaminathan 		    "Unable to allocate memory buffers.");
76282527734SSukumar Swaminathan 
76382527734SSukumar Swaminathan 		rval = ENOMEM;
76482527734SSukumar Swaminathan 		goto failed1;
76582527734SSukumar Swaminathan 	}
76682527734SSukumar Swaminathan 
76782527734SSukumar Swaminathan 	/*
76882527734SSukumar Swaminathan 	 * OutOfRange (oor) iotags are used for abort or close
76982527734SSukumar Swaminathan 	 * XRI commands or any WQE that does not require a SGL
77082527734SSukumar Swaminathan 	 */
77182527734SSukumar Swaminathan 	hba->fc_oor_iotag = hba->max_iotag;
77282527734SSukumar Swaminathan 
77382527734SSukumar Swaminathan 	if (emlxs_sli4_resource_alloc(hba)) {
77482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
77582527734SSukumar Swaminathan 		    "Unable to allocate resources.");
77682527734SSukumar Swaminathan 
77782527734SSukumar Swaminathan 		rval = ENOMEM;
77882527734SSukumar Swaminathan 		goto failed2;
77982527734SSukumar Swaminathan 	}
780*a9800bebSGarrett D'Amore emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0);
78182527734SSukumar Swaminathan 
78282527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5)
78382527734SSukumar Swaminathan 	if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) {
78482527734SSukumar Swaminathan 		hba->fca_tran->fca_num_npivports = hba->vpi_max;
78582527734SSukumar Swaminathan 	}
78682527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */
78782527734SSukumar Swaminathan 
78882527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
78982527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
79082527734SSukumar Swaminathan 
79182527734SSukumar Swaminathan 	if (emlxs_sli4_post_sgl_pages(hba, mbq)) {
79282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
79382527734SSukumar Swaminathan 		    "Unable to post sgl pages.");
79482527734SSukumar Swaminathan 
79582527734SSukumar Swaminathan 		rval = EIO;
79682527734SSukumar Swaminathan 		goto failed3;
79782527734SSukumar Swaminathan 	}
79882527734SSukumar Swaminathan 
79982527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
80082527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
80182527734SSukumar Swaminathan 
80282527734SSukumar Swaminathan 	if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) {
80382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
80482527734SSukumar Swaminathan 		    "Unable to post header templates.");
80582527734SSukumar Swaminathan 
80682527734SSukumar Swaminathan 		rval = EIO;
80782527734SSukumar Swaminathan 		goto failed3;
80882527734SSukumar Swaminathan 	}
80982527734SSukumar Swaminathan 
81082527734SSukumar Swaminathan 	/*
81182527734SSukumar Swaminathan 	 * Add our interrupt routine to kernel's interrupt chain & enable it
81282527734SSukumar Swaminathan 	 * If MSI is enabled this will cause Solaris to program the MSI address
81382527734SSukumar Swaminathan 	 * and data registers in PCI config space
81482527734SSukumar Swaminathan 	 */
81582527734SSukumar Swaminathan 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
81682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
81782527734SSukumar Swaminathan 		    "Unable to add interrupt(s).");
81882527734SSukumar Swaminathan 
81982527734SSukumar Swaminathan 		rval = EIO;
82082527734SSukumar Swaminathan 		goto failed3;
82182527734SSukumar Swaminathan 	}
82282527734SSukumar Swaminathan 
82382527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
82482527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
82582527734SSukumar Swaminathan 
82682527734SSukumar Swaminathan 	/* This MUST be done after EMLXS_INTR_ADD */
82782527734SSukumar Swaminathan 	if (emlxs_sli4_create_queues(hba, mbq)) {
82882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
82982527734SSukumar Swaminathan 		    "Unable to create queues.");
83082527734SSukumar Swaminathan 
83182527734SSukumar Swaminathan 		rval = EIO;
83282527734SSukumar Swaminathan 		goto failed3;
83382527734SSukumar Swaminathan 	}
83482527734SSukumar Swaminathan 
83582527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
83682527734SSukumar Swaminathan 
83782527734SSukumar Swaminathan 	/* Get and save the current firmware version (based on sli_mode) */
83882527734SSukumar Swaminathan 	emlxs_decode_firmware_rev(hba, vpd);
83982527734SSukumar Swaminathan 
84082527734SSukumar Swaminathan 
84182527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
84282527734SSukumar Swaminathan 
84382527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
84482527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
84582527734SSukumar Swaminathan 
84682527734SSukumar Swaminathan 	/*
84782527734SSukumar Swaminathan 	 * We need to get login parameters for NID
84882527734SSukumar Swaminathan 	 */
84982527734SSukumar Swaminathan 	(void) emlxs_mb_read_sparam(hba, mbq);
850*a9800bebSGarrett D'Amore 	mp = (MATCHMAP *)mbq->bp;
85182527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
85282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
85382527734SSukumar Swaminathan 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
85482527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
85582527734SSukumar Swaminathan 
85682527734SSukumar Swaminathan 		rval = EIO;
85782527734SSukumar Swaminathan 		goto failed3;
85882527734SSukumar Swaminathan 	}
85982527734SSukumar Swaminathan 
86082527734SSukumar Swaminathan 	/* Free the buffer since we were polling */
861*a9800bebSGarrett D'Amore 	emlxs_mem_put(hba, MEM_BUF, (void *)mp);
86282527734SSukumar Swaminathan 	mp = NULL;
86382527734SSukumar Swaminathan 
86482527734SSukumar Swaminathan 	/* If no serial number in VPD data, then use the WWPN */
86582527734SSukumar Swaminathan 	if (vpd->serial_num[0] == 0) {
86682527734SSukumar Swaminathan 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
86782527734SSukumar Swaminathan 		for (i = 0; i < 12; i++) {
86882527734SSukumar Swaminathan 			status = *outptr++;
86982527734SSukumar Swaminathan 			j = ((status & 0xf0) >> 4);
87082527734SSukumar Swaminathan 			if (j <= 9) {
87182527734SSukumar Swaminathan 				vpd->serial_num[i] =
87282527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
87382527734SSukumar Swaminathan 			} else {
87482527734SSukumar Swaminathan 				vpd->serial_num[i] =
87582527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
87682527734SSukumar Swaminathan 			}
87782527734SSukumar Swaminathan 
87882527734SSukumar Swaminathan 			i++;
87982527734SSukumar Swaminathan 			j = (status & 0xf);
88082527734SSukumar Swaminathan 			if (j <= 9) {
88182527734SSukumar Swaminathan 				vpd->serial_num[i] =
88282527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
88382527734SSukumar Swaminathan 			} else {
88482527734SSukumar Swaminathan 				vpd->serial_num[i] =
88582527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
88682527734SSukumar Swaminathan 			}
88782527734SSukumar Swaminathan 		}
88882527734SSukumar Swaminathan 
88982527734SSukumar Swaminathan 		/*
89082527734SSukumar Swaminathan 		 * Set port number and port index to zero
89182527734SSukumar Swaminathan 		 * The WWN's are unique to each port and therefore port_num
89282527734SSukumar Swaminathan 		 * must equal zero. This effects the hba_fru_details structure
89382527734SSukumar Swaminathan 		 * in fca_bind_port()
89482527734SSukumar Swaminathan 		 */
89582527734SSukumar Swaminathan 		vpd->port_num[0] = 0;
89682527734SSukumar Swaminathan 		vpd->port_index = 0;
89782527734SSukumar Swaminathan 	}
89882527734SSukumar Swaminathan 
89982527734SSukumar Swaminathan 	/* Make attempt to set a port index */
900*a9800bebSGarrett D'Amore 	if (vpd->port_index == (uint32_t)-1) {
90182527734SSukumar Swaminathan 		dev_info_t *p_dip;
90282527734SSukumar Swaminathan 		dev_info_t *c_dip;
90382527734SSukumar Swaminathan 
90482527734SSukumar Swaminathan 		p_dip = ddi_get_parent(hba->dip);
90582527734SSukumar Swaminathan 		c_dip = ddi_get_child(p_dip);
90682527734SSukumar Swaminathan 
90782527734SSukumar Swaminathan 		vpd->port_index = 0;
90882527734SSukumar Swaminathan 		while (c_dip && (hba->dip != c_dip)) {
90982527734SSukumar Swaminathan 			c_dip = ddi_get_next_sibling(c_dip);
91082527734SSukumar Swaminathan 
91182527734SSukumar Swaminathan 			if (strcmp(ddi_get_name(c_dip), "ethernet")) {
91282527734SSukumar Swaminathan 				vpd->port_index++;
91382527734SSukumar Swaminathan 			}
91482527734SSukumar Swaminathan 		}
91582527734SSukumar Swaminathan 	}
91682527734SSukumar Swaminathan 
91782527734SSukumar Swaminathan 	if (vpd->port_num[0] == 0) {
91882527734SSukumar Swaminathan 		if (hba->model_info.channels > 1) {
91982527734SSukumar Swaminathan 			(void) sprintf(vpd->port_num, "%d", vpd->port_index);
92082527734SSukumar Swaminathan 		}
92182527734SSukumar Swaminathan 	}
92282527734SSukumar Swaminathan 
92382527734SSukumar Swaminathan 	if (vpd->id[0] == 0) {
92482527734SSukumar Swaminathan 		(void) sprintf(vpd->id, "%s %d",
92582527734SSukumar Swaminathan 		    hba->model_info.model_desc, vpd->port_index);
92682527734SSukumar Swaminathan 
92782527734SSukumar Swaminathan 	}
92882527734SSukumar Swaminathan 
92982527734SSukumar Swaminathan 	if (vpd->manufacturer[0] == 0) {
93082527734SSukumar Swaminathan 		(void) strcpy(vpd->manufacturer, hba->model_info.manufacturer);
93182527734SSukumar Swaminathan 	}
93282527734SSukumar Swaminathan 
93382527734SSukumar Swaminathan 	if (vpd->part_num[0] == 0) {
93482527734SSukumar Swaminathan 		(void) strcpy(vpd->part_num, hba->model_info.model);
93582527734SSukumar Swaminathan 	}
93682527734SSukumar Swaminathan 
93782527734SSukumar Swaminathan 	if (vpd->model_desc[0] == 0) {
93882527734SSukumar Swaminathan 		(void) sprintf(vpd->model_desc, "%s %d",
93982527734SSukumar Swaminathan 		    hba->model_info.model_desc, vpd->port_index);
94082527734SSukumar Swaminathan 	}
94182527734SSukumar Swaminathan 
94282527734SSukumar Swaminathan 	if (vpd->model[0] == 0) {
94382527734SSukumar Swaminathan 		(void) strcpy(vpd->model, hba->model_info.model);
94482527734SSukumar Swaminathan 	}
94582527734SSukumar Swaminathan 
94682527734SSukumar Swaminathan 	if (vpd->prog_types[0] == 0) {
94782527734SSukumar Swaminathan 		emlxs_build_prog_types(hba, vpd->prog_types);
94882527734SSukumar Swaminathan 	}
94982527734SSukumar Swaminathan 
95082527734SSukumar Swaminathan 	/* Create the symbolic names */
95182527734SSukumar Swaminathan 	(void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s",
95282527734SSukumar Swaminathan 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
95382527734SSukumar Swaminathan 	    (char *)utsname.nodename);
95482527734SSukumar Swaminathan 
95582527734SSukumar Swaminathan 	(void) sprintf(hba->spn,
95682527734SSukumar Swaminathan 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
95782527734SSukumar Swaminathan 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
95882527734SSukumar Swaminathan 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
95982527734SSukumar Swaminathan 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
96082527734SSukumar Swaminathan 
96182527734SSukumar Swaminathan 
96282527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
96382527734SSukumar Swaminathan 	emlxs_sli4_enable_intr(hba);
96482527734SSukumar Swaminathan 
96582527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
96682527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
96782527734SSukumar Swaminathan 
96882527734SSukumar Swaminathan 	/*
96982527734SSukumar Swaminathan 	 * Setup and issue mailbox INITIALIZE LINK command
97082527734SSukumar Swaminathan 	 * At this point, the interrupt will be generated by the HW
97182527734SSukumar Swaminathan 	 * Do this only if persist-linkdown is not set
97282527734SSukumar Swaminathan 	 */
97382527734SSukumar Swaminathan 	if (cfg[CFG_PERSIST_LINKDOWN].current == 0) {
97482527734SSukumar Swaminathan 		emlxs_mb_init_link(hba, mbq,
97582527734SSukumar Swaminathan 		    cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
97682527734SSukumar Swaminathan 
97782527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0)
97882527734SSukumar Swaminathan 		    != MBX_SUCCESS) {
97982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
980*a9800bebSGarrett D'Amore 			    "Unable to initialize link. "
98182527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
98282527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
98382527734SSukumar Swaminathan 
98482527734SSukumar Swaminathan 			rval = EIO;
98582527734SSukumar Swaminathan 			goto failed3;
98682527734SSukumar Swaminathan 		}
98782527734SSukumar Swaminathan 
98882527734SSukumar Swaminathan 		/* Wait for link to come up */
98982527734SSukumar Swaminathan 		i = cfg[CFG_LINKUP_DELAY].current;
99082527734SSukumar Swaminathan 		while (i && (hba->state < FC_LINK_UP)) {
99182527734SSukumar Swaminathan 			/* Check for hardware error */
99282527734SSukumar Swaminathan 			if (hba->state == FC_ERROR) {
99382527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
99482527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
99582527734SSukumar Swaminathan 				    "Adapter error.", mb->mbxCommand,
99682527734SSukumar Swaminathan 				    mb->mbxStatus);
99782527734SSukumar Swaminathan 
99882527734SSukumar Swaminathan 				rval = EIO;
99982527734SSukumar Swaminathan 				goto failed3;
100082527734SSukumar Swaminathan 			}
100182527734SSukumar Swaminathan 
100282527734SSukumar Swaminathan 			DELAYMS(1000);
100382527734SSukumar Swaminathan 			i--;
100482527734SSukumar Swaminathan 		}
1005*a9800bebSGarrett D'Amore 	} else {
1006*a9800bebSGarrett D'Amore 		EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
100782527734SSukumar Swaminathan 	}
100882527734SSukumar Swaminathan 
100982527734SSukumar Swaminathan 	/*
101082527734SSukumar Swaminathan 	 * The leadvile driver will now handle the FLOGI at the driver level
101182527734SSukumar Swaminathan 	 */
101282527734SSukumar Swaminathan 
1013bce54adfSSukumar Swaminathan 	if (mbq) {
1014bce54adfSSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1015bce54adfSSukumar Swaminathan 		mbq = NULL;
1016bce54adfSSukumar Swaminathan 		mb = NULL;
1017bce54adfSSukumar Swaminathan 	}
101882527734SSukumar Swaminathan 	return (0);
101982527734SSukumar Swaminathan 
102082527734SSukumar Swaminathan failed3:
102182527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
102282527734SSukumar Swaminathan 
102382527734SSukumar Swaminathan 	if (mp) {
1024*a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
102582527734SSukumar Swaminathan 		mp = NULL;
102682527734SSukumar Swaminathan 	}
102782527734SSukumar Swaminathan 
102882527734SSukumar Swaminathan 
102982527734SSukumar Swaminathan 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
103082527734SSukumar Swaminathan 		(void) EMLXS_INTR_REMOVE(hba);
103182527734SSukumar Swaminathan 	}
103282527734SSukumar Swaminathan 
103382527734SSukumar Swaminathan 	emlxs_sli4_resource_free(hba);
103482527734SSukumar Swaminathan 
103582527734SSukumar Swaminathan failed2:
103682527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
103782527734SSukumar Swaminathan 
103882527734SSukumar Swaminathan failed1:
103982527734SSukumar Swaminathan 	if (mbq) {
104082527734SSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
104182527734SSukumar Swaminathan 		mbq = NULL;
104282527734SSukumar Swaminathan 		mb = NULL;
104382527734SSukumar Swaminathan 	}
104482527734SSukumar Swaminathan 
104582527734SSukumar Swaminathan 	if (hba->sli.sli4.dump_region.virt) {
104682527734SSukumar Swaminathan 		(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
104782527734SSukumar Swaminathan 	}
104882527734SSukumar Swaminathan 
104982527734SSukumar Swaminathan 	if (rval == 0) {
105082527734SSukumar Swaminathan 		rval = EIO;
105182527734SSukumar Swaminathan 	}
105282527734SSukumar Swaminathan 
105382527734SSukumar Swaminathan 	return (rval);
105482527734SSukumar Swaminathan 
105582527734SSukumar Swaminathan } /* emlxs_sli4_online() */
105682527734SSukumar Swaminathan 
105782527734SSukumar Swaminathan 
105882527734SSukumar Swaminathan static void
105982527734SSukumar Swaminathan emlxs_sli4_offline(emlxs_hba_t *hba)
106082527734SSukumar Swaminathan {
106182527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
106282527734SSukumar Swaminathan 	MAILBOXQ mboxq;
106382527734SSukumar Swaminathan 
106482527734SSukumar Swaminathan 	/* Reverse emlxs_sli4_online */
106582527734SSukumar Swaminathan 
106682527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
106782527734SSukumar Swaminathan 	if (!(hba->flag & FC_INTERLOCKED)) {
106882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
106982527734SSukumar Swaminathan 
107082527734SSukumar Swaminathan 		/* This is the only way to disable interupts */
107182527734SSukumar Swaminathan 		bzero((void *)&mboxq, sizeof (MAILBOXQ));
107282527734SSukumar Swaminathan 		emlxs_mb_resetport(hba, &mboxq);
107382527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
107482527734SSukumar Swaminathan 		    MBX_WAIT, 0) != MBX_SUCCESS) {
107582527734SSukumar Swaminathan 			/* Timeout occurred */
107682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
107782527734SSukumar Swaminathan 			    "Timeout: Offline RESET");
107882527734SSukumar Swaminathan 		}
107982527734SSukumar Swaminathan 		(void) emlxs_check_hdw_ready(hba);
108082527734SSukumar Swaminathan 	} else {
108182527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
108282527734SSukumar Swaminathan 	}
108382527734SSukumar Swaminathan 
108482527734SSukumar Swaminathan 	/* Shutdown the adapter interface */
108582527734SSukumar Swaminathan 	emlxs_sli4_hba_kill(hba);
108682527734SSukumar Swaminathan 
108782527734SSukumar Swaminathan 	/* Free SLI shared memory */
108882527734SSukumar Swaminathan 	emlxs_sli4_resource_free(hba);
108982527734SSukumar Swaminathan 
109082527734SSukumar Swaminathan 	/* Free driver shared memory */
109182527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
109282527734SSukumar Swaminathan 
109382527734SSukumar Swaminathan 	/* Free the host dump region buffer */
109482527734SSukumar Swaminathan 	(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
109582527734SSukumar Swaminathan 
109682527734SSukumar Swaminathan } /* emlxs_sli4_offline() */
109782527734SSukumar Swaminathan 
109882527734SSukumar Swaminathan 
109982527734SSukumar Swaminathan /*ARGSUSED*/
110082527734SSukumar Swaminathan static int
110182527734SSukumar Swaminathan emlxs_sli4_map_hdw(emlxs_hba_t *hba)
110282527734SSukumar Swaminathan {
110382527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
110482527734SSukumar Swaminathan 	dev_info_t		*dip;
110582527734SSukumar Swaminathan 	ddi_device_acc_attr_t	dev_attr;
110682527734SSukumar Swaminathan 	int			status;
110782527734SSukumar Swaminathan 
110882527734SSukumar Swaminathan 	dip = (dev_info_t *)hba->dip;
110982527734SSukumar Swaminathan 	dev_attr = emlxs_dev_acc_attr;
111082527734SSukumar Swaminathan 
111182527734SSukumar Swaminathan 	/*
111282527734SSukumar Swaminathan 	 * Map in Hardware BAR pages that will be used for
111382527734SSukumar Swaminathan 	 * communication with HBA.
111482527734SSukumar Swaminathan 	 */
111582527734SSukumar Swaminathan 	if (hba->sli.sli4.bar1_acc_handle == 0) {
111682527734SSukumar Swaminathan 		status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX,
111782527734SSukumar Swaminathan 		    (caddr_t *)&hba->sli.sli4.bar1_addr,
111882527734SSukumar Swaminathan 		    0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle);
111982527734SSukumar Swaminathan 		if (status != DDI_SUCCESS) {
112082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
112182527734SSukumar Swaminathan 			    &emlxs_attach_failed_msg,
112282527734SSukumar Swaminathan 			    "(PCI) ddi_regs_map_setup BAR1 failed. "
112382527734SSukumar Swaminathan 			    "stat=%d mem=%p attr=%p hdl=%p",
112482527734SSukumar Swaminathan 			    status, &hba->sli.sli4.bar1_addr, &dev_attr,
112582527734SSukumar Swaminathan 			    &hba->sli.sli4.bar1_acc_handle);
112682527734SSukumar Swaminathan 			goto failed;
112782527734SSukumar Swaminathan 		}
112882527734SSukumar Swaminathan 	}
112982527734SSukumar Swaminathan 
113082527734SSukumar Swaminathan 	if (hba->sli.sli4.bar2_acc_handle == 0) {
113182527734SSukumar Swaminathan 		status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX,
113282527734SSukumar Swaminathan 		    (caddr_t *)&hba->sli.sli4.bar2_addr,
113382527734SSukumar Swaminathan 		    0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle);
113482527734SSukumar Swaminathan 		if (status != DDI_SUCCESS) {
113582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
113682527734SSukumar Swaminathan 			    &emlxs_attach_failed_msg,
113782527734SSukumar Swaminathan 			    "ddi_regs_map_setup BAR2 failed. status=%x",
113882527734SSukumar Swaminathan 			    status);
113982527734SSukumar Swaminathan 			goto failed;
114082527734SSukumar Swaminathan 		}
114182527734SSukumar Swaminathan 	}
114282527734SSukumar Swaminathan 
114382527734SSukumar Swaminathan 	if (hba->sli.sli4.bootstrapmb.virt == 0) {
114482527734SSukumar Swaminathan 		MBUF_INFO	*buf_info;
114582527734SSukumar Swaminathan 		MBUF_INFO	bufinfo;
114682527734SSukumar Swaminathan 
114782527734SSukumar Swaminathan 		buf_info = &bufinfo;
114882527734SSukumar Swaminathan 
114982527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
115082527734SSukumar Swaminathan 		buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE;
115182527734SSukumar Swaminathan 		buf_info->flags =
115282527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
115382527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(dip, 1L);
115482527734SSukumar Swaminathan 
115582527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
115682527734SSukumar Swaminathan 
115782527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
115882527734SSukumar Swaminathan 			goto failed;
115982527734SSukumar Swaminathan 		}
116082527734SSukumar Swaminathan 
1161*a9800bebSGarrett D'Amore 		hba->sli.sli4.bootstrapmb.virt = buf_info->virt;
116282527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.phys = buf_info->phys;
116382527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE +
116482527734SSukumar Swaminathan 		    MBOX_EXTENSION_SIZE;
116582527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle;
116682527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle;
116782527734SSukumar Swaminathan 		bzero((char *)hba->sli.sli4.bootstrapmb.virt,
116882527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE);
116982527734SSukumar Swaminathan 	}
117082527734SSukumar Swaminathan 
117182527734SSukumar Swaminathan 	/* offset from beginning of register space */
117282527734SSukumar Swaminathan 	hba->sli.sli4.MPUEPSemaphore_reg_addr =
117382527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar1_addr + CSR_MPU_EP_SEMAPHORE_OFFSET);
117482527734SSukumar Swaminathan 	hba->sli.sli4.MBDB_reg_addr =
117582527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET);
117682527734SSukumar Swaminathan 	hba->sli.sli4.CQDB_reg_addr =
117782527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET);
117882527734SSukumar Swaminathan 	hba->sli.sli4.MQDB_reg_addr =
117982527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET);
118082527734SSukumar Swaminathan 	hba->sli.sli4.WQDB_reg_addr =
118182527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET);
118282527734SSukumar Swaminathan 	hba->sli.sli4.RQDB_reg_addr =
118382527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET);
118482527734SSukumar Swaminathan 	hba->chan_count = MAX_CHANNEL;
118582527734SSukumar Swaminathan 
118682527734SSukumar Swaminathan 	return (0);
118782527734SSukumar Swaminathan 
118882527734SSukumar Swaminathan failed:
118982527734SSukumar Swaminathan 
119082527734SSukumar Swaminathan 	emlxs_sli4_unmap_hdw(hba);
119182527734SSukumar Swaminathan 	return (ENOMEM);
119282527734SSukumar Swaminathan 
119382527734SSukumar Swaminathan 
119482527734SSukumar Swaminathan } /* emlxs_sli4_map_hdw() */
119582527734SSukumar Swaminathan 
119682527734SSukumar Swaminathan 
119782527734SSukumar Swaminathan /*ARGSUSED*/
119882527734SSukumar Swaminathan static void
119982527734SSukumar Swaminathan emlxs_sli4_unmap_hdw(emlxs_hba_t *hba)
120082527734SSukumar Swaminathan {
120182527734SSukumar Swaminathan 	MBUF_INFO	bufinfo;
120282527734SSukumar Swaminathan 	MBUF_INFO	*buf_info = &bufinfo;
120382527734SSukumar Swaminathan 
120482527734SSukumar Swaminathan 	/*
120582527734SSukumar Swaminathan 	 * Free map for Hardware BAR pages that were used for
120682527734SSukumar Swaminathan 	 * communication with HBA.
120782527734SSukumar Swaminathan 	 */
120882527734SSukumar Swaminathan 	if (hba->sli.sli4.bar1_acc_handle) {
120982527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle);
121082527734SSukumar Swaminathan 		hba->sli.sli4.bar1_acc_handle = 0;
121182527734SSukumar Swaminathan 	}
121282527734SSukumar Swaminathan 
121382527734SSukumar Swaminathan 	if (hba->sli.sli4.bar2_acc_handle) {
121482527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle);
121582527734SSukumar Swaminathan 		hba->sli.sli4.bar2_acc_handle = 0;
121682527734SSukumar Swaminathan 	}
121782527734SSukumar Swaminathan 	if (hba->sli.sli4.bootstrapmb.virt) {
121882527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
121982527734SSukumar Swaminathan 
122082527734SSukumar Swaminathan 		if (hba->sli.sli4.bootstrapmb.phys) {
122182527734SSukumar Swaminathan 			buf_info->phys = hba->sli.sli4.bootstrapmb.phys;
122282527734SSukumar Swaminathan 			buf_info->data_handle =
122382527734SSukumar Swaminathan 			    hba->sli.sli4.bootstrapmb.data_handle;
122482527734SSukumar Swaminathan 			buf_info->dma_handle =
122582527734SSukumar Swaminathan 			    hba->sli.sli4.bootstrapmb.dma_handle;
122682527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
122782527734SSukumar Swaminathan 		}
122882527734SSukumar Swaminathan 
1229*a9800bebSGarrett D'Amore 		buf_info->virt = hba->sli.sli4.bootstrapmb.virt;
123082527734SSukumar Swaminathan 		buf_info->size = hba->sli.sli4.bootstrapmb.size;
123182527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
123282527734SSukumar Swaminathan 
1233*a9800bebSGarrett D'Amore 		hba->sli.sli4.bootstrapmb.virt = NULL;
123482527734SSukumar Swaminathan 	}
123582527734SSukumar Swaminathan 
123682527734SSukumar Swaminathan 	return;
123782527734SSukumar Swaminathan 
123882527734SSukumar Swaminathan } /* emlxs_sli4_unmap_hdw() */
123982527734SSukumar Swaminathan 
124082527734SSukumar Swaminathan 
124182527734SSukumar Swaminathan static int
124282527734SSukumar Swaminathan emlxs_check_hdw_ready(emlxs_hba_t *hba)
124382527734SSukumar Swaminathan {
124482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
124582527734SSukumar Swaminathan 	uint32_t status;
124682527734SSukumar Swaminathan 	uint32_t i = 0;
124782527734SSukumar Swaminathan 
124882527734SSukumar Swaminathan 	/* Wait for reset completion */
124982527734SSukumar Swaminathan 	while (i < 30) {
125082527734SSukumar Swaminathan 		/* Check Semaphore register to see what the ARM state is */
125182527734SSukumar Swaminathan 		status = READ_BAR1_REG(hba, FC_SEMA_REG(hba));
125282527734SSukumar Swaminathan 
125382527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
125482527734SSukumar Swaminathan 		if (status & ARM_POST_FATAL) {
125582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
125682527734SSukumar Swaminathan 			    "SEMA Error: status=0x%x", status);
125782527734SSukumar Swaminathan 
125882527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
125982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
126082527734SSukumar Swaminathan 			/* Access handle validation */
126182527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
126282527734SSukumar Swaminathan 			    hba->sli.sli4.bar1_acc_handle);
126382527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
126482527734SSukumar Swaminathan 			return (1);
126582527734SSukumar Swaminathan 		}
126682527734SSukumar Swaminathan 		if ((status & ARM_POST_MASK) == ARM_POST_READY) {
126782527734SSukumar Swaminathan 			/* ARM Ready !! */
126882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
126982527734SSukumar Swaminathan 			    "ARM Ready: status=0x%x", status);
127082527734SSukumar Swaminathan #ifdef FMA_SUPPORT
127182527734SSukumar Swaminathan 			/* Access handle validation */
127282527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
127382527734SSukumar Swaminathan 			    hba->sli.sli4.bar1_acc_handle);
127482527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
127582527734SSukumar Swaminathan 			return (0);
127682527734SSukumar Swaminathan 		}
127782527734SSukumar Swaminathan 
127882527734SSukumar Swaminathan 		DELAYMS(1000);
127982527734SSukumar Swaminathan 		i++;
128082527734SSukumar Swaminathan 	}
128182527734SSukumar Swaminathan 
128282527734SSukumar Swaminathan 	/* Timeout occurred */
128382527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
128482527734SSukumar Swaminathan 	    "Timeout waiting for READY: status=0x%x", status);
128582527734SSukumar Swaminathan 
128682527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
128782527734SSukumar Swaminathan 
128882527734SSukumar Swaminathan #ifdef FMA_SUPPORT
128982527734SSukumar Swaminathan 	/* Access handle validation */
129082527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle);
129182527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
129282527734SSukumar Swaminathan 
129382527734SSukumar Swaminathan 	/* Log a dump event - not supported */
129482527734SSukumar Swaminathan 
129582527734SSukumar Swaminathan 	return (2);
129682527734SSukumar Swaminathan 
129782527734SSukumar Swaminathan } /* emlxs_check_hdw_ready() */
129882527734SSukumar Swaminathan 
129982527734SSukumar Swaminathan 
130082527734SSukumar Swaminathan static uint32_t
130182527734SSukumar Swaminathan emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo)
130282527734SSukumar Swaminathan {
130382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
130482527734SSukumar Swaminathan 	uint32_t status;
130582527734SSukumar Swaminathan 
130682527734SSukumar Swaminathan 	/* Wait for reset completion, tmo is in 10ms ticks */
130782527734SSukumar Swaminathan 	while (tmo) {
130882527734SSukumar Swaminathan 		/* Check Semaphore register to see what the ARM state is */
130982527734SSukumar Swaminathan 		status = READ_BAR2_REG(hba, FC_MBDB_REG(hba));
131082527734SSukumar Swaminathan 
131182527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
131282527734SSukumar Swaminathan 		if (status & BMBX_READY) {
131382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
131482527734SSukumar Swaminathan 			    "BMBX Ready: status=0x%x", status);
131582527734SSukumar Swaminathan #ifdef FMA_SUPPORT
131682527734SSukumar Swaminathan 			/* Access handle validation */
131782527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
131882527734SSukumar Swaminathan 			    hba->sli.sli4.bar2_acc_handle);
131982527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
132082527734SSukumar Swaminathan 			return (tmo);
132182527734SSukumar Swaminathan 		}
132282527734SSukumar Swaminathan 
132382527734SSukumar Swaminathan 		DELAYMS(10);
132482527734SSukumar Swaminathan 		tmo--;
132582527734SSukumar Swaminathan 	}
132682527734SSukumar Swaminathan 
132782527734SSukumar Swaminathan 	/* Timeout occurred */
132882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
132982527734SSukumar Swaminathan 	    "Timeout waiting for BMailbox: status=0x%x", status);
133082527734SSukumar Swaminathan 
133182527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
133282527734SSukumar Swaminathan 
133382527734SSukumar Swaminathan #ifdef FMA_SUPPORT
133482527734SSukumar Swaminathan 	/* Access handle validation */
133582527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle);
133682527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
133782527734SSukumar Swaminathan 
133882527734SSukumar Swaminathan 	/* Log a dump event - not supported */
133982527734SSukumar Swaminathan 
134082527734SSukumar Swaminathan 	return (0);
134182527734SSukumar Swaminathan 
134282527734SSukumar Swaminathan } /* emlxs_check_bootstrap_ready() */
134382527734SSukumar Swaminathan 
134482527734SSukumar Swaminathan 
134582527734SSukumar Swaminathan static uint32_t
134682527734SSukumar Swaminathan emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo)
134782527734SSukumar Swaminathan {
134882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
134982527734SSukumar Swaminathan 	uint32_t *iptr;
135082527734SSukumar Swaminathan 	uint32_t addr30;
135182527734SSukumar Swaminathan 
135282527734SSukumar Swaminathan 	/*
135382527734SSukumar Swaminathan 	 * This routine assumes the bootstrap mbox is loaded
135482527734SSukumar Swaminathan 	 * with the mailbox command to be executed.
135582527734SSukumar Swaminathan 	 *
135682527734SSukumar Swaminathan 	 * First, load the high 30 bits of bootstrap mailbox
135782527734SSukumar Swaminathan 	 */
135882527734SSukumar Swaminathan 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>32) & 0xfffffffc);
135982527734SSukumar Swaminathan 	addr30 |= BMBX_ADDR_HI;
136082527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_MBDB_REG(hba), addr30);
136182527734SSukumar Swaminathan 
136282527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
136382527734SSukumar Swaminathan 	if (tmo == 0) {
136482527734SSukumar Swaminathan 		return (0);
136582527734SSukumar Swaminathan 	}
136682527734SSukumar Swaminathan 
136782527734SSukumar Swaminathan 	/* Load the low 30 bits of bootstrap mailbox */
136882527734SSukumar Swaminathan 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>2) & 0xfffffffc);
136982527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_MBDB_REG(hba), addr30);
137082527734SSukumar Swaminathan 
137182527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
137282527734SSukumar Swaminathan 	if (tmo == 0) {
137382527734SSukumar Swaminathan 		return (0);
137482527734SSukumar Swaminathan 	}
137582527734SSukumar Swaminathan 
137682527734SSukumar Swaminathan 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
137782527734SSukumar Swaminathan 
137882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
137982527734SSukumar Swaminathan 	    "BootstrapMB: %p Completed %08x %08x %08x",
138082527734SSukumar Swaminathan 	    hba->sli.sli4.bootstrapmb.virt,
138182527734SSukumar Swaminathan 	    *iptr, *(iptr+1), *(iptr+2));
138282527734SSukumar Swaminathan 
138382527734SSukumar Swaminathan 	return (tmo);
138482527734SSukumar Swaminathan 
138582527734SSukumar Swaminathan } /* emlxs_issue_bootstrap_mb() */
138682527734SSukumar Swaminathan 
138782527734SSukumar Swaminathan 
138882527734SSukumar Swaminathan static int
138982527734SSukumar Swaminathan emlxs_init_bootstrap_mb(emlxs_hba_t *hba)
139082527734SSukumar Swaminathan {
139182527734SSukumar Swaminathan #ifdef FMA_SUPPORT
139282527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
139382527734SSukumar Swaminathan #endif /* FMA_SUPPORT */
139482527734SSukumar Swaminathan 	uint32_t *iptr;
139582527734SSukumar Swaminathan 	uint32_t tmo;
139682527734SSukumar Swaminathan 
139782527734SSukumar Swaminathan 	if (emlxs_check_hdw_ready(hba)) {
139882527734SSukumar Swaminathan 		return (1);
139982527734SSukumar Swaminathan 	}
140082527734SSukumar Swaminathan 
140182527734SSukumar Swaminathan 	if (hba->flag & FC_BOOTSTRAPMB_INIT) {
140282527734SSukumar Swaminathan 		return (0);  /* Already initialized */
140382527734SSukumar Swaminathan 	}
140482527734SSukumar Swaminathan 
140582527734SSukumar Swaminathan 	/* NOTE: tmo is in 10ms ticks */
140682527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, 3000);
140782527734SSukumar Swaminathan 	if (tmo == 0) {
140882527734SSukumar Swaminathan 		return (1);
140982527734SSukumar Swaminathan 	}
141082527734SSukumar Swaminathan 
141182527734SSukumar Swaminathan 	/* Special words to initialize bootstrap mbox MUST be little endian */
141282527734SSukumar Swaminathan 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
141382527734SSukumar Swaminathan 	*iptr++ = LE_SWAP32(MQE_SPECIAL_WORD0);
141482527734SSukumar Swaminathan 	*iptr = LE_SWAP32(MQE_SPECIAL_WORD1);
141582527734SSukumar Swaminathan 
141682527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
141782527734SSukumar Swaminathan 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
141882527734SSukumar Swaminathan 
1419*a9800bebSGarrett D'Amore emlxs_data_dump(port, "EndianIN", (uint32_t *)iptr, 6, 0);
142082527734SSukumar Swaminathan 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
142182527734SSukumar Swaminathan 		return (1);
142282527734SSukumar Swaminathan 	}
142382527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
142482527734SSukumar Swaminathan 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
1425*a9800bebSGarrett D'Amore emlxs_data_dump(port, "EndianOUT", (uint32_t *)iptr, 6, 0);
142682527734SSukumar Swaminathan 
1427b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
1428b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle)
1429b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
1430b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
1431b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
1432b3660a96SSukumar Swaminathan 		    "emlxs_init_bootstrap_mb: hdl=%p",
1433b3660a96SSukumar Swaminathan 		    hba->sli.sli4.bootstrapmb.dma_handle);
1434b3660a96SSukumar Swaminathan 		return (1);
1435b3660a96SSukumar Swaminathan 	}
1436b3660a96SSukumar Swaminathan #endif
143782527734SSukumar Swaminathan 	hba->flag |= FC_BOOTSTRAPMB_INIT;
143882527734SSukumar Swaminathan 	return (0);
143982527734SSukumar Swaminathan 
144082527734SSukumar Swaminathan } /* emlxs_init_bootstrap_mb() */
144182527734SSukumar Swaminathan 
144282527734SSukumar Swaminathan 
144382527734SSukumar Swaminathan static uint32_t
144482527734SSukumar Swaminathan emlxs_sli4_hba_init(emlxs_hba_t *hba)
144582527734SSukumar Swaminathan {
144682527734SSukumar Swaminathan 	int rc;
1447*a9800bebSGarrett D'Amore 	uint16_t i;
144882527734SSukumar Swaminathan 	emlxs_port_t *vport;
144982527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
145082527734SSukumar Swaminathan 	CHANNEL *cp;
145182527734SSukumar Swaminathan 
145282527734SSukumar Swaminathan 	/* Restart the adapter */
145382527734SSukumar Swaminathan 	if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) {
145482527734SSukumar Swaminathan 		return (1);
145582527734SSukumar Swaminathan 	}
145682527734SSukumar Swaminathan 
145782527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
145882527734SSukumar Swaminathan 		cp = &hba->chan[i];
145982527734SSukumar Swaminathan 		cp->iopath = (void *)&hba->sli.sli4.wq[i];
146082527734SSukumar Swaminathan 	}
146182527734SSukumar Swaminathan 
146282527734SSukumar Swaminathan 	/* Initialize all the port objects */
146382527734SSukumar Swaminathan 	hba->vpi_base = 0;
146482527734SSukumar Swaminathan 	hba->vpi_max  = 0;
146582527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
146682527734SSukumar Swaminathan 		vport = &VPORT(i);
146782527734SSukumar Swaminathan 		vport->hba = hba;
146882527734SSukumar Swaminathan 		vport->vpi = i;
1469*a9800bebSGarrett D'Amore 
1470*a9800bebSGarrett D'Amore 		vport->VPIobj.index = i;
1471*a9800bebSGarrett D'Amore 		vport->VPIobj.VPI = i;
1472*a9800bebSGarrett D'Amore 		vport->VPIobj.port = vport;
147382527734SSukumar Swaminathan 	}
147482527734SSukumar Swaminathan 
147582527734SSukumar Swaminathan 	/* Set the max node count */
147682527734SSukumar Swaminathan 	if (hba->max_nodes == 0) {
147782527734SSukumar Swaminathan 		if (cfg[CFG_NUM_NODES].current > 0) {
147882527734SSukumar Swaminathan 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
147982527734SSukumar Swaminathan 		} else {
148082527734SSukumar Swaminathan 			hba->max_nodes = 4096;
148182527734SSukumar Swaminathan 		}
148282527734SSukumar Swaminathan 	}
148382527734SSukumar Swaminathan 
148482527734SSukumar Swaminathan 	rc = emlxs_init_bootstrap_mb(hba);
148582527734SSukumar Swaminathan 	if (rc) {
148682527734SSukumar Swaminathan 		return (rc);
148782527734SSukumar Swaminathan 	}
148882527734SSukumar Swaminathan 
148982527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0;
149082527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1;
149182527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2;
149282527734SSukumar Swaminathan 
1493fe199829SSukumar Swaminathan 	/* Cache the UE MASK registers value for UE error detection */
1494fe199829SSukumar Swaminathan 	hba->sli.sli4.ue_mask_lo = ddi_get32(hba->pci_acc_handle,
1495fe199829SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_LO_OFFSET));
1496fe199829SSukumar Swaminathan 	hba->sli.sli4.ue_mask_hi = ddi_get32(hba->pci_acc_handle,
1497fe199829SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_HI_OFFSET));
1498fe199829SSukumar Swaminathan 
149982527734SSukumar Swaminathan 	return (0);
150082527734SSukumar Swaminathan 
150182527734SSukumar Swaminathan } /* emlxs_sli4_hba_init() */
150282527734SSukumar Swaminathan 
150382527734SSukumar Swaminathan 
150482527734SSukumar Swaminathan /*ARGSUSED*/
150582527734SSukumar Swaminathan static uint32_t
150682527734SSukumar Swaminathan emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
150782527734SSukumar Swaminathan 		uint32_t quiesce)
150882527734SSukumar Swaminathan {
150982527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
151082527734SSukumar Swaminathan 	emlxs_port_t *vport;
151182527734SSukumar Swaminathan 	CHANNEL *cp;
151282527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
151382527734SSukumar Swaminathan 	MAILBOXQ mboxq;
151482527734SSukumar Swaminathan 	uint32_t i;
151582527734SSukumar Swaminathan 	uint32_t rc;
1516*a9800bebSGarrett D'Amore 	uint16_t channelno;
151782527734SSukumar Swaminathan 
151882527734SSukumar Swaminathan 	if (!cfg[CFG_RESET_ENABLE].current) {
151982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
152082527734SSukumar Swaminathan 		    "Adapter reset disabled.");
152182527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
152282527734SSukumar Swaminathan 
152382527734SSukumar Swaminathan 		return (1);
152482527734SSukumar Swaminathan 	}
152582527734SSukumar Swaminathan 
152682527734SSukumar Swaminathan 	if (quiesce == 0) {
152782527734SSukumar Swaminathan 		emlxs_sli4_hba_kill(hba);
152882527734SSukumar Swaminathan 
152982527734SSukumar Swaminathan 		/*
153082527734SSukumar Swaminathan 		 * Initalize Hardware that will be used to bring
153182527734SSukumar Swaminathan 		 * SLI4 online.
153282527734SSukumar Swaminathan 		 */
153382527734SSukumar Swaminathan 		rc = emlxs_init_bootstrap_mb(hba);
153482527734SSukumar Swaminathan 		if (rc) {
153582527734SSukumar Swaminathan 			return (rc);
153682527734SSukumar Swaminathan 		}
153782527734SSukumar Swaminathan 	}
153882527734SSukumar Swaminathan 
153982527734SSukumar Swaminathan 	bzero((void *)&mboxq, sizeof (MAILBOXQ));
154082527734SSukumar Swaminathan 	emlxs_mb_resetport(hba, &mboxq);
154182527734SSukumar Swaminathan 
154282527734SSukumar Swaminathan 	if (quiesce == 0) {
154382527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
154482527734SSukumar Swaminathan 		    MBX_POLL, 0) != MBX_SUCCESS) {
154582527734SSukumar Swaminathan 			/* Timeout occurred */
154682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
154782527734SSukumar Swaminathan 			    "Timeout: RESET");
154882527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
154982527734SSukumar Swaminathan 			/* Log a dump event - not supported */
155082527734SSukumar Swaminathan 			return (1);
155182527734SSukumar Swaminathan 		}
155282527734SSukumar Swaminathan 	} else {
155382527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq,
155482527734SSukumar Swaminathan 		    MBX_POLL, 0) != MBX_SUCCESS) {
155582527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
155682527734SSukumar Swaminathan 			/* Log a dump event - not supported */
155782527734SSukumar Swaminathan 			return (1);
155882527734SSukumar Swaminathan 		}
155982527734SSukumar Swaminathan 	}
1560*a9800bebSGarrett D'Amore emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0);
156182527734SSukumar Swaminathan 
156282527734SSukumar Swaminathan 	/* Reset the hba structure */
156382527734SSukumar Swaminathan 	hba->flag &= FC_RESET_MASK;
156482527734SSukumar Swaminathan 
156582527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
156682527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
156782527734SSukumar Swaminathan 		cp->hba = hba;
156882527734SSukumar Swaminathan 		cp->channelno = channelno;
156982527734SSukumar Swaminathan 	}
157082527734SSukumar Swaminathan 
157182527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
157282527734SSukumar Swaminathan 	hba->io_count = 0;
157382527734SSukumar Swaminathan 	hba->iodone_count = 0;
157482527734SSukumar Swaminathan 	hba->topology = 0;
157582527734SSukumar Swaminathan 	hba->linkspeed = 0;
157682527734SSukumar Swaminathan 	hba->heartbeat_active = 0;
157782527734SSukumar Swaminathan 	hba->discovery_timer = 0;
157882527734SSukumar Swaminathan 	hba->linkup_timer = 0;
157982527734SSukumar Swaminathan 	hba->loopback_tics = 0;
158082527734SSukumar Swaminathan 
158182527734SSukumar Swaminathan 	/* Reset the port objects */
158282527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
158382527734SSukumar Swaminathan 		vport = &VPORT(i);
158482527734SSukumar Swaminathan 
158582527734SSukumar Swaminathan 		vport->flag &= EMLXS_PORT_RESET_MASK;
158682527734SSukumar Swaminathan 		vport->did = 0;
158782527734SSukumar Swaminathan 		vport->prev_did = 0;
158882527734SSukumar Swaminathan 		vport->lip_type = 0;
158982527734SSukumar Swaminathan 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
1590*a9800bebSGarrett D'Amore 		bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
159182527734SSukumar Swaminathan 
159282527734SSukumar Swaminathan 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
159382527734SSukumar Swaminathan 		vport->node_base.nlp_Rpi = 0;
159482527734SSukumar Swaminathan 		vport->node_base.nlp_DID = 0xffffff;
159582527734SSukumar Swaminathan 		vport->node_base.nlp_list_next = NULL;
159682527734SSukumar Swaminathan 		vport->node_base.nlp_list_prev = NULL;
159782527734SSukumar Swaminathan 		vport->node_base.nlp_active = 1;
159882527734SSukumar Swaminathan 		vport->node_count = 0;
159982527734SSukumar Swaminathan 
160082527734SSukumar Swaminathan 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
160182527734SSukumar Swaminathan 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
160282527734SSukumar Swaminathan 		}
160382527734SSukumar Swaminathan 	}
160482527734SSukumar Swaminathan 
160582527734SSukumar Swaminathan 	if (emlxs_check_hdw_ready(hba)) {
160682527734SSukumar Swaminathan 		return (1);
160782527734SSukumar Swaminathan 	}
160882527734SSukumar Swaminathan 
160982527734SSukumar Swaminathan 	return (0);
161082527734SSukumar Swaminathan 
161182527734SSukumar Swaminathan } /* emlxs_sli4_hba_reset */
161282527734SSukumar Swaminathan 
161382527734SSukumar Swaminathan 
161482527734SSukumar Swaminathan #define	SGL_CMD		0
161582527734SSukumar Swaminathan #define	SGL_RESP	1
161682527734SSukumar Swaminathan #define	SGL_DATA	2
161782527734SSukumar Swaminathan #define	SGL_LAST	0x80
161882527734SSukumar Swaminathan 
161982527734SSukumar Swaminathan /*ARGSUSED*/
162082527734SSukumar Swaminathan ULP_SGE64 *
162182527734SSukumar Swaminathan emlxs_pkt_to_sgl(emlxs_port_t *port, ULP_SGE64 *sge, fc_packet_t *pkt,
162282527734SSukumar Swaminathan     uint32_t sgl_type, uint32_t *pcnt)
162382527734SSukumar Swaminathan {
162482527734SSukumar Swaminathan #ifdef DEBUG_SGE
162582527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
162682527734SSukumar Swaminathan #endif
162782527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp;
162882527734SSukumar Swaminathan 	uint_t i;
162982527734SSukumar Swaminathan 	uint_t last;
163082527734SSukumar Swaminathan 	int32_t	size;
163182527734SSukumar Swaminathan 	int32_t	sge_size;
163282527734SSukumar Swaminathan 	uint64_t sge_addr;
163382527734SSukumar Swaminathan 	int32_t	len;
163482527734SSukumar Swaminathan 	uint32_t cnt;
163582527734SSukumar Swaminathan 	uint_t cookie_cnt;
163682527734SSukumar Swaminathan 	ULP_SGE64 stage_sge;
163782527734SSukumar Swaminathan 
163882527734SSukumar Swaminathan 	last = sgl_type & SGL_LAST;
163982527734SSukumar Swaminathan 	sgl_type &= ~SGL_LAST;
164082527734SSukumar Swaminathan 
164182527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
164282527734SSukumar Swaminathan 	switch (sgl_type) {
164382527734SSukumar Swaminathan 	case SGL_CMD:
164482527734SSukumar Swaminathan 		cp = pkt->pkt_cmd_cookie;
164582527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
164682527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
164782527734SSukumar Swaminathan 		break;
164882527734SSukumar Swaminathan 
164982527734SSukumar Swaminathan 	case SGL_RESP:
165082527734SSukumar Swaminathan 		cp = pkt->pkt_resp_cookie;
165182527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
165282527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
165382527734SSukumar Swaminathan 		break;
165482527734SSukumar Swaminathan 
165582527734SSukumar Swaminathan 
165682527734SSukumar Swaminathan 	case SGL_DATA:
165782527734SSukumar Swaminathan 		cp = pkt->pkt_data_cookie;
165882527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_data_cookie_cnt;
165982527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
166082527734SSukumar Swaminathan 		break;
166182527734SSukumar Swaminathan 	}
166282527734SSukumar Swaminathan 
166382527734SSukumar Swaminathan #else
166482527734SSukumar Swaminathan 	switch (sgl_type) {
166582527734SSukumar Swaminathan 	case SGL_CMD:
166682527734SSukumar Swaminathan 		cp = &pkt->pkt_cmd_cookie;
166782527734SSukumar Swaminathan 		cookie_cnt = 1;
166882527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
166982527734SSukumar Swaminathan 		break;
167082527734SSukumar Swaminathan 
167182527734SSukumar Swaminathan 	case SGL_RESP:
167282527734SSukumar Swaminathan 		cp = &pkt->pkt_resp_cookie;
167382527734SSukumar Swaminathan 		cookie_cnt = 1;
167482527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
167582527734SSukumar Swaminathan 		break;
167682527734SSukumar Swaminathan 
167782527734SSukumar Swaminathan 
167882527734SSukumar Swaminathan 	case SGL_DATA:
167982527734SSukumar Swaminathan 		cp = &pkt->pkt_data_cookie;
168082527734SSukumar Swaminathan 		cookie_cnt = 1;
168182527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
168282527734SSukumar Swaminathan 		break;
168382527734SSukumar Swaminathan 	}
168482527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
168582527734SSukumar Swaminathan 
168682527734SSukumar Swaminathan 	stage_sge.offset = 0;
168782527734SSukumar Swaminathan 	stage_sge.reserved = 0;
168882527734SSukumar Swaminathan 	stage_sge.last = 0;
168982527734SSukumar Swaminathan 	cnt = 0;
169082527734SSukumar Swaminathan 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
169182527734SSukumar Swaminathan 
169282527734SSukumar Swaminathan 		sge_size = cp->dmac_size;
169382527734SSukumar Swaminathan 		sge_addr = cp->dmac_laddress;
169482527734SSukumar Swaminathan 		while (sge_size && size) {
169582527734SSukumar Swaminathan 			if (cnt) {
169682527734SSukumar Swaminathan 				/* Copy staged SGE before we build next one */
169782527734SSukumar Swaminathan 				BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
169882527734SSukumar Swaminathan 				    (uint8_t *)sge, sizeof (ULP_SGE64));
169982527734SSukumar Swaminathan 				sge++;
170082527734SSukumar Swaminathan 			}
170182527734SSukumar Swaminathan 			len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
170282527734SSukumar Swaminathan 			len = MIN(size, len);
170382527734SSukumar Swaminathan 
170482527734SSukumar Swaminathan 			stage_sge.addrHigh =
170582527734SSukumar Swaminathan 			    PADDR_HI(sge_addr);
170682527734SSukumar Swaminathan 			stage_sge.addrLow =
170782527734SSukumar Swaminathan 			    PADDR_LO(sge_addr);
170882527734SSukumar Swaminathan 			stage_sge.length = len;
170982527734SSukumar Swaminathan 			if (sgl_type == SGL_DATA) {
171082527734SSukumar Swaminathan 				stage_sge.offset = cnt;
171182527734SSukumar Swaminathan 			}
171282527734SSukumar Swaminathan #ifdef DEBUG_SGE
1713*a9800bebSGarrett D'Amore 			emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge,
171482527734SSukumar Swaminathan 			    4, 0);
171582527734SSukumar Swaminathan #endif
171682527734SSukumar Swaminathan 			sge_addr += len;
171782527734SSukumar Swaminathan 			sge_size -= len;
171882527734SSukumar Swaminathan 
171982527734SSukumar Swaminathan 			cnt += len;
172082527734SSukumar Swaminathan 			size -= len;
172182527734SSukumar Swaminathan 		}
172282527734SSukumar Swaminathan 	}
172382527734SSukumar Swaminathan 
172482527734SSukumar Swaminathan 	if (last) {
172582527734SSukumar Swaminathan 		stage_sge.last = 1;
172682527734SSukumar Swaminathan 	}
172782527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
172882527734SSukumar Swaminathan 	    sizeof (ULP_SGE64));
1729*a9800bebSGarrett D'Amore 
173082527734SSukumar Swaminathan 	sge++;
173182527734SSukumar Swaminathan 
173282527734SSukumar Swaminathan 	*pcnt = cnt;
173382527734SSukumar Swaminathan 	return (sge);
173482527734SSukumar Swaminathan 
173582527734SSukumar Swaminathan } /* emlxs_pkt_to_sgl */
173682527734SSukumar Swaminathan 
173782527734SSukumar Swaminathan 
173882527734SSukumar Swaminathan /*ARGSUSED*/
173982527734SSukumar Swaminathan uint32_t
174082527734SSukumar Swaminathan emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
174182527734SSukumar Swaminathan {
174282527734SSukumar Swaminathan 	fc_packet_t *pkt;
1743*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
174482527734SSukumar Swaminathan 	ULP_SGE64 *sge;
174582527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
174682527734SSukumar Swaminathan 	IOCBQ *iocbq;
174782527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
174882527734SSukumar Swaminathan 	uint32_t cmd_cnt;
174982527734SSukumar Swaminathan 	uint32_t resp_cnt;
175082527734SSukumar Swaminathan 	uint32_t cnt;
175182527734SSukumar Swaminathan 
175282527734SSukumar Swaminathan 	iocbq = (IOCBQ *) &sbp->iocbq;
175382527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
175482527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
1755*a9800bebSGarrett D'Amore 	xrip = sbp->xrip;
1756*a9800bebSGarrett D'Amore 	sge = xrip->SGList.virt;
175782527734SSukumar Swaminathan 
175882527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
175982527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
176082527734SSukumar Swaminathan #else
176182527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
176282527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
176382527734SSukumar Swaminathan 
176482527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
176582527734SSukumar Swaminathan 	if (iocbq->flag & IOCB_FCP_CMD) {
176682527734SSukumar Swaminathan 
176782527734SSukumar Swaminathan 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
176882527734SSukumar Swaminathan 			return (1);
176982527734SSukumar Swaminathan 		}
177082527734SSukumar Swaminathan 
177182527734SSukumar Swaminathan 		/* CMD payload */
177282527734SSukumar Swaminathan 		sge = emlxs_pkt_to_sgl(port, sge, pkt, SGL_CMD, &cmd_cnt);
177382527734SSukumar Swaminathan 
177482527734SSukumar Swaminathan 		/* DATA payload */
177582527734SSukumar Swaminathan 		if (pkt->pkt_datalen != 0) {
177682527734SSukumar Swaminathan 			/* RSP payload */
177782527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
177882527734SSukumar Swaminathan 			    SGL_RESP, &resp_cnt);
177982527734SSukumar Swaminathan 
178082527734SSukumar Swaminathan 			/* Data portion */
178182527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
178282527734SSukumar Swaminathan 			    SGL_DATA | SGL_LAST, &cnt);
178382527734SSukumar Swaminathan 		} else {
178482527734SSukumar Swaminathan 			/* RSP payload */
178582527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
178682527734SSukumar Swaminathan 			    SGL_RESP | SGL_LAST, &resp_cnt);
178782527734SSukumar Swaminathan 		}
178882527734SSukumar Swaminathan 
178982527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.addrHigh =
179082527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
179182527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.addrLow =
179282527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
179382527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt;
179482527734SSukumar Swaminathan 		wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt;
179582527734SSukumar Swaminathan 
179682527734SSukumar Swaminathan 	} else {
179782527734SSukumar Swaminathan 
179882527734SSukumar Swaminathan 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
179982527734SSukumar Swaminathan 			/* CMD payload */
180082527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
180182527734SSukumar Swaminathan 			    SGL_CMD | SGL_LAST, &cmd_cnt);
180282527734SSukumar Swaminathan 		} else {
180382527734SSukumar Swaminathan 			/* CMD payload */
180482527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
180582527734SSukumar Swaminathan 			    SGL_CMD, &cmd_cnt);
180682527734SSukumar Swaminathan 
180782527734SSukumar Swaminathan 			/* RSP payload */
180882527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
180982527734SSukumar Swaminathan 			    SGL_RESP | SGL_LAST, &resp_cnt);
181082527734SSukumar Swaminathan 			wqe->un.GenReq.PayloadLength = cmd_cnt;
181182527734SSukumar Swaminathan 		}
181282527734SSukumar Swaminathan 
181382527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.addrHigh =
181482527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
181582527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.addrLow =
181682527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
181782527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt;
181882527734SSukumar Swaminathan 	}
181982527734SSukumar Swaminathan 	return (0);
182082527734SSukumar Swaminathan } /* emlxs_sli4_bde_setup */
182182527734SSukumar Swaminathan 
182282527734SSukumar Swaminathan 
182382527734SSukumar Swaminathan 
182482527734SSukumar Swaminathan 
182582527734SSukumar Swaminathan static void
182682527734SSukumar Swaminathan emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
182782527734SSukumar Swaminathan {
182882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
182982527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
183082527734SSukumar Swaminathan 	uint32_t channelno;
183182527734SSukumar Swaminathan 	int32_t throttle;
183282527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
183382527734SSukumar Swaminathan 	emlxs_wqe_t *wqeslot;
183482527734SSukumar Swaminathan 	WQ_DESC_t *wq;
183582527734SSukumar Swaminathan 	uint32_t flag;
183682527734SSukumar Swaminathan 	uint32_t wqdb;
1837*a9800bebSGarrett D'Amore 	uint16_t next_wqe;
1838b3660a96SSukumar Swaminathan 	off_t offset;
183982527734SSukumar Swaminathan 
184082527734SSukumar Swaminathan 
184182527734SSukumar Swaminathan 	channelno = cp->channelno;
184282527734SSukumar Swaminathan 	wq = (WQ_DESC_t *)cp->iopath;
184382527734SSukumar Swaminathan 
184482527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
184582527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
184682527734SSukumar Swaminathan 	    "ISSUE WQE channel: %x  %p", channelno, wq);
184782527734SSukumar Swaminathan #endif
184882527734SSukumar Swaminathan 
184982527734SSukumar Swaminathan 	throttle = 0;
185082527734SSukumar Swaminathan 
185182527734SSukumar Swaminathan 	/* Check if FCP ring and adapter is not ready */
185282527734SSukumar Swaminathan 	/* We may use any ring for FCP_CMD */
185382527734SSukumar Swaminathan 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
185482527734SSukumar Swaminathan 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
185582527734SSukumar Swaminathan 		    !(((emlxs_port_t *)iocbq->port)->tgt_mode)) {
185682527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
185782527734SSukumar Swaminathan 			return;
185882527734SSukumar Swaminathan 		}
185982527734SSukumar Swaminathan 	}
186082527734SSukumar Swaminathan 
186182527734SSukumar Swaminathan 	/* Attempt to acquire CMD_RING lock */
1862*a9800bebSGarrett D'Amore 	if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) {
186382527734SSukumar Swaminathan 		/* Queue it for later */
186482527734SSukumar Swaminathan 		if (iocbq) {
186582527734SSukumar Swaminathan 			if ((hba->io_count -
186682527734SSukumar Swaminathan 			    hba->channel_tx_count) > 10) {
186782527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
186882527734SSukumar Swaminathan 				return;
186982527734SSukumar Swaminathan 			} else {
187082527734SSukumar Swaminathan 
1871*a9800bebSGarrett D'Amore 				mutex_enter(&EMLXS_QUE_LOCK(channelno));
187282527734SSukumar Swaminathan 			}
187382527734SSukumar Swaminathan 		} else {
187482527734SSukumar Swaminathan 			return;
187582527734SSukumar Swaminathan 		}
187682527734SSukumar Swaminathan 	}
1877*a9800bebSGarrett D'Amore 	/* EMLXS_QUE_LOCK acquired */
187882527734SSukumar Swaminathan 
187982527734SSukumar Swaminathan 	/* Throttle check only applies to non special iocb */
188082527734SSukumar Swaminathan 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
188182527734SSukumar Swaminathan 		/* Check if HBA is full */
188282527734SSukumar Swaminathan 		throttle = hba->io_throttle - hba->io_active;
188382527734SSukumar Swaminathan 		if (throttle <= 0) {
188482527734SSukumar Swaminathan 			/* Hitting adapter throttle limit */
188582527734SSukumar Swaminathan 			/* Queue it for later */
188682527734SSukumar Swaminathan 			if (iocbq) {
188782527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
188882527734SSukumar Swaminathan 			}
188982527734SSukumar Swaminathan 
189082527734SSukumar Swaminathan 			goto busy;
189182527734SSukumar Swaminathan 		}
189282527734SSukumar Swaminathan 	}
189382527734SSukumar Swaminathan 
189482527734SSukumar Swaminathan 	/* Check to see if we have room for this WQE */
189582527734SSukumar Swaminathan 	next_wqe = wq->host_index + 1;
189682527734SSukumar Swaminathan 	if (next_wqe >= wq->max_index) {
189782527734SSukumar Swaminathan 		next_wqe = 0;
189882527734SSukumar Swaminathan 	}
189982527734SSukumar Swaminathan 
190082527734SSukumar Swaminathan 	if (next_wqe == wq->port_index) {
190182527734SSukumar Swaminathan 		/* Queue it for later */
190282527734SSukumar Swaminathan 		if (iocbq) {
190382527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
190482527734SSukumar Swaminathan 		}
190582527734SSukumar Swaminathan 		goto busy;
190682527734SSukumar Swaminathan 	}
190782527734SSukumar Swaminathan 
190882527734SSukumar Swaminathan 	/*
190982527734SSukumar Swaminathan 	 * We have a command ring slot available
191082527734SSukumar Swaminathan 	 * Make sure we have an iocb to send
191182527734SSukumar Swaminathan 	 */
191282527734SSukumar Swaminathan 	if (iocbq) {
191382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
191482527734SSukumar Swaminathan 
191582527734SSukumar Swaminathan 		/* Check if the ring already has iocb's waiting */
191682527734SSukumar Swaminathan 		if (cp->nodeq.q_first != NULL) {
191782527734SSukumar Swaminathan 			/* Put the current iocbq on the tx queue */
191882527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 0);
191982527734SSukumar Swaminathan 
192082527734SSukumar Swaminathan 			/*
192182527734SSukumar Swaminathan 			 * Attempt to replace it with the next iocbq
192282527734SSukumar Swaminathan 			 * in the tx queue
192382527734SSukumar Swaminathan 			 */
192482527734SSukumar Swaminathan 			iocbq = emlxs_tx_get(cp, 0);
192582527734SSukumar Swaminathan 		}
192682527734SSukumar Swaminathan 
192782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
192882527734SSukumar Swaminathan 	} else {
192982527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
193082527734SSukumar Swaminathan 	}
193182527734SSukumar Swaminathan 
193282527734SSukumar Swaminathan sendit:
193382527734SSukumar Swaminathan 	/* Process each iocbq */
193482527734SSukumar Swaminathan 	while (iocbq) {
193582527734SSukumar Swaminathan 
193682527734SSukumar Swaminathan 		wqe = &iocbq->wqe;
193782527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
193882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
193982527734SSukumar Swaminathan 		    "ISSUE QID %d WQE iotag: %x xri: %x", wq->qid,
194082527734SSukumar Swaminathan 		    wqe->RequestTag, wqe->XRITag);
194182527734SSukumar Swaminathan #endif
194282527734SSukumar Swaminathan 
194382527734SSukumar Swaminathan 		sbp = iocbq->sbp;
194482527734SSukumar Swaminathan 		if (sbp) {
194582527734SSukumar Swaminathan 			/* If exchange removed after wqe was prep'ed, drop it */
1946*a9800bebSGarrett D'Amore 			if (!(sbp->xrip)) {
194782527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
194882527734SSukumar Swaminathan 				    "Xmit WQE iotag: %x xri: %x aborted",
194982527734SSukumar Swaminathan 				    wqe->RequestTag, wqe->XRITag);
195082527734SSukumar Swaminathan 
195182527734SSukumar Swaminathan 				/* Get next iocb from the tx queue */
195282527734SSukumar Swaminathan 				iocbq = emlxs_tx_get(cp, 1);
195382527734SSukumar Swaminathan 				continue;
195482527734SSukumar Swaminathan 			}
195582527734SSukumar Swaminathan 
195682527734SSukumar Swaminathan 			if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) {
195782527734SSukumar Swaminathan 
195882527734SSukumar Swaminathan 				/* Perform delay */
195982527734SSukumar Swaminathan 				if ((channelno == hba->channel_els) &&
196082527734SSukumar Swaminathan 				    !(iocbq->flag & IOCB_FCP_CMD)) {
196182527734SSukumar Swaminathan 					drv_usecwait(100000);
196282527734SSukumar Swaminathan 				} else {
196382527734SSukumar Swaminathan 					drv_usecwait(20000);
196482527734SSukumar Swaminathan 				}
196582527734SSukumar Swaminathan 			}
196682527734SSukumar Swaminathan 		}
196782527734SSukumar Swaminathan 
196882527734SSukumar Swaminathan 		/*
196982527734SSukumar Swaminathan 		 * At this point, we have a command ring slot available
197082527734SSukumar Swaminathan 		 * and an iocb to send
197182527734SSukumar Swaminathan 		 */
197282527734SSukumar Swaminathan 		wq->release_depth--;
197382527734SSukumar Swaminathan 		if (wq->release_depth == 0) {
197482527734SSukumar Swaminathan 			wq->release_depth = WQE_RELEASE_DEPTH;
197582527734SSukumar Swaminathan 			wqe->WQEC = 1;
197682527734SSukumar Swaminathan 		}
197782527734SSukumar Swaminathan 
197882527734SSukumar Swaminathan 
197982527734SSukumar Swaminathan 		HBASTATS.IocbIssued[channelno]++;
198082527734SSukumar Swaminathan 
198182527734SSukumar Swaminathan 		/* Check for ULP pkt request */
198282527734SSukumar Swaminathan 		if (sbp) {
198382527734SSukumar Swaminathan 			mutex_enter(&sbp->mtx);
198482527734SSukumar Swaminathan 
198582527734SSukumar Swaminathan 			if (sbp->node == NULL) {
198682527734SSukumar Swaminathan 				/* Set node to base node by default */
198782527734SSukumar Swaminathan 				iocbq->node = (void *)&port->node_base;
198882527734SSukumar Swaminathan 				sbp->node = (void *)&port->node_base;
198982527734SSukumar Swaminathan 			}
199082527734SSukumar Swaminathan 
199182527734SSukumar Swaminathan 			sbp->pkt_flags |= PACKET_IN_CHIPQ;
199282527734SSukumar Swaminathan 			mutex_exit(&sbp->mtx);
199382527734SSukumar Swaminathan 
199482527734SSukumar Swaminathan 			atomic_add_32(&hba->io_active, 1);
1995*a9800bebSGarrett D'Amore 			sbp->xrip->flag |= EMLXS_XRI_PENDING_IO;
199682527734SSukumar Swaminathan 		}
199782527734SSukumar Swaminathan 
199882527734SSukumar Swaminathan 
199982527734SSukumar Swaminathan 		/* Free the local iocb if there is no sbp tracking it */
200082527734SSukumar Swaminathan 		if (sbp) {
200182527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
200282527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
200382527734SSukumar Swaminathan 			if (sbp->fct_cmd) {
200482527734SSukumar Swaminathan 				emlxs_fct_io_trace(port, sbp->fct_cmd,
200582527734SSukumar Swaminathan 				    EMLXS_FCT_IOCB_ISSUED);
200682527734SSukumar Swaminathan 				emlxs_fct_io_trace(port, sbp->fct_cmd,
200782527734SSukumar Swaminathan 				    icmd->ULPCOMMAND);
200882527734SSukumar Swaminathan 			}
200982527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
201082527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
201182527734SSukumar Swaminathan 			cp->hbaSendCmd_sbp++;
201282527734SSukumar Swaminathan 			iocbq->channel = cp;
201382527734SSukumar Swaminathan 		} else {
201482527734SSukumar Swaminathan 			cp->hbaSendCmd++;
201582527734SSukumar Swaminathan 		}
201682527734SSukumar Swaminathan 
201782527734SSukumar Swaminathan 		flag = iocbq->flag;
201882527734SSukumar Swaminathan 
201982527734SSukumar Swaminathan 		/* Send the iocb */
202082527734SSukumar Swaminathan 		wqeslot = (emlxs_wqe_t *)wq->addr.virt;
202182527734SSukumar Swaminathan 		wqeslot += wq->host_index;
202282527734SSukumar Swaminathan 
202382527734SSukumar Swaminathan 		wqe->CQId = wq->cqid;
202482527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot,
202582527734SSukumar Swaminathan 		    sizeof (emlxs_wqe_t));
202682527734SSukumar Swaminathan #ifdef DEBUG_WQE
2027*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0);
202882527734SSukumar Swaminathan #endif
2029b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
2030b3660a96SSukumar Swaminathan 		    wq->addr.virt) -
2031b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
2032b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
2033b3660a96SSukumar Swaminathan 
2034b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset,
203582527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
203682527734SSukumar Swaminathan 
203782527734SSukumar Swaminathan 		/* Ring the WQ Doorbell */
203882527734SSukumar Swaminathan 		wqdb = wq->qid;
203982527734SSukumar Swaminathan 		wqdb |= ((1 << 24) | (wq->host_index << 16));
204082527734SSukumar Swaminathan 
204182527734SSukumar Swaminathan 
204282527734SSukumar Swaminathan 		WRITE_BAR2_REG(hba, FC_WQDB_REG(hba), wqdb);
204382527734SSukumar Swaminathan 		wq->host_index = next_wqe;
204482527734SSukumar Swaminathan 
204582527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
204682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
204782527734SSukumar Swaminathan 		    "WQ RING: %08x", wqdb);
204882527734SSukumar Swaminathan #endif
204982527734SSukumar Swaminathan 
205082527734SSukumar Swaminathan 		/*
205182527734SSukumar Swaminathan 		 * After this, the sbp / iocb / wqe should not be
205282527734SSukumar Swaminathan 		 * accessed in the xmit path.
205382527734SSukumar Swaminathan 		 */
205482527734SSukumar Swaminathan 
205582527734SSukumar Swaminathan 		if (!sbp) {
2056*a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
205782527734SSukumar Swaminathan 		}
205882527734SSukumar Swaminathan 
205982527734SSukumar Swaminathan 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
206082527734SSukumar Swaminathan 			/* Check if HBA is full */
206182527734SSukumar Swaminathan 			throttle = hba->io_throttle - hba->io_active;
206282527734SSukumar Swaminathan 			if (throttle <= 0) {
206382527734SSukumar Swaminathan 				goto busy;
206482527734SSukumar Swaminathan 			}
206582527734SSukumar Swaminathan 		}
206682527734SSukumar Swaminathan 
206782527734SSukumar Swaminathan 		/* Check to see if we have room for another WQE */
206882527734SSukumar Swaminathan 		next_wqe++;
206982527734SSukumar Swaminathan 		if (next_wqe >= wq->max_index) {
207082527734SSukumar Swaminathan 			next_wqe = 0;
207182527734SSukumar Swaminathan 		}
207282527734SSukumar Swaminathan 
207382527734SSukumar Swaminathan 		if (next_wqe == wq->port_index) {
207482527734SSukumar Swaminathan 			/* Queue it for later */
207582527734SSukumar Swaminathan 			goto busy;
207682527734SSukumar Swaminathan 		}
207782527734SSukumar Swaminathan 
207882527734SSukumar Swaminathan 
207982527734SSukumar Swaminathan 		/* Get the next iocb from the tx queue if there is one */
208082527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
208182527734SSukumar Swaminathan 	}
208282527734SSukumar Swaminathan 
2083*a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
208482527734SSukumar Swaminathan 
208582527734SSukumar Swaminathan 	return;
208682527734SSukumar Swaminathan 
208782527734SSukumar Swaminathan busy:
208882527734SSukumar Swaminathan 	if (throttle <= 0) {
208982527734SSukumar Swaminathan 		HBASTATS.IocbThrottled++;
209082527734SSukumar Swaminathan 	} else {
209182527734SSukumar Swaminathan 		HBASTATS.IocbRingFull[channelno]++;
209282527734SSukumar Swaminathan 	}
209382527734SSukumar Swaminathan 
2094*a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
209582527734SSukumar Swaminathan 
209682527734SSukumar Swaminathan 	return;
209782527734SSukumar Swaminathan 
209882527734SSukumar Swaminathan } /* emlxs_sli4_issue_iocb_cmd() */
209982527734SSukumar Swaminathan 
210082527734SSukumar Swaminathan 
210182527734SSukumar Swaminathan /*ARGSUSED*/
210282527734SSukumar Swaminathan static uint32_t
2103*a9800bebSGarrett D'Amore emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb,
2104*a9800bebSGarrett D'Amore     uint32_t tmo)
210582527734SSukumar Swaminathan {
2106*a9800bebSGarrett D'Amore 	emlxs_hba_t *hba = HBA;
210782527734SSukumar Swaminathan 	MAILBOXQ	*mbq;
210882527734SSukumar Swaminathan 	MAILBOX4	*mb4;
210982527734SSukumar Swaminathan 	MATCHMAP	*mp;
211082527734SSukumar Swaminathan 	uint32_t	*iptr;
211182527734SSukumar Swaminathan 	uint32_t	mqdb;
2112b3660a96SSukumar Swaminathan 	off_t		offset;
211382527734SSukumar Swaminathan 
211482527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)mb;
211582527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mb;
211682527734SSukumar Swaminathan 	mp = (MATCHMAP *) mbq->nonembed;
2117*a9800bebSGarrett D'Amore 	hba->mbox_mqe = (void *)mqe;
211882527734SSukumar Swaminathan 
211982527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
212082527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
212182527734SSukumar Swaminathan 		/*
212282527734SSukumar Swaminathan 		 * If this is an embedded mbox, everything should fit
212382527734SSukumar Swaminathan 		 * into the mailbox area.
212482527734SSukumar Swaminathan 		 */
212582527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
212682527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
212782527734SSukumar Swaminathan 
212882527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
212982527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
213082527734SSukumar Swaminathan 
2131*a9800bebSGarrett D'Amore 		if (mb->mbxCommand != MBX_HEARTBEAT) {
2132*a9800bebSGarrett D'Amore 			emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe,
2133*a9800bebSGarrett D'Amore 			    18, 0);
2134*a9800bebSGarrett D'Amore 		}
213582527734SSukumar Swaminathan 	} else {
213682527734SSukumar Swaminathan 		/* SLI_CONFIG and non-embedded */
213782527734SSukumar Swaminathan 
213882527734SSukumar Swaminathan 		/*
213982527734SSukumar Swaminathan 		 * If this is not embedded, the MQ area
214082527734SSukumar Swaminathan 		 * MUST contain a SGE pointer to a larger area for the
214182527734SSukumar Swaminathan 		 * non-embedded mailbox command.
214282527734SSukumar Swaminathan 		 * mp will point to the actual mailbox command which
214382527734SSukumar Swaminathan 		 * should be copied into the non-embedded area.
214482527734SSukumar Swaminathan 		 */
214582527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.sge_cnt = 1;
214682527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.payload_length = mp->size;
214782527734SSukumar Swaminathan 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
214882527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
214982527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
215082527734SSukumar Swaminathan 		*iptr = mp->size;
215182527734SSukumar Swaminathan 
215282527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
215382527734SSukumar Swaminathan 
215482527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
215582527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
215682527734SSukumar Swaminathan 
215782527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
215882527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
215982527734SSukumar Swaminathan 
2160b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
2161b3660a96SSukumar Swaminathan 		    hba->sli.sli4.mq.addr.virt) -
2162b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
2163b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
2164b3660a96SSukumar Swaminathan 
2165b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
216682527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
216782527734SSukumar Swaminathan 
2168*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0);
216982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
217082527734SSukumar Swaminathan 		    "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt));
2171*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
217282527734SSukumar Swaminathan 	}
217382527734SSukumar Swaminathan 
217482527734SSukumar Swaminathan 	/* Ring the MQ Doorbell */
217582527734SSukumar Swaminathan 	mqdb = hba->sli.sli4.mq.qid;
217682527734SSukumar Swaminathan 	mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK);
217782527734SSukumar Swaminathan 
2178*a9800bebSGarrett D'Amore 	if (mb->mbxCommand != MBX_HEARTBEAT) {
2179*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2180*a9800bebSGarrett D'Amore 		    "MQ RING: %08x", mqdb);
2181*a9800bebSGarrett D'Amore 	}
218282527734SSukumar Swaminathan 
218382527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_MQDB_REG(hba), mqdb);
218482527734SSukumar Swaminathan 	return (MBX_SUCCESS);
218582527734SSukumar Swaminathan 
218682527734SSukumar Swaminathan } /* emlxs_sli4_issue_mq() */
218782527734SSukumar Swaminathan 
218882527734SSukumar Swaminathan 
218982527734SSukumar Swaminathan /*ARGSUSED*/
219082527734SSukumar Swaminathan static uint32_t
219182527734SSukumar Swaminathan emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo)
219282527734SSukumar Swaminathan {
219382527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
219482527734SSukumar Swaminathan 	MAILBOXQ	*mbq;
219582527734SSukumar Swaminathan 	MAILBOX4	*mb4;
2196b3660a96SSukumar Swaminathan 	MATCHMAP	*mp = NULL;
219782527734SSukumar Swaminathan 	uint32_t	*iptr;
2198b3660a96SSukumar Swaminathan 	int		nonembed = 0;
219982527734SSukumar Swaminathan 
220082527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)mb;
220182527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mb;
220282527734SSukumar Swaminathan 	mp = (MATCHMAP *) mbq->nonembed;
2203*a9800bebSGarrett D'Amore 	hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt;
220482527734SSukumar Swaminathan 
220582527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
220682527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
220782527734SSukumar Swaminathan 		/*
220882527734SSukumar Swaminathan 		 * If this is an embedded mbox, everything should fit
220982527734SSukumar Swaminathan 		 * into the bootstrap mailbox area.
221082527734SSukumar Swaminathan 		 */
221182527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
221282527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
221382527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
221482527734SSukumar Swaminathan 
221582527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
221682527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV);
2217*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0);
221882527734SSukumar Swaminathan 	} else {
221982527734SSukumar Swaminathan 		/*
222082527734SSukumar Swaminathan 		 * If this is not embedded, the bootstrap mailbox area
222182527734SSukumar Swaminathan 		 * MUST contain a SGE pointer to a larger area for the
222282527734SSukumar Swaminathan 		 * non-embedded mailbox command.
222382527734SSukumar Swaminathan 		 * mp will point to the actual mailbox command which
222482527734SSukumar Swaminathan 		 * should be copied into the non-embedded area.
222582527734SSukumar Swaminathan 		 */
2226b3660a96SSukumar Swaminathan 		nonembed = 1;
222782527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.sge_cnt = 1;
222882527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.payload_length = mp->size;
222982527734SSukumar Swaminathan 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
223082527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
223182527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
223282527734SSukumar Swaminathan 		*iptr = mp->size;
223382527734SSukumar Swaminathan 
223482527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
223582527734SSukumar Swaminathan 
223682527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
223782527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
223882527734SSukumar Swaminathan 
223982527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
224082527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
224182527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
224282527734SSukumar Swaminathan 
224382527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
224482527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
224582527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
224682527734SSukumar Swaminathan 
2247*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0);
224882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
224982527734SSukumar Swaminathan 		    "Extension Addr %p %p", mp->phys,
225082527734SSukumar Swaminathan 		    (uint32_t *)((uint8_t *)mp->virt));
225182527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mp->virt);
2252*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
225382527734SSukumar Swaminathan 	}
225482527734SSukumar Swaminathan 
225582527734SSukumar Swaminathan 
225682527734SSukumar Swaminathan 	/* NOTE: tmo is in 10ms ticks */
225782527734SSukumar Swaminathan 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
225882527734SSukumar Swaminathan 		return (MBX_TIMEOUT);
225982527734SSukumar Swaminathan 	}
226082527734SSukumar Swaminathan 
226182527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
226282527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
226382527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
226482527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL);
226582527734SSukumar Swaminathan 
226682527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
226782527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
226882527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
226982527734SSukumar Swaminathan 
2270*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0);
227182527734SSukumar Swaminathan 
227282527734SSukumar Swaminathan 	} else {
227382527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
227482527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
227582527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
227682527734SSukumar Swaminathan 
227782527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
227882527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
227982527734SSukumar Swaminathan 
228082527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
228182527734SSukumar Swaminathan 
228282527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
228382527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
228482527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
228582527734SSukumar Swaminathan 
2286*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0);
228782527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mp->virt);
2288*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
228982527734SSukumar Swaminathan 	}
229082527734SSukumar Swaminathan 
2291b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
2292b3660a96SSukumar Swaminathan 	if (nonembed && mp) {
2293b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
2294b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
2295b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
2296b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
2297b3660a96SSukumar Swaminathan 			    "emlxs_sli4_issue_bootstrap: mp_hdl=%p",
2298b3660a96SSukumar Swaminathan 			    mp->dma_handle);
2299b3660a96SSukumar Swaminathan 			return (MBXERR_DMA_ERROR);
2300b3660a96SSukumar Swaminathan 		}
2301b3660a96SSukumar Swaminathan 	}
2302b3660a96SSukumar Swaminathan 
2303b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba,
2304b3660a96SSukumar Swaminathan 	    hba->sli.sli4.bootstrapmb.dma_handle)
2305b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
2306b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
2307b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
2308b3660a96SSukumar Swaminathan 		    "emlxs_sli4_issue_bootstrap: hdl=%p",
2309b3660a96SSukumar Swaminathan 		    hba->sli.sli4.bootstrapmb.dma_handle);
2310b3660a96SSukumar Swaminathan 		return (MBXERR_DMA_ERROR);
2311b3660a96SSukumar Swaminathan 	}
2312b3660a96SSukumar Swaminathan #endif
2313b3660a96SSukumar Swaminathan 
231482527734SSukumar Swaminathan 	return (MBX_SUCCESS);
231582527734SSukumar Swaminathan 
231682527734SSukumar Swaminathan } /* emlxs_sli4_issue_bootstrap() */
231782527734SSukumar Swaminathan 
231882527734SSukumar Swaminathan 
231982527734SSukumar Swaminathan /*ARGSUSED*/
232082527734SSukumar Swaminathan static uint32_t
232182527734SSukumar Swaminathan emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
232282527734SSukumar Swaminathan     uint32_t tmo)
232382527734SSukumar Swaminathan {
2324*a9800bebSGarrett D'Amore 	emlxs_port_t	*port;
232582527734SSukumar Swaminathan 	MAILBOX4	*mb4;
232682527734SSukumar Swaminathan 	MAILBOX		*mb;
232782527734SSukumar Swaminathan 	mbox_rsp_hdr_t	*hdr_rsp;
232882527734SSukumar Swaminathan 	MATCHMAP	*mp;
232982527734SSukumar Swaminathan 	uint32_t	*iptr;
233082527734SSukumar Swaminathan 	uint32_t	rc;
233182527734SSukumar Swaminathan 	uint32_t	i;
233282527734SSukumar Swaminathan 	uint32_t	tmo_local;
233382527734SSukumar Swaminathan 
2334*a9800bebSGarrett D'Amore 	if (!mbq->port) {
2335*a9800bebSGarrett D'Amore 		mbq->port = &PPORT;
2336*a9800bebSGarrett D'Amore 	}
2337*a9800bebSGarrett D'Amore 
2338*a9800bebSGarrett D'Amore 	port = (emlxs_port_t *)mbq->port;
2339*a9800bebSGarrett D'Amore 
234082527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mbq;
234182527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
234282527734SSukumar Swaminathan 
234382527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
234482527734SSukumar Swaminathan 	rc = MBX_SUCCESS;
234582527734SSukumar Swaminathan 
234682527734SSukumar Swaminathan 	/* Check for minimum timeouts */
234782527734SSukumar Swaminathan 	switch (mb->mbxCommand) {
234882527734SSukumar Swaminathan 	/* Mailbox commands that erase/write flash */
234982527734SSukumar Swaminathan 	case MBX_DOWN_LOAD:
235082527734SSukumar Swaminathan 	case MBX_UPDATE_CFG:
235182527734SSukumar Swaminathan 	case MBX_LOAD_AREA:
235282527734SSukumar Swaminathan 	case MBX_LOAD_EXP_ROM:
235382527734SSukumar Swaminathan 	case MBX_WRITE_NV:
235482527734SSukumar Swaminathan 	case MBX_FLASH_WR_ULA:
235582527734SSukumar Swaminathan 	case MBX_DEL_LD_ENTRY:
235682527734SSukumar Swaminathan 	case MBX_LOAD_SM:
235782527734SSukumar Swaminathan 		if (tmo < 300) {
235882527734SSukumar Swaminathan 			tmo = 300;
235982527734SSukumar Swaminathan 		}
236082527734SSukumar Swaminathan 		break;
236182527734SSukumar Swaminathan 
236282527734SSukumar Swaminathan 	default:
236382527734SSukumar Swaminathan 		if (tmo < 30) {
236482527734SSukumar Swaminathan 			tmo = 30;
236582527734SSukumar Swaminathan 		}
236682527734SSukumar Swaminathan 		break;
236782527734SSukumar Swaminathan 	}
236882527734SSukumar Swaminathan 
236982527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
237082527734SSukumar Swaminathan 	tmo_local = tmo * 100;
237182527734SSukumar Swaminathan 
237282527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
237382527734SSukumar Swaminathan 
237482527734SSukumar Swaminathan 	/* Adjust wait flag */
237582527734SSukumar Swaminathan 	if (flag != MBX_NOWAIT) {
237682527734SSukumar Swaminathan 		if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) {
237782527734SSukumar Swaminathan 			flag = MBX_SLEEP;
237882527734SSukumar Swaminathan 		} else {
237982527734SSukumar Swaminathan 			flag = MBX_POLL;
238082527734SSukumar Swaminathan 		}
238182527734SSukumar Swaminathan 	} else {
238282527734SSukumar Swaminathan 		/* Must have interrupts enabled to perform MBX_NOWAIT */
238382527734SSukumar Swaminathan 		if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) {
238482527734SSukumar Swaminathan 
238582527734SSukumar Swaminathan 			mb->mbxStatus = MBX_HARDWARE_ERROR;
238682527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
238782527734SSukumar Swaminathan 
238882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2389*a9800bebSGarrett D'Amore 			    "Interrupts disabled. %s failed.",
239082527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
239182527734SSukumar Swaminathan 
239282527734SSukumar Swaminathan 			return (MBX_HARDWARE_ERROR);
239382527734SSukumar Swaminathan 		}
239482527734SSukumar Swaminathan 	}
239582527734SSukumar Swaminathan 
2396bce54adfSSukumar Swaminathan 	/* Check for hardware error ; special case SLI_CONFIG */
2397bce54adfSSukumar Swaminathan 	if ((hba->flag & FC_HARDWARE_ERROR) &&
2398bce54adfSSukumar Swaminathan 	    ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
2399bce54adfSSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
2400bce54adfSSukumar Swaminathan 	    COMMON_OPCODE_RESET))) {
240182527734SSukumar Swaminathan 		mb->mbxStatus = MBX_HARDWARE_ERROR;
240282527734SSukumar Swaminathan 
240382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
240482527734SSukumar Swaminathan 
240582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
240682527734SSukumar Swaminathan 		    "Hardware error reported. %s failed. status=%x mb=%p",
240782527734SSukumar Swaminathan 		    emlxs_mb_cmd_xlate(mb->mbxCommand),  mb->mbxStatus, mb);
240882527734SSukumar Swaminathan 
240982527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
241082527734SSukumar Swaminathan 	}
241182527734SSukumar Swaminathan 
241282527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
241382527734SSukumar Swaminathan 		/* If we are not polling, then queue it for later */
241482527734SSukumar Swaminathan 		if (flag == MBX_NOWAIT) {
241582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
241682527734SSukumar Swaminathan 			    "Busy.      %s: mb=%p NoWait.",
241782527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
241882527734SSukumar Swaminathan 
241982527734SSukumar Swaminathan 			emlxs_mb_put(hba, mbq);
242082527734SSukumar Swaminathan 
242182527734SSukumar Swaminathan 			HBASTATS.MboxBusy++;
242282527734SSukumar Swaminathan 
242382527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
242482527734SSukumar Swaminathan 
242582527734SSukumar Swaminathan 			return (MBX_BUSY);
242682527734SSukumar Swaminathan 		}
242782527734SSukumar Swaminathan 
242882527734SSukumar Swaminathan 		while (hba->mbox_queue_flag) {
242982527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
243082527734SSukumar Swaminathan 
243182527734SSukumar Swaminathan 			if (tmo_local-- == 0) {
243282527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
243382527734SSukumar Swaminathan 				    &emlxs_mbox_event_msg,
243482527734SSukumar Swaminathan 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
243582527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
243682527734SSukumar Swaminathan 				    tmo);
243782527734SSukumar Swaminathan 
243882527734SSukumar Swaminathan 				/* Non-lethalStatus mailbox timeout */
243982527734SSukumar Swaminathan 				/* Does not indicate a hardware error */
244082527734SSukumar Swaminathan 				mb->mbxStatus = MBX_TIMEOUT;
244182527734SSukumar Swaminathan 				return (MBX_TIMEOUT);
244282527734SSukumar Swaminathan 			}
244382527734SSukumar Swaminathan 
244482527734SSukumar Swaminathan 			DELAYMS(10);
244582527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
244682527734SSukumar Swaminathan 		}
244782527734SSukumar Swaminathan 	}
244882527734SSukumar Swaminathan 
244982527734SSukumar Swaminathan 	/* Initialize mailbox area */
245082527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
245182527734SSukumar Swaminathan 
2452*a9800bebSGarrett D'Amore 	if (mb->mbxCommand == MBX_DOWN_LINK) {
2453*a9800bebSGarrett D'Amore 		hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK;
2454*a9800bebSGarrett D'Amore 	}
2455*a9800bebSGarrett D'Amore 
245682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
245782527734SSukumar Swaminathan 	switch (flag) {
245882527734SSukumar Swaminathan 
245982527734SSukumar Swaminathan 	case MBX_NOWAIT:
246082527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_HEARTBEAT) {
246182527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
246282527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
246382527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
246482527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
246582527734SSukumar Swaminathan 				    "Sending.   %s: mb=%p NoWait. embedded %d",
246682527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
246782527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
246882527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
246982527734SSukumar Swaminathan 			}
247082527734SSukumar Swaminathan 		}
247182527734SSukumar Swaminathan 
247282527734SSukumar Swaminathan 		iptr = hba->sli.sli4.mq.addr.virt;
247382527734SSukumar Swaminathan 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
247482527734SSukumar Swaminathan 		hba->sli.sli4.mq.host_index++;
247582527734SSukumar Swaminathan 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
247682527734SSukumar Swaminathan 			hba->sli.sli4.mq.host_index = 0;
247782527734SSukumar Swaminathan 		}
247882527734SSukumar Swaminathan 
247982527734SSukumar Swaminathan 		if (mbq->bp) {
248082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
248182527734SSukumar Swaminathan 			    "BDE virt %p phys %p size x%x",
248282527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->virt,
248382527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->phys,
248482527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->size);
2485*a9800bebSGarrett D'Amore 			emlxs_data_dump(port, "DATA",
248682527734SSukumar Swaminathan 			    (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0);
248782527734SSukumar Swaminathan 		}
2488*a9800bebSGarrett D'Amore 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
248982527734SSukumar Swaminathan 		break;
249082527734SSukumar Swaminathan 
249182527734SSukumar Swaminathan 	case MBX_POLL:
249282527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
249382527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
249482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
249582527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Poll. embedded %d",
249682527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
249782527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
249882527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
249982527734SSukumar Swaminathan 		}
250082527734SSukumar Swaminathan 
250182527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
250282527734SSukumar Swaminathan 
250382527734SSukumar Swaminathan 		/* Clean up the mailbox area */
250482527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
250582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
250682527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%x Poll. embedded %d",
250782527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
250882527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
250982527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
251082527734SSukumar Swaminathan 
251182527734SSukumar Swaminathan 			hba->flag |= FC_MBOX_TIMEOUT;
251282527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
251382527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
251482527734SSukumar Swaminathan 
251582527734SSukumar Swaminathan 		} else {
251682527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
251782527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
251882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
251982527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
2520*a9800bebSGarrett D'Amore 				    "Completed.   %s: mb=%p status=%x Poll. "
252182527734SSukumar Swaminathan 				    "embedded %d",
252282527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
252382527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
252482527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
252582527734SSukumar Swaminathan 			}
252682527734SSukumar Swaminathan 
252782527734SSukumar Swaminathan 			/* Process the result */
252882527734SSukumar Swaminathan 			if (!(mbq->flag & MBQ_PASSTHRU)) {
252982527734SSukumar Swaminathan 				if (mbq->mbox_cmpl) {
253082527734SSukumar Swaminathan 					(void) (mbq->mbox_cmpl)(hba, mbq);
253182527734SSukumar Swaminathan 				}
253282527734SSukumar Swaminathan 			}
253382527734SSukumar Swaminathan 
253482527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
253582527734SSukumar Swaminathan 		}
253682527734SSukumar Swaminathan 
253782527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
253882527734SSukumar Swaminathan 		if (mp) {
253982527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
254082527734SSukumar Swaminathan 			if (hdr_rsp->status) {
2541*a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
2542*a9800bebSGarrett D'Amore 				    &emlxs_mbox_detail_msg,
2543*a9800bebSGarrett D'Amore 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
2544*a9800bebSGarrett D'Amore 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2545*a9800bebSGarrett D'Amore 				    hdr_rsp->status, hdr_rsp->extra_status);
2546*a9800bebSGarrett D'Amore 
254782527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
254882527734SSukumar Swaminathan 			}
254982527734SSukumar Swaminathan 		}
255082527734SSukumar Swaminathan 		rc = mb->mbxStatus;
255182527734SSukumar Swaminathan 
255282527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
255382527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)emlxs_mb_get(hba);
255482527734SSukumar Swaminathan 		if (mbq) {
255582527734SSukumar Swaminathan 			/* Attempt to send pending mailboxes */
255682527734SSukumar Swaminathan 			i =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
255782527734SSukumar Swaminathan 			if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
2558*a9800bebSGarrett D'Amore 				emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
255982527734SSukumar Swaminathan 			}
256082527734SSukumar Swaminathan 		}
256182527734SSukumar Swaminathan 		break;
256282527734SSukumar Swaminathan 
256382527734SSukumar Swaminathan 	case MBX_SLEEP:
256482527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
256582527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
256682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
256782527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Sleep. embedded %d",
256882527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
256982527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
257082527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
257182527734SSukumar Swaminathan 		}
257282527734SSukumar Swaminathan 
257382527734SSukumar Swaminathan 		iptr = hba->sli.sli4.mq.addr.virt;
257482527734SSukumar Swaminathan 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
257582527734SSukumar Swaminathan 		hba->sli.sli4.mq.host_index++;
257682527734SSukumar Swaminathan 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
257782527734SSukumar Swaminathan 			hba->sli.sli4.mq.host_index = 0;
257882527734SSukumar Swaminathan 		}
257982527734SSukumar Swaminathan 
2580*a9800bebSGarrett D'Amore 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
258182527734SSukumar Swaminathan 
258282527734SSukumar Swaminathan 		if (rc != MBX_SUCCESS) {
258382527734SSukumar Swaminathan 			break;
258482527734SSukumar Swaminathan 		}
258582527734SSukumar Swaminathan 
258682527734SSukumar Swaminathan 		/* Wait for completion */
258782527734SSukumar Swaminathan 		/* The driver clock is timing the mailbox. */
258882527734SSukumar Swaminathan 
258982527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
259082527734SSukumar Swaminathan 		while (!(mbq->flag & MBQ_COMPLETED)) {
259182527734SSukumar Swaminathan 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
259282527734SSukumar Swaminathan 		}
259382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
259482527734SSukumar Swaminathan 
259582527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
259682527734SSukumar Swaminathan 		if (mp) {
259782527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
259882527734SSukumar Swaminathan 			if (hdr_rsp->status) {
2599*a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
2600*a9800bebSGarrett D'Amore 				    &emlxs_mbox_detail_msg,
2601*a9800bebSGarrett D'Amore 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
2602*a9800bebSGarrett D'Amore 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2603*a9800bebSGarrett D'Amore 				    hdr_rsp->status, hdr_rsp->extra_status);
2604*a9800bebSGarrett D'Amore 
260582527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
260682527734SSukumar Swaminathan 			}
260782527734SSukumar Swaminathan 		}
260882527734SSukumar Swaminathan 		rc = mb->mbxStatus;
260982527734SSukumar Swaminathan 
261082527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
261182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
261282527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%x Sleep. embedded %d",
261382527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
261482527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
261582527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
261682527734SSukumar Swaminathan 		} else {
261782527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
261882527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
261982527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
262082527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
2621*a9800bebSGarrett D'Amore 				    "Completed.   %s: mb=%p status=%x Sleep. "
262282527734SSukumar Swaminathan 				    "embedded %d",
262382527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
262482527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
262582527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
262682527734SSukumar Swaminathan 			}
262782527734SSukumar Swaminathan 		}
262882527734SSukumar Swaminathan 		break;
262982527734SSukumar Swaminathan 	}
263082527734SSukumar Swaminathan 
263182527734SSukumar Swaminathan 	return (rc);
263282527734SSukumar Swaminathan 
263382527734SSukumar Swaminathan } /* emlxs_sli4_issue_mbox_cmd() */
263482527734SSukumar Swaminathan 
263582527734SSukumar Swaminathan 
263682527734SSukumar Swaminathan 
263782527734SSukumar Swaminathan /*ARGSUSED*/
263882527734SSukumar Swaminathan static uint32_t
263982527734SSukumar Swaminathan emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
264082527734SSukumar Swaminathan     uint32_t tmo)
264182527734SSukumar Swaminathan {
264282527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
264382527734SSukumar Swaminathan 	MAILBOX		*mb;
264482527734SSukumar Swaminathan 	mbox_rsp_hdr_t	*hdr_rsp;
264582527734SSukumar Swaminathan 	MATCHMAP	*mp;
264682527734SSukumar Swaminathan 	uint32_t	rc;
264782527734SSukumar Swaminathan 	uint32_t	tmo_local;
264882527734SSukumar Swaminathan 
264982527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
265082527734SSukumar Swaminathan 
265182527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
265282527734SSukumar Swaminathan 	rc = MBX_SUCCESS;
265382527734SSukumar Swaminathan 
265482527734SSukumar Swaminathan 	if (tmo < 30) {
265582527734SSukumar Swaminathan 		tmo = 30;
265682527734SSukumar Swaminathan 	}
265782527734SSukumar Swaminathan 
265882527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
265982527734SSukumar Swaminathan 	tmo_local = tmo * 100;
266082527734SSukumar Swaminathan 
266182527734SSukumar Swaminathan 	flag = MBX_POLL;
266282527734SSukumar Swaminathan 
266382527734SSukumar Swaminathan 	/* Check for hardware error */
266482527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
266582527734SSukumar Swaminathan 		mb->mbxStatus = MBX_HARDWARE_ERROR;
266682527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
266782527734SSukumar Swaminathan 	}
266882527734SSukumar Swaminathan 
266982527734SSukumar Swaminathan 	/* Initialize mailbox area */
267082527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
267182527734SSukumar Swaminathan 
267282527734SSukumar Swaminathan 	switch (flag) {
267382527734SSukumar Swaminathan 
267482527734SSukumar Swaminathan 	case MBX_POLL:
267582527734SSukumar Swaminathan 
267682527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
267782527734SSukumar Swaminathan 
267882527734SSukumar Swaminathan 		/* Clean up the mailbox area */
267982527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
268082527734SSukumar Swaminathan 			hba->flag |= FC_MBOX_TIMEOUT;
268182527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
268282527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
268382527734SSukumar Swaminathan 
268482527734SSukumar Swaminathan 		} else {
268582527734SSukumar Swaminathan 			/* Process the result */
268682527734SSukumar Swaminathan 			if (!(mbq->flag & MBQ_PASSTHRU)) {
268782527734SSukumar Swaminathan 				if (mbq->mbox_cmpl) {
268882527734SSukumar Swaminathan 					(void) (mbq->mbox_cmpl)(hba, mbq);
268982527734SSukumar Swaminathan 				}
269082527734SSukumar Swaminathan 			}
269182527734SSukumar Swaminathan 
269282527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
269382527734SSukumar Swaminathan 		}
269482527734SSukumar Swaminathan 
269582527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
269682527734SSukumar Swaminathan 		if (mp) {
269782527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
269882527734SSukumar Swaminathan 			if (hdr_rsp->status) {
2699*a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
2700*a9800bebSGarrett D'Amore 				    &emlxs_mbox_detail_msg,
2701*a9800bebSGarrett D'Amore 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
2702*a9800bebSGarrett D'Amore 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2703*a9800bebSGarrett D'Amore 				    hdr_rsp->status, hdr_rsp->extra_status);
2704*a9800bebSGarrett D'Amore 
270582527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
270682527734SSukumar Swaminathan 			}
270782527734SSukumar Swaminathan 		}
270882527734SSukumar Swaminathan 		rc = mb->mbxStatus;
270982527734SSukumar Swaminathan 
271082527734SSukumar Swaminathan 		break;
271182527734SSukumar Swaminathan 	}
271282527734SSukumar Swaminathan 
271382527734SSukumar Swaminathan 	return (rc);
271482527734SSukumar Swaminathan 
271582527734SSukumar Swaminathan } /* emlxs_sli4_issue_mbox_cmd4quiesce() */
271682527734SSukumar Swaminathan 
271782527734SSukumar Swaminathan 
271882527734SSukumar Swaminathan 
271982527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
272082527734SSukumar Swaminathan /*ARGSUSED*/
272182527734SSukumar Swaminathan static uint32_t
272282527734SSukumar Swaminathan emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel)
272382527734SSukumar Swaminathan {
272482527734SSukumar Swaminathan 	return (IOERR_NO_RESOURCES);
272582527734SSukumar Swaminathan 
272682527734SSukumar Swaminathan } /* emlxs_sli4_prep_fct_iocb() */
272782527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
272882527734SSukumar Swaminathan 
272982527734SSukumar Swaminathan 
273082527734SSukumar Swaminathan /*ARGSUSED*/
273182527734SSukumar Swaminathan extern uint32_t
273282527734SSukumar Swaminathan emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
273382527734SSukumar Swaminathan {
273482527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
273582527734SSukumar Swaminathan 	fc_packet_t *pkt;
273682527734SSukumar Swaminathan 	CHANNEL *cp;
2737*a9800bebSGarrett D'Amore 	RPIobj_t *rpip;
2738*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
273982527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
274082527734SSukumar Swaminathan 	IOCBQ *iocbq;
274182527734SSukumar Swaminathan 	NODELIST *node;
274282527734SSukumar Swaminathan 	uint16_t iotag;
274382527734SSukumar Swaminathan 	uint32_t did;
2744b3660a96SSukumar Swaminathan 	off_t offset;
274582527734SSukumar Swaminathan 
274682527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
274782527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
274882527734SSukumar Swaminathan 	cp = &hba->chan[channel];
274982527734SSukumar Swaminathan 
275082527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
275182527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
275282527734SSukumar Swaminathan 	iocbq->port = (void *) port;
275382527734SSukumar Swaminathan 
275482527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
275582527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
275682527734SSukumar Swaminathan 
275782527734SSukumar Swaminathan 	/* Find target node object */
275882527734SSukumar Swaminathan 	node = (NODELIST *)iocbq->node;
2759*a9800bebSGarrett D'Amore 	rpip = EMLXS_NODE_TO_RPI(port, node);
276082527734SSukumar Swaminathan 
2761*a9800bebSGarrett D'Amore 	if (!rpip) {
276282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
276382527734SSukumar Swaminathan 		    "Unable to find rpi. did=0x%x", did);
276482527734SSukumar Swaminathan 
276582527734SSukumar Swaminathan 		emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
276682527734SSukumar Swaminathan 		    IOERR_INVALID_RPI, 0);
276782527734SSukumar Swaminathan 		return (0xff);
276882527734SSukumar Swaminathan 	}
276982527734SSukumar Swaminathan 
277082527734SSukumar Swaminathan 	sbp->channel = cp;
277182527734SSukumar Swaminathan 	/* Next allocate an Exchange for this command */
2772*a9800bebSGarrett D'Amore 	xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip);
277382527734SSukumar Swaminathan 
2774*a9800bebSGarrett D'Amore 	if (!xrip) {
277582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
277682527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate exchange. did=0x%x", did);
277782527734SSukumar Swaminathan 
277882527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
277982527734SSukumar Swaminathan 	}
278082527734SSukumar Swaminathan 	sbp->bmp = NULL;
278182527734SSukumar Swaminathan 	iotag = sbp->iotag;
278282527734SSukumar Swaminathan 
278382527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
278482527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,  /* DEBUG */
2785*a9800bebSGarrett D'Amore 	    "Prep FCP iotag: %x xri: %x", iotag, xrip->XRI);
278682527734SSukumar Swaminathan #endif
278782527734SSukumar Swaminathan 
278882527734SSukumar Swaminathan 	/* Indicate this is a FCP cmd */
278982527734SSukumar Swaminathan 	iocbq->flag |= IOCB_FCP_CMD;
279082527734SSukumar Swaminathan 
279182527734SSukumar Swaminathan 	if (emlxs_sli4_bde_setup(port, sbp)) {
2792*a9800bebSGarrett D'Amore 		emlxs_sli4_free_xri(hba, sbp, xrip, 1);
279382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
279482527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
279582527734SSukumar Swaminathan 
279682527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
279782527734SSukumar Swaminathan 	}
279882527734SSukumar Swaminathan 
279982527734SSukumar Swaminathan 
280082527734SSukumar Swaminathan 	/* DEBUG */
280182527734SSukumar Swaminathan #ifdef DEBUG_FCP
280282527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2803*a9800bebSGarrett D'Amore 	    "SGLaddr virt %p phys %p size %d", xrip->SGList.virt,
2804*a9800bebSGarrett D'Amore 	    xrip->SGList.phys, pkt->pkt_datalen);
2805*a9800bebSGarrett D'Amore 	emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt, 20, 0);
280682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
280782527734SSukumar Swaminathan 	    "CMD virt %p len %d:%d:%d",
280882527734SSukumar Swaminathan 	    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
2809*a9800bebSGarrett D'Amore 	emlxs_data_dump(port, "FCP CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
281082527734SSukumar Swaminathan #endif
281182527734SSukumar Swaminathan 
2812b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
2813*a9800bebSGarrett D'Amore 	    xrip->SGList.virt) -
2814b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
2815b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
2816b3660a96SSukumar Swaminathan 
2817*a9800bebSGarrett D'Amore 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
2818*a9800bebSGarrett D'Amore 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
281982527734SSukumar Swaminathan 
282082527734SSukumar Swaminathan 	/* if device is FCP-2 device, set the following bit */
282182527734SSukumar Swaminathan 	/* that says to run the FC-TAPE protocol. */
282282527734SSukumar Swaminathan 	if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
282382527734SSukumar Swaminathan 		wqe->ERP = 1;
282482527734SSukumar Swaminathan 	}
282582527734SSukumar Swaminathan 
282682527734SSukumar Swaminathan 	if (pkt->pkt_datalen == 0) {
282782527734SSukumar Swaminathan 		wqe->Command = CMD_FCP_ICMND64_CR;
282882527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
282982527734SSukumar Swaminathan 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
283082527734SSukumar Swaminathan 		wqe->Command = CMD_FCP_IREAD64_CR;
283182527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
283282527734SSukumar Swaminathan 		wqe->PU = PARM_READ_CHECK;
283382527734SSukumar Swaminathan 	} else {
283482527734SSukumar Swaminathan 		wqe->Command = CMD_FCP_IWRITE64_CR;
283582527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_OUT;
283682527734SSukumar Swaminathan 	}
283782527734SSukumar Swaminathan 	wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen;
283882527734SSukumar Swaminathan 
2839*a9800bebSGarrett D'Amore 	wqe->ContextTag = rpip->RPI;
284082527734SSukumar Swaminathan 	wqe->ContextType = WQE_RPI_CONTEXT;
2841*a9800bebSGarrett D'Amore 	wqe->XRITag = xrip->XRI;
284282527734SSukumar Swaminathan 	wqe->Timer =
284382527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
284482527734SSukumar Swaminathan 
284582527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
284682527734SSukumar Swaminathan 		wqe->CCPE = 1;
284782527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
284882527734SSukumar Swaminathan 	}
284982527734SSukumar Swaminathan 
285082527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
285182527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
285282527734SSukumar Swaminathan 		wqe->Class = CLASS2;
285382527734SSukumar Swaminathan 		break;
285482527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
285582527734SSukumar Swaminathan 	default:
285682527734SSukumar Swaminathan 		wqe->Class = CLASS3;
285782527734SSukumar Swaminathan 		break;
285882527734SSukumar Swaminathan 	}
285982527734SSukumar Swaminathan 	sbp->class = wqe->Class;
286082527734SSukumar Swaminathan 	wqe->RequestTag = iotag;
286181a990d5SRichard Lowe 	wqe->CQId = 0x3ff;  /* default CQ for response */
286282527734SSukumar Swaminathan 	return (FC_SUCCESS);
286382527734SSukumar Swaminathan } /* emlxs_sli4_prep_fcp_iocb() */
286482527734SSukumar Swaminathan 
286582527734SSukumar Swaminathan 
286682527734SSukumar Swaminathan /*ARGSUSED*/
286782527734SSukumar Swaminathan static uint32_t
286882527734SSukumar Swaminathan emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
286982527734SSukumar Swaminathan {
287082527734SSukumar Swaminathan 	return (FC_TRAN_BUSY);
287182527734SSukumar Swaminathan 
287282527734SSukumar Swaminathan } /* emlxs_sli4_prep_ip_iocb() */
287382527734SSukumar Swaminathan 
287482527734SSukumar Swaminathan 
287582527734SSukumar Swaminathan /*ARGSUSED*/
287682527734SSukumar Swaminathan static uint32_t
287782527734SSukumar Swaminathan emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
287882527734SSukumar Swaminathan {
287982527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
288082527734SSukumar Swaminathan 	fc_packet_t *pkt;
288182527734SSukumar Swaminathan 	IOCBQ *iocbq;
288282527734SSukumar Swaminathan 	IOCB *iocb;
288382527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
2884*a9800bebSGarrett D'Amore 	FCFIobj_t *fcfp;
2885*a9800bebSGarrett D'Amore 	RPIobj_t *rpip = NULL;
2886*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
288782527734SSukumar Swaminathan 	CHANNEL *cp;
288882527734SSukumar Swaminathan 	uint32_t did;
288982527734SSukumar Swaminathan 	uint32_t cmd;
289082527734SSukumar Swaminathan 	ULP_SGE64 stage_sge;
289182527734SSukumar Swaminathan 	ULP_SGE64 *sge;
289282527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
289382527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_resp;
289482527734SSukumar Swaminathan 	emlxs_node_t *node;
2895b3660a96SSukumar Swaminathan 	off_t offset;
289682527734SSukumar Swaminathan 
289782527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
289882527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
289982527734SSukumar Swaminathan 
290082527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
290182527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
290282527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
290382527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
290482527734SSukumar Swaminathan 	bzero((void *)iocb, sizeof (IOCB));
290582527734SSukumar Swaminathan 	cp = &hba->chan[hba->channel_els];
290682527734SSukumar Swaminathan 
290782527734SSukumar Swaminathan 	/* Initalize iocbq */
290882527734SSukumar Swaminathan 	iocbq->port = (void *) port;
290982527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
291082527734SSukumar Swaminathan 
291182527734SSukumar Swaminathan 	sbp->channel = cp;
291282527734SSukumar Swaminathan 	sbp->bmp = NULL;
291382527734SSukumar Swaminathan 
291482527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
291582527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
291682527734SSukumar Swaminathan 	cp_resp = pkt->pkt_resp_cookie;
291782527734SSukumar Swaminathan #else
291882527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
291982527734SSukumar Swaminathan 	cp_resp = &pkt->pkt_resp_cookie;
292082527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
292182527734SSukumar Swaminathan 
292282527734SSukumar Swaminathan 	/* CMD payload */
292382527734SSukumar Swaminathan 	sge = &stage_sge;
292482527734SSukumar Swaminathan 	sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
292582527734SSukumar Swaminathan 	sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress);
292682527734SSukumar Swaminathan 	sge->length = pkt->pkt_cmdlen;
292782527734SSukumar Swaminathan 	sge->offset = 0;
2928*a9800bebSGarrett D'Amore 	sge->reserved = 0;
292982527734SSukumar Swaminathan 
293082527734SSukumar Swaminathan 	/* Initalize iocb */
293182527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
293282527734SSukumar Swaminathan 		/* ELS Response */
293382527734SSukumar Swaminathan 
2934*a9800bebSGarrett D'Amore 		xrip = emlxs_sli4_register_xri(hba, sbp,
2935*a9800bebSGarrett D'Amore 		    pkt->pkt_cmd_fhdr.rx_id);
293682527734SSukumar Swaminathan 
2937*a9800bebSGarrett D'Amore 		if (!xrip) {
293882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
293982527734SSukumar Swaminathan 			    "Unable to find XRI. rxid=%x",
294082527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
294182527734SSukumar Swaminathan 
294282527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
294382527734SSukumar Swaminathan 			    IOERR_NO_XRI, 0);
294482527734SSukumar Swaminathan 			return (0xff);
294582527734SSukumar Swaminathan 		}
294682527734SSukumar Swaminathan 
2947*a9800bebSGarrett D'Amore 		rpip = xrip->rpip;
294882527734SSukumar Swaminathan 
2949*a9800bebSGarrett D'Amore 		if (!rpip) {
295082527734SSukumar Swaminathan 			/* This means that we had a node registered */
295182527734SSukumar Swaminathan 			/* when the unsol request came in but the node */
295282527734SSukumar Swaminathan 			/* has since been unregistered. */
295382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
295482527734SSukumar Swaminathan 			    "Unable to find RPI. rxid=%x",
295582527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
295682527734SSukumar Swaminathan 
295782527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
295882527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
295982527734SSukumar Swaminathan 			return (0xff);
296082527734SSukumar Swaminathan 		}
296182527734SSukumar Swaminathan 
296282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
296382527734SSukumar Swaminathan 		    "Prep ELS XRI: xri=%x iotag=%x oxid=%x rpi=%x",
2964*a9800bebSGarrett D'Amore 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
296582527734SSukumar Swaminathan 
296682527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_ELS_RSP64_CX;
296782527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
296882527734SSukumar Swaminathan 
296982527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh;
297082527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.addrLow = sge->addrLow;
297182527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
297282527734SSukumar Swaminathan 
297382527734SSukumar Swaminathan 		wqe->un.ElsRsp.RemoteId = did;
297482527734SSukumar Swaminathan 		wqe->PU = 0x3;
297582527734SSukumar Swaminathan 
297682527734SSukumar Swaminathan 		sge->last = 1;
297782527734SSukumar Swaminathan 		/* Now sge is fully staged */
297882527734SSukumar Swaminathan 
2979*a9800bebSGarrett D'Amore 		sge = xrip->SGList.virt;
298082527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
298182527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
298282527734SSukumar Swaminathan 
2983*a9800bebSGarrett D'Amore 		wqe->ContextTag = port->VPIobj.VPI;
298482527734SSukumar Swaminathan 		wqe->ContextType = WQE_VPI_CONTEXT;
2985*a9800bebSGarrett D'Amore 		wqe->OXId = xrip->rx_id;
298682527734SSukumar Swaminathan 
298782527734SSukumar Swaminathan 	} else {
298882527734SSukumar Swaminathan 		/* ELS Request */
298982527734SSukumar Swaminathan 
299082527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
2991*a9800bebSGarrett D'Amore 		rpip = EMLXS_NODE_TO_RPI(port, node);
2992*a9800bebSGarrett D'Amore 		fcfp = port->VPIobj.vfip->fcfp;
299382527734SSukumar Swaminathan 
2994*a9800bebSGarrett D'Amore 		if (!rpip) {
2995*a9800bebSGarrett D'Amore 			rpip = port->VPIobj.rpip;
299682527734SSukumar Swaminathan 		}
299782527734SSukumar Swaminathan 
299882527734SSukumar Swaminathan 		/* Next allocate an Exchange for this command */
2999*a9800bebSGarrett D'Amore 		xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip);
300082527734SSukumar Swaminathan 
3001*a9800bebSGarrett D'Amore 		if (!xrip) {
300282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3003*a9800bebSGarrett D'Amore 			    "Adapter Busy. Unable to allocate exchange. "
300482527734SSukumar Swaminathan 			    "did=0x%x", did);
300582527734SSukumar Swaminathan 
300682527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
300782527734SSukumar Swaminathan 		}
300882527734SSukumar Swaminathan 
300982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3010*a9800bebSGarrett D'Amore 		    "Prep ELS XRI: xri=%x iotag=%x rpi=%x", xrip->XRI,
3011*a9800bebSGarrett D'Amore 		    xrip->iotag, rpip->RPI);
301282527734SSukumar Swaminathan 
301382527734SSukumar Swaminathan 		wqe->Command = CMD_ELS_REQUEST64_CR;
301482527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_ELS;
301582527734SSukumar Swaminathan 
301682527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh;
301782527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.addrLow = sge->addrLow;
301882527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
301982527734SSukumar Swaminathan 
302082527734SSukumar Swaminathan 		/* setup for rsp */
302182527734SSukumar Swaminathan 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
302282527734SSukumar Swaminathan 		iocb->ULPPU = 1;	/* Wd4 is relative offset */
302382527734SSukumar Swaminathan 
302482527734SSukumar Swaminathan 		sge->last = 0;
302582527734SSukumar Swaminathan 
3026*a9800bebSGarrett D'Amore 		sge = xrip->SGList.virt;
302782527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
302882527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
302982527734SSukumar Swaminathan 
303082527734SSukumar Swaminathan 		wqe->un.ElsCmd.PayloadLength =
303182527734SSukumar Swaminathan 		    pkt->pkt_cmdlen; /* Byte offset of rsp data */
303282527734SSukumar Swaminathan 
303382527734SSukumar Swaminathan 		/* RSP payload */
303482527734SSukumar Swaminathan 		sge = &stage_sge;
303582527734SSukumar Swaminathan 		sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress);
303682527734SSukumar Swaminathan 		sge->addrLow = PADDR_LO(cp_resp->dmac_laddress);
303782527734SSukumar Swaminathan 		sge->length = pkt->pkt_rsplen;
3038b3660a96SSukumar Swaminathan 		sge->offset = 0;
303982527734SSukumar Swaminathan 		sge->last = 1;
304082527734SSukumar Swaminathan 		/* Now sge is fully staged */
304182527734SSukumar Swaminathan 
3042*a9800bebSGarrett D'Amore 		sge = xrip->SGList.virt;
304382527734SSukumar Swaminathan 		sge++;
304482527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
304582527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
304682527734SSukumar Swaminathan #ifdef DEBUG_ELS
304782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
304882527734SSukumar Swaminathan 		    "SGLaddr virt %p phys %p",
3049*a9800bebSGarrett D'Amore 		    xrip->SGList.virt, xrip->SGList.phys);
305082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
305182527734SSukumar Swaminathan 		    "PAYLOAD virt %p phys %p",
305282527734SSukumar Swaminathan 		    pkt->pkt_cmd, cp_cmd->dmac_laddress);
3053*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt,
3054*a9800bebSGarrett D'Amore 		    12, 0);
305582527734SSukumar Swaminathan #endif
305682527734SSukumar Swaminathan 
305782527734SSukumar Swaminathan 		cmd = *((uint32_t *)pkt->pkt_cmd);
305882527734SSukumar Swaminathan 		cmd &= ELS_CMD_MASK;
305982527734SSukumar Swaminathan 
306082527734SSukumar Swaminathan 		switch (cmd) {
306182527734SSukumar Swaminathan 		case ELS_CMD_FLOGI:
306282527734SSukumar Swaminathan 			wqe->un.ElsCmd.SP = 1;
3063*a9800bebSGarrett D'Amore 			wqe->ContextTag = fcfp->FCFI;
306482527734SSukumar Swaminathan 			wqe->ContextType = WQE_FCFI_CONTEXT;
306582527734SSukumar Swaminathan 			if (hba->flag & FC_FIP_SUPPORTED) {
306682527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
306782527734SSukumar Swaminathan 				wqe->ELSId |= WQE_ELSID_FLOGI;
306882527734SSukumar Swaminathan 			}
306982527734SSukumar Swaminathan 			break;
307082527734SSukumar Swaminathan 		case ELS_CMD_FDISC:
307182527734SSukumar Swaminathan 			wqe->un.ElsCmd.SP = 1;
3072*a9800bebSGarrett D'Amore 			wqe->ContextTag = port->VPIobj.VPI;
307382527734SSukumar Swaminathan 			wqe->ContextType = WQE_VPI_CONTEXT;
307482527734SSukumar Swaminathan 			if (hba->flag & FC_FIP_SUPPORTED) {
307582527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
307682527734SSukumar Swaminathan 				wqe->ELSId |= WQE_ELSID_FDISC;
307782527734SSukumar Swaminathan 			}
307882527734SSukumar Swaminathan 			break;
307982527734SSukumar Swaminathan 		case ELS_CMD_LOGO:
3080*a9800bebSGarrett D'Amore 			if (did == FABRIC_DID) {
3081*a9800bebSGarrett D'Amore 				wqe->ContextTag = fcfp->FCFI;
3082*a9800bebSGarrett D'Amore 				wqe->ContextType = WQE_FCFI_CONTEXT;
3083*a9800bebSGarrett D'Amore 				if (hba->flag & FC_FIP_SUPPORTED) {
3084*a9800bebSGarrett D'Amore 					wqe->CmdType |= WQE_TYPE_MASK_FIP;
3085*a9800bebSGarrett D'Amore 					wqe->ELSId |= WQE_ELSID_LOGO;
3086*a9800bebSGarrett D'Amore 				}
3087*a9800bebSGarrett D'Amore 			} else {
3088*a9800bebSGarrett D'Amore 				wqe->ContextTag = port->VPIobj.VPI;
3089*a9800bebSGarrett D'Amore 				wqe->ContextType = WQE_VPI_CONTEXT;
309082527734SSukumar Swaminathan 			}
309182527734SSukumar Swaminathan 			break;
309282527734SSukumar Swaminathan 
309382527734SSukumar Swaminathan 		case ELS_CMD_SCR:
309482527734SSukumar Swaminathan 		case ELS_CMD_PLOGI:
309582527734SSukumar Swaminathan 		case ELS_CMD_PRLI:
309682527734SSukumar Swaminathan 		default:
3097*a9800bebSGarrett D'Amore 			wqe->ContextTag = port->VPIobj.VPI;
309882527734SSukumar Swaminathan 			wqe->ContextType = WQE_VPI_CONTEXT;
309982527734SSukumar Swaminathan 			break;
310082527734SSukumar Swaminathan 		}
310182527734SSukumar Swaminathan 		wqe->un.ElsCmd.RemoteId = did;
310282527734SSukumar Swaminathan 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
310382527734SSukumar Swaminathan 	}
310482527734SSukumar Swaminathan 
3105b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
3106*a9800bebSGarrett D'Amore 	    xrip->SGList.virt) -
3107b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
3108b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
3109b3660a96SSukumar Swaminathan 
3110*a9800bebSGarrett D'Amore 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
3111*a9800bebSGarrett D'Amore 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
311282527734SSukumar Swaminathan 
311382527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
311482527734SSukumar Swaminathan 		wqe->CCPE = 1;
311582527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
311682527734SSukumar Swaminathan 	}
311782527734SSukumar Swaminathan 
311882527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
311982527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
312082527734SSukumar Swaminathan 		wqe->Class = CLASS2;
312182527734SSukumar Swaminathan 		break;
312282527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
312382527734SSukumar Swaminathan 	default:
312482527734SSukumar Swaminathan 		wqe->Class = CLASS3;
312582527734SSukumar Swaminathan 		break;
312682527734SSukumar Swaminathan 	}
312782527734SSukumar Swaminathan 	sbp->class = wqe->Class;
3128*a9800bebSGarrett D'Amore 	wqe->XRITag = xrip->XRI;
3129*a9800bebSGarrett D'Amore 	wqe->RequestTag = xrip->iotag;
313082527734SSukumar Swaminathan 	wqe->CQId = 0x3ff;
313182527734SSukumar Swaminathan 	return (FC_SUCCESS);
313282527734SSukumar Swaminathan 
313382527734SSukumar Swaminathan } /* emlxs_sli4_prep_els_iocb() */
313482527734SSukumar Swaminathan 
313582527734SSukumar Swaminathan 
313682527734SSukumar Swaminathan /*ARGSUSED*/
313782527734SSukumar Swaminathan static uint32_t
313882527734SSukumar Swaminathan emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
313982527734SSukumar Swaminathan {
314082527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
314182527734SSukumar Swaminathan 	fc_packet_t *pkt;
314282527734SSukumar Swaminathan 	IOCBQ *iocbq;
314382527734SSukumar Swaminathan 	IOCB *iocb;
314482527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
314582527734SSukumar Swaminathan 	NODELIST *node = NULL;
314682527734SSukumar Swaminathan 	CHANNEL *cp;
3147*a9800bebSGarrett D'Amore 	RPIobj_t *rpip;
3148*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
314982527734SSukumar Swaminathan 	uint32_t did;
3150b3660a96SSukumar Swaminathan 	off_t offset;
315182527734SSukumar Swaminathan 
315282527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
315382527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
315482527734SSukumar Swaminathan 
315582527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
315682527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
315782527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
315882527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
315982527734SSukumar Swaminathan 	bzero((void *)iocb, sizeof (IOCB));
316082527734SSukumar Swaminathan 
316182527734SSukumar Swaminathan 	cp = &hba->chan[hba->channel_ct];
316282527734SSukumar Swaminathan 
316382527734SSukumar Swaminathan 	iocbq->port = (void *) port;
316482527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
316582527734SSukumar Swaminathan 
316682527734SSukumar Swaminathan 	sbp->bmp = NULL;
316782527734SSukumar Swaminathan 	sbp->channel = cp;
316882527734SSukumar Swaminathan 
316982527734SSukumar Swaminathan 	/* Initalize wqe */
317082527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
317182527734SSukumar Swaminathan 		/* CT Response */
317282527734SSukumar Swaminathan 
3173*a9800bebSGarrett D'Amore 		xrip = emlxs_sli4_register_xri(hba, sbp,
3174*a9800bebSGarrett D'Amore 		    pkt->pkt_cmd_fhdr.rx_id);
317582527734SSukumar Swaminathan 
3176*a9800bebSGarrett D'Amore 		if (!xrip) {
317782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
317882527734SSukumar Swaminathan 			    "Unable to find XRI. rxid=%x",
317982527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
318082527734SSukumar Swaminathan 
318182527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
318282527734SSukumar Swaminathan 			    IOERR_NO_XRI, 0);
318382527734SSukumar Swaminathan 			return (0xff);
318482527734SSukumar Swaminathan 		}
318582527734SSukumar Swaminathan 
3186*a9800bebSGarrett D'Amore 		rpip = xrip->rpip;
318782527734SSukumar Swaminathan 
3188*a9800bebSGarrett D'Amore 		if (!rpip) {
318982527734SSukumar Swaminathan 			/* This means that we had a node registered */
319082527734SSukumar Swaminathan 			/* when the unsol request came in but the node */
319182527734SSukumar Swaminathan 			/* has since been unregistered. */
319282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
319382527734SSukumar Swaminathan 			    "Unable to find RPI. rxid=%x",
319482527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
319582527734SSukumar Swaminathan 
319682527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
319782527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
319882527734SSukumar Swaminathan 			return (0xff);
319982527734SSukumar Swaminathan 		}
320082527734SSukumar Swaminathan 
320182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3202*a9800bebSGarrett D'Amore 		    "Prep CT XRI: xri=%x iotag=%x oxid=%x", xrip->XRI,
3203*a9800bebSGarrett D'Amore 		    xrip->iotag, xrip->rx_id);
320482527734SSukumar Swaminathan 
320582527734SSukumar Swaminathan 		if (emlxs_sli4_bde_setup(port, sbp)) {
320682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
320782527734SSukumar Swaminathan 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
320882527734SSukumar Swaminathan 
320982527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
321082527734SSukumar Swaminathan 		}
321182527734SSukumar Swaminathan 
321282527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
321382527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_SEQUENCE64_CR;
321482527734SSukumar Swaminathan 		wqe->un.XmitSeq.la = 1;
321582527734SSukumar Swaminathan 
321682527734SSukumar Swaminathan 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
321782527734SSukumar Swaminathan 			wqe->un.XmitSeq.ls = 1;
321882527734SSukumar Swaminathan 		}
321982527734SSukumar Swaminathan 
322082527734SSukumar Swaminathan 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
322182527734SSukumar Swaminathan 			wqe->un.XmitSeq.si = 1;
322282527734SSukumar Swaminathan 		}
322382527734SSukumar Swaminathan 
322482527734SSukumar Swaminathan 		wqe->un.XmitSeq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
322582527734SSukumar Swaminathan 		wqe->un.XmitSeq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
322682527734SSukumar Swaminathan 		wqe->un.XmitSeq.Type  = pkt->pkt_cmd_fhdr.type;
3227*a9800bebSGarrett D'Amore 		wqe->OXId = xrip->rx_id;
322862379b58SSukumar Swaminathan 		wqe->XC = 0; /* xri_tag is a new exchange */
322982527734SSukumar Swaminathan 		wqe->CmdSpecific[0] = wqe->un.GenReq.Payload.tus.f.bdeSize;
323082527734SSukumar Swaminathan 
323182527734SSukumar Swaminathan 	} else {
323282527734SSukumar Swaminathan 		/* CT Request */
323382527734SSukumar Swaminathan 
323482527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
3235*a9800bebSGarrett D'Amore 		rpip = EMLXS_NODE_TO_RPI(port, node);
323682527734SSukumar Swaminathan 
3237*a9800bebSGarrett D'Amore 		if (!rpip) {
323882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3239*a9800bebSGarrett D'Amore 			    "Unable to find rpi. did=0x%x rpi=%x",
3240*a9800bebSGarrett D'Amore 			    did, node->nlp_Rpi);
324182527734SSukumar Swaminathan 
324282527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
324382527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
324482527734SSukumar Swaminathan 			return (0xff);
324582527734SSukumar Swaminathan 		}
324682527734SSukumar Swaminathan 
324782527734SSukumar Swaminathan 		/* Next allocate an Exchange for this command */
3248*a9800bebSGarrett D'Amore 		xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip);
324982527734SSukumar Swaminathan 
3250*a9800bebSGarrett D'Amore 		if (!xrip) {
325182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3252*a9800bebSGarrett D'Amore 			    "Adapter Busy. Unable to allocate exchange. "
325382527734SSukumar Swaminathan 			    "did=0x%x", did);
325482527734SSukumar Swaminathan 
325582527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
325682527734SSukumar Swaminathan 		}
325782527734SSukumar Swaminathan 
325882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3259*a9800bebSGarrett D'Amore 		    "Prep CT XRI: %x iotag %x", xrip->XRI, xrip->iotag);
326082527734SSukumar Swaminathan 
326182527734SSukumar Swaminathan 		if (emlxs_sli4_bde_setup(port, sbp)) {
326282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
326382527734SSukumar Swaminathan 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
326482527734SSukumar Swaminathan 
3265*a9800bebSGarrett D'Amore 			emlxs_sli4_free_xri(hba, sbp, xrip, 1);
326682527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
326782527734SSukumar Swaminathan 		}
326882527734SSukumar Swaminathan 
326982527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
327082527734SSukumar Swaminathan 		wqe->Command = CMD_GEN_REQUEST64_CR;
327182527734SSukumar Swaminathan 		wqe->un.GenReq.la = 1;
327282527734SSukumar Swaminathan 		wqe->un.GenReq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
327382527734SSukumar Swaminathan 		wqe->un.GenReq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
327482527734SSukumar Swaminathan 		wqe->un.GenReq.Type  = pkt->pkt_cmd_fhdr.type;
327582527734SSukumar Swaminathan 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
327682527734SSukumar Swaminathan 
327782527734SSukumar Swaminathan #ifdef DEBUG_CT
327882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3279*a9800bebSGarrett D'Amore 		    "SGLaddr virt %p phys %p", xrip->SGList.virt,
3280*a9800bebSGarrett D'Amore 		    xrip->SGList.phys);
3281*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt,
3282*a9800bebSGarrett D'Amore 		    12, 0);
328382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
328482527734SSukumar Swaminathan 		    "CMD virt %p len %d:%d",
328582527734SSukumar Swaminathan 		    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
3286*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "DATA", (uint32_t *)pkt->pkt_cmd, 20, 0);
328782527734SSukumar Swaminathan #endif /* DEBUG_CT */
328882527734SSukumar Swaminathan 	}
328982527734SSukumar Swaminathan 
329082527734SSukumar Swaminathan 	/* Setup for rsp */
329182527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
329282527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
329382527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
329482527734SSukumar Swaminathan 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
329582527734SSukumar Swaminathan 
3296b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
3297*a9800bebSGarrett D'Amore 	    xrip->SGList.virt) -
3298b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
3299b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
3300b3660a96SSukumar Swaminathan 
3301*a9800bebSGarrett D'Amore 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
3302*a9800bebSGarrett D'Amore 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
330382527734SSukumar Swaminathan 
3304*a9800bebSGarrett D'Amore 	wqe->ContextTag = rpip->RPI;
330582527734SSukumar Swaminathan 	wqe->ContextType = WQE_RPI_CONTEXT;
3306*a9800bebSGarrett D'Amore 	wqe->XRITag = xrip->XRI;
330782527734SSukumar Swaminathan 
330882527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
330982527734SSukumar Swaminathan 		wqe->CCPE = 1;
331082527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
331182527734SSukumar Swaminathan 	}
331282527734SSukumar Swaminathan 
331382527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
331482527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
331582527734SSukumar Swaminathan 		wqe->Class = CLASS2;
331682527734SSukumar Swaminathan 		break;
331782527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
331882527734SSukumar Swaminathan 	default:
331982527734SSukumar Swaminathan 		wqe->Class = CLASS3;
332082527734SSukumar Swaminathan 		break;
332182527734SSukumar Swaminathan 	}
332282527734SSukumar Swaminathan 	sbp->class = wqe->Class;
3323*a9800bebSGarrett D'Amore 	wqe->RequestTag = xrip->iotag;
332481a990d5SRichard Lowe 	wqe->CQId = 0x3ff;
332582527734SSukumar Swaminathan 	return (FC_SUCCESS);
332682527734SSukumar Swaminathan 
332782527734SSukumar Swaminathan } /* emlxs_sli4_prep_ct_iocb() */
332882527734SSukumar Swaminathan 
332982527734SSukumar Swaminathan 
333082527734SSukumar Swaminathan /*ARGSUSED*/
333182527734SSukumar Swaminathan static int
3332*a9800bebSGarrett D'Amore emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
333382527734SSukumar Swaminathan {
333482527734SSukumar Swaminathan 	uint32_t *ptr;
333582527734SSukumar Swaminathan 	EQE_u eqe;
333682527734SSukumar Swaminathan 	int rc = 0;
3337b3660a96SSukumar Swaminathan 	off_t offset;
333882527734SSukumar Swaminathan 
333982527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
334082527734SSukumar Swaminathan 	ptr = eq->addr.virt;
334182527734SSukumar Swaminathan 	ptr += eq->host_index;
334282527734SSukumar Swaminathan 
3343b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
3344b3660a96SSukumar Swaminathan 	    eq->addr.virt) -
3345b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
3346b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
3347b3660a96SSukumar Swaminathan 
3348b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
334982527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
335082527734SSukumar Swaminathan 
335182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
335282527734SSukumar Swaminathan 
3353*a9800bebSGarrett D'Amore 	eqe.word = *ptr;
3354*a9800bebSGarrett D'Amore 	eqe.word = BE_SWAP32(eqe.word);
335582527734SSukumar Swaminathan 
3356*a9800bebSGarrett D'Amore 	if (eqe.word & EQE_VALID) {
3357*a9800bebSGarrett D'Amore 		rc = 1;
335882527734SSukumar Swaminathan 	}
335982527734SSukumar Swaminathan 
336082527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
336182527734SSukumar Swaminathan 
336282527734SSukumar Swaminathan 	return (rc);
336382527734SSukumar Swaminathan 
3364*a9800bebSGarrett D'Amore } /* emlxs_sli4_read_eq */
336582527734SSukumar Swaminathan 
336682527734SSukumar Swaminathan 
336782527734SSukumar Swaminathan /*ARGSUSED*/
336882527734SSukumar Swaminathan static void
336982527734SSukumar Swaminathan emlxs_sli4_poll_intr(emlxs_hba_t *hba, uint32_t att_bit)
337082527734SSukumar Swaminathan {
337182527734SSukumar Swaminathan 	int rc = 0;
337282527734SSukumar Swaminathan 	int i;
337382527734SSukumar Swaminathan 	char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
337482527734SSukumar Swaminathan 	char arg2;
337582527734SSukumar Swaminathan 
337682527734SSukumar Swaminathan 	/*
337782527734SSukumar Swaminathan 	 * Poll the eqe to see if the valid bit is set or not
337882527734SSukumar Swaminathan 	 */
337982527734SSukumar Swaminathan 
338082527734SSukumar Swaminathan 	for (;;) {
338182527734SSukumar Swaminathan 		if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
338282527734SSukumar Swaminathan 			/* only poll eqe0 */
3383*a9800bebSGarrett D'Amore 			rc = emlxs_sli4_read_eq(hba,
338482527734SSukumar Swaminathan 			    &hba->sli.sli4.eq[0]);
338582527734SSukumar Swaminathan 			if (rc == 1) {
338682527734SSukumar Swaminathan 				(void) bcopy((char *)&arg[0],
338782527734SSukumar Swaminathan 				    (char *)&arg2, sizeof (char));
338882527734SSukumar Swaminathan 				break;
338982527734SSukumar Swaminathan 			}
339082527734SSukumar Swaminathan 		} else {
339182527734SSukumar Swaminathan 			/* poll every msi vector */
339282527734SSukumar Swaminathan 			for (i = 0; i < hba->intr_count; i++) {
3393*a9800bebSGarrett D'Amore 				rc = emlxs_sli4_read_eq(hba,
339482527734SSukumar Swaminathan 				    &hba->sli.sli4.eq[i]);
339582527734SSukumar Swaminathan 
339682527734SSukumar Swaminathan 				if (rc == 1) {
339782527734SSukumar Swaminathan 					break;
339882527734SSukumar Swaminathan 				}
339982527734SSukumar Swaminathan 			}
340082527734SSukumar Swaminathan 			if ((i != hba->intr_count) && (rc == 1)) {
340182527734SSukumar Swaminathan 				(void) bcopy((char *)&arg[i],
340282527734SSukumar Swaminathan 				    (char *)&arg2, sizeof (char));
340382527734SSukumar Swaminathan 				break;
340482527734SSukumar Swaminathan 			}
340582527734SSukumar Swaminathan 		}
340682527734SSukumar Swaminathan 	}
340782527734SSukumar Swaminathan 
340882527734SSukumar Swaminathan 	/* process it here */
340982527734SSukumar Swaminathan 	rc = emlxs_sli4_msi_intr((char *)hba, (char *)&arg2);
341082527734SSukumar Swaminathan 
341182527734SSukumar Swaminathan 	return;
341282527734SSukumar Swaminathan 
341382527734SSukumar Swaminathan } /* emlxs_sli4_poll_intr() */
341482527734SSukumar Swaminathan 
341582527734SSukumar Swaminathan 
341682527734SSukumar Swaminathan /*ARGSUSED*/
341782527734SSukumar Swaminathan static void
341882527734SSukumar Swaminathan emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
341982527734SSukumar Swaminathan {
342082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
342182527734SSukumar Swaminathan 
3422*a9800bebSGarrett D'Amore 	/* Save the event tag */
3423*a9800bebSGarrett D'Amore 	hba->link_event_tag = cqe->un.link.event_tag;
342482527734SSukumar Swaminathan 
342582527734SSukumar Swaminathan 	switch (cqe->event_code) {
342682527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_LINK_STATE:
3427*a9800bebSGarrett D'Amore 		switch (cqe->un.link.link_status) {
342882527734SSukumar Swaminathan 		case ASYNC_EVENT_PHYS_LINK_UP:
342982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3430*a9800bebSGarrett D'Amore 			    "Link Async Event: PHYS_LINK_UP. val=%d type=%x",
3431*a9800bebSGarrett D'Amore 			    cqe->valid, cqe->event_type);
343282527734SSukumar Swaminathan 			break;
343382527734SSukumar Swaminathan 
343482527734SSukumar Swaminathan 		case ASYNC_EVENT_PHYS_LINK_DOWN:
343582527734SSukumar Swaminathan 		case ASYNC_EVENT_LOGICAL_LINK_DOWN:
3436*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3437*a9800bebSGarrett D'Amore 			    "Link Async Event: LINK_DOWN. val=%d type=%x",
3438*a9800bebSGarrett D'Amore 			    cqe->valid, cqe->event_type);
3439*a9800bebSGarrett D'Amore 
3440*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_linkdown_notify(port);
3441*a9800bebSGarrett D'Amore 
3442*a9800bebSGarrett D'Amore 			mutex_enter(&EMLXS_PORT_LOCK);
3443*a9800bebSGarrett D'Amore 			hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
3444*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_PORT_LOCK);
344582527734SSukumar Swaminathan 			break;
344682527734SSukumar Swaminathan 
344782527734SSukumar Swaminathan 		case ASYNC_EVENT_LOGICAL_LINK_UP:
3448*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3449*a9800bebSGarrett D'Amore 			    "Link Async Event: LOGICAL_LINK_UP. val=%d type=%x",
3450*a9800bebSGarrett D'Amore 			    cqe->valid, cqe->event_type);
345182527734SSukumar Swaminathan 
3452*a9800bebSGarrett D'Amore 			if (cqe->un.link.port_speed == PHY_1GHZ_LINK) {
3453*a9800bebSGarrett D'Amore 				hba->linkspeed = LA_1GHZ_LINK;
3454*a9800bebSGarrett D'Amore 			} else {
3455*a9800bebSGarrett D'Amore 				hba->linkspeed = LA_10GHZ_LINK;
345682527734SSukumar Swaminathan 			}
3457*a9800bebSGarrett D'Amore 			hba->topology = TOPOLOGY_PT_PT;
3458*a9800bebSGarrett D'Amore 			hba->qos_linkspeed = cqe->un.link.qos_link_speed;
3459*a9800bebSGarrett D'Amore 
3460*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_linkup_notify(port);
346182527734SSukumar Swaminathan 			break;
346282527734SSukumar Swaminathan 		}
346382527734SSukumar Swaminathan 		break;
346482527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_FCOE_FIP:
3465*a9800bebSGarrett D'Amore 		switch (cqe->un.fcoe.evt_type) {
346682527734SSukumar Swaminathan 		case ASYNC_EVENT_NEW_FCF_DISC:
346782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3468*a9800bebSGarrett D'Amore 			    "FCOE Async Event: FCF_FOUND %d:%d",
3469*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
3470*a9800bebSGarrett D'Amore 
3471*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_found_notify(port,
3472*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
347382527734SSukumar Swaminathan 			break;
347482527734SSukumar Swaminathan 		case ASYNC_EVENT_FCF_TABLE_FULL:
3475*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3476*a9800bebSGarrett D'Amore 			    "FCOE Async Event: FCFTAB_FULL %d:%d",
3477*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
3478*a9800bebSGarrett D'Amore 
3479*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_full_notify(port);
348082527734SSukumar Swaminathan 			break;
348182527734SSukumar Swaminathan 		case ASYNC_EVENT_FCF_DEAD:
348282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3483*a9800bebSGarrett D'Amore 			    "FCOE Async Event: FCF_LOST %d:%d",
3484*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
3485*a9800bebSGarrett D'Amore 
3486*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_lost_notify(port,
3487*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
348882527734SSukumar Swaminathan 			break;
348982527734SSukumar Swaminathan 		case ASYNC_EVENT_VIRT_LINK_CLEAR:
349082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3491*a9800bebSGarrett D'Amore 			    "FCOE Async Event: CVL %d",
3492*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
3493*a9800bebSGarrett D'Amore 
3494*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_cvl_notify(port,
3495*a9800bebSGarrett D'Amore 			    (cqe->un.fcoe.ref_index - hba->vpi_base));
3496*a9800bebSGarrett D'Amore 			break;
3497*a9800bebSGarrett D'Amore 
3498*a9800bebSGarrett D'Amore 		case ASYNC_EVENT_FCF_MODIFIED:
3499*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3500*a9800bebSGarrett D'Amore 			    "FCOE Async Event: FCF_CHANGED %d",
3501*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
3502*a9800bebSGarrett D'Amore 
3503*a9800bebSGarrett D'Amore 			(void) emlxs_fcf_changed_notify(port,
3504*a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
350582527734SSukumar Swaminathan 			break;
350682527734SSukumar Swaminathan 		}
350782527734SSukumar Swaminathan 		break;
350882527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_DCBX:
350982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3510*a9800bebSGarrett D'Amore 		    "DCBX Async Event Code %d: Not supported",
351182527734SSukumar Swaminathan 		    cqe->event_code);
351282527734SSukumar Swaminathan 		break;
3513*a9800bebSGarrett D'Amore 	case ASYNC_EVENT_CODE_GRP_5:
3514*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3515*a9800bebSGarrett D'Amore 		    "Group 5 Async Event type %d", cqe->event_type);
3516*a9800bebSGarrett D'Amore 		if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) {
3517*a9800bebSGarrett D'Amore 			hba->qos_linkspeed = cqe->un.qos.qos_link_speed;
3518*a9800bebSGarrett D'Amore 		}
3519*a9800bebSGarrett D'Amore 		break;
352082527734SSukumar Swaminathan 	default:
352182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
352282527734SSukumar Swaminathan 		    "Unknown Async Event Code %d", cqe->event_code);
352382527734SSukumar Swaminathan 		break;
352482527734SSukumar Swaminathan 	}
352582527734SSukumar Swaminathan 
352682527734SSukumar Swaminathan } /* emlxs_sli4_process_async_event() */
352782527734SSukumar Swaminathan 
352882527734SSukumar Swaminathan 
352982527734SSukumar Swaminathan /*ARGSUSED*/
353082527734SSukumar Swaminathan static void
353182527734SSukumar Swaminathan emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe)
353282527734SSukumar Swaminathan {
353382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
353482527734SSukumar Swaminathan 	MAILBOX4 *mb;
353582527734SSukumar Swaminathan 	MATCHMAP *mbox_bp;
353682527734SSukumar Swaminathan 	MATCHMAP *mbox_nonembed;
3537*a9800bebSGarrett D'Amore 	MAILBOXQ *mbq = NULL;
353882527734SSukumar Swaminathan 	uint32_t size;
353982527734SSukumar Swaminathan 	uint32_t *iptr;
354082527734SSukumar Swaminathan 	int rc;
3541b3660a96SSukumar Swaminathan 	off_t offset;
354282527734SSukumar Swaminathan 
354382527734SSukumar Swaminathan 	if (cqe->consumed && !cqe->completed) {
354482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3545*a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. Entry consumed but not completed");
354682527734SSukumar Swaminathan 		return;
354782527734SSukumar Swaminathan 	}
354882527734SSukumar Swaminathan 
3549*a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_PORT_LOCK);
355082527734SSukumar Swaminathan 	switch (hba->mbox_queue_flag) {
355182527734SSukumar Swaminathan 	case 0:
355282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
3553*a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. No mailbox active.");
3554*a9800bebSGarrett D'Amore 
3555*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
355682527734SSukumar Swaminathan 		return;
355782527734SSukumar Swaminathan 
355882527734SSukumar Swaminathan 	case MBX_POLL:
355982527734SSukumar Swaminathan 
356082527734SSukumar Swaminathan 		/* Mark mailbox complete, this should wake up any polling */
356182527734SSukumar Swaminathan 		/* threads. This can happen if interrupts are enabled while */
356282527734SSukumar Swaminathan 		/* a polled mailbox command is outstanding. If we don't set */
356382527734SSukumar Swaminathan 		/* MBQ_COMPLETED here, the polling thread may wait until */
356482527734SSukumar Swaminathan 		/* timeout error occurs */
356582527734SSukumar Swaminathan 
356682527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
356782527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
356882527734SSukumar Swaminathan 		if (mbq) {
3569*a9800bebSGarrett D'Amore 			port = (emlxs_port_t *)mbq->port;
357082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3571*a9800bebSGarrett D'Amore 			    "CQ ENTRY: Mbox event. Completing Polled command.");
357282527734SSukumar Swaminathan 			mbq->flag |= MBQ_COMPLETED;
357382527734SSukumar Swaminathan 		}
357482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
357582527734SSukumar Swaminathan 
3576*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
357782527734SSukumar Swaminathan 		return;
357882527734SSukumar Swaminathan 
357982527734SSukumar Swaminathan 	case MBX_SLEEP:
358082527734SSukumar Swaminathan 	case MBX_NOWAIT:
3581*a9800bebSGarrett D'Amore 		/* Check mbox_timer, it acts as a service flag too */
3582*a9800bebSGarrett D'Amore 		/* The first to service the mbox queue will clear the timer */
3583*a9800bebSGarrett D'Amore 		if (hba->mbox_timer) {
3584*a9800bebSGarrett D'Amore 			hba->mbox_timer = 0;
3585*a9800bebSGarrett D'Amore 
3586*a9800bebSGarrett D'Amore 			mutex_enter(&EMLXS_MBOX_LOCK);
3587*a9800bebSGarrett D'Amore 			mbq = (MAILBOXQ *)hba->mbox_mbq;
3588*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_MBOX_LOCK);
3589*a9800bebSGarrett D'Amore 		}
3590*a9800bebSGarrett D'Amore 
3591*a9800bebSGarrett D'Amore 		if (!mbq) {
3592*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3593*a9800bebSGarrett D'Amore 			    "Mailbox event. No service required.");
3594*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_PORT_LOCK);
3595*a9800bebSGarrett D'Amore 			return;
3596*a9800bebSGarrett D'Amore 		}
3597*a9800bebSGarrett D'Amore 
359882527734SSukumar Swaminathan 		mb = (MAILBOX4 *)mbq;
3599*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
360082527734SSukumar Swaminathan 		break;
360182527734SSukumar Swaminathan 
360282527734SSukumar Swaminathan 	default:
360382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
3604*a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).",
3605*a9800bebSGarrett D'Amore 		    hba->mbox_queue_flag);
3606*a9800bebSGarrett D'Amore 
3607*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
360882527734SSukumar Swaminathan 		return;
360982527734SSukumar Swaminathan 	}
361082527734SSukumar Swaminathan 
3611*a9800bebSGarrett D'Amore 	/* Set port context */
3612*a9800bebSGarrett D'Amore 	port = (emlxs_port_t *)mbq->port;
3613*a9800bebSGarrett D'Amore 
3614b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
3615b3660a96SSukumar Swaminathan 	    hba->sli.sli4.mq.addr.virt) -
3616b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
3617b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
3618b3660a96SSukumar Swaminathan 
361982527734SSukumar Swaminathan 	/* Now that we are the owner, DMA Sync entire MQ if needed */
3620b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
362182527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORDEV);
362282527734SSukumar Swaminathan 
362382527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb,
362482527734SSukumar Swaminathan 	    MAILBOX_CMD_SLI4_BSIZE);
362582527734SSukumar Swaminathan 
3626*a9800bebSGarrett D'Amore 	if (mb->mbxCommand != MBX_HEARTBEAT) {
3627*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3628*a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x",
3629*a9800bebSGarrett D'Amore 		    mb->mbxStatus, mb->mbxCommand);
3630*a9800bebSGarrett D'Amore 
3631*a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe,
3632*a9800bebSGarrett D'Amore 		    12, 0);
3633*a9800bebSGarrett D'Amore 	}
363482527734SSukumar Swaminathan 
363582527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_SLI_CONFIG) {
363682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
363782527734SSukumar Swaminathan 		    "Mbox sge_cnt: %d length: %d embed: %d",
363882527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.sge_cnt,
363982527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.payload_length,
364082527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.embedded);
364182527734SSukumar Swaminathan 	}
364282527734SSukumar Swaminathan 
364382527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
364482527734SSukumar Swaminathan 	if (mbq->bp) {
364582527734SSukumar Swaminathan 		mbox_bp = (MATCHMAP *)mbq->bp;
364682527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
364782527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
3648b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3649b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle)
3650b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3651b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3652b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3653b3660a96SSukumar Swaminathan 			    "emlxs_sli4_process_mbox_event: hdl=%p",
3654b3660a96SSukumar Swaminathan 			    mbox_bp->dma_handle);
3655b3660a96SSukumar Swaminathan 
3656b3660a96SSukumar Swaminathan 			mb->mbxStatus = MBXERR_DMA_ERROR;
3657b3660a96SSukumar Swaminathan }
3658b3660a96SSukumar Swaminathan #endif
365982527734SSukumar Swaminathan 	}
366082527734SSukumar Swaminathan 
366182527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
366282527734SSukumar Swaminathan 	if (mbq->nonembed) {
366382527734SSukumar Swaminathan 		mbox_nonembed = (MATCHMAP *)mbq->nonembed;
366482527734SSukumar Swaminathan 		size = mbox_nonembed->size;
366582527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size,
366682527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
366782527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt);
366882527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size);
366982527734SSukumar Swaminathan 
3670b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3671b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
3672b3660a96SSukumar Swaminathan 		    mbox_nonembed->dma_handle) != DDI_FM_OK) {
3673b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3674b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3675b3660a96SSukumar Swaminathan 			    "emlxs_sli4_process_mbox_event: hdl=%p",
3676b3660a96SSukumar Swaminathan 			    mbox_nonembed->dma_handle);
3677b3660a96SSukumar Swaminathan 
3678b3660a96SSukumar Swaminathan 			mb->mbxStatus = MBXERR_DMA_ERROR;
3679b3660a96SSukumar Swaminathan 		}
3680b3660a96SSukumar Swaminathan #endif
3681*a9800bebSGarrett D'Amore emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
368282527734SSukumar Swaminathan 	}
368382527734SSukumar Swaminathan 
368482527734SSukumar Swaminathan 	/* Mailbox has been completely received at this point */
368582527734SSukumar Swaminathan 
368682527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_HEARTBEAT) {
368782527734SSukumar Swaminathan 		hba->heartbeat_active = 0;
368882527734SSukumar Swaminathan 		goto done;
368982527734SSukumar Swaminathan 	}
369082527734SSukumar Swaminathan 
369182527734SSukumar Swaminathan 	if (hba->mbox_queue_flag == MBX_SLEEP) {
369282527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
369382527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
369482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
369582527734SSukumar Swaminathan 			    "Received.  %s: status=%x Sleep.",
369682527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
369782527734SSukumar Swaminathan 			    mb->mbxStatus);
369882527734SSukumar Swaminathan 		}
369982527734SSukumar Swaminathan 	} else {
370082527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
370182527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
370282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
370382527734SSukumar Swaminathan 			    "Completed. %s: status=%x",
370482527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
370582527734SSukumar Swaminathan 			    mb->mbxStatus);
370682527734SSukumar Swaminathan 		}
370782527734SSukumar Swaminathan 	}
370882527734SSukumar Swaminathan 
370982527734SSukumar Swaminathan 	/* Filter out passthru mailbox */
371082527734SSukumar Swaminathan 	if (mbq->flag & MBQ_PASSTHRU) {
371182527734SSukumar Swaminathan 		goto done;
371282527734SSukumar Swaminathan 	}
371382527734SSukumar Swaminathan 
371482527734SSukumar Swaminathan 	if (mb->mbxStatus) {
371582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
371682527734SSukumar Swaminathan 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
371782527734SSukumar Swaminathan 		    (uint32_t)mb->mbxStatus);
371882527734SSukumar Swaminathan 	}
371982527734SSukumar Swaminathan 
372082527734SSukumar Swaminathan 	if (mbq->mbox_cmpl) {
372182527734SSukumar Swaminathan 		rc = (mbq->mbox_cmpl)(hba, mbq);
372282527734SSukumar Swaminathan 
372382527734SSukumar Swaminathan 		/* If mbox was retried, return immediately */
372482527734SSukumar Swaminathan 		if (rc) {
372582527734SSukumar Swaminathan 			return;
372682527734SSukumar Swaminathan 		}
372782527734SSukumar Swaminathan 	}
372882527734SSukumar Swaminathan 
372982527734SSukumar Swaminathan done:
373082527734SSukumar Swaminathan 
373182527734SSukumar Swaminathan 	/* Clean up the mailbox area */
373282527734SSukumar Swaminathan 	emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus);
373382527734SSukumar Swaminathan 
373482527734SSukumar Swaminathan 	/* Attempt to send pending mailboxes */
373582527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
373682527734SSukumar Swaminathan 	if (mbq) {
373782527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
373882527734SSukumar Swaminathan 		rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
373982527734SSukumar Swaminathan 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
3740*a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
374182527734SSukumar Swaminathan 		}
374282527734SSukumar Swaminathan 	}
374382527734SSukumar Swaminathan 	return;
374482527734SSukumar Swaminathan 
374582527734SSukumar Swaminathan } /* emlxs_sli4_process_mbox_event() */
374682527734SSukumar Swaminathan 
374782527734SSukumar Swaminathan 
3748bce54adfSSukumar Swaminathan /*ARGSUSED*/
374982527734SSukumar Swaminathan static void
375082527734SSukumar Swaminathan emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp)
375182527734SSukumar Swaminathan {
3752bce54adfSSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
375382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3754bce54adfSSukumar Swaminathan #endif
375582527734SSukumar Swaminathan 	IOCBQ *iocbq;
375682527734SSukumar Swaminathan 	IOCB *iocb;
3757*a9800bebSGarrett D'Amore 	uint32_t *iptr;
3758*a9800bebSGarrett D'Amore 	fc_packet_t *pkt;
375982527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
376082527734SSukumar Swaminathan 
376182527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
376282527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
376382527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
376482527734SSukumar Swaminathan 
376582527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
376682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
376782527734SSukumar Swaminathan 	    "CQE to IOCB: cmd:x%x tag:x%x xri:x%x", wqe->Command,
376882527734SSukumar Swaminathan 	    wqe->RequestTag, wqe->XRITag);
376982527734SSukumar Swaminathan #endif
377082527734SSukumar Swaminathan 
377182527734SSukumar Swaminathan 	iocb->ULPSTATUS = cqe->Status;
377282527734SSukumar Swaminathan 	iocb->un.ulpWord[4] = cqe->Parameter;
377382527734SSukumar Swaminathan 	iocb->ULPIOTAG = cqe->RequestTag;
377482527734SSukumar Swaminathan 	iocb->ULPCONTEXT = wqe->XRITag;
377582527734SSukumar Swaminathan 
377682527734SSukumar Swaminathan 	switch (wqe->Command) {
377782527734SSukumar Swaminathan 
377882527734SSukumar Swaminathan 	case CMD_FCP_ICMND64_CR:
377982527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX;
378082527734SSukumar Swaminathan 		break;
378182527734SSukumar Swaminathan 
378282527734SSukumar Swaminathan 	case CMD_FCP_IREAD64_CR:
378382527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX;
378482527734SSukumar Swaminathan 		iocb->ULPPU = PARM_READ_CHECK;
378582527734SSukumar Swaminathan 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
378682527734SSukumar Swaminathan 			iocb->un.fcpi64.fcpi_parm =
378782527734SSukumar Swaminathan 			    wqe->un.FcpCmd.TotalTransferCount -
378882527734SSukumar Swaminathan 			    cqe->CmdSpecific;
378982527734SSukumar Swaminathan 		}
379082527734SSukumar Swaminathan 		break;
379182527734SSukumar Swaminathan 
379282527734SSukumar Swaminathan 	case CMD_FCP_IWRITE64_CR:
379382527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX;
379482527734SSukumar Swaminathan 		break;
379582527734SSukumar Swaminathan 
379682527734SSukumar Swaminathan 	case CMD_ELS_REQUEST64_CR:
379782527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX;
379882527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific;
379982527734SSukumar Swaminathan 		if (iocb->ULPSTATUS == 0) {
380082527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
380182527734SSukumar Swaminathan 		}
3802*a9800bebSGarrett D'Amore 		if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
3803*a9800bebSGarrett D'Amore 			/* For LS_RJT, the driver populates the rsp buffer */
3804*a9800bebSGarrett D'Amore 			pkt = PRIV2PKT(sbp);
3805*a9800bebSGarrett D'Amore 			iptr = (uint32_t *)pkt->pkt_resp;
3806*a9800bebSGarrett D'Amore 			*iptr++ = ELS_CMD_LS_RJT;
3807*a9800bebSGarrett D'Amore 			*iptr = cqe->Parameter;
3808*a9800bebSGarrett D'Amore 		}
380982527734SSukumar Swaminathan 		break;
381082527734SSukumar Swaminathan 
381182527734SSukumar Swaminathan 	case CMD_GEN_REQUEST64_CR:
381282527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
381382527734SSukumar Swaminathan 		iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
381482527734SSukumar Swaminathan 		break;
381582527734SSukumar Swaminathan 
381682527734SSukumar Swaminathan 	case CMD_XMIT_SEQUENCE64_CR:
381782527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
381882527734SSukumar Swaminathan 		break;
381982527734SSukumar Swaminathan 
382082527734SSukumar Swaminathan 	default:
382182527734SSukumar Swaminathan 		iocb->ULPCOMMAND = wqe->Command;
382282527734SSukumar Swaminathan 
382382527734SSukumar Swaminathan 	}
382482527734SSukumar Swaminathan 
382582527734SSukumar Swaminathan } /* emlxs_CQE_to_IOCB() */
382682527734SSukumar Swaminathan 
382782527734SSukumar Swaminathan 
382882527734SSukumar Swaminathan /*ARGSUSED*/
382982527734SSukumar Swaminathan static void
383082527734SSukumar Swaminathan emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba)
383182527734SSukumar Swaminathan {
3832bce54adfSSukumar Swaminathan #ifdef SFCT_SUPPORT
3833bce54adfSSukumar Swaminathan #ifdef FCT_IO_TRACE
3834bce54adfSSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3835bce54adfSSukumar Swaminathan #endif /* FCT_IO_TRACE */
3836bce54adfSSukumar Swaminathan #endif /* SFCT_SUPPORT */
383782527734SSukumar Swaminathan 	CHANNEL *cp;
383882527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
383982527734SSukumar Swaminathan 	IOCBQ *iocbq;
3840*a9800bebSGarrett D'Amore 	uint16_t i;
384182527734SSukumar Swaminathan 	uint32_t trigger;
384282527734SSukumar Swaminathan 	CQE_CmplWQ_t cqe;
384382527734SSukumar Swaminathan 
384482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
384582527734SSukumar Swaminathan 	for (i = 0; i < hba->max_iotag; i++) {
384682527734SSukumar Swaminathan 		sbp = hba->fc_table[i];
384782527734SSukumar Swaminathan 		if (sbp == NULL || sbp == STALE_PACKET) {
384882527734SSukumar Swaminathan 			continue;
384982527734SSukumar Swaminathan 		}
3850*a9800bebSGarrett D'Amore 		hba->fc_table[i] = STALE_PACKET;
385182527734SSukumar Swaminathan 		hba->io_count--;
3852*a9800bebSGarrett D'Amore 		sbp->iotag = 0;
385382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
385482527734SSukumar Swaminathan 
385582527734SSukumar Swaminathan 		cp = sbp->channel;
385682527734SSukumar Swaminathan 		bzero(&cqe, sizeof (CQE_CmplWQ_t));
385782527734SSukumar Swaminathan 		cqe.RequestTag = i;
385882527734SSukumar Swaminathan 		cqe.Status = IOSTAT_LOCAL_REJECT;
385982527734SSukumar Swaminathan 		cqe.Parameter = IOERR_SEQUENCE_TIMEOUT;
386082527734SSukumar Swaminathan 
386182527734SSukumar Swaminathan 		cp->hbaCmplCmd_sbp++;
386282527734SSukumar Swaminathan 
386382527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
386482527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
386582527734SSukumar Swaminathan 		if (sbp->fct_cmd) {
386682527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
386782527734SSukumar Swaminathan 			    EMLXS_FCT_IOCB_COMPLETE);
386882527734SSukumar Swaminathan 		}
386982527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
387082527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
387182527734SSukumar Swaminathan 
387282527734SSukumar Swaminathan 		atomic_add_32(&hba->io_active, -1);
387382527734SSukumar Swaminathan 
387482527734SSukumar Swaminathan 		/* Copy entry to sbp's iocbq */
387582527734SSukumar Swaminathan 		iocbq = &sbp->iocbq;
387682527734SSukumar Swaminathan 		emlxs_CQE_to_IOCB(hba, &cqe, sbp);
387782527734SSukumar Swaminathan 
387882527734SSukumar Swaminathan 		iocbq->next = NULL;
387982527734SSukumar Swaminathan 
388082527734SSukumar Swaminathan 		/* Exchange is no longer busy on-chip, free it */
3881*a9800bebSGarrett D'Amore 		emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1);
388282527734SSukumar Swaminathan 
388382527734SSukumar Swaminathan 		if (!(sbp->pkt_flags &
388482527734SSukumar Swaminathan 		    (PACKET_POLLED | PACKET_ALLOCATED))) {
388582527734SSukumar Swaminathan 			/* Add the IOCB to the channel list */
388682527734SSukumar Swaminathan 			mutex_enter(&cp->rsp_lock);
388782527734SSukumar Swaminathan 			if (cp->rsp_head == NULL) {
388882527734SSukumar Swaminathan 				cp->rsp_head = iocbq;
388982527734SSukumar Swaminathan 				cp->rsp_tail = iocbq;
389082527734SSukumar Swaminathan 			} else {
389182527734SSukumar Swaminathan 				cp->rsp_tail->next = iocbq;
389282527734SSukumar Swaminathan 				cp->rsp_tail = iocbq;
389382527734SSukumar Swaminathan 			}
389482527734SSukumar Swaminathan 			mutex_exit(&cp->rsp_lock);
389582527734SSukumar Swaminathan 			trigger = 1;
389682527734SSukumar Swaminathan 		} else {
389782527734SSukumar Swaminathan 			emlxs_proc_channel_event(hba, cp, iocbq);
389882527734SSukumar Swaminathan 		}
389982527734SSukumar Swaminathan 		mutex_enter(&EMLXS_FCTAB_LOCK);
390082527734SSukumar Swaminathan 	}
390182527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
390282527734SSukumar Swaminathan 
390382527734SSukumar Swaminathan 	if (trigger) {
390482527734SSukumar Swaminathan 		for (i = 0; i < hba->chan_count; i++) {
390582527734SSukumar Swaminathan 			cp = &hba->chan[i];
390682527734SSukumar Swaminathan 			if (cp->rsp_head != NULL) {
390782527734SSukumar Swaminathan 				emlxs_thread_trigger2(&cp->intr_thread,
390882527734SSukumar Swaminathan 				    emlxs_proc_channel, cp);
390982527734SSukumar Swaminathan 			}
391082527734SSukumar Swaminathan 		}
391182527734SSukumar Swaminathan 	}
391282527734SSukumar Swaminathan 
391382527734SSukumar Swaminathan } /* emlxs_sli4_hba_flush_chipq() */
391482527734SSukumar Swaminathan 
391582527734SSukumar Swaminathan 
391682527734SSukumar Swaminathan /*ARGSUSED*/
391782527734SSukumar Swaminathan static void
391882527734SSukumar Swaminathan emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba,
391982527734SSukumar Swaminathan     CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
392082527734SSukumar Swaminathan {
392182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
392282527734SSukumar Swaminathan 	CHANNEL *cp;
392382527734SSukumar Swaminathan 	uint16_t request_tag;
3924*a9800bebSGarrett D'Amore 	CQE_u	*cq_entry;
392582527734SSukumar Swaminathan 
392682527734SSukumar Swaminathan 	request_tag = cqe->RequestTag;
392782527734SSukumar Swaminathan 
3928*a9800bebSGarrett D'Amore 	cq_entry = (CQE_u *)cqe;
3929*a9800bebSGarrett D'Amore 
393082527734SSukumar Swaminathan 	/* 1 to 1 mapping between CQ and channel */
393182527734SSukumar Swaminathan 	cp = cq->channelp;
393282527734SSukumar Swaminathan 
393382527734SSukumar Swaminathan 	cp->hbaCmplCmd++;
393482527734SSukumar Swaminathan 
393582527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
393682527734SSukumar Swaminathan 	    "CQ ENTRY: OOR Cmpl: tag=%x", request_tag);
393782527734SSukumar Swaminathan 
3938*a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3939*a9800bebSGarrett D'Amore 	    "CQ ENTRY: %08x %08x %08x %08x", cq_entry->word[0],
3940*a9800bebSGarrett D'Amore 	    cq_entry->word[1], cq_entry->word[2], cq_entry->word[3]);
3941*a9800bebSGarrett D'Amore 
394282527734SSukumar Swaminathan } /* emlxs_sli4_process_oor_wqe_cmpl() */
394382527734SSukumar Swaminathan 
394482527734SSukumar Swaminathan 
394582527734SSukumar Swaminathan /*ARGSUSED*/
394682527734SSukumar Swaminathan static void
394782527734SSukumar Swaminathan emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
394882527734SSukumar Swaminathan {
394982527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
395082527734SSukumar Swaminathan 	CHANNEL *cp;
395182527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
395282527734SSukumar Swaminathan 	IOCBQ *iocbq;
395382527734SSukumar Swaminathan 	uint16_t request_tag;
395482527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
395582527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd;
395682527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
395782527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
395882527734SSukumar Swaminathan 
395982527734SSukumar Swaminathan 	request_tag = cqe->RequestTag;
396082527734SSukumar Swaminathan 
396182527734SSukumar Swaminathan 	/* 1 to 1 mapping between CQ and channel */
396282527734SSukumar Swaminathan 	cp = cq->channelp;
396382527734SSukumar Swaminathan 
3964*a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_FCTAB_LOCK);
396582527734SSukumar Swaminathan 	sbp = hba->fc_table[request_tag];
396682527734SSukumar Swaminathan 	atomic_add_32(&hba->io_active, -1);
396782527734SSukumar Swaminathan 
396882527734SSukumar Swaminathan 	if (sbp == STALE_PACKET) {
396982527734SSukumar Swaminathan 		cp->hbaCmplCmd_sbp++;
3970*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
397182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
397282527734SSukumar Swaminathan 		    "CQ ENTRY: Stale sbp. tag=%x. Dropping...", request_tag);
397382527734SSukumar Swaminathan 		return;
397482527734SSukumar Swaminathan 	}
397582527734SSukumar Swaminathan 
3976*a9800bebSGarrett D'Amore 	if (!sbp || !(sbp->xrip)) {
397782527734SSukumar Swaminathan 		cp->hbaCmplCmd++;
3978*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
397982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
398082527734SSukumar Swaminathan 		    "CQ ENTRY: NULL sbp %p. tag=%x. Dropping...",
398182527734SSukumar Swaminathan 		    sbp, request_tag);
398282527734SSukumar Swaminathan 		return;
398382527734SSukumar Swaminathan 	}
398482527734SSukumar Swaminathan 
398582527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
398682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
398782527734SSukumar Swaminathan 	    "CQ ENTRY: process wqe compl");
398882527734SSukumar Swaminathan #endif
398982527734SSukumar Swaminathan 
399082527734SSukumar Swaminathan 	cp->hbaCmplCmd_sbp++;
399182527734SSukumar Swaminathan 
399282527734SSukumar Swaminathan 	/* Copy entry to sbp's iocbq */
399382527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
399482527734SSukumar Swaminathan 	emlxs_CQE_to_IOCB(hba, cqe, sbp);
399582527734SSukumar Swaminathan 
399682527734SSukumar Swaminathan 	iocbq->next = NULL;
399782527734SSukumar Swaminathan 
399882527734SSukumar Swaminathan 	if (cqe->XB) {
399982527734SSukumar Swaminathan 		/* Mark exchange as ABORT in progress */
4000*a9800bebSGarrett D'Amore 		sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO;
4001*a9800bebSGarrett D'Amore 		sbp->xrip->flag |= EMLXS_XRI_ABORT_INP;
400282527734SSukumar Swaminathan 
400382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
400482527734SSukumar Swaminathan 		    "CQ ENTRY: ABORT INP: tag=%x xri=%x", request_tag,
4005*a9800bebSGarrett D'Amore 		    sbp->xrip->XRI);
400682527734SSukumar Swaminathan 
4007*a9800bebSGarrett D'Amore 		emlxs_sli4_free_xri(hba, sbp, 0, 0);
400882527734SSukumar Swaminathan 	} else {
400982527734SSukumar Swaminathan 		/* Exchange is no longer busy on-chip, free it */
4010*a9800bebSGarrett D'Amore 		emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 0);
4011*a9800bebSGarrett D'Amore 	}
4012*a9800bebSGarrett D'Amore 
4013*a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_FCTAB_LOCK);
4014*a9800bebSGarrett D'Amore 
4015*a9800bebSGarrett D'Amore #ifdef SFCT_SUPPORT
4016*a9800bebSGarrett D'Amore 	fct_cmd = sbp->fct_cmd;
4017*a9800bebSGarrett D'Amore 	if (fct_cmd) {
4018*a9800bebSGarrett D'Amore 		cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4019*a9800bebSGarrett D'Amore 		mutex_enter(&cmd_sbp->fct_mtx);
4020*a9800bebSGarrett D'Amore 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE);
4021*a9800bebSGarrett D'Amore 		mutex_exit(&cmd_sbp->fct_mtx);
402282527734SSukumar Swaminathan 	}
4023*a9800bebSGarrett D'Amore #endif /* SFCT_SUPPORT */
402482527734SSukumar Swaminathan 
402582527734SSukumar Swaminathan 	/*
402682527734SSukumar Swaminathan 	 * If this is NOT a polled command completion
402782527734SSukumar Swaminathan 	 * or a driver allocated pkt, then defer pkt
402882527734SSukumar Swaminathan 	 * completion.
402982527734SSukumar Swaminathan 	 */
403082527734SSukumar Swaminathan 	if (!(sbp->pkt_flags &
403182527734SSukumar Swaminathan 	    (PACKET_POLLED | PACKET_ALLOCATED))) {
403282527734SSukumar Swaminathan 		/* Add the IOCB to the channel list */
403382527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
403482527734SSukumar Swaminathan 		if (cp->rsp_head == NULL) {
403582527734SSukumar Swaminathan 			cp->rsp_head = iocbq;
403682527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
403782527734SSukumar Swaminathan 		} else {
403882527734SSukumar Swaminathan 			cp->rsp_tail->next = iocbq;
403982527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
404082527734SSukumar Swaminathan 		}
404182527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
404282527734SSukumar Swaminathan 
404382527734SSukumar Swaminathan 		/* Delay triggering thread till end of ISR */
404482527734SSukumar Swaminathan 		cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
404582527734SSukumar Swaminathan 	} else {
404682527734SSukumar Swaminathan 		emlxs_proc_channel_event(hba, cp, iocbq);
404782527734SSukumar Swaminathan 	}
404882527734SSukumar Swaminathan 
404982527734SSukumar Swaminathan } /* emlxs_sli4_process_wqe_cmpl() */
405082527734SSukumar Swaminathan 
405182527734SSukumar Swaminathan 
405282527734SSukumar Swaminathan /*ARGSUSED*/
405382527734SSukumar Swaminathan static void
405482527734SSukumar Swaminathan emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq,
405582527734SSukumar Swaminathan     CQE_RelWQ_t *cqe)
405682527734SSukumar Swaminathan {
4057bce54adfSSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
405882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4059bce54adfSSukumar Swaminathan #endif
406082527734SSukumar Swaminathan 	WQ_DESC_t *wq;
406182527734SSukumar Swaminathan 	CHANNEL *cp;
406282527734SSukumar Swaminathan 	uint32_t i;
406382527734SSukumar Swaminathan 
406482527734SSukumar Swaminathan 	i = cqe->WQid;
406582527734SSukumar Swaminathan 	wq = &hba->sli.sli4.wq[hba->sli.sli4.wq_map[i]];
406682527734SSukumar Swaminathan 
406782527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
406882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
406982527734SSukumar Swaminathan 	    "CQ ENTRY: process release wqe: old %d new %d", wq->port_index,
407082527734SSukumar Swaminathan 	    cqe->WQindex);
407182527734SSukumar Swaminathan #endif
407282527734SSukumar Swaminathan 
407382527734SSukumar Swaminathan 	wq->port_index = cqe->WQindex;
407482527734SSukumar Swaminathan 
407582527734SSukumar Swaminathan 	/* Cmd ring may be available. Try sending more iocbs */
407682527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
407782527734SSukumar Swaminathan 		cp = &hba->chan[i];
407882527734SSukumar Swaminathan 		if (wq == (WQ_DESC_t *)cp->iopath) {
407982527734SSukumar Swaminathan 			emlxs_sli4_issue_iocb_cmd(hba, cp, 0);
408082527734SSukumar Swaminathan 		}
408182527734SSukumar Swaminathan 	}
408282527734SSukumar Swaminathan 
408382527734SSukumar Swaminathan } /* emlxs_sli4_process_release_wqe() */
408482527734SSukumar Swaminathan 
408582527734SSukumar Swaminathan 
408682527734SSukumar Swaminathan /*ARGSUSED*/
408782527734SSukumar Swaminathan emlxs_iocbq_t *
408882527734SSukumar Swaminathan emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr)
408982527734SSukumar Swaminathan {
409082527734SSukumar Swaminathan 	emlxs_queue_t *q;
409182527734SSukumar Swaminathan 	emlxs_iocbq_t *iocbq;
409282527734SSukumar Swaminathan 	emlxs_iocbq_t *prev;
409382527734SSukumar Swaminathan 	fc_frame_hdr_t *fchdr2;
409482527734SSukumar Swaminathan 	RXQ_DESC_t *rxq;
409582527734SSukumar Swaminathan 
409682527734SSukumar Swaminathan 	switch (fchdr->type) {
409782527734SSukumar Swaminathan 	case 1: /* ELS */
409882527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
409982527734SSukumar Swaminathan 		break;
410082527734SSukumar Swaminathan 	case 0x20: /* CT */
410182527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
410282527734SSukumar Swaminathan 		break;
410382527734SSukumar Swaminathan 	default:
410482527734SSukumar Swaminathan 		return (NULL);
410582527734SSukumar Swaminathan 	}
410682527734SSukumar Swaminathan 
410782527734SSukumar Swaminathan 	mutex_enter(&rxq->lock);
410882527734SSukumar Swaminathan 
410982527734SSukumar Swaminathan 	q = &rxq->active;
411082527734SSukumar Swaminathan 	iocbq  = (emlxs_iocbq_t *)q->q_first;
411182527734SSukumar Swaminathan 	prev = NULL;
411282527734SSukumar Swaminathan 
411382527734SSukumar Swaminathan 	while (iocbq) {
411482527734SSukumar Swaminathan 
411582527734SSukumar Swaminathan 		fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord;
411682527734SSukumar Swaminathan 
411782527734SSukumar Swaminathan 		if ((fchdr2->s_id == fchdr->s_id) &&
411882527734SSukumar Swaminathan 		    (fchdr2->ox_id == fchdr->ox_id) &&
411982527734SSukumar Swaminathan 		    (fchdr2->seq_id == fchdr->seq_id)) {
412082527734SSukumar Swaminathan 			/* Remove iocbq */
412182527734SSukumar Swaminathan 			if (prev) {
412282527734SSukumar Swaminathan 				prev->next = iocbq->next;
412382527734SSukumar Swaminathan 			}
412482527734SSukumar Swaminathan 			if (q->q_first == (uint8_t *)iocbq) {
412582527734SSukumar Swaminathan 				q->q_first = (uint8_t *)iocbq->next;
412682527734SSukumar Swaminathan 			}
412782527734SSukumar Swaminathan 			if (q->q_last == (uint8_t *)iocbq) {
412882527734SSukumar Swaminathan 				q->q_last = (uint8_t *)prev;
412982527734SSukumar Swaminathan 			}
413082527734SSukumar Swaminathan 			q->q_cnt--;
413182527734SSukumar Swaminathan 
413282527734SSukumar Swaminathan 			break;
413382527734SSukumar Swaminathan 		}
413482527734SSukumar Swaminathan 
413582527734SSukumar Swaminathan 		prev  = iocbq;
413682527734SSukumar Swaminathan 		iocbq = iocbq->next;
413782527734SSukumar Swaminathan 	}
413882527734SSukumar Swaminathan 
413982527734SSukumar Swaminathan 	mutex_exit(&rxq->lock);
414082527734SSukumar Swaminathan 
414182527734SSukumar Swaminathan 	return (iocbq);
414282527734SSukumar Swaminathan 
414382527734SSukumar Swaminathan } /* emlxs_sli4_rxq_get() */
414482527734SSukumar Swaminathan 
414582527734SSukumar Swaminathan 
414682527734SSukumar Swaminathan /*ARGSUSED*/
414782527734SSukumar Swaminathan void
414882527734SSukumar Swaminathan emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq)
414982527734SSukumar Swaminathan {
415082527734SSukumar Swaminathan 	emlxs_queue_t *q;
415182527734SSukumar Swaminathan 	fc_frame_hdr_t *fchdr;
415282527734SSukumar Swaminathan 	RXQ_DESC_t *rxq;
415382527734SSukumar Swaminathan 
415482527734SSukumar Swaminathan 	fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR;
415582527734SSukumar Swaminathan 
415682527734SSukumar Swaminathan 	switch (fchdr->type) {
415782527734SSukumar Swaminathan 	case 1: /* ELS */
415882527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
415982527734SSukumar Swaminathan 		break;
416082527734SSukumar Swaminathan 	case 0x20: /* CT */
416182527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
416282527734SSukumar Swaminathan 		break;
416382527734SSukumar Swaminathan 	default:
416482527734SSukumar Swaminathan 		return;
416582527734SSukumar Swaminathan 	}
416682527734SSukumar Swaminathan 
416782527734SSukumar Swaminathan 	mutex_enter(&rxq->lock);
416882527734SSukumar Swaminathan 
416982527734SSukumar Swaminathan 	q = &rxq->active;
417082527734SSukumar Swaminathan 
417182527734SSukumar Swaminathan 	if (q->q_last) {
417282527734SSukumar Swaminathan 		((emlxs_iocbq_t *)q->q_last)->next = iocbq;
417382527734SSukumar Swaminathan 		q->q_cnt++;
417482527734SSukumar Swaminathan 	} else {
417582527734SSukumar Swaminathan 		q->q_first = (uint8_t *)iocbq;
417682527734SSukumar Swaminathan 		q->q_cnt = 1;
417782527734SSukumar Swaminathan 	}
417882527734SSukumar Swaminathan 
417982527734SSukumar Swaminathan 	q->q_last = (uint8_t *)iocbq;
418082527734SSukumar Swaminathan 	iocbq->next = NULL;
418182527734SSukumar Swaminathan 
418282527734SSukumar Swaminathan 	mutex_exit(&rxq->lock);
418382527734SSukumar Swaminathan 
418482527734SSukumar Swaminathan 	return;
418582527734SSukumar Swaminathan 
418682527734SSukumar Swaminathan } /* emlxs_sli4_rxq_put() */
418782527734SSukumar Swaminathan 
418882527734SSukumar Swaminathan 
418982527734SSukumar Swaminathan static void
4190*a9800bebSGarrett D'Amore emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid)
419182527734SSukumar Swaminathan {
4192*a9800bebSGarrett D'Amore 	emlxs_hba_t *hba = HBA;
419382527734SSukumar Swaminathan 	emlxs_rqdbu_t rqdb;
419482527734SSukumar Swaminathan 
419582527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
419682527734SSukumar Swaminathan 	    "RQ POST: rqid=%d count=1", rqid);
419782527734SSukumar Swaminathan 
419882527734SSukumar Swaminathan 	/* Ring the RQ doorbell once to repost the RQ buffer */
419982527734SSukumar Swaminathan 	rqdb.word = 0;
420082527734SSukumar Swaminathan 	rqdb.db.Qid = rqid;
420182527734SSukumar Swaminathan 	rqdb.db.NumPosted = 1;
420282527734SSukumar Swaminathan 
420382527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_RQDB_REG(hba), rqdb.word);
420482527734SSukumar Swaminathan 
420582527734SSukumar Swaminathan } /* emlxs_sli4_rq_post() */
420682527734SSukumar Swaminathan 
420782527734SSukumar Swaminathan 
420882527734SSukumar Swaminathan /*ARGSUSED*/
420982527734SSukumar Swaminathan static void
421082527734SSukumar Swaminathan emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq,
421182527734SSukumar Swaminathan     CQE_UnsolRcv_t *cqe)
421282527734SSukumar Swaminathan {
421382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
421482527734SSukumar Swaminathan 	emlxs_port_t *vport;
421582527734SSukumar Swaminathan 	RQ_DESC_t *hdr_rq;
421682527734SSukumar Swaminathan 	RQ_DESC_t *data_rq;
4217b3660a96SSukumar Swaminathan 	MBUF_INFO *hdr_mp;
4218b3660a96SSukumar Swaminathan 	MBUF_INFO *data_mp;
421982527734SSukumar Swaminathan 	MATCHMAP *seq_mp;
422082527734SSukumar Swaminathan 	uint32_t *data;
422182527734SSukumar Swaminathan 	fc_frame_hdr_t fchdr;
422282527734SSukumar Swaminathan 	uint32_t hdr_rqi;
422382527734SSukumar Swaminathan 	uint32_t host_index;
422482527734SSukumar Swaminathan 	emlxs_iocbq_t *iocbq = NULL;
422582527734SSukumar Swaminathan 	emlxs_iocb_t *iocb;
422682527734SSukumar Swaminathan 	emlxs_node_t *node;
422782527734SSukumar Swaminathan 	uint32_t i;
422882527734SSukumar Swaminathan 	uint32_t seq_len;
422982527734SSukumar Swaminathan 	uint32_t seq_cnt;
423082527734SSukumar Swaminathan 	uint32_t buf_type;
423182527734SSukumar Swaminathan 	char label[32];
423282527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
423382527734SSukumar Swaminathan 	CHANNEL *cp;
423482527734SSukumar Swaminathan 	uint16_t iotag;
4235*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
4236*a9800bebSGarrett D'Amore 	RPIobj_t *rpip = NULL;
423782527734SSukumar Swaminathan 	uint32_t	cmd;
423882527734SSukumar Swaminathan 	uint32_t posted = 0;
423982527734SSukumar Swaminathan 	uint32_t abort = 1;
4240b3660a96SSukumar Swaminathan 	off_t offset;
424182527734SSukumar Swaminathan 
424282527734SSukumar Swaminathan 	hdr_rqi = hba->sli.sli4.rq_map[cqe->RQid];
424382527734SSukumar Swaminathan 	hdr_rq  = &hba->sli.sli4.rq[hdr_rqi];
424482527734SSukumar Swaminathan 	data_rq = &hba->sli.sli4.rq[hdr_rqi + 1];
424582527734SSukumar Swaminathan 
424682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4247*a9800bebSGarrett D'Amore 	    "CQ ENTRY: Unsol Rcv: RQid=%d,%d index=%d status=%x "
424882527734SSukumar Swaminathan 	    "hdr_size=%d data_size=%d",
424982527734SSukumar Swaminathan 	    cqe->RQid, hdr_rqi, hdr_rq->host_index, cqe->Status, cqe->hdr_size,
425082527734SSukumar Swaminathan 	    cqe->data_size);
425182527734SSukumar Swaminathan 
425282527734SSukumar Swaminathan 	/* Validate the CQE */
425382527734SSukumar Swaminathan 
425482527734SSukumar Swaminathan 	/* Check status */
425582527734SSukumar Swaminathan 	switch (cqe->Status) {
425682527734SSukumar Swaminathan 	case RQ_STATUS_SUCCESS: /* 0x10 */
425782527734SSukumar Swaminathan 		break;
425882527734SSukumar Swaminathan 
425982527734SSukumar Swaminathan 	case RQ_STATUS_BUFLEN_EXCEEDED:  /* 0x11 */
426082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
426182527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload truncated.");
426282527734SSukumar Swaminathan 		break;
426382527734SSukumar Swaminathan 
426482527734SSukumar Swaminathan 	case RQ_STATUS_NEED_BUFFER: /* 0x12 */
426582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
426682527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload buffer needed.");
426782527734SSukumar Swaminathan 		return;
426882527734SSukumar Swaminathan 
426982527734SSukumar Swaminathan 	case RQ_STATUS_FRAME_DISCARDED:  /* 0x13 */
427082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
427182527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
427282527734SSukumar Swaminathan 		return;
427382527734SSukumar Swaminathan 
427482527734SSukumar Swaminathan 	default:
427582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
427682527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Unknown status=%x.",
427782527734SSukumar Swaminathan 		    cqe->Status);
427882527734SSukumar Swaminathan 		break;
427982527734SSukumar Swaminathan 	}
428082527734SSukumar Swaminathan 
428182527734SSukumar Swaminathan 	/* Make sure there is a frame header */
428282527734SSukumar Swaminathan 	if (cqe->hdr_size < sizeof (fc_frame_hdr_t)) {
428382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
428482527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
428582527734SSukumar Swaminathan 		return;
428682527734SSukumar Swaminathan 	}
428782527734SSukumar Swaminathan 
428882527734SSukumar Swaminathan 	/* Update host index */
428982527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock);
429082527734SSukumar Swaminathan 	host_index = hdr_rq->host_index;
429182527734SSukumar Swaminathan 	hdr_rq->host_index++;
429282527734SSukumar Swaminathan 	if (hdr_rq->host_index >= hdr_rq->max_index) {
429382527734SSukumar Swaminathan 		hdr_rq->host_index = 0;
429482527734SSukumar Swaminathan 	}
429582527734SSukumar Swaminathan 	data_rq->host_index = hdr_rq->host_index;
429682527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock);
429782527734SSukumar Swaminathan 
429882527734SSukumar Swaminathan 	/* Get the next header rqb */
4299b3660a96SSukumar Swaminathan 	hdr_mp  = &hdr_rq->rqb[host_index];
430082527734SSukumar Swaminathan 
4301b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) -
4302b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt));
4303b3660a96SSukumar Swaminathan 
4304b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset,
430582527734SSukumar Swaminathan 	    sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
430682527734SSukumar Swaminathan 
430782527734SSukumar Swaminathan 	LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr,
430882527734SSukumar Swaminathan 	    sizeof (fc_frame_hdr_t));
430982527734SSukumar Swaminathan 
431082527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4311*a9800bebSGarrett D'Amore 	    "RQ HDR[%d]: rctl:%x type:%x "
431282527734SSukumar Swaminathan 	    "sid:%x did:%x oxid:%x rxid:%x",
431382527734SSukumar Swaminathan 	    host_index, fchdr.r_ctl, fchdr.type,
431482527734SSukumar Swaminathan 	    fchdr.s_id,  fchdr.d_id, fchdr.ox_id, fchdr.rx_id);
431582527734SSukumar Swaminathan 
431682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
431782527734SSukumar Swaminathan 	    "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
431882527734SSukumar Swaminathan 	    host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt,
431982527734SSukumar Swaminathan 	    fchdr.df_ctl, fchdr.ro);
432082527734SSukumar Swaminathan 
432182527734SSukumar Swaminathan 	/* Verify fc header type */
432282527734SSukumar Swaminathan 	switch (fchdr.type) {
432382527734SSukumar Swaminathan 	case 0: /* BLS */
432482527734SSukumar Swaminathan 		if (fchdr.r_ctl != 0x81) {
432582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4326*a9800bebSGarrett D'Amore 			    "RQ ENTRY: Unexpected FC rctl (0x%x) "
432782527734SSukumar Swaminathan 			    "received. Dropping...",
432882527734SSukumar Swaminathan 			    fchdr.r_ctl);
432982527734SSukumar Swaminathan 
433082527734SSukumar Swaminathan 			goto done;
433182527734SSukumar Swaminathan 		}
433282527734SSukumar Swaminathan 
433382527734SSukumar Swaminathan 		/* Make sure there is no payload */
433482527734SSukumar Swaminathan 		if (cqe->data_size != 0) {
433582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
433682527734SSukumar Swaminathan 			    "RQ ENTRY: ABTS payload provided. Dropping...");
433782527734SSukumar Swaminathan 
433882527734SSukumar Swaminathan 			goto done;
433982527734SSukumar Swaminathan 		}
434082527734SSukumar Swaminathan 
434182527734SSukumar Swaminathan 		buf_type = 0xFFFFFFFF;
434282527734SSukumar Swaminathan 		(void) strcpy(label, "ABTS");
434382527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_els];
434482527734SSukumar Swaminathan 		break;
434582527734SSukumar Swaminathan 
434682527734SSukumar Swaminathan 	case 0x01: /* ELS */
434782527734SSukumar Swaminathan 		/* Make sure there is a payload */
434882527734SSukumar Swaminathan 		if (cqe->data_size == 0) {
434982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4350*a9800bebSGarrett D'Amore 			    "RQ ENTRY: Unsol Rcv: No ELS payload provided. "
435182527734SSukumar Swaminathan 			    "Dropping...");
435282527734SSukumar Swaminathan 
435382527734SSukumar Swaminathan 			goto done;
435482527734SSukumar Swaminathan 		}
435582527734SSukumar Swaminathan 
435682527734SSukumar Swaminathan 		buf_type = MEM_ELSBUF;
435782527734SSukumar Swaminathan 		(void) strcpy(label, "Unsol ELS");
435882527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_els];
435982527734SSukumar Swaminathan 		break;
436082527734SSukumar Swaminathan 
436182527734SSukumar Swaminathan 	case 0x20: /* CT */
436282527734SSukumar Swaminathan 		/* Make sure there is a payload */
436382527734SSukumar Swaminathan 		if (cqe->data_size == 0) {
436482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4365*a9800bebSGarrett D'Amore 			    "RQ ENTRY: Unsol Rcv: No CT payload provided. "
436682527734SSukumar Swaminathan 			    "Dropping...");
436782527734SSukumar Swaminathan 
436882527734SSukumar Swaminathan 			goto done;
436982527734SSukumar Swaminathan 		}
437082527734SSukumar Swaminathan 
437182527734SSukumar Swaminathan 		buf_type = MEM_CTBUF;
437282527734SSukumar Swaminathan 		(void) strcpy(label, "Unsol CT");
437382527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_ct];
437482527734SSukumar Swaminathan 		break;
437582527734SSukumar Swaminathan 
437682527734SSukumar Swaminathan 	default:
437782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
437882527734SSukumar Swaminathan 		    "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
437982527734SSukumar Swaminathan 		    fchdr.type);
438082527734SSukumar Swaminathan 
438182527734SSukumar Swaminathan 		goto done;
438282527734SSukumar Swaminathan 	}
438382527734SSukumar Swaminathan 	/* Fc Header is valid */
438482527734SSukumar Swaminathan 
438582527734SSukumar Swaminathan 	/* Check if this is an active sequence */
438682527734SSukumar Swaminathan 	iocbq = emlxs_sli4_rxq_get(hba, &fchdr);
438782527734SSukumar Swaminathan 
438882527734SSukumar Swaminathan 	if (!iocbq) {
438982527734SSukumar Swaminathan 		if (fchdr.type != 0) {
439082527734SSukumar Swaminathan 			if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) {
439182527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4392*a9800bebSGarrett D'Amore 				    "RQ ENTRY: %s: First of sequence not"
439382527734SSukumar Swaminathan 				    " set.  Dropping...",
439482527734SSukumar Swaminathan 				    label);
439582527734SSukumar Swaminathan 
439682527734SSukumar Swaminathan 				goto done;
439782527734SSukumar Swaminathan 			}
439882527734SSukumar Swaminathan 		}
439982527734SSukumar Swaminathan 
440082527734SSukumar Swaminathan 		if (fchdr.seq_cnt != 0) {
440182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4402*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Sequence count not zero (%d).  "
440382527734SSukumar Swaminathan 			    "Dropping...",
440482527734SSukumar Swaminathan 			    label, fchdr.seq_cnt);
440582527734SSukumar Swaminathan 
440682527734SSukumar Swaminathan 			goto done;
440782527734SSukumar Swaminathan 		}
440882527734SSukumar Swaminathan 
440982527734SSukumar Swaminathan 		/* Find vport (defaults to physical port) */
441082527734SSukumar Swaminathan 		for (i = 0; i < MAX_VPORTS; i++) {
441182527734SSukumar Swaminathan 			vport = &VPORT(i);
441282527734SSukumar Swaminathan 
441382527734SSukumar Swaminathan 			if (vport->did == fchdr.d_id) {
441482527734SSukumar Swaminathan 				port = vport;
441582527734SSukumar Swaminathan 				break;
441682527734SSukumar Swaminathan 			}
441782527734SSukumar Swaminathan 		}
441882527734SSukumar Swaminathan 
441982527734SSukumar Swaminathan 		/* Allocate an IOCBQ */
442082527734SSukumar Swaminathan 		iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba,
442182527734SSukumar Swaminathan 		    MEM_IOCB, 1);
442282527734SSukumar Swaminathan 
442382527734SSukumar Swaminathan 		if (!iocbq) {
442482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4425*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of IOCB "
442682527734SSukumar Swaminathan 			    "resources.  Dropping...",
442782527734SSukumar Swaminathan 			    label);
442882527734SSukumar Swaminathan 
442982527734SSukumar Swaminathan 			goto done;
443082527734SSukumar Swaminathan 		}
443182527734SSukumar Swaminathan 
443282527734SSukumar Swaminathan 		seq_mp = NULL;
443382527734SSukumar Swaminathan 		if (fchdr.type != 0) {
443482527734SSukumar Swaminathan 			/* Allocate a buffer */
443582527734SSukumar Swaminathan 			seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type, 1);
443682527734SSukumar Swaminathan 
443782527734SSukumar Swaminathan 			if (!seq_mp) {
443882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4439*a9800bebSGarrett D'Amore 				    "RQ ENTRY: %s: Out of buffer "
444082527734SSukumar Swaminathan 				    "resources.  Dropping...",
444182527734SSukumar Swaminathan 				    label);
444282527734SSukumar Swaminathan 
444382527734SSukumar Swaminathan 				goto done;
444482527734SSukumar Swaminathan 			}
444582527734SSukumar Swaminathan 
444682527734SSukumar Swaminathan 			iocbq->bp = (uint8_t *)seq_mp;
444782527734SSukumar Swaminathan 		}
444882527734SSukumar Swaminathan 
444982527734SSukumar Swaminathan 		node = (void *)emlxs_node_find_did(port, fchdr.s_id);
445082527734SSukumar Swaminathan 		if (node == NULL) {
445182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
445282527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Node not found. sid=%x",
445382527734SSukumar Swaminathan 			    label, fchdr.s_id);
445482527734SSukumar Swaminathan 		}
445582527734SSukumar Swaminathan 
445682527734SSukumar Swaminathan 		/* Initialize the iocbq */
445782527734SSukumar Swaminathan 		iocbq->port = port;
445882527734SSukumar Swaminathan 		iocbq->channel = cp;
445982527734SSukumar Swaminathan 		iocbq->node = node;
446082527734SSukumar Swaminathan 
446182527734SSukumar Swaminathan 		iocb = &iocbq->iocb;
446282527734SSukumar Swaminathan 		iocb->RXSEQCNT = 0;
446382527734SSukumar Swaminathan 		iocb->RXSEQLEN = 0;
446482527734SSukumar Swaminathan 
446582527734SSukumar Swaminathan 		seq_len = 0;
446682527734SSukumar Swaminathan 		seq_cnt = 0;
446782527734SSukumar Swaminathan 
446882527734SSukumar Swaminathan 	} else {
446982527734SSukumar Swaminathan 
447082527734SSukumar Swaminathan 		iocb = &iocbq->iocb;
447182527734SSukumar Swaminathan 		port = iocbq->port;
447282527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
447382527734SSukumar Swaminathan 
447482527734SSukumar Swaminathan 		seq_mp = (MATCHMAP *)iocbq->bp;
447582527734SSukumar Swaminathan 		seq_len = iocb->RXSEQLEN;
447682527734SSukumar Swaminathan 		seq_cnt = iocb->RXSEQCNT;
447782527734SSukumar Swaminathan 
447882527734SSukumar Swaminathan 		/* Check sequence order */
447982527734SSukumar Swaminathan 		if (fchdr.seq_cnt != seq_cnt) {
448082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4481*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of order frame received "
448282527734SSukumar Swaminathan 			    "(%d != %d).  Dropping...",
448382527734SSukumar Swaminathan 			    label, fchdr.seq_cnt, seq_cnt);
448482527734SSukumar Swaminathan 
448582527734SSukumar Swaminathan 			goto done;
448682527734SSukumar Swaminathan 		}
448782527734SSukumar Swaminathan 	}
448882527734SSukumar Swaminathan 
448982527734SSukumar Swaminathan 	/* We now have an iocbq */
449082527734SSukumar Swaminathan 
4491*a9800bebSGarrett D'Amore 	if (!port->VPIobj.vfip) {
4492*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4493*a9800bebSGarrett D'Amore 		    "RQ ENTRY: %s: No fabric connection. "
4494*a9800bebSGarrett D'Amore 		    "Dropping...",
4495*a9800bebSGarrett D'Amore 		    label);
4496*a9800bebSGarrett D'Amore 
4497*a9800bebSGarrett D'Amore 		goto done;
4498*a9800bebSGarrett D'Amore 	}
4499*a9800bebSGarrett D'Amore 
450082527734SSukumar Swaminathan 	/* Save the frame data to our seq buffer */
450182527734SSukumar Swaminathan 	if (cqe->data_size && seq_mp) {
450282527734SSukumar Swaminathan 		/* Get the next data rqb */
4503b3660a96SSukumar Swaminathan 		data_mp = &data_rq->rqb[host_index];
4504b3660a96SSukumar Swaminathan 
4505b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
4506b3660a96SSukumar Swaminathan 		    data_mp->virt) -
4507b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
4508b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
450982527734SSukumar Swaminathan 
4510b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset,
451182527734SSukumar Swaminathan 		    cqe->data_size, DDI_DMA_SYNC_FORKERNEL);
451282527734SSukumar Swaminathan 
451382527734SSukumar Swaminathan 		data = (uint32_t *)data_mp->virt;
451482527734SSukumar Swaminathan 
451582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
451682527734SSukumar Swaminathan 		    "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
451782527734SSukumar Swaminathan 		    host_index, data[0], data[1], data[2], data[3],
451882527734SSukumar Swaminathan 		    data[4], data[5]);
451982527734SSukumar Swaminathan 
452082527734SSukumar Swaminathan 		/* Check sequence length */
452182527734SSukumar Swaminathan 		if ((seq_len + cqe->data_size) > seq_mp->size) {
452282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4523*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Sequence buffer overflow. "
452482527734SSukumar Swaminathan 			    "(%d > %d). Dropping...",
452582527734SSukumar Swaminathan 			    label, (seq_len + cqe->data_size), seq_mp->size);
452682527734SSukumar Swaminathan 
452782527734SSukumar Swaminathan 			goto done;
452882527734SSukumar Swaminathan 		}
452982527734SSukumar Swaminathan 
453082527734SSukumar Swaminathan 		/* Copy data to local receive buffer */
453182527734SSukumar Swaminathan 		bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt +
453282527734SSukumar Swaminathan 		    seq_len), cqe->data_size);
453382527734SSukumar Swaminathan 
453482527734SSukumar Swaminathan 		seq_len += cqe->data_size;
453582527734SSukumar Swaminathan 	}
453682527734SSukumar Swaminathan 
453782527734SSukumar Swaminathan 	/* If this is not the last frame of sequence, queue it. */
453882527734SSukumar Swaminathan 	if (!(fchdr.f_ctl & F_CTL_END_SEQ)) {
453982527734SSukumar Swaminathan 		/* Save sequence header */
454082527734SSukumar Swaminathan 		if (seq_cnt == 0) {
454182527734SSukumar Swaminathan 			bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR,
454282527734SSukumar Swaminathan 			    sizeof (fc_frame_hdr_t));
454382527734SSukumar Swaminathan 		}
454482527734SSukumar Swaminathan 
454582527734SSukumar Swaminathan 		/* Update sequence info in iocb */
454682527734SSukumar Swaminathan 		iocb->RXSEQCNT = seq_cnt + 1;
454782527734SSukumar Swaminathan 		iocb->RXSEQLEN = seq_len;
454882527734SSukumar Swaminathan 
454982527734SSukumar Swaminathan 		/* Queue iocbq for next frame */
455082527734SSukumar Swaminathan 		emlxs_sli4_rxq_put(hba, iocbq);
455182527734SSukumar Swaminathan 
455282527734SSukumar Swaminathan 		/* Don't free resources */
455382527734SSukumar Swaminathan 		iocbq = NULL;
455482527734SSukumar Swaminathan 
455582527734SSukumar Swaminathan 		/* No need to abort */
455682527734SSukumar Swaminathan 		abort = 0;
455782527734SSukumar Swaminathan 
455882527734SSukumar Swaminathan 		goto done;
455982527734SSukumar Swaminathan 	}
456082527734SSukumar Swaminathan 
4561*a9800bebSGarrett D'Amore 	emlxs_sli4_rq_post(port, hdr_rq->qid);
456282527734SSukumar Swaminathan 	posted = 1;
456382527734SSukumar Swaminathan 
456482527734SSukumar Swaminathan 	/* End of sequence found. Process request now. */
456582527734SSukumar Swaminathan 
456682527734SSukumar Swaminathan 	if (seq_cnt > 0) {
456782527734SSukumar Swaminathan 		/* Retrieve first frame of sequence */
456882527734SSukumar Swaminathan 		bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr,
456982527734SSukumar Swaminathan 		    sizeof (fc_frame_hdr_t));
457082527734SSukumar Swaminathan 
457182527734SSukumar Swaminathan 		bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t));
457282527734SSukumar Swaminathan 	}
457382527734SSukumar Swaminathan 
457482527734SSukumar Swaminathan 	/* Build rcv iocb and process it */
457582527734SSukumar Swaminathan 	switch (fchdr.type) {
457682527734SSukumar Swaminathan 	case 0: /* BLS */
457782527734SSukumar Swaminathan 
457882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
457982527734SSukumar Swaminathan 		    "RQ ENTRY: %s: xid:%x sid:%x. Sending BLS ACC...",
458082527734SSukumar Swaminathan 		    label, fchdr.ox_id, fchdr.s_id);
458182527734SSukumar Swaminathan 
458282527734SSukumar Swaminathan 		iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL);
458382527734SSukumar Swaminathan 
458482527734SSukumar Swaminathan 		/* Set up an iotag using special Abort iotags */
4585fe199829SSukumar Swaminathan 		mutex_enter(&EMLXS_FCTAB_LOCK);
458682527734SSukumar Swaminathan 		if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) {
458782527734SSukumar Swaminathan 			hba->fc_oor_iotag = hba->max_iotag;
458882527734SSukumar Swaminathan 		}
458982527734SSukumar Swaminathan 		iotag = hba->fc_oor_iotag++;
4590fe199829SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
459182527734SSukumar Swaminathan 
459282527734SSukumar Swaminathan 		/* BLS ACC Response */
459382527734SSukumar Swaminathan 		wqe = &iocbq->wqe;
459482527734SSukumar Swaminathan 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
459582527734SSukumar Swaminathan 
459682527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_BLS_RSP64_CX;
459782527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
459882527734SSukumar Swaminathan 
459982527734SSukumar Swaminathan 		wqe->un.BlsRsp.Payload0 = 0x80;
460082527734SSukumar Swaminathan 		wqe->un.BlsRsp.Payload1 = fchdr.seq_id;
460182527734SSukumar Swaminathan 
460282527734SSukumar Swaminathan 		wqe->un.BlsRsp.OXId = fchdr.ox_id;
460382527734SSukumar Swaminathan 		wqe->un.BlsRsp.RXId = fchdr.rx_id;
460482527734SSukumar Swaminathan 
460582527734SSukumar Swaminathan 		wqe->un.BlsRsp.SeqCntLow = 0;
460682527734SSukumar Swaminathan 		wqe->un.BlsRsp.SeqCntHigh = 0xFFFF;
460782527734SSukumar Swaminathan 
460882527734SSukumar Swaminathan 		wqe->un.BlsRsp.XO = 0;
460982527734SSukumar Swaminathan 		wqe->un.BlsRsp.AR = 0;
461082527734SSukumar Swaminathan 		wqe->un.BlsRsp.PT = 1;
461182527734SSukumar Swaminathan 		wqe->un.BlsRsp.RemoteId = fchdr.s_id;
461282527734SSukumar Swaminathan 
461382527734SSukumar Swaminathan 		wqe->PU = 0x3;
4614*a9800bebSGarrett D'Amore 		wqe->ContextTag = port->VPIobj.VPI;
461582527734SSukumar Swaminathan 		wqe->ContextType = WQE_VPI_CONTEXT;
461682527734SSukumar Swaminathan 		wqe->OXId = (volatile uint16_t) fchdr.ox_id;
461782527734SSukumar Swaminathan 		wqe->XRITag = 0xffff;
461882527734SSukumar Swaminathan 
461982527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
462082527734SSukumar Swaminathan 			wqe->CCPE = 1;
462182527734SSukumar Swaminathan 			wqe->CCP = fchdr.rsvd;
462282527734SSukumar Swaminathan 		}
462382527734SSukumar Swaminathan 
462482527734SSukumar Swaminathan 		wqe->Class = CLASS3;
462582527734SSukumar Swaminathan 		wqe->RequestTag = iotag;
462682527734SSukumar Swaminathan 		wqe->CQId = 0x3ff;
462782527734SSukumar Swaminathan 
462882527734SSukumar Swaminathan 		emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq);
462982527734SSukumar Swaminathan 
463082527734SSukumar Swaminathan 		break;
463182527734SSukumar Swaminathan 
463282527734SSukumar Swaminathan 	case 1: /* ELS */
4633*a9800bebSGarrett D'Amore 		if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
4634*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4635*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Port not yet enabled. "
4636*a9800bebSGarrett D'Amore 			    "Dropping...",
4637*a9800bebSGarrett D'Amore 			    label);
4638*a9800bebSGarrett D'Amore 
4639*a9800bebSGarrett D'Amore 			goto done;
4640*a9800bebSGarrett D'Amore 		}
4641*a9800bebSGarrett D'Amore 
464282527734SSukumar Swaminathan 		cmd = *((uint32_t *)seq_mp->virt);
464382527734SSukumar Swaminathan 		cmd &= ELS_CMD_MASK;
4644*a9800bebSGarrett D'Amore 		rpip = NULL;
464582527734SSukumar Swaminathan 
464682527734SSukumar Swaminathan 		if (cmd != ELS_CMD_LOGO) {
4647*a9800bebSGarrett D'Amore 			rpip = EMLXS_NODE_TO_RPI(port, node);
464882527734SSukumar Swaminathan 		}
464982527734SSukumar Swaminathan 
4650*a9800bebSGarrett D'Amore 		if (!rpip) {
4651*a9800bebSGarrett D'Amore 			rpip = port->VPIobj.rpip;
465282527734SSukumar Swaminathan 		}
465382527734SSukumar Swaminathan 
4654*a9800bebSGarrett D'Amore 		xrip = emlxs_sli4_reserve_xri(hba, rpip);
465582527734SSukumar Swaminathan 
4656*a9800bebSGarrett D'Amore 		if (!xrip) {
465782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4658*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of exchange "
465982527734SSukumar Swaminathan 			    "resources.  Dropping...",
466082527734SSukumar Swaminathan 			    label);
466182527734SSukumar Swaminathan 
466282527734SSukumar Swaminathan 			goto done;
466382527734SSukumar Swaminathan 		}
466482527734SSukumar Swaminathan 
4665*a9800bebSGarrett D'Amore 		xrip->rx_id = fchdr.ox_id;
466682527734SSukumar Swaminathan 
466782527734SSukumar Swaminathan 		/* Build CMD_RCV_ELS64_CX */
466882527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0;
466982527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.tus.f.bdeSize  = seq_len;
467082527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.addrLow  = PADDR_LO(seq_mp->phys);
467182527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys);
467282527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 1;
467382527734SSukumar Swaminathan 
467482527734SSukumar Swaminathan 		iocb->un.rcvels64.remoteID = fchdr.s_id;
467582527734SSukumar Swaminathan 		iocb->un.rcvels64.parmRo = fchdr.d_id;
467682527734SSukumar Swaminathan 
467782527734SSukumar Swaminathan 		iocb->ULPPU = 0x3;
4678*a9800bebSGarrett D'Amore 		iocb->ULPCONTEXT = xrip->XRI;
467982527734SSukumar Swaminathan 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
468082527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
468182527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
468282527734SSukumar Swaminathan 
468382527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.seq_len = seq_len;
4684*a9800bebSGarrett D'Amore 		iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
468582527734SSukumar Swaminathan 
468682527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
468782527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccpe = 1;
468882527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
468982527734SSukumar Swaminathan 		}
469082527734SSukumar Swaminathan 
469182527734SSukumar Swaminathan 		(void) emlxs_els_handle_unsol_req(port, iocbq->channel,
469282527734SSukumar Swaminathan 		    iocbq, seq_mp, seq_len);
469382527734SSukumar Swaminathan 
469482527734SSukumar Swaminathan 		break;
469582527734SSukumar Swaminathan 
469682527734SSukumar Swaminathan 	case 0x20: /* CT */
4697*a9800bebSGarrett D'Amore 		if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
4698*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4699*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Port not yet enabled. "
4700*a9800bebSGarrett D'Amore 			    "Dropping...",
4701*a9800bebSGarrett D'Amore 			    label);
4702*a9800bebSGarrett D'Amore 
4703*a9800bebSGarrett D'Amore 			goto done;
4704*a9800bebSGarrett D'Amore 		}
470582527734SSukumar Swaminathan 
470682527734SSukumar Swaminathan 		if (!node) {
470782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4708*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Node not found (did=%x).  "
470982527734SSukumar Swaminathan 			    "Dropping...",
471082527734SSukumar Swaminathan 			    label, fchdr.d_id);
471182527734SSukumar Swaminathan 
471282527734SSukumar Swaminathan 			goto done;
471382527734SSukumar Swaminathan 		}
471482527734SSukumar Swaminathan 
4715*a9800bebSGarrett D'Amore 		rpip = EMLXS_NODE_TO_RPI(port, node);
471682527734SSukumar Swaminathan 
4717*a9800bebSGarrett D'Amore 		if (!rpip) {
471882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4719*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: RPI not found (did=%x rpi=%x).  "
472082527734SSukumar Swaminathan 			    "Dropping...",
472182527734SSukumar Swaminathan 			    label, fchdr.d_id, node->nlp_Rpi);
472282527734SSukumar Swaminathan 
472382527734SSukumar Swaminathan 			goto done;
472482527734SSukumar Swaminathan 		}
472582527734SSukumar Swaminathan 
4726*a9800bebSGarrett D'Amore 		xrip = emlxs_sli4_reserve_xri(hba, rpip);
472782527734SSukumar Swaminathan 
4728*a9800bebSGarrett D'Amore 		if (!xrip) {
472982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4730*a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of exchange "
473182527734SSukumar Swaminathan 			    "resources.  Dropping...",
473282527734SSukumar Swaminathan 			    label);
473382527734SSukumar Swaminathan 
473482527734SSukumar Swaminathan 			goto done;
473582527734SSukumar Swaminathan 		}
473682527734SSukumar Swaminathan 
4737*a9800bebSGarrett D'Amore 		xrip->rx_id = fchdr.ox_id;
473882527734SSukumar Swaminathan 
473982527734SSukumar Swaminathan 		/* Build CMD_RCV_SEQ64_CX */
474082527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
474182527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
474282527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
474382527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
474482527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 1;
474582527734SSukumar Swaminathan 
474682527734SSukumar Swaminathan 		iocb->un.rcvseq64.xrsqRo = 0;
474782527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl;
474882527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type;
474982527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl;
475082527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl;
475182527734SSukumar Swaminathan 
475282527734SSukumar Swaminathan 		iocb->ULPPU = 0x3;
4753*a9800bebSGarrett D'Amore 		iocb->ULPCONTEXT = xrip->XRI;
4754*a9800bebSGarrett D'Amore 		iocb->ULPIOTAG = rpip->RPI;
475582527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
475682527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX;
475782527734SSukumar Swaminathan 
475882527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.seq_len = seq_len;
4759*a9800bebSGarrett D'Amore 		iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
476082527734SSukumar Swaminathan 
476182527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
476282527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccpe = 1;
476382527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
476482527734SSukumar Swaminathan 		}
476582527734SSukumar Swaminathan 
476682527734SSukumar Swaminathan 		(void) emlxs_ct_handle_unsol_req(port, iocbq->channel,
476782527734SSukumar Swaminathan 		    iocbq, seq_mp, seq_len);
476882527734SSukumar Swaminathan 
476982527734SSukumar Swaminathan 		break;
477082527734SSukumar Swaminathan 	}
477182527734SSukumar Swaminathan 
477282527734SSukumar Swaminathan 	/* Sequence handled, no need to abort */
477382527734SSukumar Swaminathan 	abort = 0;
477482527734SSukumar Swaminathan 
477582527734SSukumar Swaminathan done:
477682527734SSukumar Swaminathan 
477782527734SSukumar Swaminathan 	if (!posted) {
4778*a9800bebSGarrett D'Amore 		emlxs_sli4_rq_post(port, hdr_rq->qid);
477982527734SSukumar Swaminathan 	}
478082527734SSukumar Swaminathan 
478182527734SSukumar Swaminathan 	if (abort) {
478282527734SSukumar Swaminathan 		/* Send ABTS for this exchange */
478382527734SSukumar Swaminathan 		/* !!! Currently, we have no implementation for this !!! */
478482527734SSukumar Swaminathan 		abort = 0;
478582527734SSukumar Swaminathan 	}
478682527734SSukumar Swaminathan 
478782527734SSukumar Swaminathan 	/* Return memory resources to pools */
478882527734SSukumar Swaminathan 	if (iocbq) {
478982527734SSukumar Swaminathan 		if (iocbq->bp) {
4790*a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, buf_type, (void *)iocbq->bp);
479182527734SSukumar Swaminathan 		}
479282527734SSukumar Swaminathan 
4793*a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
479482527734SSukumar Swaminathan 	}
479582527734SSukumar Swaminathan 
4796b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
4797b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba,
4798b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.dma_handle)
4799b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
4800b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
4801b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
4802b3660a96SSukumar Swaminathan 		    "emlxs_sli4_process_unsol_rcv: hdl=%p",
4803b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.dma_handle);
4804b3660a96SSukumar Swaminathan 
4805b3660a96SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_restart_thread,
4806*a9800bebSGarrett D'Amore 		    0, 0);
4807b3660a96SSukumar Swaminathan 	}
4808b3660a96SSukumar Swaminathan #endif
480982527734SSukumar Swaminathan 	return;
481082527734SSukumar Swaminathan 
481182527734SSukumar Swaminathan } /* emlxs_sli4_process_unsol_rcv() */
481282527734SSukumar Swaminathan 
481382527734SSukumar Swaminathan 
481482527734SSukumar Swaminathan /*ARGSUSED*/
481582527734SSukumar Swaminathan static void
481682527734SSukumar Swaminathan emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq,
481782527734SSukumar Swaminathan     CQE_XRI_Abort_t *cqe)
481882527734SSukumar Swaminathan {
481982527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4820*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
4821*a9800bebSGarrett D'Amore 
4822*a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_FCTAB_LOCK);
482382527734SSukumar Swaminathan 
4824*a9800bebSGarrett D'Amore 	xrip = emlxs_sli4_find_xri(hba, cqe->XRI);
4825*a9800bebSGarrett D'Amore 	if (xrip == NULL) {
482682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
482782527734SSukumar Swaminathan 		    "CQ ENTRY: process xri aborted ignored");
4828*a9800bebSGarrett D'Amore 
4829*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
483082527734SSukumar Swaminathan 		return;
483182527734SSukumar Swaminathan 	}
483282527734SSukumar Swaminathan 
483382527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
483482527734SSukumar Swaminathan 	    "CQ ENTRY: process xri x%x aborted: IA %d EO %d BR %d",
483582527734SSukumar Swaminathan 	    cqe->XRI, cqe->IA, cqe->EO, cqe->BR);
483682527734SSukumar Swaminathan 
4837*a9800bebSGarrett D'Amore 	if (!(xrip->flag & EMLXS_XRI_ABORT_INP)) {
483882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
483982527734SSukumar Swaminathan 		    "XRI Aborted: Bad state: x%x xri x%x",
4840*a9800bebSGarrett D'Amore 		    xrip->flag, xrip->XRI);
4841*a9800bebSGarrett D'Amore 
4842*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
484382527734SSukumar Swaminathan 		return;
484482527734SSukumar Swaminathan 	}
484582527734SSukumar Swaminathan 
484682527734SSukumar Swaminathan 	/* Exchange is no longer busy on-chip, free it */
4847*a9800bebSGarrett D'Amore 	emlxs_sli4_free_xri(hba, 0, xrip, 0);
4848*a9800bebSGarrett D'Amore 
4849*a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_FCTAB_LOCK);
4850*a9800bebSGarrett D'Amore 
4851*a9800bebSGarrett D'Amore 	return;
485282527734SSukumar Swaminathan 
485382527734SSukumar Swaminathan } /* emlxs_sli4_process_xri_aborted () */
485482527734SSukumar Swaminathan 
485582527734SSukumar Swaminathan 
485682527734SSukumar Swaminathan /*ARGSUSED*/
485782527734SSukumar Swaminathan static void
485882527734SSukumar Swaminathan emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq)
485982527734SSukumar Swaminathan {
486082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
486182527734SSukumar Swaminathan 	CQE_u *cqe;
486282527734SSukumar Swaminathan 	CQE_u cq_entry;
486382527734SSukumar Swaminathan 	uint32_t cqdb;
486482527734SSukumar Swaminathan 	int num_entries = 0;
4865b3660a96SSukumar Swaminathan 	off_t offset;
486682527734SSukumar Swaminathan 
486782527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
486882527734SSukumar Swaminathan 
486982527734SSukumar Swaminathan 	cqe = (CQE_u *)cq->addr.virt;
487082527734SSukumar Swaminathan 	cqe += cq->host_index;
487182527734SSukumar Swaminathan 
4872b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
4873b3660a96SSukumar Swaminathan 	    cq->addr.virt) -
4874b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
4875b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
4876b3660a96SSukumar Swaminathan 
4877b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset,
487882527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
487982527734SSukumar Swaminathan 
488082527734SSukumar Swaminathan 	for (;;) {
488182527734SSukumar Swaminathan 		cq_entry.word[3] = BE_SWAP32(cqe->word[3]);
488282527734SSukumar Swaminathan 		if (!(cq_entry.word[3] & CQE_VALID))
488382527734SSukumar Swaminathan 			break;
488482527734SSukumar Swaminathan 
488582527734SSukumar Swaminathan 		cq_entry.word[2] = BE_SWAP32(cqe->word[2]);
488682527734SSukumar Swaminathan 		cq_entry.word[1] = BE_SWAP32(cqe->word[1]);
488782527734SSukumar Swaminathan 		cq_entry.word[0] = BE_SWAP32(cqe->word[0]);
488882527734SSukumar Swaminathan 
488982527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
489082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
489182527734SSukumar Swaminathan 		    "CQ ENTRY: %08x %08x %08x %08x", cq_entry.word[0],
489282527734SSukumar Swaminathan 		    cq_entry.word[1], cq_entry.word[2], cq_entry.word[3]);
489382527734SSukumar Swaminathan #endif
489482527734SSukumar Swaminathan 
489582527734SSukumar Swaminathan 		num_entries++;
489682527734SSukumar Swaminathan 		cqe->word[3] = 0;
489782527734SSukumar Swaminathan 
489882527734SSukumar Swaminathan 		cq->host_index++;
489982527734SSukumar Swaminathan 		if (cq->host_index >= cq->max_index) {
490082527734SSukumar Swaminathan 			cq->host_index = 0;
490182527734SSukumar Swaminathan 			cqe = (CQE_u *)cq->addr.virt;
490282527734SSukumar Swaminathan 		} else {
490382527734SSukumar Swaminathan 			cqe++;
490482527734SSukumar Swaminathan 		}
490582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
490682527734SSukumar Swaminathan 
490782527734SSukumar Swaminathan 		/* Now handle specific cq type */
490882527734SSukumar Swaminathan 		if (cq->type == EMLXS_CQ_TYPE_GROUP1) {
490982527734SSukumar Swaminathan 			if (cq_entry.cqAsyncEntry.async_evt) {
491082527734SSukumar Swaminathan 				emlxs_sli4_process_async_event(hba,
491182527734SSukumar Swaminathan 				    (CQE_ASYNC_t *)&cq_entry);
491282527734SSukumar Swaminathan 			} else {
491382527734SSukumar Swaminathan 				emlxs_sli4_process_mbox_event(hba,
491482527734SSukumar Swaminathan 				    (CQE_MBOX_t *)&cq_entry);
491582527734SSukumar Swaminathan 			}
491682527734SSukumar Swaminathan 		} else { /* EMLXS_CQ_TYPE_GROUP2 */
491782527734SSukumar Swaminathan 			switch (cq_entry.cqCmplEntry.Code) {
491882527734SSukumar Swaminathan 			case CQE_TYPE_WQ_COMPLETION:
491982527734SSukumar Swaminathan 				if (cq_entry.cqCmplEntry.RequestTag <
492082527734SSukumar Swaminathan 				    hba->max_iotag) {
492182527734SSukumar Swaminathan 					emlxs_sli4_process_wqe_cmpl(hba, cq,
492282527734SSukumar Swaminathan 					    (CQE_CmplWQ_t *)&cq_entry);
492382527734SSukumar Swaminathan 				} else {
492482527734SSukumar Swaminathan 					emlxs_sli4_process_oor_wqe_cmpl(hba, cq,
492582527734SSukumar Swaminathan 					    (CQE_CmplWQ_t *)&cq_entry);
492682527734SSukumar Swaminathan 				}
492782527734SSukumar Swaminathan 				break;
492882527734SSukumar Swaminathan 			case CQE_TYPE_RELEASE_WQE:
492982527734SSukumar Swaminathan 				emlxs_sli4_process_release_wqe(hba, cq,
493082527734SSukumar Swaminathan 				    (CQE_RelWQ_t *)&cq_entry);
493182527734SSukumar Swaminathan 				break;
493282527734SSukumar Swaminathan 			case CQE_TYPE_UNSOL_RCV:
493382527734SSukumar Swaminathan 				emlxs_sli4_process_unsol_rcv(hba, cq,
493482527734SSukumar Swaminathan 				    (CQE_UnsolRcv_t *)&cq_entry);
493582527734SSukumar Swaminathan 				break;
493682527734SSukumar Swaminathan 			case CQE_TYPE_XRI_ABORTED:
493782527734SSukumar Swaminathan 				emlxs_sli4_process_xri_aborted(hba, cq,
493882527734SSukumar Swaminathan 				    (CQE_XRI_Abort_t *)&cq_entry);
493982527734SSukumar Swaminathan 				break;
494082527734SSukumar Swaminathan 			default:
494182527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
494282527734SSukumar Swaminathan 				    "Invalid CQ entry %d: %08x %08x %08x %08x",
494382527734SSukumar Swaminathan 				    cq_entry.cqCmplEntry.Code, cq_entry.word[0],
494482527734SSukumar Swaminathan 				    cq_entry.word[1], cq_entry.word[2],
494582527734SSukumar Swaminathan 				    cq_entry.word[3]);
494682527734SSukumar Swaminathan 				break;
494782527734SSukumar Swaminathan 			}
494882527734SSukumar Swaminathan 		}
494982527734SSukumar Swaminathan 
495082527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
495182527734SSukumar Swaminathan 	}
495282527734SSukumar Swaminathan 
495382527734SSukumar Swaminathan 	cqdb = cq->qid;
495482527734SSukumar Swaminathan 	cqdb |= CQ_DB_REARM;
495582527734SSukumar Swaminathan 	if (num_entries != 0) {
495682527734SSukumar Swaminathan 		cqdb |= ((num_entries << CQ_DB_POP_SHIFT) & CQ_DB_POP_MASK);
495782527734SSukumar Swaminathan 	}
495882527734SSukumar Swaminathan 
495982527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
496082527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
496182527734SSukumar Swaminathan 	    "CQ CLEAR: %08x: pops:x%x", cqdb, num_entries);
496282527734SSukumar Swaminathan #endif
496382527734SSukumar Swaminathan 
496482527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), cqdb);
496582527734SSukumar Swaminathan 
496682527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
496782527734SSukumar Swaminathan 
496882527734SSukumar Swaminathan } /* emlxs_sli4_process_cq() */
496982527734SSukumar Swaminathan 
497082527734SSukumar Swaminathan 
497182527734SSukumar Swaminathan /*ARGSUSED*/
497282527734SSukumar Swaminathan static void
497382527734SSukumar Swaminathan emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
497482527734SSukumar Swaminathan {
4975bce54adfSSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
497682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4977bce54adfSSukumar Swaminathan #endif
497882527734SSukumar Swaminathan 	uint32_t eqdb;
497982527734SSukumar Swaminathan 	uint32_t *ptr;
498082527734SSukumar Swaminathan 	CHANNEL *cp;
498182527734SSukumar Swaminathan 	EQE_u eqe;
498282527734SSukumar Swaminathan 	uint32_t i;
498382527734SSukumar Swaminathan 	uint32_t value;
498482527734SSukumar Swaminathan 	int num_entries = 0;
4985b3660a96SSukumar Swaminathan 	off_t offset;
498682527734SSukumar Swaminathan 
498782527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
498882527734SSukumar Swaminathan 
498982527734SSukumar Swaminathan 	ptr = eq->addr.virt;
499082527734SSukumar Swaminathan 	ptr += eq->host_index;
499182527734SSukumar Swaminathan 
4992b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
4993b3660a96SSukumar Swaminathan 	    eq->addr.virt) -
4994b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
4995b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
4996b3660a96SSukumar Swaminathan 
4997b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
499882527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
499982527734SSukumar Swaminathan 
500082527734SSukumar Swaminathan 	for (;;) {
500182527734SSukumar Swaminathan 		eqe.word = *ptr;
500282527734SSukumar Swaminathan 		eqe.word = BE_SWAP32(eqe.word);
500382527734SSukumar Swaminathan 
500482527734SSukumar Swaminathan 		if (!(eqe.word & EQE_VALID))
500582527734SSukumar Swaminathan 			break;
500682527734SSukumar Swaminathan 
500782527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
500882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
500982527734SSukumar Swaminathan 		    "EQ ENTRY: %08x", eqe.word);
501082527734SSukumar Swaminathan #endif
501182527734SSukumar Swaminathan 
501282527734SSukumar Swaminathan 		*ptr = 0;
501382527734SSukumar Swaminathan 		num_entries++;
501482527734SSukumar Swaminathan 		eq->host_index++;
501582527734SSukumar Swaminathan 		if (eq->host_index >= eq->max_index) {
501682527734SSukumar Swaminathan 			eq->host_index = 0;
501782527734SSukumar Swaminathan 			ptr = eq->addr.virt;
501882527734SSukumar Swaminathan 		} else {
501982527734SSukumar Swaminathan 			ptr++;
502082527734SSukumar Swaminathan 		}
502182527734SSukumar Swaminathan 
502282527734SSukumar Swaminathan 		value = hba->sli.sli4.cq_map[eqe.entry.CQId];
502382527734SSukumar Swaminathan 
502482527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
502582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
502682527734SSukumar Swaminathan 		    "EQ ENTRY:  CQIndex:x%x: cqid:x%x", value, eqe.entry.CQId);
502782527734SSukumar Swaminathan #endif
502882527734SSukumar Swaminathan 
502982527734SSukumar Swaminathan 		emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[value]);
503082527734SSukumar Swaminathan 	}
503182527734SSukumar Swaminathan 
503282527734SSukumar Swaminathan 	eqdb = eq->qid;
503382527734SSukumar Swaminathan 	eqdb |= (EQ_DB_CLEAR | EQ_DB_EVENT | EQ_DB_REARM);
503482527734SSukumar Swaminathan 
503582527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
503682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
503782527734SSukumar Swaminathan 	    "EQ CLEAR: %08x: pops:x%x", eqdb, num_entries);
503882527734SSukumar Swaminathan #endif
503982527734SSukumar Swaminathan 
504082527734SSukumar Swaminathan 	if (num_entries != 0) {
504182527734SSukumar Swaminathan 		eqdb |= ((num_entries << EQ_DB_POP_SHIFT) & EQ_DB_POP_MASK);
504282527734SSukumar Swaminathan 		for (i = 0; i < hba->chan_count; i++) {
504382527734SSukumar Swaminathan 			cp = &hba->chan[i];
504482527734SSukumar Swaminathan 			if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) {
504582527734SSukumar Swaminathan 				cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER;
504682527734SSukumar Swaminathan 				emlxs_thread_trigger2(&cp->intr_thread,
504782527734SSukumar Swaminathan 				    emlxs_proc_channel, cp);
504882527734SSukumar Swaminathan 			}
504982527734SSukumar Swaminathan 		}
505082527734SSukumar Swaminathan 	}
505182527734SSukumar Swaminathan 
505282527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), eqdb);
505382527734SSukumar Swaminathan 
505482527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
505582527734SSukumar Swaminathan 
505682527734SSukumar Swaminathan } /* emlxs_sli4_process_eq() */
505782527734SSukumar Swaminathan 
505882527734SSukumar Swaminathan 
505982527734SSukumar Swaminathan #ifdef MSI_SUPPORT
506082527734SSukumar Swaminathan /*ARGSUSED*/
506182527734SSukumar Swaminathan static uint32_t
506282527734SSukumar Swaminathan emlxs_sli4_msi_intr(char *arg1, char *arg2)
506382527734SSukumar Swaminathan {
506482527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
5065bce54adfSSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
506682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5067bce54adfSSukumar Swaminathan #endif
506882527734SSukumar Swaminathan 	uint16_t msgid;
506982527734SSukumar Swaminathan 	int rc;
507082527734SSukumar Swaminathan 
507182527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
507282527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
507382527734SSukumar Swaminathan 	    "msiINTR arg1:%p arg2:%p", arg1, arg2);
507482527734SSukumar Swaminathan #endif
507582527734SSukumar Swaminathan 
507682527734SSukumar Swaminathan 	/* Check for legacy interrupt handling */
507782527734SSukumar Swaminathan 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
507882527734SSukumar Swaminathan 		rc = emlxs_sli4_intx_intr(arg1);
507982527734SSukumar Swaminathan 		return (rc);
508082527734SSukumar Swaminathan 	}
508182527734SSukumar Swaminathan 
508282527734SSukumar Swaminathan 	/* Get MSI message id */
508382527734SSukumar Swaminathan 	msgid = (uint16_t)((unsigned long)arg2);
508482527734SSukumar Swaminathan 
508582527734SSukumar Swaminathan 	/* Validate the message id */
508682527734SSukumar Swaminathan 	if (msgid >= hba->intr_count) {
508782527734SSukumar Swaminathan 		msgid = 0;
508882527734SSukumar Swaminathan 	}
508982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
509082527734SSukumar Swaminathan 
5091bce54adfSSukumar Swaminathan 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
509282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
509382527734SSukumar Swaminathan 		return (DDI_INTR_UNCLAIMED);
509482527734SSukumar Swaminathan 	}
509582527734SSukumar Swaminathan 
509682527734SSukumar Swaminathan 	/* The eq[] index == the MSI vector number */
509782527734SSukumar Swaminathan 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]);
509882527734SSukumar Swaminathan 
509982527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
510082527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
510182527734SSukumar Swaminathan 
510282527734SSukumar Swaminathan } /* emlxs_sli4_msi_intr() */
510382527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
510482527734SSukumar Swaminathan 
510582527734SSukumar Swaminathan 
510682527734SSukumar Swaminathan /*ARGSUSED*/
510782527734SSukumar Swaminathan static int
510882527734SSukumar Swaminathan emlxs_sli4_intx_intr(char *arg)
510982527734SSukumar Swaminathan {
511082527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
5111bce54adfSSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
511282527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5113bce54adfSSukumar Swaminathan #endif
511482527734SSukumar Swaminathan 
511582527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
511682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
511782527734SSukumar Swaminathan 	    "intxINTR arg:%p", arg);
511882527734SSukumar Swaminathan #endif
511982527734SSukumar Swaminathan 
512082527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
512182527734SSukumar Swaminathan 
5122bce54adfSSukumar Swaminathan 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
512382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
512482527734SSukumar Swaminathan 		return (DDI_INTR_UNCLAIMED);
512582527734SSukumar Swaminathan 	}
512682527734SSukumar Swaminathan 
512782527734SSukumar Swaminathan 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]);
512882527734SSukumar Swaminathan 
512982527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
513082527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
513182527734SSukumar Swaminathan } /* emlxs_sli4_intx_intr() */
513282527734SSukumar Swaminathan 
513382527734SSukumar Swaminathan 
513482527734SSukumar Swaminathan static void
513582527734SSukumar Swaminathan emlxs_sli4_hba_kill(emlxs_hba_t *hba)
513682527734SSukumar Swaminathan {
513782527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
513882527734SSukumar Swaminathan 	uint32_t j;
513982527734SSukumar Swaminathan 
514082527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
514182527734SSukumar Swaminathan 	if (hba->flag & FC_INTERLOCKED) {
514282527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
514382527734SSukumar Swaminathan 
514482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
514582527734SSukumar Swaminathan 
514682527734SSukumar Swaminathan 		return;
514782527734SSukumar Swaminathan 	}
514882527734SSukumar Swaminathan 
514982527734SSukumar Swaminathan 	j = 0;
515082527734SSukumar Swaminathan 	while (j++ < 10000) {
515182527734SSukumar Swaminathan 		if (hba->mbox_queue_flag == 0) {
515282527734SSukumar Swaminathan 			break;
515382527734SSukumar Swaminathan 		}
515482527734SSukumar Swaminathan 
515582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
515682527734SSukumar Swaminathan 		DELAYUS(100);
515782527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
515882527734SSukumar Swaminathan 	}
515982527734SSukumar Swaminathan 
516082527734SSukumar Swaminathan 	if (hba->mbox_queue_flag != 0) {
516182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
516282527734SSukumar Swaminathan 		    "Board kill failed. Mailbox busy.");
516382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
516482527734SSukumar Swaminathan 		return;
516582527734SSukumar Swaminathan 	}
516682527734SSukumar Swaminathan 
516782527734SSukumar Swaminathan 	hba->flag |= FC_INTERLOCKED;
516882527734SSukumar Swaminathan 
516982527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
517082527734SSukumar Swaminathan 
517182527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
517282527734SSukumar Swaminathan 
517382527734SSukumar Swaminathan } /* emlxs_sli4_hba_kill() */
517482527734SSukumar Swaminathan 
517582527734SSukumar Swaminathan 
517682527734SSukumar Swaminathan static void
517782527734SSukumar Swaminathan emlxs_sli4_enable_intr(emlxs_hba_t *hba)
517882527734SSukumar Swaminathan {
517982527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
518082527734SSukumar Swaminathan 	int i;
518182527734SSukumar Swaminathan 	int num_cq;
518282527734SSukumar Swaminathan 	uint32_t data;
518382527734SSukumar Swaminathan 
518482527734SSukumar Swaminathan 	hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED;
518582527734SSukumar Swaminathan 
518682527734SSukumar Swaminathan 	num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) +
518782527734SSukumar Swaminathan 	    EMLXS_CQ_OFFSET_WQ;
518882527734SSukumar Swaminathan 
518982527734SSukumar Swaminathan 	/* ARM EQ / CQs */
519082527734SSukumar Swaminathan 	for (i = 0; i < num_cq; i++) {
519182527734SSukumar Swaminathan 		data = hba->sli.sli4.cq[i].qid;
519282527734SSukumar Swaminathan 		data |= CQ_DB_REARM;
519382527734SSukumar Swaminathan 		WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), data);
519482527734SSukumar Swaminathan 	}
519582527734SSukumar Swaminathan 	for (i = 0; i < hba->intr_count; i++) {
519682527734SSukumar Swaminathan 		data = hba->sli.sli4.eq[i].qid;
519782527734SSukumar Swaminathan 		data |= (EQ_DB_REARM | EQ_DB_EVENT);
519882527734SSukumar Swaminathan 		WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), data);
519982527734SSukumar Swaminathan 	}
520082527734SSukumar Swaminathan } /* emlxs_sli4_enable_intr() */
520182527734SSukumar Swaminathan 
520282527734SSukumar Swaminathan 
520382527734SSukumar Swaminathan static void
520482527734SSukumar Swaminathan emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att)
520582527734SSukumar Swaminathan {
520682527734SSukumar Swaminathan 	if (att) {
520782527734SSukumar Swaminathan 		return;
520882527734SSukumar Swaminathan 	}
520982527734SSukumar Swaminathan 
521082527734SSukumar Swaminathan 	hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
521182527734SSukumar Swaminathan 
521282527734SSukumar Swaminathan 	/* Short of reset, we cannot disable interrupts */
521382527734SSukumar Swaminathan } /* emlxs_sli4_disable_intr() */
521482527734SSukumar Swaminathan 
521582527734SSukumar Swaminathan 
521682527734SSukumar Swaminathan static void
521782527734SSukumar Swaminathan emlxs_sli4_resource_free(emlxs_hba_t *hba)
521882527734SSukumar Swaminathan {
521982527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
522082527734SSukumar Swaminathan 	MBUF_INFO	*buf_info;
522182527734SSukumar Swaminathan 	uint32_t	i;
522282527734SSukumar Swaminathan 
5223*a9800bebSGarrett D'Amore 	emlxs_fcf_fini(hba);
522482527734SSukumar Swaminathan 
522582527734SSukumar Swaminathan 	buf_info = &hba->sli.sli4.HeaderTmplate;
522682527734SSukumar Swaminathan 	if (buf_info->virt) {
522782527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
522882527734SSukumar Swaminathan 	}
522982527734SSukumar Swaminathan 
523082527734SSukumar Swaminathan 	if (hba->sli.sli4.XRIp) {
523182527734SSukumar Swaminathan 		if ((hba->sli.sli4.XRIinuse_f !=
523282527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
523382527734SSukumar Swaminathan 		    (hba->sli.sli4.XRIinuse_b !=
523482527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
5235*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
523682527734SSukumar Swaminathan 			    "XRIs inuse during free!: %p %p != %p\n",
523782527734SSukumar Swaminathan 			    hba->sli.sli4.XRIinuse_f,
523882527734SSukumar Swaminathan 			    hba->sli.sli4.XRIinuse_b,
523982527734SSukumar Swaminathan 			    &hba->sli.sli4.XRIinuse_f);
524082527734SSukumar Swaminathan 		}
524182527734SSukumar Swaminathan 		kmem_free(hba->sli.sli4.XRIp,
524282527734SSukumar Swaminathan 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
524382527734SSukumar Swaminathan 		hba->sli.sli4.XRIp = NULL;
5244b3660a96SSukumar Swaminathan 
5245b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIfree_f =
5246b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5247b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIfree_b =
5248b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
524982527734SSukumar Swaminathan 		hba->sli.sli4.xrif_count = 0;
525082527734SSukumar Swaminathan 	}
525182527734SSukumar Swaminathan 
525282527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_EQS; i++) {
5253b3660a96SSukumar Swaminathan 		mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock);
525482527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
525582527734SSukumar Swaminathan 	}
525682527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQS; i++) {
525782527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
525882527734SSukumar Swaminathan 	}
525982527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQS; i++) {
526082527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
526182527734SSukumar Swaminathan 	}
526282527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5263b3660a96SSukumar Swaminathan 		mutex_destroy(&hba->sli.sli4.rq[i].lock);
5264b3660a96SSukumar Swaminathan 		mutex_destroy(&hba->sli.sli4.rxq[i].lock);
5265b3660a96SSukumar Swaminathan 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
526682527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
526782527734SSukumar Swaminathan 	}
526882527734SSukumar Swaminathan 
526982527734SSukumar Swaminathan 	/* Free the MQ */
5270b3660a96SSukumar Swaminathan 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
5271b3660a96SSukumar Swaminathan 
5272b3660a96SSukumar Swaminathan 	buf_info = &hba->sli.sli4.slim2;
5273b3660a96SSukumar Swaminathan 	if (buf_info->virt) {
527482527734SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA;
527582527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
5276b3660a96SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
527782527734SSukumar Swaminathan 	}
527882527734SSukumar Swaminathan 
527982527734SSukumar Swaminathan 	/* Cleanup queue ordinal mapping */
528082527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) {
528182527734SSukumar Swaminathan 		hba->sli.sli4.eq_map[i] = 0xffff;
528282527734SSukumar Swaminathan 	}
528382527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQ_IDS; i++) {
528482527734SSukumar Swaminathan 		hba->sli.sli4.cq_map[i] = 0xffff;
528582527734SSukumar Swaminathan 	}
528682527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQ_IDS; i++) {
528782527734SSukumar Swaminathan 		hba->sli.sli4.wq_map[i] = 0xffff;
528882527734SSukumar Swaminathan 	}
528982527734SSukumar Swaminathan 
529082527734SSukumar Swaminathan } /* emlxs_sli4_resource_free() */
529182527734SSukumar Swaminathan 
529282527734SSukumar Swaminathan 
529382527734SSukumar Swaminathan static int
529482527734SSukumar Swaminathan emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
529582527734SSukumar Swaminathan {
529682527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
529782527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
529882527734SSukumar Swaminathan 	MBUF_INFO	*buf_info;
529982527734SSukumar Swaminathan 	uint16_t	index;
530082527734SSukumar Swaminathan 	int		num_eq;
530182527734SSukumar Swaminathan 	int		num_wq;
5302*a9800bebSGarrett D'Amore 	uint16_t	i;
530382527734SSukumar Swaminathan 	uint32_t	j;
530482527734SSukumar Swaminathan 	uint32_t	k;
530582527734SSukumar Swaminathan 	uint32_t	word;
5306*a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
530782527734SSukumar Swaminathan 	char		buf[64];
530882527734SSukumar Swaminathan 	RQE_t		*rqe;
5309b3660a96SSukumar Swaminathan 	MBUF_INFO	*rqb;
5310b3660a96SSukumar Swaminathan 	uint64_t	phys;
5311b3660a96SSukumar Swaminathan 	uint64_t	tmp_phys;
5312b3660a96SSukumar Swaminathan 	char		*virt;
5313b3660a96SSukumar Swaminathan 	char		*tmp_virt;
5314b3660a96SSukumar Swaminathan 	void		*data_handle;
5315b3660a96SSukumar Swaminathan 	void		*dma_handle;
5316b3660a96SSukumar Swaminathan 	int32_t		size;
5317b3660a96SSukumar Swaminathan 	off_t		offset;
5318b3660a96SSukumar Swaminathan 	uint32_t	count = 0;
531982527734SSukumar Swaminathan 
5320*a9800bebSGarrett D'Amore 	emlxs_fcf_init(hba);
532182527734SSukumar Swaminathan 
5322b3660a96SSukumar Swaminathan 	/* EQs - 1 per Interrupt vector */
5323b3660a96SSukumar Swaminathan 	num_eq = hba->intr_count;
5324b3660a96SSukumar Swaminathan 	/* CQs  - number of WQs + 1 for RQs + 1 for mbox/async events */
5325b3660a96SSukumar Swaminathan 	num_wq = cfg[CFG_NUM_WQ].current * num_eq;
532682527734SSukumar Swaminathan 
5327b3660a96SSukumar Swaminathan 	/* Calculate total dmable memory we need */
5328b3660a96SSukumar Swaminathan 	/* EQ */
5329b3660a96SSukumar Swaminathan 	count += num_eq * 4096;
5330b3660a96SSukumar Swaminathan 	/* CQ */
5331b3660a96SSukumar Swaminathan 	count += (num_wq + EMLXS_CQ_OFFSET_WQ) * 4096;
5332b3660a96SSukumar Swaminathan 	/* WQ */
5333b3660a96SSukumar Swaminathan 	count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES);
5334b3660a96SSukumar Swaminathan 	/* MQ */
5335b3660a96SSukumar Swaminathan 	count +=  EMLXS_MAX_MQS * 4096;
5336b3660a96SSukumar Swaminathan 	/* RQ */
5337b3660a96SSukumar Swaminathan 	count +=  EMLXS_MAX_RQS * 4096;
5338b3660a96SSukumar Swaminathan 	/* RQB/E */
5339b3660a96SSukumar Swaminathan 	count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE);
5340b3660a96SSukumar Swaminathan 	/* SGL */
5341b3660a96SSukumar Swaminathan 	count += hba->sli.sli4.XRICount * hba->sli.sli4.mem_sgl_size;
5342b3660a96SSukumar Swaminathan 	/* RPI Head Template */
5343b3660a96SSukumar Swaminathan 	count += hba->sli.sli4.RPICount * sizeof (RPIHdrTmplate_t);
5344b3660a96SSukumar Swaminathan 
5345b3660a96SSukumar Swaminathan 	/* Allocate slim2 for SLI4 */
5346b3660a96SSukumar Swaminathan 	buf_info = &hba->sli.sli4.slim2;
5347b3660a96SSukumar Swaminathan 	buf_info->size = count;
5348b3660a96SSukumar Swaminathan 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5349b3660a96SSukumar Swaminathan 	buf_info->align = ddi_ptob(hba->dip, 1L);
5350b3660a96SSukumar Swaminathan 
5351b3660a96SSukumar Swaminathan 	(void) emlxs_mem_alloc(hba, buf_info);
535282527734SSukumar Swaminathan 
5353b3660a96SSukumar Swaminathan 	if (buf_info->virt == NULL) {
5354b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
5355b3660a96SSukumar Swaminathan 		    &emlxs_init_failed_msg,
5356b3660a96SSukumar Swaminathan 		    "Unable to allocate internal memory for SLI4: %d",
5357b3660a96SSukumar Swaminathan 		    count);
5358b3660a96SSukumar Swaminathan 		goto failed;
535982527734SSukumar Swaminathan 	}
5360b3660a96SSukumar Swaminathan 	bzero(buf_info->virt, buf_info->size);
5361b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
5362b3660a96SSukumar Swaminathan 	    buf_info->size, DDI_DMA_SYNC_FORDEV);
536382527734SSukumar Swaminathan 
5364b3660a96SSukumar Swaminathan 	/* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
5365b3660a96SSukumar Swaminathan 	data_handle = buf_info->data_handle;
5366b3660a96SSukumar Swaminathan 	dma_handle = buf_info->dma_handle;
5367b3660a96SSukumar Swaminathan 	phys = buf_info->phys;
5368b3660a96SSukumar Swaminathan 	virt = (char *)buf_info->virt;
536982527734SSukumar Swaminathan 
537082527734SSukumar Swaminathan 	/* Allocate space for queues */
5371b3660a96SSukumar Swaminathan 	size = 4096;
537282527734SSukumar Swaminathan 	for (i = 0; i < num_eq; i++) {
537382527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.eq[i].addr;
537482527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
537582527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
5376b3660a96SSukumar Swaminathan 			buf_info->size = size;
537782527734SSukumar Swaminathan 			buf_info->flags =
537882527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
537982527734SSukumar Swaminathan 			buf_info->align = ddi_ptob(hba->dip, 1L);
5380b3660a96SSukumar Swaminathan 			buf_info->phys = phys;
5381*a9800bebSGarrett D'Amore 			buf_info->virt = (void *)virt;
5382b3660a96SSukumar Swaminathan 			buf_info->data_handle = data_handle;
5383b3660a96SSukumar Swaminathan 			buf_info->dma_handle = dma_handle;
538482527734SSukumar Swaminathan 
5385b3660a96SSukumar Swaminathan 			phys += size;
5386b3660a96SSukumar Swaminathan 			virt += size;
538782527734SSukumar Swaminathan 
538882527734SSukumar Swaminathan 			hba->sli.sli4.eq[i].max_index = EQ_DEPTH;
538982527734SSukumar Swaminathan 		}
539082527734SSukumar Swaminathan 
539182527734SSukumar Swaminathan 		(void) sprintf(buf, "%s_eq%d_lastwq_lock mutex",
539282527734SSukumar Swaminathan 		    DRIVER_NAME, i);
539382527734SSukumar Swaminathan 		mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, buf,
539482527734SSukumar Swaminathan 		    MUTEX_DRIVER, NULL);
539582527734SSukumar Swaminathan 	}
5396b3660a96SSukumar Swaminathan 
5397b3660a96SSukumar Swaminathan 	size = 4096;
539882527734SSukumar Swaminathan 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
539982527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.cq[i].addr;
540082527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
540182527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
5402b3660a96SSukumar Swaminathan 			buf_info->size = size;
540382527734SSukumar Swaminathan 			buf_info->flags =
540482527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
540582527734SSukumar Swaminathan 			buf_info->align = ddi_ptob(hba->dip, 1L);
5406b3660a96SSukumar Swaminathan 			buf_info->phys = phys;
5407*a9800bebSGarrett D'Amore 			buf_info->virt = (void *)virt;
5408b3660a96SSukumar Swaminathan 			buf_info->data_handle = data_handle;
5409b3660a96SSukumar Swaminathan 			buf_info->dma_handle = dma_handle;
541082527734SSukumar Swaminathan 
5411b3660a96SSukumar Swaminathan 			phys += size;
5412b3660a96SSukumar Swaminathan 			virt += size;
541382527734SSukumar Swaminathan 
541482527734SSukumar Swaminathan 			hba->sli.sli4.cq[i].max_index = CQ_DEPTH;
541582527734SSukumar Swaminathan 		}
541682527734SSukumar Swaminathan 	}
5417b3660a96SSukumar Swaminathan 
541882527734SSukumar Swaminathan 	/* WQs - NUM_WQ config parameter * number of EQs */
5419b3660a96SSukumar Swaminathan 	size = 4096 * EMLXS_NUM_WQ_PAGES;
542082527734SSukumar Swaminathan 	for (i = 0; i < num_wq; i++) {
542182527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.wq[i].addr;
542282527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
542382527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
5424b3660a96SSukumar Swaminathan 			buf_info->size = size;
542582527734SSukumar Swaminathan 			buf_info->flags =
542682527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
542782527734SSukumar Swaminathan 			buf_info->align = ddi_ptob(hba->dip, 1L);
5428b3660a96SSukumar Swaminathan 			buf_info->phys = phys;
5429*a9800bebSGarrett D'Amore 			buf_info->virt = (void *)virt;
5430b3660a96SSukumar Swaminathan 			buf_info->data_handle = data_handle;
5431b3660a96SSukumar Swaminathan 			buf_info->dma_handle = dma_handle;
543282527734SSukumar Swaminathan 
5433b3660a96SSukumar Swaminathan 			phys += size;
5434b3660a96SSukumar Swaminathan 			virt += size;
543582527734SSukumar Swaminathan 
543682527734SSukumar Swaminathan 			hba->sli.sli4.wq[i].max_index = WQ_DEPTH;
543782527734SSukumar Swaminathan 			hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH;
543882527734SSukumar Swaminathan 		}
543982527734SSukumar Swaminathan 	}
544082527734SSukumar Swaminathan 
5441b3660a96SSukumar Swaminathan 	/* MQ */
5442b3660a96SSukumar Swaminathan 	size = 4096;
5443b3660a96SSukumar Swaminathan 	buf_info = &hba->sli.sli4.mq.addr;
5444b3660a96SSukumar Swaminathan 	if (!buf_info->virt) {
5445b3660a96SSukumar Swaminathan 		bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
5446b3660a96SSukumar Swaminathan 		buf_info->size = size;
5447b3660a96SSukumar Swaminathan 		buf_info->flags =
5448b3660a96SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5449b3660a96SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
5450b3660a96SSukumar Swaminathan 		buf_info->phys = phys;
5451*a9800bebSGarrett D'Amore 		buf_info->virt = (void *)virt;
5452b3660a96SSukumar Swaminathan 		buf_info->data_handle = data_handle;
5453b3660a96SSukumar Swaminathan 		buf_info->dma_handle = dma_handle;
5454b3660a96SSukumar Swaminathan 
5455b3660a96SSukumar Swaminathan 		phys += size;
5456b3660a96SSukumar Swaminathan 		virt += size;
5457b3660a96SSukumar Swaminathan 
5458b3660a96SSukumar Swaminathan 		hba->sli.sli4.mq.max_index = MQ_DEPTH;
5459b3660a96SSukumar Swaminathan 	}
5460b3660a96SSukumar Swaminathan 
546182527734SSukumar Swaminathan 	/* RXQs */
546282527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
546382527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
546482527734SSukumar Swaminathan 
546582527734SSukumar Swaminathan 		(void) sprintf(buf, "%s_rxq%d_lock mutex", DRIVER_NAME, i);
546682527734SSukumar Swaminathan 		mutex_init(&hba->sli.sli4.rxq[i].lock, buf, MUTEX_DRIVER, NULL);
546782527734SSukumar Swaminathan 	}
546882527734SSukumar Swaminathan 
546982527734SSukumar Swaminathan 	/* RQs */
5470b3660a96SSukumar Swaminathan 	size = 4096;
547182527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
547282527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.rq[i].addr;
547382527734SSukumar Swaminathan 		if (buf_info->virt) {
547482527734SSukumar Swaminathan 			continue;
547582527734SSukumar Swaminathan 		}
547682527734SSukumar Swaminathan 
547782527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
5478b3660a96SSukumar Swaminathan 		buf_info->size = size;
547982527734SSukumar Swaminathan 		buf_info->flags =
548082527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
548182527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
5482b3660a96SSukumar Swaminathan 		buf_info->phys = phys;
5483*a9800bebSGarrett D'Amore 		buf_info->virt = (void *)virt;
5484b3660a96SSukumar Swaminathan 		buf_info->data_handle = data_handle;
5485b3660a96SSukumar Swaminathan 		buf_info->dma_handle = dma_handle;
548682527734SSukumar Swaminathan 
5487b3660a96SSukumar Swaminathan 		phys += size;
5488b3660a96SSukumar Swaminathan 		virt += size;
548982527734SSukumar Swaminathan 
549082527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].max_index = RQ_DEPTH;
549182527734SSukumar Swaminathan 
5492b3660a96SSukumar Swaminathan 		(void) sprintf(buf, "%s_rq%d_lock mutex", DRIVER_NAME, i);
5493b3660a96SSukumar Swaminathan 		mutex_init(&hba->sli.sli4.rq[i].lock, buf, MUTEX_DRIVER, NULL);
5494b3660a96SSukumar Swaminathan 	}
549582527734SSukumar Swaminathan 
5496b3660a96SSukumar Swaminathan 	/* Setup RQE */
5497b3660a96SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5498b3660a96SSukumar Swaminathan 		size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE;
5499b3660a96SSukumar Swaminathan 		tmp_phys = phys;
5500b3660a96SSukumar Swaminathan 		tmp_virt = virt;
550182527734SSukumar Swaminathan 
550282527734SSukumar Swaminathan 		/* Initialize the RQEs */
550382527734SSukumar Swaminathan 		rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt;
550482527734SSukumar Swaminathan 		for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) {
5505b3660a96SSukumar Swaminathan 			phys = tmp_phys;
5506b3660a96SSukumar Swaminathan 			virt = tmp_virt;
550782527734SSukumar Swaminathan 			for (k = 0; k < RQB_COUNT; k++) {
5508b3660a96SSukumar Swaminathan 				word = PADDR_HI(phys);
550982527734SSukumar Swaminathan 				rqe->AddrHi = BE_SWAP32(word);
551082527734SSukumar Swaminathan 
5511b3660a96SSukumar Swaminathan 				word = PADDR_LO(phys);
551282527734SSukumar Swaminathan 				rqe->AddrLo = BE_SWAP32(word);
551382527734SSukumar Swaminathan 
5514b3660a96SSukumar Swaminathan 				rqb = &hba->sli.sli4.rq[i].
5515b3660a96SSukumar Swaminathan 				    rqb[k + (j * RQB_COUNT)];
5516b3660a96SSukumar Swaminathan 				rqb->size = size;
5517b3660a96SSukumar Swaminathan 				rqb->flags = FC_MBUF_DMA |
5518b3660a96SSukumar Swaminathan 				    FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5519b3660a96SSukumar Swaminathan 				rqb->align = ddi_ptob(hba->dip, 1L);
5520b3660a96SSukumar Swaminathan 				rqb->phys = phys;
5521*a9800bebSGarrett D'Amore 				rqb->virt = (void *)virt;
5522b3660a96SSukumar Swaminathan 				rqb->data_handle = data_handle;
5523b3660a96SSukumar Swaminathan 				rqb->dma_handle = dma_handle;
5524b3660a96SSukumar Swaminathan 
5525b3660a96SSukumar Swaminathan 				phys += size;
5526b3660a96SSukumar Swaminathan 				virt += size;
552782527734SSukumar Swaminathan #ifdef RQ_DEBUG
552882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
552982527734SSukumar Swaminathan 				    "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p tag=%08x",
553082527734SSukumar Swaminathan 				    i, j, k, mp, mp->tag);
553182527734SSukumar Swaminathan #endif
553282527734SSukumar Swaminathan 
553382527734SSukumar Swaminathan 				rqe++;
553482527734SSukumar Swaminathan 			}
553582527734SSukumar Swaminathan 		}
553682527734SSukumar Swaminathan 
5537b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
5538b3660a96SSukumar Swaminathan 		    hba->sli.sli4.rq[i].addr.virt) -
5539b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
5540b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
5541b3660a96SSukumar Swaminathan 
554282527734SSukumar Swaminathan 		/* Sync the RQ buffer list */
5543b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset,
554482527734SSukumar Swaminathan 		    hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV);
5545b3660a96SSukumar Swaminathan 	}
554682527734SSukumar Swaminathan 
5547b3660a96SSukumar Swaminathan 	if ((!hba->sli.sli4.XRIp) && (hba->sli.sli4.XRICount)) {
5548b3660a96SSukumar Swaminathan 		/* Initialize double linked lists */
5549b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIinuse_f =
5550b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5551b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIinuse_b =
5552b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5553b3660a96SSukumar Swaminathan 		hba->sli.sli4.xria_count = 0;
5554b3660a96SSukumar Swaminathan 
5555b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIfree_f =
5556b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5557b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIfree_b =
5558b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5559b3660a96SSukumar Swaminathan 		hba->sli.sli4.xria_count = 0;
5560b3660a96SSukumar Swaminathan 
5561b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
5562b3660a96SSukumar Swaminathan 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
5563b3660a96SSukumar Swaminathan 
5564*a9800bebSGarrett D'Amore 		xrip = hba->sli.sli4.XRIp;
5565b3660a96SSukumar Swaminathan 		index = hba->sli.sli4.XRIBase;
5566b3660a96SSukumar Swaminathan 		size = hba->sli.sli4.mem_sgl_size;
5567b3660a96SSukumar Swaminathan 		for (i = 0; i < hba->sli.sli4.XRICount; i++) {
5568*a9800bebSGarrett D'Amore 			xrip->sge_count =
5569b3660a96SSukumar Swaminathan 			    (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64));
5570*a9800bebSGarrett D'Amore 			xrip->XRI = index;
5571*a9800bebSGarrett D'Amore 			xrip->iotag = i;
5572*a9800bebSGarrett D'Amore 			if ((xrip->XRI == 0) || (xrip->iotag == 0)) {
5573b3660a96SSukumar Swaminathan 				index++; /* Skip XRI 0 or IOTag 0 */
5574*a9800bebSGarrett D'Amore 				xrip++;
5575b3660a96SSukumar Swaminathan 				continue;
5576b3660a96SSukumar Swaminathan 			}
5577*a9800bebSGarrett D'Amore 			/* Add xrip to end of free list */
5578*a9800bebSGarrett D'Amore 			xrip->_b = hba->sli.sli4.XRIfree_b;
5579*a9800bebSGarrett D'Amore 			hba->sli.sli4.XRIfree_b->_f = xrip;
5580*a9800bebSGarrett D'Amore 			xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5581*a9800bebSGarrett D'Amore 			hba->sli.sli4.XRIfree_b = xrip;
5582b3660a96SSukumar Swaminathan 			hba->sli.sli4.xrif_count++;
5583b3660a96SSukumar Swaminathan 
5584*a9800bebSGarrett D'Amore 			/* Allocate SGL for this xrip */
5585*a9800bebSGarrett D'Amore 			buf_info = &xrip->SGList;
5586b3660a96SSukumar Swaminathan 			buf_info->size = size;
5587b3660a96SSukumar Swaminathan 			buf_info->flags =
5588b3660a96SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5589b3660a96SSukumar Swaminathan 			buf_info->align = size;
5590b3660a96SSukumar Swaminathan 			buf_info->phys = phys;
5591*a9800bebSGarrett D'Amore 			buf_info->virt = (void *)virt;
5592b3660a96SSukumar Swaminathan 			buf_info->data_handle = data_handle;
5593b3660a96SSukumar Swaminathan 			buf_info->dma_handle = dma_handle;
5594b3660a96SSukumar Swaminathan 
5595b3660a96SSukumar Swaminathan 			phys += size;
5596b3660a96SSukumar Swaminathan 			virt += size;
5597b3660a96SSukumar Swaminathan 
5598*a9800bebSGarrett D'Amore 			xrip++;
5599b3660a96SSukumar Swaminathan 			index++;
5600b3660a96SSukumar Swaminathan 		}
560182527734SSukumar Swaminathan 	}
560282527734SSukumar Swaminathan 
5603b3660a96SSukumar Swaminathan 	size = sizeof (RPIHdrTmplate_t) * hba->sli.sli4.RPICount;
5604b3660a96SSukumar Swaminathan 	buf_info = &hba->sli.sli4.HeaderTmplate;
5605b3660a96SSukumar Swaminathan 	if ((buf_info->virt == NULL) && (hba->sli.sli4.RPICount)) {
5606b3660a96SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
5607b3660a96SSukumar Swaminathan 		buf_info->size = size;
5608b3660a96SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
560982527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
5610b3660a96SSukumar Swaminathan 		buf_info->phys = phys;
5611*a9800bebSGarrett D'Amore 		buf_info->virt = (void *)virt;
5612b3660a96SSukumar Swaminathan 		buf_info->data_handle = data_handle;
5613b3660a96SSukumar Swaminathan 		buf_info->dma_handle = dma_handle;
5614b3660a96SSukumar Swaminathan 	}
561582527734SSukumar Swaminathan 
5616b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5617b3660a96SSukumar Swaminathan 	if (hba->sli.sli4.slim2.dma_handle) {
5618b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
5619b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.dma_handle)
5620b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
5621b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
5622b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
5623b3660a96SSukumar Swaminathan 			    "emlxs_sli4_resource_alloc: hdl=%p",
5624b3660a96SSukumar Swaminathan 			    hba->sli.sli4.slim2.dma_handle);
562582527734SSukumar Swaminathan 			goto failed;
562682527734SSukumar Swaminathan 		}
562782527734SSukumar Swaminathan 	}
5628b3660a96SSukumar Swaminathan #endif
562982527734SSukumar Swaminathan 
563082527734SSukumar Swaminathan 	return (0);
563182527734SSukumar Swaminathan 
563282527734SSukumar Swaminathan failed:
563382527734SSukumar Swaminathan 
563482527734SSukumar Swaminathan 	(void) emlxs_sli4_resource_free(hba);
563582527734SSukumar Swaminathan 	return (ENOMEM);
563682527734SSukumar Swaminathan 
563782527734SSukumar Swaminathan } /* emlxs_sli4_resource_alloc */
563882527734SSukumar Swaminathan 
563982527734SSukumar Swaminathan 
5640*a9800bebSGarrett D'Amore static XRIobj_t *
5641*a9800bebSGarrett D'Amore emlxs_sli4_reserve_xri(emlxs_hba_t *hba,  RPIobj_t *rpip)
564282527734SSukumar Swaminathan {
5643*a9800bebSGarrett D'Amore 	emlxs_port_t	*port = &PPORT;
5644*a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
5645*a9800bebSGarrett D'Amore 	uint16_t	iotag;
564682527734SSukumar Swaminathan 
5647*a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_FCTAB_LOCK);
564882527734SSukumar Swaminathan 
5649*a9800bebSGarrett D'Amore 	xrip = hba->sli.sli4.XRIfree_f;
565082527734SSukumar Swaminathan 
5651*a9800bebSGarrett D'Amore 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
5652*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
565382527734SSukumar Swaminathan 
5654*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5655*a9800bebSGarrett D'Amore 		    "Unable to reserve XRI");
565682527734SSukumar Swaminathan 
5657*a9800bebSGarrett D'Amore 		return (NULL);
5658*a9800bebSGarrett D'Amore 	}
565982527734SSukumar Swaminathan 
5660*a9800bebSGarrett D'Amore 	iotag = xrip->iotag;
566182527734SSukumar Swaminathan 
5662*a9800bebSGarrett D'Amore 	if ((!iotag) ||
5663*a9800bebSGarrett D'Amore 	    ((hba->fc_table[iotag] != NULL) &&
5664*a9800bebSGarrett D'Amore 	    (hba->fc_table[iotag] != STALE_PACKET))) {
5665*a9800bebSGarrett D'Amore 		/*
5666*a9800bebSGarrett D'Amore 		 * No more command slots available, retry later
5667*a9800bebSGarrett D'Amore 		 */
5668*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5669*a9800bebSGarrett D'Amore 		    "Adapter Busy. Unable to reserve iotag");
567082527734SSukumar Swaminathan 
5671*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
5672*a9800bebSGarrett D'Amore 		return (NULL);
567382527734SSukumar Swaminathan 	}
567482527734SSukumar Swaminathan 
5675*a9800bebSGarrett D'Amore 	xrip->state = XRI_STATE_ALLOCATED;
5676*a9800bebSGarrett D'Amore 	xrip->flag = EMLXS_XRI_RESERVED;
5677*a9800bebSGarrett D'Amore 	xrip->rpip = rpip;
5678*a9800bebSGarrett D'Amore 	xrip->sbp = NULL;
567982527734SSukumar Swaminathan 
5680*a9800bebSGarrett D'Amore 	if (rpip) {
5681*a9800bebSGarrett D'Amore 		rpip->xri_count++;
5682*a9800bebSGarrett D'Amore 	}
568382527734SSukumar Swaminathan 
5684*a9800bebSGarrett D'Amore 	/* Take it off free list */
5685*a9800bebSGarrett D'Amore 	(xrip->_b)->_f = xrip->_f;
5686*a9800bebSGarrett D'Amore 	(xrip->_f)->_b = xrip->_b;
5687*a9800bebSGarrett D'Amore 	xrip->_f = NULL;
5688*a9800bebSGarrett D'Amore 	xrip->_b = NULL;
5689*a9800bebSGarrett D'Amore 	hba->sli.sli4.xrif_count--;
569082527734SSukumar Swaminathan 
569182527734SSukumar Swaminathan 	/* Add it to end of inuse list */
5692*a9800bebSGarrett D'Amore 	xrip->_b = hba->sli.sli4.XRIinuse_b;
5693*a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b->_f = xrip;
5694*a9800bebSGarrett D'Amore 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5695*a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b = xrip;
569682527734SSukumar Swaminathan 	hba->sli.sli4.xria_count++;
569782527734SSukumar Swaminathan 
569882527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
5699*a9800bebSGarrett D'Amore 	return (xrip);
570082527734SSukumar Swaminathan 
570182527734SSukumar Swaminathan } /* emlxs_sli4_reserve_xri() */
570282527734SSukumar Swaminathan 
570382527734SSukumar Swaminathan 
570482527734SSukumar Swaminathan extern uint32_t
5705*a9800bebSGarrett D'Amore emlxs_sli4_unreserve_xri(emlxs_hba_t *hba, uint16_t xri, uint32_t lock)
570682527734SSukumar Swaminathan {
570782527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5708*a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
570982527734SSukumar Swaminathan 
5710*a9800bebSGarrett D'Amore 	if (lock) {
5711*a9800bebSGarrett D'Amore 		mutex_enter(&EMLXS_FCTAB_LOCK);
5712*a9800bebSGarrett D'Amore 	}
571382527734SSukumar Swaminathan 
5714*a9800bebSGarrett D'Amore 	xrip = emlxs_sli4_find_xri(hba, xri);
5715*a9800bebSGarrett D'Amore 
5716*a9800bebSGarrett D'Amore 	if (!xrip || xrip->state == XRI_STATE_FREE) {
5717*a9800bebSGarrett D'Amore 		if (lock) {
5718*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
5719*a9800bebSGarrett D'Amore 		}
572082527734SSukumar Swaminathan 
572182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5722*a9800bebSGarrett D'Amore 		    "emlxs_sli4_unreserve_xri: xri=%x already freed.",
5723*a9800bebSGarrett D'Amore 		    xrip->XRI);
572482527734SSukumar Swaminathan 		return (0);
572582527734SSukumar Swaminathan 	}
572682527734SSukumar Swaminathan 
5727*a9800bebSGarrett D'Amore 	if (!(xrip->flag & EMLXS_XRI_RESERVED)) {
5728*a9800bebSGarrett D'Amore 		if (lock) {
5729*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
5730*a9800bebSGarrett D'Amore 		}
5731*a9800bebSGarrett D'Amore 
573282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5733*a9800bebSGarrett D'Amore 		    "emlxs_sli4_unreserve_xri: xri=%x in use.", xrip->XRI);
573482527734SSukumar Swaminathan 		return (1);
573582527734SSukumar Swaminathan 	}
573682527734SSukumar Swaminathan 
5737*a9800bebSGarrett D'Amore 	if (xrip->iotag &&
5738*a9800bebSGarrett D'Amore 	    (hba->fc_table[xrip->iotag] != NULL) &&
5739*a9800bebSGarrett D'Amore 	    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
5740*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5741*a9800bebSGarrett D'Amore 		    "emlxs_sli4_unreserve_xri:%x  sbp dropped:%p",
5742*a9800bebSGarrett D'Amore 		    xrip->XRI, hba->fc_table[xrip->iotag]);
5743*a9800bebSGarrett D'Amore 
5744*a9800bebSGarrett D'Amore 		hba->fc_table[xrip->iotag] = NULL;
574582527734SSukumar Swaminathan 		hba->io_count--;
574682527734SSukumar Swaminathan 	}
574782527734SSukumar Swaminathan 
5748*a9800bebSGarrett D'Amore 	xrip->state = XRI_STATE_FREE;
574982527734SSukumar Swaminathan 
5750*a9800bebSGarrett D'Amore 	if (xrip->rpip) {
5751*a9800bebSGarrett D'Amore 		xrip->rpip->xri_count--;
5752*a9800bebSGarrett D'Amore 		xrip->rpip = NULL;
575382527734SSukumar Swaminathan 	}
575482527734SSukumar Swaminathan 
575582527734SSukumar Swaminathan 	/* Take it off inuse list */
5756*a9800bebSGarrett D'Amore 	(xrip->_b)->_f = xrip->_f;
5757*a9800bebSGarrett D'Amore 	(xrip->_f)->_b = xrip->_b;
5758*a9800bebSGarrett D'Amore 	xrip->_f = NULL;
5759*a9800bebSGarrett D'Amore 	xrip->_b = NULL;
576082527734SSukumar Swaminathan 	hba->sli.sli4.xria_count--;
576182527734SSukumar Swaminathan 
576282527734SSukumar Swaminathan 	/* Add it to end of free list */
5763*a9800bebSGarrett D'Amore 	xrip->_b = hba->sli.sli4.XRIfree_b;
5764*a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIfree_b->_f = xrip;
5765*a9800bebSGarrett D'Amore 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5766*a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIfree_b = xrip;
576782527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count++;
576882527734SSukumar Swaminathan 
576982527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5770*a9800bebSGarrett D'Amore 	    "emlxs_sli4_unreserve_xri: xri=%x unreserved.", xrip->XRI);
577182527734SSukumar Swaminathan 
5772*a9800bebSGarrett D'Amore 	if (lock) {
5773*a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
5774*a9800bebSGarrett D'Amore 	}
577582527734SSukumar Swaminathan 
577682527734SSukumar Swaminathan 	return (0);
577782527734SSukumar Swaminathan 
577882527734SSukumar Swaminathan } /* emlxs_sli4_unreserve_xri() */
577982527734SSukumar Swaminathan 
578082527734SSukumar Swaminathan 
578182527734SSukumar Swaminathan static XRIobj_t *
578282527734SSukumar Swaminathan emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri)
578382527734SSukumar Swaminathan {
578482527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
578582527734SSukumar Swaminathan 	uint16_t	iotag;
5786*a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
578782527734SSukumar Swaminathan 
578882527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
578982527734SSukumar Swaminathan 
5790*a9800bebSGarrett D'Amore 	xrip = emlxs_sli4_find_xri(hba, xri);
5791*a9800bebSGarrett D'Amore 
5792*a9800bebSGarrett D'Amore 	if (!xrip) {
579382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
579482527734SSukumar Swaminathan 		    "emlxs_sli4_register_xri: XRI not found.");
579582527734SSukumar Swaminathan 
579682527734SSukumar Swaminathan 
579782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
579882527734SSukumar Swaminathan 		return (NULL);
579982527734SSukumar Swaminathan 	}
580082527734SSukumar Swaminathan 
5801*a9800bebSGarrett D'Amore 	if ((xrip->state == XRI_STATE_FREE) ||
5802*a9800bebSGarrett D'Amore 	    !(xrip->flag & EMLXS_XRI_RESERVED)) {
580382527734SSukumar Swaminathan 
580482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5805*a9800bebSGarrett D'Amore 		    "emlxs_sli4_register_xri: Invalid XRI. xrip=%p "
5806*a9800bebSGarrett D'Amore 		    "state=%x flag=%x",
5807*a9800bebSGarrett D'Amore 		    xrip, xrip->state, xrip->flag);
580882527734SSukumar Swaminathan 
580982527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
581082527734SSukumar Swaminathan 		return (NULL);
581182527734SSukumar Swaminathan 	}
581282527734SSukumar Swaminathan 
5813*a9800bebSGarrett D'Amore 	iotag = xrip->iotag;
581482527734SSukumar Swaminathan 
581582527734SSukumar Swaminathan 	if ((!iotag) ||
5816*a9800bebSGarrett D'Amore 	    ((hba->fc_table[iotag] != NULL) &&
5817*a9800bebSGarrett D'Amore 	    (hba->fc_table[iotag] != STALE_PACKET))) {
581882527734SSukumar Swaminathan 
581982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5820*a9800bebSGarrett D'Amore 		    "emlxs_sli4_register_xri: Invalid fc_table entry. "
582182527734SSukumar Swaminathan 		    "iotag=%x entry=%p",
582282527734SSukumar Swaminathan 		    iotag, hba->fc_table[iotag]);
582382527734SSukumar Swaminathan 
582482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
582582527734SSukumar Swaminathan 		return (NULL);
582682527734SSukumar Swaminathan 	}
582782527734SSukumar Swaminathan 
582882527734SSukumar Swaminathan 	hba->fc_table[iotag] = sbp;
582982527734SSukumar Swaminathan 	hba->io_count++;
583082527734SSukumar Swaminathan 
583182527734SSukumar Swaminathan 	sbp->iotag = iotag;
5832*a9800bebSGarrett D'Amore 	sbp->xrip = xrip;
583382527734SSukumar Swaminathan 
5834*a9800bebSGarrett D'Amore 	xrip->flag &= ~EMLXS_XRI_RESERVED;
5835*a9800bebSGarrett D'Amore 	xrip->sbp = sbp;
583682527734SSukumar Swaminathan 
583782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
583882527734SSukumar Swaminathan 
5839*a9800bebSGarrett D'Amore 	return (xrip);
584082527734SSukumar Swaminathan 
584182527734SSukumar Swaminathan } /* emlxs_sli4_register_xri() */
584282527734SSukumar Swaminathan 
584382527734SSukumar Swaminathan 
584482527734SSukumar Swaminathan /* Performs both reserve and register functions for XRI */
584582527734SSukumar Swaminathan static XRIobj_t *
5846*a9800bebSGarrett D'Amore emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rpip)
584782527734SSukumar Swaminathan {
584882527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5849*a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
585082527734SSukumar Swaminathan 	uint16_t	iotag;
585182527734SSukumar Swaminathan 
585282527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
585382527734SSukumar Swaminathan 
5854*a9800bebSGarrett D'Amore 	xrip = hba->sli.sli4.XRIfree_f;
585582527734SSukumar Swaminathan 
5856*a9800bebSGarrett D'Amore 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
585782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
585882527734SSukumar Swaminathan 
585982527734SSukumar Swaminathan 		return (NULL);
586082527734SSukumar Swaminathan 	}
586182527734SSukumar Swaminathan 
586282527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
5863*a9800bebSGarrett D'Amore 	iotag = xrip->iotag;
586482527734SSukumar Swaminathan 
586582527734SSukumar Swaminathan 	if ((!iotag) ||
5866*a9800bebSGarrett D'Amore 	    ((hba->fc_table[iotag] != NULL) &&
5867*a9800bebSGarrett D'Amore 	    (hba->fc_table[iotag] != STALE_PACKET))) {
586882527734SSukumar Swaminathan 		/*
586982527734SSukumar Swaminathan 		 * No more command slots available, retry later
587082527734SSukumar Swaminathan 		 */
587182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5872*a9800bebSGarrett D'Amore 		    "Adapter Busy. Unable to alloc iotag:(0x%x)(%p)",
5873*a9800bebSGarrett D'Amore 		    iotag, hba->fc_table[iotag]);
587482527734SSukumar Swaminathan 
587582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
587682527734SSukumar Swaminathan 		return (NULL);
587782527734SSukumar Swaminathan 	}
587882527734SSukumar Swaminathan 
587982527734SSukumar Swaminathan 	hba->fc_table[iotag] = sbp;
588082527734SSukumar Swaminathan 	hba->io_count++;
588182527734SSukumar Swaminathan 
588282527734SSukumar Swaminathan 	sbp->iotag = iotag;
5883*a9800bebSGarrett D'Amore 	sbp->xrip = xrip;
588482527734SSukumar Swaminathan 
5885*a9800bebSGarrett D'Amore 	xrip->state = XRI_STATE_ALLOCATED;
5886*a9800bebSGarrett D'Amore 	xrip->flag = 0;
5887*a9800bebSGarrett D'Amore 	xrip->rpip = rpip;
5888*a9800bebSGarrett D'Amore 	xrip->sbp = sbp;
588982527734SSukumar Swaminathan 
5890*a9800bebSGarrett D'Amore 	if (rpip) {
5891*a9800bebSGarrett D'Amore 		rpip->xri_count++;
589282527734SSukumar Swaminathan 	}
589382527734SSukumar Swaminathan 
589482527734SSukumar Swaminathan 	/* Take it off free list */
5895*a9800bebSGarrett D'Amore 	(xrip->_b)->_f = xrip->_f;
5896*a9800bebSGarrett D'Amore 	(xrip->_f)->_b = xrip->_b;
5897*a9800bebSGarrett D'Amore 	xrip->_f = NULL;
5898*a9800bebSGarrett D'Amore 	xrip->_b = NULL;
589982527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count--;
590082527734SSukumar Swaminathan 
590182527734SSukumar Swaminathan 	/* Add it to end of inuse list */
5902*a9800bebSGarrett D'Amore 	xrip->_b = hba->sli.sli4.XRIinuse_b;
5903*a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b->_f = xrip;
5904*a9800bebSGarrett D'Amore 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5905*a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b = xrip;
590682527734SSukumar Swaminathan 	hba->sli.sli4.xria_count++;
590782527734SSukumar Swaminathan 
590882527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
590982527734SSukumar Swaminathan 
5910*a9800bebSGarrett D'Amore 	return (xrip);
591182527734SSukumar Swaminathan 
591282527734SSukumar Swaminathan } /* emlxs_sli4_alloc_xri() */
591382527734SSukumar Swaminathan 
591482527734SSukumar Swaminathan 
5915*a9800bebSGarrett D'Amore /* EMLXS_FCTAB_LOCK must be held to enter */
591682527734SSukumar Swaminathan extern XRIobj_t *
591782527734SSukumar Swaminathan emlxs_sli4_find_xri(emlxs_hba_t *hba, uint16_t xri)
591882527734SSukumar Swaminathan {
591982527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5920*a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
592182527734SSukumar Swaminathan 
5922*a9800bebSGarrett D'Amore 	xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
5923*a9800bebSGarrett D'Amore 	while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
5924*a9800bebSGarrett D'Amore 		if ((xrip->state >= XRI_STATE_ALLOCATED) &&
5925*a9800bebSGarrett D'Amore 		    (xrip->XRI == xri)) {
5926*a9800bebSGarrett D'Amore 			return (xrip);
592782527734SSukumar Swaminathan 		}
5928*a9800bebSGarrett D'Amore 		xrip = xrip->_f;
592982527734SSukumar Swaminathan 	}
593082527734SSukumar Swaminathan 
5931*a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5932*a9800bebSGarrett D'Amore 	    "Unable to find XRI x%x", xri);
593382527734SSukumar Swaminathan 
5934*a9800bebSGarrett D'Amore 	return (NULL);
593582527734SSukumar Swaminathan 
5936*a9800bebSGarrett D'Amore } /* emlxs_sli4_find_xri() */
593782527734SSukumar Swaminathan 
593882527734SSukumar Swaminathan 
593982527734SSukumar Swaminathan 
594082527734SSukumar Swaminathan 
594182527734SSukumar Swaminathan extern void
5942*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xrip,
5943*a9800bebSGarrett D'Amore     uint8_t lock)
594482527734SSukumar Swaminathan {
594582527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
594682527734SSukumar Swaminathan 
5947*a9800bebSGarrett D'Amore 	if (lock) {
5948*a9800bebSGarrett D'Amore 		mutex_enter(&EMLXS_FCTAB_LOCK);
594982527734SSukumar Swaminathan 	}
595082527734SSukumar Swaminathan 
5951*a9800bebSGarrett D'Amore 	if (xrip) {
5952*a9800bebSGarrett D'Amore 		if (xrip->state == XRI_STATE_FREE) {
5953*a9800bebSGarrett D'Amore 			if (lock) {
5954*a9800bebSGarrett D'Amore 				mutex_exit(&EMLXS_FCTAB_LOCK);
5955*a9800bebSGarrett D'Amore 			}
595682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5957*a9800bebSGarrett D'Amore 			    "Free XRI:%x, Already freed", xrip->XRI);
595882527734SSukumar Swaminathan 			return;
595982527734SSukumar Swaminathan 		}
596082527734SSukumar Swaminathan 
5961*a9800bebSGarrett D'Amore 		if (xrip->iotag &&
5962*a9800bebSGarrett D'Amore 		    (hba->fc_table[xrip->iotag] != NULL) &&
5963*a9800bebSGarrett D'Amore 		    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
5964*a9800bebSGarrett D'Amore 			hba->fc_table[xrip->iotag] = NULL;
596582527734SSukumar Swaminathan 			hba->io_count--;
596682527734SSukumar Swaminathan 		}
596782527734SSukumar Swaminathan 
5968*a9800bebSGarrett D'Amore 		xrip->state = XRI_STATE_FREE;
5969*a9800bebSGarrett D'Amore 		xrip->flag  = 0;
597082527734SSukumar Swaminathan 
5971*a9800bebSGarrett D'Amore 		if (xrip->rpip) {
5972*a9800bebSGarrett D'Amore 			xrip->rpip->xri_count--;
5973*a9800bebSGarrett D'Amore 			xrip->rpip = NULL;
597482527734SSukumar Swaminathan 		}
597582527734SSukumar Swaminathan 
597682527734SSukumar Swaminathan 		/* Take it off inuse list */
5977*a9800bebSGarrett D'Amore 		(xrip->_b)->_f = xrip->_f;
5978*a9800bebSGarrett D'Amore 		(xrip->_f)->_b = xrip->_b;
5979*a9800bebSGarrett D'Amore 		xrip->_f = NULL;
5980*a9800bebSGarrett D'Amore 		xrip->_b = NULL;
598182527734SSukumar Swaminathan 		hba->sli.sli4.xria_count--;
598282527734SSukumar Swaminathan 
598382527734SSukumar Swaminathan 		/* Add it to end of free list */
5984*a9800bebSGarrett D'Amore 		xrip->_b = hba->sli.sli4.XRIfree_b;
5985*a9800bebSGarrett D'Amore 		hba->sli.sli4.XRIfree_b->_f = xrip;
5986*a9800bebSGarrett D'Amore 		xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
5987*a9800bebSGarrett D'Amore 		hba->sli.sli4.XRIfree_b = xrip;
598882527734SSukumar Swaminathan 		hba->sli.sli4.xrif_count++;
598982527734SSukumar Swaminathan 	}
599082527734SSukumar Swaminathan 
599182527734SSukumar Swaminathan 	if (sbp) {
5992*a9800bebSGarrett D'Amore 		if (!(sbp->pkt_flags & PACKET_VALID) ||
5993*a9800bebSGarrett D'Amore 		    (sbp->pkt_flags &
5994*a9800bebSGarrett D'Amore 		    (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) {
5995*a9800bebSGarrett D'Amore 			if (lock) {
5996*a9800bebSGarrett D'Amore 				mutex_exit(&EMLXS_FCTAB_LOCK);
5997*a9800bebSGarrett D'Amore 			}
5998*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5999*a9800bebSGarrett D'Amore 			    "Free XRI: sbp invalid. sbp=%p flags=%x xri=%x",
6000*a9800bebSGarrett D'Amore 			    sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0));
6001*a9800bebSGarrett D'Amore 			return;
6002*a9800bebSGarrett D'Amore 		}
600382527734SSukumar Swaminathan 
6004*a9800bebSGarrett D'Amore 		sbp->xrip = 0;
6005*a9800bebSGarrett D'Amore 
6006*a9800bebSGarrett D'Amore 		if (xrip && (xrip->iotag != sbp->iotag)) {
6007*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
600882527734SSukumar Swaminathan 			    "sbp / iotag mismatch %p iotag:%d %d", sbp,
6009*a9800bebSGarrett D'Amore 			    sbp->iotag, xrip->iotag);
601082527734SSukumar Swaminathan 		}
601182527734SSukumar Swaminathan 
601282527734SSukumar Swaminathan 		if (sbp->iotag) {
6013*a9800bebSGarrett D'Amore 			if (sbp == hba->fc_table[sbp->iotag]) {
601482527734SSukumar Swaminathan 				hba->fc_table[sbp->iotag] = NULL;
601582527734SSukumar Swaminathan 				hba->io_count--;
601682527734SSukumar Swaminathan 			}
601782527734SSukumar Swaminathan 			sbp->iotag = 0;
601882527734SSukumar Swaminathan 		}
601982527734SSukumar Swaminathan 
6020*a9800bebSGarrett D'Amore 		if (lock) {
6021*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
6022*a9800bebSGarrett D'Amore 		}
602382527734SSukumar Swaminathan 
602482527734SSukumar Swaminathan 		/* Clean up the sbp */
602582527734SSukumar Swaminathan 		mutex_enter(&sbp->mtx);
602682527734SSukumar Swaminathan 
602782527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_TXQ) {
602882527734SSukumar Swaminathan 			sbp->pkt_flags &= ~PACKET_IN_TXQ;
602982527734SSukumar Swaminathan 			hba->channel_tx_count--;
603082527734SSukumar Swaminathan 		}
603182527734SSukumar Swaminathan 
603282527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
603382527734SSukumar Swaminathan 			sbp->pkt_flags &= ~PACKET_IN_CHIPQ;
603482527734SSukumar Swaminathan 		}
603582527734SSukumar Swaminathan 
603682527734SSukumar Swaminathan 		mutex_exit(&sbp->mtx);
603782527734SSukumar Swaminathan 	} else {
6038*a9800bebSGarrett D'Amore 		if (lock) {
6039*a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
6040*a9800bebSGarrett D'Amore 		}
604182527734SSukumar Swaminathan 	}
604282527734SSukumar Swaminathan 
604382527734SSukumar Swaminathan } /* emlxs_sli4_free_xri() */
604482527734SSukumar Swaminathan 
604582527734SSukumar Swaminathan 
604682527734SSukumar Swaminathan static int
604782527734SSukumar Swaminathan emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq)
604882527734SSukumar Swaminathan {
604982527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
605082527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
6051*a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
605282527734SSukumar Swaminathan 	MATCHMAP	*mp;
605382527734SSukumar Swaminathan 	mbox_req_hdr_t 	*hdr_req;
605482527734SSukumar Swaminathan 	uint32_t	i, cnt, xri_cnt;
605582527734SSukumar Swaminathan 	uint32_t	size;
605682527734SSukumar Swaminathan 	IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl;
605782527734SSukumar Swaminathan 
605882527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
605982527734SSukumar Swaminathan 	mbq->bp = NULL;
606082527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
606182527734SSukumar Swaminathan 
606282527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) {
606382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
606482527734SSukumar Swaminathan 		    "Unable to POST_SGL. Mailbox cmd=%x  ",
606582527734SSukumar Swaminathan 		    mb->mbxCommand);
606682527734SSukumar Swaminathan 		return (EIO);
606782527734SSukumar Swaminathan 	}
6068*a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
606982527734SSukumar Swaminathan 
607082527734SSukumar Swaminathan 	/*
607182527734SSukumar Swaminathan 	 * Signifies a non embedded command
607282527734SSukumar Swaminathan 	 */
607382527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
607482527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
607582527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
607682527734SSukumar Swaminathan 
607782527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
607882527734SSukumar Swaminathan 	post_sgl =
607982527734SSukumar Swaminathan 	    (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1);
608082527734SSukumar Swaminathan 
608182527734SSukumar Swaminathan 
6082*a9800bebSGarrett D'Amore 	xrip = hba->sli.sli4.XRIp;
608382527734SSukumar Swaminathan 	cnt = hba->sli.sli4.XRICount;
608482527734SSukumar Swaminathan 	while (cnt) {
608582527734SSukumar Swaminathan 		bzero((void *) hdr_req, mp->size);
608682527734SSukumar Swaminathan 		size = mp->size - IOCTL_HEADER_SZ;
608782527734SSukumar Swaminathan 
608882527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.payload_length =
608982527734SSukumar Swaminathan 		    mp->size;
609082527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
609182527734SSukumar Swaminathan 		    IOCTL_SUBSYSTEM_FCOE;
609282527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
609382527734SSukumar Swaminathan 		    FCOE_OPCODE_CFG_POST_SGL_PAGES;
609482527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
609582527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size;
609682527734SSukumar Swaminathan 
609782527734SSukumar Swaminathan 		hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
609882527734SSukumar Swaminathan 		hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES;
609982527734SSukumar Swaminathan 		hdr_req->timeout = 0;
610082527734SSukumar Swaminathan 		hdr_req->req_length = size;
610182527734SSukumar Swaminathan 
610282527734SSukumar Swaminathan 		post_sgl->params.request.xri_count = 0;
6103*a9800bebSGarrett D'Amore 		post_sgl->params.request.xri_start = xrip->XRI;
610482527734SSukumar Swaminathan 		xri_cnt = (size - sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
610582527734SSukumar Swaminathan 		    sizeof (FCOE_SGL_PAGES);
610682527734SSukumar Swaminathan 		for (i = 0; i < xri_cnt; i++) {
610782527734SSukumar Swaminathan 
610882527734SSukumar Swaminathan 			post_sgl->params.request.xri_count++;
610982527734SSukumar Swaminathan 			post_sgl->params.request.pages[i].sgl_page0.addrLow =
6110*a9800bebSGarrett D'Amore 			    PADDR_LO(xrip->SGList.phys);
611182527734SSukumar Swaminathan 			post_sgl->params.request.pages[i].sgl_page0.addrHigh =
6112*a9800bebSGarrett D'Amore 			    PADDR_HI(xrip->SGList.phys);
611382527734SSukumar Swaminathan 			cnt--;
6114*a9800bebSGarrett D'Amore 			xrip++;
611582527734SSukumar Swaminathan 			if (cnt == 0) {
611682527734SSukumar Swaminathan 				break;
611782527734SSukumar Swaminathan 			}
611882527734SSukumar Swaminathan 		}
611982527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
612082527734SSukumar Swaminathan 		    MBX_SUCCESS) {
612182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
612282527734SSukumar Swaminathan 			    "Unable to POST_SGL. Mailbox cmd=%x status=%x "
612382527734SSukumar Swaminathan 			    "XRI cnt:%d start:%d",
612482527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus,
612582527734SSukumar Swaminathan 			    post_sgl->params.request.xri_count,
612682527734SSukumar Swaminathan 			    post_sgl->params.request.xri_start);
6127*a9800bebSGarrett D'Amore 			emlxs_mem_buf_free(hba, mp);
6128*a9800bebSGarrett D'Amore 			mbq->nonembed = NULL;
612982527734SSukumar Swaminathan 			return (EIO);
613082527734SSukumar Swaminathan 		}
613182527734SSukumar Swaminathan 	}
6132*a9800bebSGarrett D'Amore 	emlxs_mem_buf_free(hba, mp);
6133*a9800bebSGarrett D'Amore 	mbq->nonembed = NULL;
613482527734SSukumar Swaminathan 	return (0);
613582527734SSukumar Swaminathan 
613682527734SSukumar Swaminathan } /* emlxs_sli4_post_sgl_pages() */
613782527734SSukumar Swaminathan 
613882527734SSukumar Swaminathan 
613982527734SSukumar Swaminathan static int
614082527734SSukumar Swaminathan emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq)
614182527734SSukumar Swaminathan {
614282527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
614382527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
614482527734SSukumar Swaminathan 	int		i, cnt;
614582527734SSukumar Swaminathan 	uint64_t	addr;
614682527734SSukumar Swaminathan 	IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr;
614782527734SSukumar Swaminathan 
614882527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
614982527734SSukumar Swaminathan 	mbq->bp = NULL;
615082527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
615182527734SSukumar Swaminathan 
615282527734SSukumar Swaminathan 	/*
615382527734SSukumar Swaminathan 	 * Signifies an embedded command
615482527734SSukumar Swaminathan 	 */
615582527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 1;
615682527734SSukumar Swaminathan 
615782527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
615882527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
615982527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.payload_length =
616082527734SSukumar Swaminathan 	    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
616182527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
616282527734SSukumar Swaminathan 	    IOCTL_SUBSYSTEM_FCOE;
616382527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
616482527734SSukumar Swaminathan 	    FCOE_OPCODE_POST_HDR_TEMPLATES;
616582527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
616682527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
616782527734SSukumar Swaminathan 	    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
616882527734SSukumar Swaminathan 	post_hdr =
616982527734SSukumar Swaminathan 	    (IOCTL_FCOE_POST_HDR_TEMPLATES *)&mb->un.varSLIConfig.payload;
617082527734SSukumar Swaminathan 	addr = hba->sli.sli4.HeaderTmplate.phys;
617182527734SSukumar Swaminathan 	post_hdr->params.request.num_pages = 0;
617282527734SSukumar Swaminathan 	i = 0;
617382527734SSukumar Swaminathan 	cnt = hba->sli.sli4.HeaderTmplate.size;
617482527734SSukumar Swaminathan 	while (cnt > 0) {
617582527734SSukumar Swaminathan 		post_hdr->params.request.num_pages++;
617682527734SSukumar Swaminathan 		post_hdr->params.request.pages[i].addrLow = PADDR_LO(addr);
617782527734SSukumar Swaminathan 		post_hdr->params.request.pages[i].addrHigh = PADDR_HI(addr);
617882527734SSukumar Swaminathan 		i++;
617982527734SSukumar Swaminathan 		addr += 4096;
618082527734SSukumar Swaminathan 		cnt -= 4096;
618182527734SSukumar Swaminathan 	}
618282527734SSukumar Swaminathan 	post_hdr->params.request.starting_rpi_index = hba->sli.sli4.RPIBase;
618382527734SSukumar Swaminathan 
618482527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
618582527734SSukumar Swaminathan 	    MBX_SUCCESS) {
618682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
618782527734SSukumar Swaminathan 		    "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x status=%x ",
618882527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
618982527734SSukumar Swaminathan 		return (EIO);
619082527734SSukumar Swaminathan 	}
6191*a9800bebSGarrett D'Amore emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0);
619282527734SSukumar Swaminathan 	return (0);
619382527734SSukumar Swaminathan 
619482527734SSukumar Swaminathan } /* emlxs_sli4_post_hdr_tmplates() */
619582527734SSukumar Swaminathan 
619682527734SSukumar Swaminathan 
619782527734SSukumar Swaminathan static int
619882527734SSukumar Swaminathan emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq)
619982527734SSukumar Swaminathan {
620082527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
620182527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
620282527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
620382527734SSukumar Swaminathan 	IOCTL_COMMON_EQ_CREATE *eq;
620482527734SSukumar Swaminathan 	IOCTL_COMMON_CQ_CREATE *cq;
620582527734SSukumar Swaminathan 	IOCTL_FCOE_WQ_CREATE *wq;
620682527734SSukumar Swaminathan 	IOCTL_FCOE_RQ_CREATE *rq;
620782527734SSukumar Swaminathan 	IOCTL_COMMON_MQ_CREATE *mq;
6208*a9800bebSGarrett D'Amore 	IOCTL_COMMON_MCC_CREATE_EXT *mcc_ext;
620982527734SSukumar Swaminathan 	emlxs_rqdbu_t	rqdb;
6210*a9800bebSGarrett D'Amore 	uint16_t i, j;
6211*a9800bebSGarrett D'Amore 	uint16_t num_cq, total_cq;
6212*a9800bebSGarrett D'Amore 	uint16_t num_wq, total_wq;
621382527734SSukumar Swaminathan 
621482527734SSukumar Swaminathan 	/*
621582527734SSukumar Swaminathan 	 * The first CQ is reserved for ASYNC events,
621682527734SSukumar Swaminathan 	 * the second is reserved for unsol rcv, the rest
621782527734SSukumar Swaminathan 	 * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
621882527734SSukumar Swaminathan 	 */
621982527734SSukumar Swaminathan 
622082527734SSukumar Swaminathan 	/* First initialize queue ordinal mapping */
622182527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) {
622282527734SSukumar Swaminathan 		hba->sli.sli4.eq_map[i] = 0xffff;
622382527734SSukumar Swaminathan 	}
622482527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQ_IDS; i++) {
622582527734SSukumar Swaminathan 		hba->sli.sli4.cq_map[i] = 0xffff;
622682527734SSukumar Swaminathan 	}
622782527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQ_IDS; i++) {
622882527734SSukumar Swaminathan 		hba->sli.sli4.wq_map[i] = 0xffff;
622982527734SSukumar Swaminathan 	}
623082527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQ_IDS; i++) {
623182527734SSukumar Swaminathan 		hba->sli.sli4.rq_map[i] = 0xffff;
623282527734SSukumar Swaminathan 	}
623382527734SSukumar Swaminathan 
623482527734SSukumar Swaminathan 	total_cq = 0;
623582527734SSukumar Swaminathan 	total_wq = 0;
623682527734SSukumar Swaminathan 
623782527734SSukumar Swaminathan 	/* Create EQ's */
623882527734SSukumar Swaminathan 	for (i = 0; i < hba->intr_count; i++) {
623982527734SSukumar Swaminathan 		emlxs_mb_eq_create(hba, mbq, i);
624082527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
624182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
624282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
624382527734SSukumar Swaminathan 			    "Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
624482527734SSukumar Swaminathan 			    i, mb->mbxCommand, mb->mbxStatus);
624582527734SSukumar Swaminathan 			return (EIO);
624682527734SSukumar Swaminathan 		}
624782527734SSukumar Swaminathan 		eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
624882527734SSukumar Swaminathan 		hba->sli.sli4.eq[i].qid = eq->params.response.EQId;
624982527734SSukumar Swaminathan 		hba->sli.sli4.eq_map[eq->params.response.EQId] = i;
625082527734SSukumar Swaminathan 		hba->sli.sli4.eq[i].lastwq = total_wq;
625182527734SSukumar Swaminathan 
6252*a9800bebSGarrett D'Amore emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0);
625382527734SSukumar Swaminathan 		num_wq = cfg[CFG_NUM_WQ].current;
625482527734SSukumar Swaminathan 		num_cq = num_wq;
625582527734SSukumar Swaminathan 		if (i == 0) {
625682527734SSukumar Swaminathan 			/* One for RQ handling, one for mbox/event handling */
625782527734SSukumar Swaminathan 			num_cq += EMLXS_CQ_OFFSET_WQ;
625882527734SSukumar Swaminathan 		}
625982527734SSukumar Swaminathan 
626082527734SSukumar Swaminathan 		for (j = 0; j < num_cq; j++) {
626182527734SSukumar Swaminathan 			/* Reuse mbq from previous mbox */
626282527734SSukumar Swaminathan 			bzero(mbq, sizeof (MAILBOXQ));
626382527734SSukumar Swaminathan 
626482527734SSukumar Swaminathan 			hba->sli.sli4.cq[total_cq].eqid =
626582527734SSukumar Swaminathan 			    hba->sli.sli4.eq[i].qid;
626682527734SSukumar Swaminathan 
626782527734SSukumar Swaminathan 			emlxs_mb_cq_create(hba, mbq, total_cq);
626882527734SSukumar Swaminathan 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
626982527734SSukumar Swaminathan 			    MBX_SUCCESS) {
627082527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
627182527734SSukumar Swaminathan 				    &emlxs_init_failed_msg, "Unable to Create "
627282527734SSukumar Swaminathan 				    "CQ %d: Mailbox cmd=%x status=%x ",
627382527734SSukumar Swaminathan 				    total_cq, mb->mbxCommand, mb->mbxStatus);
627482527734SSukumar Swaminathan 				return (EIO);
627582527734SSukumar Swaminathan 			}
627682527734SSukumar Swaminathan 			cq = (IOCTL_COMMON_CQ_CREATE *)
627782527734SSukumar Swaminathan 			    &mb->un.varSLIConfig.payload;
627882527734SSukumar Swaminathan 			hba->sli.sli4.cq[total_cq].qid =
627982527734SSukumar Swaminathan 			    cq->params.response.CQId;
628082527734SSukumar Swaminathan 			hba->sli.sli4.cq_map[cq->params.response.CQId] =
628182527734SSukumar Swaminathan 			    total_cq;
628282527734SSukumar Swaminathan 
628382527734SSukumar Swaminathan 			switch (total_cq) {
628482527734SSukumar Swaminathan 			case EMLXS_CQ_MBOX:
628582527734SSukumar Swaminathan 				/* First CQ is for async event handling */
628682527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
628782527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP1;
628882527734SSukumar Swaminathan 				break;
628982527734SSukumar Swaminathan 
629082527734SSukumar Swaminathan 			case EMLXS_CQ_RCV:
629182527734SSukumar Swaminathan 				/* Second CQ is for unsol receive handling */
629282527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
629382527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP2;
629482527734SSukumar Swaminathan 				break;
629582527734SSukumar Swaminathan 
629682527734SSukumar Swaminathan 			default:
629782527734SSukumar Swaminathan 				/* Setup CQ to channel mapping */
629882527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
629982527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP2;
630082527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].channelp =
630182527734SSukumar Swaminathan 				    &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ];
630282527734SSukumar Swaminathan 				break;
630382527734SSukumar Swaminathan 			}
6304*a9800bebSGarrett D'Amore emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb, 18, 0);
630582527734SSukumar Swaminathan 			total_cq++;
630682527734SSukumar Swaminathan 		}
630782527734SSukumar Swaminathan 
630882527734SSukumar Swaminathan 		for (j = 0; j < num_wq; j++) {
630982527734SSukumar Swaminathan 			/* Reuse mbq from previous mbox */
631082527734SSukumar Swaminathan 			bzero(mbq, sizeof (MAILBOXQ));
631182527734SSukumar Swaminathan 
631282527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].cqid =
631382527734SSukumar Swaminathan 			    hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid;
631482527734SSukumar Swaminathan 
631582527734SSukumar Swaminathan 			emlxs_mb_wq_create(hba, mbq, total_wq);
631682527734SSukumar Swaminathan 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
631782527734SSukumar Swaminathan 			    MBX_SUCCESS) {
631882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
631982527734SSukumar Swaminathan 				    &emlxs_init_failed_msg, "Unable to Create "
632082527734SSukumar Swaminathan 				    "WQ %d: Mailbox cmd=%x status=%x ",
632182527734SSukumar Swaminathan 				    total_wq, mb->mbxCommand, mb->mbxStatus);
632282527734SSukumar Swaminathan 				return (EIO);
632382527734SSukumar Swaminathan 			}
632482527734SSukumar Swaminathan 			wq = (IOCTL_FCOE_WQ_CREATE *)
632582527734SSukumar Swaminathan 			    &mb->un.varSLIConfig.payload;
632682527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].qid =
632782527734SSukumar Swaminathan 			    wq->params.response.WQId;
632882527734SSukumar Swaminathan 			hba->sli.sli4.wq_map[wq->params.response.WQId] =
632982527734SSukumar Swaminathan 			    total_wq;
633082527734SSukumar Swaminathan 
633182527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].cqid =
633282527734SSukumar Swaminathan 			    hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid;
6333*a9800bebSGarrett D'Amore emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb, 18, 0);
633482527734SSukumar Swaminathan 			total_wq++;
633582527734SSukumar Swaminathan 		}
6336*a9800bebSGarrett D'Amore 		hba->last_msiid = i;
633782527734SSukumar Swaminathan 	}
633882527734SSukumar Swaminathan 
633982527734SSukumar Swaminathan 	/* We assume 1 RQ pair will handle ALL incoming data */
634082527734SSukumar Swaminathan 	/* Create RQs */
634182527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
634282527734SSukumar Swaminathan 		/* Personalize the RQ */
634382527734SSukumar Swaminathan 		switch (i) {
634482527734SSukumar Swaminathan 		case 0:
634582527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid =
634682527734SSukumar Swaminathan 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
634782527734SSukumar Swaminathan 			break;
634882527734SSukumar Swaminathan 		case 1:
634982527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid =
635082527734SSukumar Swaminathan 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
635182527734SSukumar Swaminathan 			break;
635282527734SSukumar Swaminathan 		default:
635382527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid = 0xffff;
635482527734SSukumar Swaminathan 		}
635582527734SSukumar Swaminathan 
635682527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
635782527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
635882527734SSukumar Swaminathan 
635982527734SSukumar Swaminathan 		emlxs_mb_rq_create(hba, mbq, i);
636082527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
636182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
636282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
636382527734SSukumar Swaminathan 			    "Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
636482527734SSukumar Swaminathan 			    i, mb->mbxCommand, mb->mbxStatus);
636582527734SSukumar Swaminathan 			return (EIO);
636682527734SSukumar Swaminathan 		}
636782527734SSukumar Swaminathan 		rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
636882527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].qid = rq->params.response.RQId;
636982527734SSukumar Swaminathan 		hba->sli.sli4.rq_map[rq->params.response.RQId] = i;
6370*a9800bebSGarrett D'Amore emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0);
637182527734SSukumar Swaminathan 
637282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
637382527734SSukumar Swaminathan 		    "RQ CREATE: rq[%d].qid=%d cqid=%d",
637482527734SSukumar Swaminathan 		    i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid);
637582527734SSukumar Swaminathan 
637682527734SSukumar Swaminathan 		/* Initialize the host_index */
637782527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].host_index = 0;
637882527734SSukumar Swaminathan 
637982527734SSukumar Swaminathan 		/* If Data queue was just created, */
638082527734SSukumar Swaminathan 		/* then post buffers using the header qid */
638182527734SSukumar Swaminathan 		if ((i & 0x1)) {
638282527734SSukumar Swaminathan 			/* Ring the RQ doorbell to post buffers */
638382527734SSukumar Swaminathan 			rqdb.word = 0;
638482527734SSukumar Swaminathan 			rqdb.db.Qid = hba->sli.sli4.rq[i-1].qid;
638582527734SSukumar Swaminathan 			rqdb.db.NumPosted = RQB_COUNT;
638682527734SSukumar Swaminathan 
638782527734SSukumar Swaminathan 			WRITE_BAR2_REG(hba, FC_RQDB_REG(hba), rqdb.word);
638882527734SSukumar Swaminathan 
638982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
639082527734SSukumar Swaminathan 			    "RQ CREATE: Doorbell rang: qid=%d count=%d",
639182527734SSukumar Swaminathan 			    hba->sli.sli4.rq[i-1].qid, RQB_COUNT);
639282527734SSukumar Swaminathan 		}
639382527734SSukumar Swaminathan 	}
639482527734SSukumar Swaminathan 
639582527734SSukumar Swaminathan 	/* Create MQ */
639682527734SSukumar Swaminathan 
639782527734SSukumar Swaminathan 	/* Personalize the MQ */
639882527734SSukumar Swaminathan 	hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid;
639982527734SSukumar Swaminathan 
640082527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
640182527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
640282527734SSukumar Swaminathan 
6403*a9800bebSGarrett D'Amore 	emlxs_mb_mcc_create_ext(hba, mbq);
640482527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
640582527734SSukumar Swaminathan 	    MBX_SUCCESS) {
640682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6407*a9800bebSGarrett D'Amore 		    "Unable to Create MCC_EXT %d: Mailbox cmd=%x status=%x ",
640882527734SSukumar Swaminathan 		    i, mb->mbxCommand, mb->mbxStatus);
640982527734SSukumar Swaminathan 
6410*a9800bebSGarrett D'Amore 		/* Reuse mbq from previous mbox */
6411*a9800bebSGarrett D'Amore 		bzero(mbq, sizeof (MAILBOXQ));
641282527734SSukumar Swaminathan 
6413*a9800bebSGarrett D'Amore 		emlxs_mb_mq_create(hba, mbq);
6414*a9800bebSGarrett D'Amore 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6415*a9800bebSGarrett D'Amore 		    MBX_SUCCESS) {
6416*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6417*a9800bebSGarrett D'Amore 			    "Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
6418*a9800bebSGarrett D'Amore 			    i, mb->mbxCommand, mb->mbxStatus);
6419*a9800bebSGarrett D'Amore 			return (EIO);
6420*a9800bebSGarrett D'Amore 		}
642182527734SSukumar Swaminathan 
6422*a9800bebSGarrett D'Amore 		mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
6423*a9800bebSGarrett D'Amore 		hba->sli.sli4.mq.qid = mq->params.response.MQId;
642482527734SSukumar Swaminathan 		return (0);
642582527734SSukumar Swaminathan 	}
642682527734SSukumar Swaminathan 
6427*a9800bebSGarrett D'Amore 	mcc_ext = (IOCTL_COMMON_MCC_CREATE_EXT *)&mb->un.varSLIConfig.payload;
6428*a9800bebSGarrett D'Amore 	hba->sli.sli4.mq.qid = mcc_ext->params.response.id;
642982527734SSukumar Swaminathan 	return (0);
643082527734SSukumar Swaminathan 
6431*a9800bebSGarrett D'Amore } /* emlxs_sli4_create_queues() */
643282527734SSukumar Swaminathan 
643382527734SSukumar Swaminathan 
643482527734SSukumar Swaminathan /*ARGSUSED*/
643582527734SSukumar Swaminathan extern int
643682527734SSukumar Swaminathan emlxs_sli4_check_fcf_config(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec)
643782527734SSukumar Swaminathan {
643882527734SSukumar Swaminathan 	int i;
643982527734SSukumar Swaminathan 
644082527734SSukumar Swaminathan 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
644182527734SSukumar Swaminathan 		if (!hba->sli.sli4.cfgFCOE.length) {
644282527734SSukumar Swaminathan 			/* Nothing specified, so everything matches */
644382527734SSukumar Swaminathan 			/* For nonFIP only use index 0 */
644482527734SSukumar Swaminathan 			if (fcfrec->fcf_index == 0) {
644582527734SSukumar Swaminathan 				return (1);  /* success */
644682527734SSukumar Swaminathan 			}
644782527734SSukumar Swaminathan 			return (0);
644882527734SSukumar Swaminathan 		}
644982527734SSukumar Swaminathan 
645082527734SSukumar Swaminathan 		/* Just check FCMap for now */
645182527734SSukumar Swaminathan 		if (bcmp((char *)fcfrec->fc_map,
645282527734SSukumar Swaminathan 		    hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) {
645382527734SSukumar Swaminathan 			return (1);  /* success */
645482527734SSukumar Swaminathan 		}
645582527734SSukumar Swaminathan 		return (0);
645682527734SSukumar Swaminathan 	}
645782527734SSukumar Swaminathan 
645882527734SSukumar Swaminathan 	/* For FIP mode, the FCF record must match Config Region 23 */
645982527734SSukumar Swaminathan 
646082527734SSukumar Swaminathan 	if (!hba->sli.sli4.cfgFCF.length) {
646182527734SSukumar Swaminathan 		/* Nothing specified, so everything matches */
646282527734SSukumar Swaminathan 		return (1);  /* success */
646382527734SSukumar Swaminathan 	}
646482527734SSukumar Swaminathan 
646582527734SSukumar Swaminathan 	/* Just check FabricName for now */
646682527734SSukumar Swaminathan 	for (i = 0; i < MAX_FCFCONNECTLIST_ENTRIES; i++) {
646782527734SSukumar Swaminathan 		if ((hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) &&
6468*a9800bebSGarrett D'Amore 		    (bcmp((char *)fcfrec->fabric_name_identifier,
6469*a9800bebSGarrett D'Amore 		    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0)) {
6470*a9800bebSGarrett D'Amore 			return (1);  /* success */
647182527734SSukumar Swaminathan 		}
647282527734SSukumar Swaminathan 	}
6473*a9800bebSGarrett D'Amore 	return (0);
647482527734SSukumar Swaminathan 
6475*a9800bebSGarrett D'Amore } /* emlxs_sli4_check_fcf_config() */
647682527734SSukumar Swaminathan 
647782527734SSukumar Swaminathan 
647882527734SSukumar Swaminathan extern void
647982527734SSukumar Swaminathan emlxs_sli4_timer(emlxs_hba_t *hba)
648082527734SSukumar Swaminathan {
648182527734SSukumar Swaminathan 	/* Perform SLI4 level timer checks */
648282527734SSukumar Swaminathan 
6483*a9800bebSGarrett D'Amore 	emlxs_fcf_timer_notify(hba);
6484*a9800bebSGarrett D'Amore 
648582527734SSukumar Swaminathan 	emlxs_sli4_timer_check_mbox(hba);
648682527734SSukumar Swaminathan 
648782527734SSukumar Swaminathan 	return;
648882527734SSukumar Swaminathan 
648982527734SSukumar Swaminathan } /* emlxs_sli4_timer() */
649082527734SSukumar Swaminathan 
649182527734SSukumar Swaminathan 
649282527734SSukumar Swaminathan static void
649382527734SSukumar Swaminathan emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba)
649482527734SSukumar Swaminathan {
649582527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
649682527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
649782527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
649882527734SSukumar Swaminathan 
649982527734SSukumar Swaminathan 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
650082527734SSukumar Swaminathan 		return;
650182527734SSukumar Swaminathan 	}
650282527734SSukumar Swaminathan 
650382527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
650482527734SSukumar Swaminathan 
650582527734SSukumar Swaminathan 	/* Return if timer hasn't expired */
650682527734SSukumar Swaminathan 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
650782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
650882527734SSukumar Swaminathan 		return;
650982527734SSukumar Swaminathan 	}
6510*a9800bebSGarrett D'Amore 
6511*a9800bebSGarrett D'Amore 	/* The first to service the mbox queue will clear the timer */
651282527734SSukumar Swaminathan 	hba->mbox_timer = 0;
651382527734SSukumar Swaminathan 
651482527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
651582527734SSukumar Swaminathan 		if (hba->mbox_mbq) {
651682527734SSukumar Swaminathan 			mb = (MAILBOX *)hba->mbox_mbq;
651782527734SSukumar Swaminathan 		}
651882527734SSukumar Swaminathan 	}
651982527734SSukumar Swaminathan 
652082527734SSukumar Swaminathan 	if (mb) {
652182527734SSukumar Swaminathan 		switch (hba->mbox_queue_flag) {
652282527734SSukumar Swaminathan 		case MBX_NOWAIT:
652382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
652482527734SSukumar Swaminathan 			    "%s: Nowait.",
652582527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
652682527734SSukumar Swaminathan 			break;
652782527734SSukumar Swaminathan 
652882527734SSukumar Swaminathan 		case MBX_SLEEP:
652982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
653082527734SSukumar Swaminathan 			    "%s: mb=%p Sleep.",
653182527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
653282527734SSukumar Swaminathan 			    mb);
653382527734SSukumar Swaminathan 			break;
653482527734SSukumar Swaminathan 
653582527734SSukumar Swaminathan 		case MBX_POLL:
653682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
653782527734SSukumar Swaminathan 			    "%s: mb=%p Polled.",
653882527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
653982527734SSukumar Swaminathan 			    mb);
654082527734SSukumar Swaminathan 			break;
654182527734SSukumar Swaminathan 
654282527734SSukumar Swaminathan 		default:
654382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
654482527734SSukumar Swaminathan 			    "%s: mb=%p (%d).",
654582527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
654682527734SSukumar Swaminathan 			    mb, hba->mbox_queue_flag);
654782527734SSukumar Swaminathan 			break;
654882527734SSukumar Swaminathan 		}
654982527734SSukumar Swaminathan 	} else {
655082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
655182527734SSukumar Swaminathan 	}
655282527734SSukumar Swaminathan 
655382527734SSukumar Swaminathan 	hba->flag |= FC_MBOX_TIMEOUT;
655482527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
655582527734SSukumar Swaminathan 
655682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
655782527734SSukumar Swaminathan 
655882527734SSukumar Swaminathan 	/* Perform mailbox cleanup */
655982527734SSukumar Swaminathan 	/* This will wake any sleeping or polling threads */
656082527734SSukumar Swaminathan 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
656182527734SSukumar Swaminathan 
656282527734SSukumar Swaminathan 	/* Trigger adapter shutdown */
6563*a9800bebSGarrett D'Amore 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
656482527734SSukumar Swaminathan 
656582527734SSukumar Swaminathan 	return;
656682527734SSukumar Swaminathan 
656782527734SSukumar Swaminathan } /* emlxs_sli4_timer_check_mbox() */
656882527734SSukumar Swaminathan 
656982527734SSukumar Swaminathan 
657082527734SSukumar Swaminathan extern void
6571*a9800bebSGarrett D'Amore emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err)
657282527734SSukumar Swaminathan {
657382527734SSukumar Swaminathan 	void *msg;
657482527734SSukumar Swaminathan 
657582527734SSukumar Swaminathan 	if (err) {
657682527734SSukumar Swaminathan 		msg = &emlxs_sli_err_msg;
657782527734SSukumar Swaminathan 	} else {
657882527734SSukumar Swaminathan 		msg = &emlxs_sli_detail_msg;
657982527734SSukumar Swaminathan 	}
658082527734SSukumar Swaminathan 
658182527734SSukumar Swaminathan 	if (cnt) {
658282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
658382527734SSukumar Swaminathan 		    "%s00:  %08x %08x %08x %08x %08x %08x", str, *iptr,
658482527734SSukumar Swaminathan 		    *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5));
658582527734SSukumar Swaminathan 	}
658682527734SSukumar Swaminathan 	if (cnt > 6) {
658782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
658882527734SSukumar Swaminathan 		    "%s06:  %08x %08x %08x %08x %08x %08x", str, *(iptr+6),
658982527734SSukumar Swaminathan 		    *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11));
659082527734SSukumar Swaminathan 	}
659182527734SSukumar Swaminathan 	if (cnt > 12) {
659282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
659382527734SSukumar Swaminathan 		    "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12),
659482527734SSukumar Swaminathan 		    *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17));
659582527734SSukumar Swaminathan 	}
659682527734SSukumar Swaminathan 	if (cnt > 18) {
659782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
659882527734SSukumar Swaminathan 		    "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18),
659982527734SSukumar Swaminathan 		    *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23));
660082527734SSukumar Swaminathan 	}
660182527734SSukumar Swaminathan 	if (cnt > 24) {
660282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
660382527734SSukumar Swaminathan 		    "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24),
660482527734SSukumar Swaminathan 		    *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29));
660582527734SSukumar Swaminathan 	}
660682527734SSukumar Swaminathan 	if (cnt > 30) {
660782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
660882527734SSukumar Swaminathan 		    "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30),
660982527734SSukumar Swaminathan 		    *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35));
661082527734SSukumar Swaminathan 	}
661182527734SSukumar Swaminathan 	if (cnt > 36) {
661282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
661382527734SSukumar Swaminathan 		    "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36),
661482527734SSukumar Swaminathan 		    *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41));
661582527734SSukumar Swaminathan 	}
661682527734SSukumar Swaminathan 
661782527734SSukumar Swaminathan } /* emlxs_data_dump() */
661882527734SSukumar Swaminathan 
661982527734SSukumar Swaminathan 
662082527734SSukumar Swaminathan extern void
662182527734SSukumar Swaminathan emlxs_ue_dump(emlxs_hba_t *hba, char *str)
662282527734SSukumar Swaminathan {
662382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
662482527734SSukumar Swaminathan 	uint32_t ue_h;
662582527734SSukumar Swaminathan 	uint32_t ue_l;
662682527734SSukumar Swaminathan 	uint32_t on1;
662782527734SSukumar Swaminathan 	uint32_t on2;
662882527734SSukumar Swaminathan 
662982527734SSukumar Swaminathan 	ue_l = ddi_get32(hba->pci_acc_handle,
663082527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET));
663182527734SSukumar Swaminathan 	ue_h = ddi_get32(hba->pci_acc_handle,
663282527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET));
663382527734SSukumar Swaminathan 	on1 = ddi_get32(hba->pci_acc_handle,
663482527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
663582527734SSukumar Swaminathan 	on2 = ddi_get32(hba->pci_acc_handle,
663682527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
663782527734SSukumar Swaminathan 
663882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
663982527734SSukumar Swaminathan 	    "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
664082527734SSukumar Swaminathan 	    ue_l, ue_h, on1, on2);
664182527734SSukumar Swaminathan 
664282527734SSukumar Swaminathan #ifdef FMA_SUPPORT
664382527734SSukumar Swaminathan 	/* Access handle validation */
664482527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
664582527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
664682527734SSukumar Swaminathan 
664782527734SSukumar Swaminathan } /* emlxs_ue_dump() */
664882527734SSukumar Swaminathan 
664982527734SSukumar Swaminathan 
6650*a9800bebSGarrett D'Amore static void
665182527734SSukumar Swaminathan emlxs_sli4_poll_erratt(emlxs_hba_t *hba)
665282527734SSukumar Swaminathan {
665382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
665482527734SSukumar Swaminathan 	uint32_t ue_h;
665582527734SSukumar Swaminathan 	uint32_t ue_l;
665682527734SSukumar Swaminathan 
665782527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
665882527734SSukumar Swaminathan 		return;
665982527734SSukumar Swaminathan 	}
666082527734SSukumar Swaminathan 
6661fe199829SSukumar Swaminathan 	ue_l = ddi_get32(hba->pci_acc_handle,
6662fe199829SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET));
6663fe199829SSukumar Swaminathan 	ue_h = ddi_get32(hba->pci_acc_handle,
6664fe199829SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET));
666582527734SSukumar Swaminathan 
6666fe199829SSukumar Swaminathan 	if ((~hba->sli.sli4.ue_mask_lo & ue_l) ||
6667*a9800bebSGarrett D'Amore 	    (~hba->sli.sli4.ue_mask_hi & ue_h) ||
6668*a9800bebSGarrett D'Amore 	    (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
666982527734SSukumar Swaminathan 		/* Unrecoverable error detected */
667082527734SSukumar Swaminathan 		/* Shut the HBA down */
667182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
6672fe199829SSukumar Swaminathan 		    "Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x "
6673fe199829SSukumar Swaminathan 		    "maskHigh:%08x",
6674fe199829SSukumar Swaminathan 		    ue_l, ue_h, hba->sli.sli4.ue_mask_lo,
6675fe199829SSukumar Swaminathan 		    hba->sli.sli4.ue_mask_hi);
667682527734SSukumar Swaminathan 
667782527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
667882527734SSukumar Swaminathan 
667982527734SSukumar Swaminathan 		emlxs_sli4_hba_flush_chipq(hba);
668082527734SSukumar Swaminathan 
6681*a9800bebSGarrett D'Amore 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
668282527734SSukumar Swaminathan 	}
668382527734SSukumar Swaminathan 
668482527734SSukumar Swaminathan } /* emlxs_sli4_poll_erratt() */
668582527734SSukumar Swaminathan 
6686*a9800bebSGarrett D'Amore 
6687*a9800bebSGarrett D'Amore extern uint32_t
6688*a9800bebSGarrett D'Amore emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
6689*a9800bebSGarrett D'Amore     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
669082527734SSukumar Swaminathan {
669182527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
6692*a9800bebSGarrett D'Amore 	NODELIST	*node;
6693*a9800bebSGarrett D'Amore 	RPIobj_t	*rpip;
6694*a9800bebSGarrett D'Amore 	uint32_t	rval;
6695*a9800bebSGarrett D'Amore 
6696*a9800bebSGarrett D'Amore 	/* Check for invalid node ids to register */
6697*a9800bebSGarrett D'Amore 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
6698*a9800bebSGarrett D'Amore 		return (1);
6699*a9800bebSGarrett D'Amore 	}
6700*a9800bebSGarrett D'Amore 
6701*a9800bebSGarrett D'Amore 	if (did & 0xff000000) {
6702*a9800bebSGarrett D'Amore 		return (1);
6703*a9800bebSGarrett D'Amore 	}
6704*a9800bebSGarrett D'Amore 
6705*a9800bebSGarrett D'Amore 	if ((rval = emlxs_mb_check_sparm(hba, param))) {
6706*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6707*a9800bebSGarrett D'Amore 		    "Invalid service parameters. did=%06x rval=%d", did,
6708*a9800bebSGarrett D'Amore 		    rval);
6709*a9800bebSGarrett D'Amore 
6710*a9800bebSGarrett D'Amore 		return (1);
6711*a9800bebSGarrett D'Amore 	}
6712*a9800bebSGarrett D'Amore 
6713*a9800bebSGarrett D'Amore 	/* Check if the node limit has been reached */
6714*a9800bebSGarrett D'Amore 	if (port->node_count >= hba->max_nodes) {
6715*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6716*a9800bebSGarrett D'Amore 		    "Limit reached. did=%06x count=%d", did,
6717*a9800bebSGarrett D'Amore 		    port->node_count);
6718*a9800bebSGarrett D'Amore 
6719*a9800bebSGarrett D'Amore 		return (1);
6720*a9800bebSGarrett D'Amore 	}
6721*a9800bebSGarrett D'Amore 
6722*a9800bebSGarrett D'Amore 	node = emlxs_node_find_did(port, did);
6723*a9800bebSGarrett D'Amore 	rpip = EMLXS_NODE_TO_RPI(port, node);
6724*a9800bebSGarrett D'Amore 
6725*a9800bebSGarrett D'Amore 	rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp,
6726*a9800bebSGarrett D'Amore 	    (void *)ubp, (void *)iocbq);
6727*a9800bebSGarrett D'Amore 
6728*a9800bebSGarrett D'Amore 	return (rval);
6729*a9800bebSGarrett D'Amore 
6730*a9800bebSGarrett D'Amore } /* emlxs_sli4_reg_did() */
6731*a9800bebSGarrett D'Amore 
6732*a9800bebSGarrett D'Amore 
6733*a9800bebSGarrett D'Amore extern uint32_t
6734*a9800bebSGarrett D'Amore emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node,
6735*a9800bebSGarrett D'Amore     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
6736*a9800bebSGarrett D'Amore {
6737*a9800bebSGarrett D'Amore 	RPIobj_t	*rpip;
6738*a9800bebSGarrett D'Amore 	uint32_t	rval;
6739*a9800bebSGarrett D'Amore 
6740*a9800bebSGarrett D'Amore 	if (!node) {
6741*a9800bebSGarrett D'Amore 		/* Unreg all nodes */
6742*a9800bebSGarrett D'Amore 		(void) emlxs_sli4_unreg_all_nodes(port);
6743*a9800bebSGarrett D'Amore 		return (1);
6744*a9800bebSGarrett D'Amore 	}
6745*a9800bebSGarrett D'Amore 
6746*a9800bebSGarrett D'Amore 	/* Check for base node */
6747*a9800bebSGarrett D'Amore 	if (node == &port->node_base) {
6748*a9800bebSGarrett D'Amore 		/* Just flush base node */
6749*a9800bebSGarrett D'Amore 		(void) emlxs_tx_node_flush(port, &port->node_base,
6750*a9800bebSGarrett D'Amore 		    0, 0, 0);
6751*a9800bebSGarrett D'Amore 
6752*a9800bebSGarrett D'Amore 		(void) emlxs_chipq_node_flush(port, 0,
6753*a9800bebSGarrett D'Amore 		    &port->node_base, 0);
6754*a9800bebSGarrett D'Amore 
6755*a9800bebSGarrett D'Amore 		port->did = 0;
6756*a9800bebSGarrett D'Amore 
6757*a9800bebSGarrett D'Amore 		/* Return now */
6758*a9800bebSGarrett D'Amore 		return (1);
6759*a9800bebSGarrett D'Amore 	}
6760*a9800bebSGarrett D'Amore 
6761*a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6762*a9800bebSGarrett D'Amore 	    "unreg_node:%p did=%x rpi=%d",
6763*a9800bebSGarrett D'Amore 	    node, node->nlp_DID, node->nlp_Rpi);
6764*a9800bebSGarrett D'Amore 
6765*a9800bebSGarrett D'Amore 	rpip = EMLXS_NODE_TO_RPI(port, node);
6766*a9800bebSGarrett D'Amore 
6767*a9800bebSGarrett D'Amore 	if (!rpip) {
6768*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6769*a9800bebSGarrett D'Amore 		    "unreg_node:%p did=%x rpi=%d. RPI not found.",
6770*a9800bebSGarrett D'Amore 		    node, node->nlp_DID, node->nlp_Rpi);
6771*a9800bebSGarrett D'Amore 
6772*a9800bebSGarrett D'Amore 		emlxs_node_rm(port, node);
6773*a9800bebSGarrett D'Amore 		return (1);
6774*a9800bebSGarrett D'Amore 	}
6775*a9800bebSGarrett D'Amore 
6776*a9800bebSGarrett D'Amore 	rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp,
6777*a9800bebSGarrett D'Amore 	    (void *)iocbq);
6778*a9800bebSGarrett D'Amore 
6779*a9800bebSGarrett D'Amore 	return (rval);
6780*a9800bebSGarrett D'Amore 
6781*a9800bebSGarrett D'Amore } /* emlxs_sli4_unreg_node() */
6782*a9800bebSGarrett D'Amore 
6783*a9800bebSGarrett D'Amore 
6784*a9800bebSGarrett D'Amore extern uint32_t
6785*a9800bebSGarrett D'Amore emlxs_sli4_unreg_all_nodes(emlxs_port_t *port)
6786*a9800bebSGarrett D'Amore {
678782527734SSukumar Swaminathan 	NODELIST	*nlp;
678882527734SSukumar Swaminathan 	int		i;
6789*a9800bebSGarrett D'Amore 	uint32_t 	found;
679082527734SSukumar Swaminathan 
6791*a9800bebSGarrett D'Amore 	/* Set the node tags */
6792*a9800bebSGarrett D'Amore 	/* We will process all nodes with this tag */
6793*a9800bebSGarrett D'Amore 	rw_enter(&port->node_rwlock, RW_READER);
6794*a9800bebSGarrett D'Amore 	found = 0;
679582527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
679682527734SSukumar Swaminathan 		nlp = port->node_table[i];
679782527734SSukumar Swaminathan 		while (nlp != NULL) {
6798*a9800bebSGarrett D'Amore 			found = 1;
6799*a9800bebSGarrett D'Amore 			nlp->nlp_tag = 1;
6800*a9800bebSGarrett D'Amore 			nlp = nlp->nlp_list_next;
680182527734SSukumar Swaminathan 		}
680282527734SSukumar Swaminathan 	}
680382527734SSukumar Swaminathan 	rw_exit(&port->node_rwlock);
680482527734SSukumar Swaminathan 
6805*a9800bebSGarrett D'Amore 	if (!found) {
6806*a9800bebSGarrett D'Amore 		return (0);
6807*a9800bebSGarrett D'Amore 	}
6808*a9800bebSGarrett D'Amore 
6809*a9800bebSGarrett D'Amore 	for (;;) {
6810*a9800bebSGarrett D'Amore 		rw_enter(&port->node_rwlock, RW_READER);
6811*a9800bebSGarrett D'Amore 		found = 0;
6812*a9800bebSGarrett D'Amore 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6813*a9800bebSGarrett D'Amore 			nlp = port->node_table[i];
6814*a9800bebSGarrett D'Amore 			while (nlp != NULL) {
6815*a9800bebSGarrett D'Amore 				if (!nlp->nlp_tag) {
6816*a9800bebSGarrett D'Amore 					nlp = nlp->nlp_list_next;
6817*a9800bebSGarrett D'Amore 					continue;
6818*a9800bebSGarrett D'Amore 				}
6819*a9800bebSGarrett D'Amore 				nlp->nlp_tag = 0;
6820*a9800bebSGarrett D'Amore 				found = 1;
6821*a9800bebSGarrett D'Amore 				break;
6822*a9800bebSGarrett D'Amore 			}
6823*a9800bebSGarrett D'Amore 
6824*a9800bebSGarrett D'Amore 			if (found) {
6825*a9800bebSGarrett D'Amore 				break;
6826*a9800bebSGarrett D'Amore 			}
6827*a9800bebSGarrett D'Amore 		}
6828*a9800bebSGarrett D'Amore 		rw_exit(&port->node_rwlock);
6829*a9800bebSGarrett D'Amore 
6830*a9800bebSGarrett D'Amore 		if (!found) {
6831*a9800bebSGarrett D'Amore 			break;
6832*a9800bebSGarrett D'Amore 		}
6833*a9800bebSGarrett D'Amore 
6834*a9800bebSGarrett D'Amore 		(void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0);
6835*a9800bebSGarrett D'Amore 	}
6836*a9800bebSGarrett D'Amore 
683782527734SSukumar Swaminathan 	return (0);
6838*a9800bebSGarrett D'Amore 
6839*a9800bebSGarrett D'Amore } /* emlxs_sli4_unreg_all_nodes() */
6840