1291a2b48SSukumar Swaminathan /*
2291a2b48SSukumar Swaminathan  * CDDL HEADER START
3291a2b48SSukumar Swaminathan  *
4291a2b48SSukumar Swaminathan  * The contents of this file are subject to the terms of the
5291a2b48SSukumar Swaminathan  * Common Development and Distribution License (the "License").
6291a2b48SSukumar Swaminathan  * You may not use this file except in compliance with the License.
7291a2b48SSukumar Swaminathan  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10291a2b48SSukumar Swaminathan  * See the License for the specific language governing permissions
11291a2b48SSukumar Swaminathan  * and limitations under the License.
12291a2b48SSukumar Swaminathan  *
13291a2b48SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
14291a2b48SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15291a2b48SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
16291a2b48SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
17291a2b48SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
18291a2b48SSukumar Swaminathan  *
19291a2b48SSukumar Swaminathan  * CDDL HEADER END
20291a2b48SSukumar Swaminathan  */
21291a2b48SSukumar Swaminathan 
22291a2b48SSukumar Swaminathan /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25291a2b48SSukumar Swaminathan  */
26291a2b48SSukumar Swaminathan 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28291a2b48SSukumar Swaminathan 
29291a2b48SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
3082527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI3_C);
31291a2b48SSukumar Swaminathan 
3282527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq);
3382527734SSukumar Swaminathan static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba);
3482527734SSukumar Swaminathan static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
35291a2b48SSukumar Swaminathan 	uint32_t ha_copy);
36291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
37291a2b48SSukumar Swaminathan static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
38291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3982527734SSukumar Swaminathan 
40291a2b48SSukumar Swaminathan static uint32_t	emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
41291a2b48SSukumar Swaminathan 
4282527734SSukumar Swaminathan static uint32_t emlxs_disable_traffic_cop = 1;
43291a2b48SSukumar Swaminathan 
4482527734SSukumar Swaminathan static int			emlxs_sli3_map_hdw(emlxs_hba_t *hba);
45291a2b48SSukumar Swaminathan 
4682527734SSukumar Swaminathan static void			emlxs_sli3_unmap_hdw(emlxs_hba_t *hba);
47291a2b48SSukumar Swaminathan 
4882527734SSukumar Swaminathan static int32_t			emlxs_sli3_online(emlxs_hba_t *hba);
49291a2b48SSukumar Swaminathan 
50*8f23e9faSHans Rosenfeld static void			emlxs_sli3_offline(emlxs_hba_t *hba,
51*8f23e9faSHans Rosenfeld 					uint32_t reset_requested);
52291a2b48SSukumar Swaminathan 
5382527734SSukumar Swaminathan static uint32_t			emlxs_sli3_hba_reset(emlxs_hba_t *hba,
5482527734SSukumar Swaminathan 					uint32_t restart, uint32_t skip_post,
5582527734SSukumar Swaminathan 					uint32_t quiesce);
56291a2b48SSukumar Swaminathan 
5782527734SSukumar Swaminathan static void			emlxs_sli3_hba_kill(emlxs_hba_t *hba);
5882527734SSukumar Swaminathan static void			emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba);
5982527734SSukumar Swaminathan static uint32_t			emlxs_sli3_hba_init(emlxs_hba_t *hba);
60291a2b48SSukumar Swaminathan 
6182527734SSukumar Swaminathan static uint32_t			emlxs_sli2_bde_setup(emlxs_port_t *port,
6282527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
6382527734SSukumar Swaminathan static uint32_t			emlxs_sli3_bde_setup(emlxs_port_t *port,
6482527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
6582527734SSukumar Swaminathan static uint32_t			emlxs_sli2_fct_bde_setup(emlxs_port_t *port,
6682527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
6782527734SSukumar Swaminathan static uint32_t			emlxs_sli3_fct_bde_setup(emlxs_port_t *port,
6882527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
69291a2b48SSukumar Swaminathan 
70291a2b48SSukumar Swaminathan 
7182527734SSukumar Swaminathan static void			emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba,
7282527734SSukumar Swaminathan 					CHANNEL *rp, IOCBQ *iocb_cmd);
73291a2b48SSukumar Swaminathan 
74291a2b48SSukumar Swaminathan 
7582527734SSukumar Swaminathan static uint32_t			emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba,
7682527734SSukumar Swaminathan 					MAILBOXQ *mbq, int32_t flg,
7782527734SSukumar Swaminathan 					uint32_t tmo);
78291a2b48SSukumar Swaminathan 
79291a2b48SSukumar Swaminathan 
8082527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
8182527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_fct_iocb(emlxs_port_t *port,
8282527734SSukumar Swaminathan 					emlxs_buf_t *cmd_sbp, int channel);
83291a2b48SSukumar Swaminathan 
8482527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
85291a2b48SSukumar Swaminathan 
8682527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port,
8782527734SSukumar Swaminathan 					emlxs_buf_t *sbp, int ring);
88291a2b48SSukumar Swaminathan 
8982527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_ip_iocb(emlxs_port_t *port,
9082527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
91291a2b48SSukumar Swaminathan 
9282527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_els_iocb(emlxs_port_t *port,
9382527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
94291a2b48SSukumar Swaminathan 
95291a2b48SSukumar Swaminathan 
9682527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_ct_iocb(emlxs_port_t *port,
9782527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
98291a2b48SSukumar Swaminathan 
99291a2b48SSukumar Swaminathan 
100*8f23e9faSHans Rosenfeld static void			emlxs_sli3_poll_intr(emlxs_hba_t *hba);
101291a2b48SSukumar Swaminathan 
10282527734SSukumar Swaminathan static int32_t			emlxs_sli3_intx_intr(char *arg);
10382527734SSukumar Swaminathan #ifdef MSI_SUPPORT
10482527734SSukumar Swaminathan static uint32_t			emlxs_sli3_msi_intr(char *arg1, char *arg2);
10582527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
106291a2b48SSukumar Swaminathan 
10782527734SSukumar Swaminathan static void			emlxs_sli3_enable_intr(emlxs_hba_t *hba);
10882527734SSukumar Swaminathan 
10982527734SSukumar Swaminathan static void			emlxs_sli3_disable_intr(emlxs_hba_t *hba,
11082527734SSukumar Swaminathan 					uint32_t att);
11182527734SSukumar Swaminathan 
112a9800bebSGarrett D'Amore 
11382527734SSukumar Swaminathan static void			emlxs_handle_ff_error(emlxs_hba_t *hba);
11482527734SSukumar Swaminathan 
11582527734SSukumar Swaminathan static uint32_t			emlxs_handle_mb_event(emlxs_hba_t *hba);
11682527734SSukumar Swaminathan 
11782527734SSukumar Swaminathan static void			emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba);
11882527734SSukumar Swaminathan 
11982527734SSukumar Swaminathan static uint32_t			emlxs_mb_config_port(emlxs_hba_t *hba,
12082527734SSukumar Swaminathan 					MAILBOXQ *mbq, uint32_t sli_mode,
12182527734SSukumar Swaminathan 					uint32_t hbainit);
12282527734SSukumar Swaminathan static void			emlxs_enable_latt(emlxs_hba_t *hba);
12382527734SSukumar Swaminathan 
12482527734SSukumar Swaminathan static uint32_t			emlxs_check_attention(emlxs_hba_t *hba);
12582527734SSukumar Swaminathan 
12682527734SSukumar Swaminathan static uint32_t			emlxs_get_attention(emlxs_hba_t *hba,
127a9800bebSGarrett D'Amore 					int32_t msgid);
12882527734SSukumar Swaminathan static void			emlxs_proc_attention(emlxs_hba_t *hba,
12982527734SSukumar Swaminathan 					uint32_t ha_copy);
13082527734SSukumar Swaminathan /* static int			emlxs_handle_rcv_seq(emlxs_hba_t *hba, */
13182527734SSukumar Swaminathan 					/* CHANNEL *cp, IOCBQ *iocbq); */
13282527734SSukumar Swaminathan /* static void			emlxs_update_HBQ_index(emlxs_hba_t *hba, */
13382527734SSukumar Swaminathan 					/* uint32_t hbq_id); */
13482527734SSukumar Swaminathan /* static void			emlxs_hbq_free_all(emlxs_hba_t *hba, */
13582527734SSukumar Swaminathan 					/* uint32_t hbq_id); */
13682527734SSukumar Swaminathan static uint32_t			emlxs_hbq_setup(emlxs_hba_t *hba,
13782527734SSukumar Swaminathan 					uint32_t hbq_id);
138*8f23e9faSHans Rosenfeld static void			emlxs_sli3_timer(emlxs_hba_t *hba);
139*8f23e9faSHans Rosenfeld 
140*8f23e9faSHans Rosenfeld static void			emlxs_sli3_poll_erratt(emlxs_hba_t *hba);
14182527734SSukumar Swaminathan 
142*8f23e9faSHans Rosenfeld static uint32_t			emlxs_sli3_reg_did(emlxs_port_t *port,
143*8f23e9faSHans Rosenfeld 					uint32_t did, SERV_PARM *param,
144*8f23e9faSHans Rosenfeld 					emlxs_buf_t *sbp, fc_unsol_buf_t *ubp,
145*8f23e9faSHans Rosenfeld 					IOCBQ *iocbq);
146*8f23e9faSHans Rosenfeld 
147*8f23e9faSHans Rosenfeld static uint32_t			emlxs_sli3_unreg_node(emlxs_port_t *port,
148*8f23e9faSHans Rosenfeld 					NODELIST *node, emlxs_buf_t *sbp,
149*8f23e9faSHans Rosenfeld 					fc_unsol_buf_t *ubp, IOCBQ *iocbq);
15082527734SSukumar Swaminathan 
15182527734SSukumar Swaminathan 
15282527734SSukumar Swaminathan /* Define SLI3 API functions */
15382527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli3_api = {
15482527734SSukumar Swaminathan 	emlxs_sli3_map_hdw,
15582527734SSukumar Swaminathan 	emlxs_sli3_unmap_hdw,
15682527734SSukumar Swaminathan 	emlxs_sli3_online,
15782527734SSukumar Swaminathan 	emlxs_sli3_offline,
15882527734SSukumar Swaminathan 	emlxs_sli3_hba_reset,
15982527734SSukumar Swaminathan 	emlxs_sli3_hba_kill,
16082527734SSukumar Swaminathan 	emlxs_sli3_issue_iocb_cmd,
16182527734SSukumar Swaminathan 	emlxs_sli3_issue_mbox_cmd,
16282527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
16382527734SSukumar Swaminathan 	emlxs_sli3_prep_fct_iocb,
16482527734SSukumar Swaminathan #else
16582527734SSukumar Swaminathan 	NULL,
16682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
16782527734SSukumar Swaminathan 	emlxs_sli3_prep_fcp_iocb,
16882527734SSukumar Swaminathan 	emlxs_sli3_prep_ip_iocb,
16982527734SSukumar Swaminathan 	emlxs_sli3_prep_els_iocb,
17082527734SSukumar Swaminathan 	emlxs_sli3_prep_ct_iocb,
17182527734SSukumar Swaminathan 	emlxs_sli3_poll_intr,
17282527734SSukumar Swaminathan 	emlxs_sli3_intx_intr,
17382527734SSukumar Swaminathan 	emlxs_sli3_msi_intr,
17482527734SSukumar Swaminathan 	emlxs_sli3_disable_intr,
17582527734SSukumar Swaminathan 	emlxs_sli3_timer,
176*8f23e9faSHans Rosenfeld 	emlxs_sli3_poll_erratt,
177*8f23e9faSHans Rosenfeld 	emlxs_sli3_reg_did,
178*8f23e9faSHans Rosenfeld 	emlxs_sli3_unreg_node
17982527734SSukumar Swaminathan };
180291a2b48SSukumar Swaminathan 
181291a2b48SSukumar Swaminathan 
18282527734SSukumar Swaminathan /*
18382527734SSukumar Swaminathan  * emlxs_sli3_online()
18482527734SSukumar Swaminathan  *
18582527734SSukumar Swaminathan  * This routine will start initialization of the SLI2/3 HBA.
18682527734SSukumar Swaminathan  */
18782527734SSukumar Swaminathan static int32_t
18882527734SSukumar Swaminathan emlxs_sli3_online(emlxs_hba_t *hba)
18982527734SSukumar Swaminathan {
19082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
19182527734SSukumar Swaminathan 	emlxs_config_t *cfg;
19282527734SSukumar Swaminathan 	emlxs_vpd_t *vpd;
19382527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
19482527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
19582527734SSukumar Swaminathan 	RING *rp;
19682527734SSukumar Swaminathan 	CHANNEL *cp;
19782527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
19882527734SSukumar Swaminathan 	MATCHMAP *mp1 = NULL;
19982527734SSukumar Swaminathan 	uint8_t *inptr;
20082527734SSukumar Swaminathan 	uint8_t *outptr;
20182527734SSukumar Swaminathan 	uint32_t status;
202a9800bebSGarrett D'Amore 	uint16_t i;
20382527734SSukumar Swaminathan 	uint32_t j;
20482527734SSukumar Swaminathan 	uint32_t read_rev_reset;
20582527734SSukumar Swaminathan 	uint32_t key = 0;
20682527734SSukumar Swaminathan 	uint32_t fw_check;
2076a573d82SSukumar Swaminathan 	uint32_t kern_update = 0;
20882527734SSukumar Swaminathan 	uint32_t rval = 0;
20982527734SSukumar Swaminathan 	uint32_t offset;
21082527734SSukumar Swaminathan 	uint8_t vpd_data[DMP_VPD_SIZE];
21182527734SSukumar Swaminathan 	uint32_t MaxRbusSize;
21282527734SSukumar Swaminathan 	uint32_t MaxIbusSize;
21382527734SSukumar Swaminathan 	uint32_t sli_mode;
21482527734SSukumar Swaminathan 	uint32_t sli_mode_mask;
215291a2b48SSukumar Swaminathan 
21682527734SSukumar Swaminathan 	cfg = &CFG;
21782527734SSukumar Swaminathan 	vpd = &VPD;
21882527734SSukumar Swaminathan 	MaxRbusSize = 0;
21982527734SSukumar Swaminathan 	MaxIbusSize = 0;
22082527734SSukumar Swaminathan 	read_rev_reset = 0;
22182527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
222291a2b48SSukumar Swaminathan 
22382527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
22482527734SSukumar Swaminathan 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
22582527734SSukumar Swaminathan 	}
226291a2b48SSukumar Swaminathan 
227a9800bebSGarrett D'Amore 	/* Set the fw_check flag */
228a9800bebSGarrett D'Amore 	fw_check = cfg[CFG_FW_CHECK].current;
2296a573d82SSukumar Swaminathan 
230a9800bebSGarrett D'Amore 	if ((fw_check & 0x04) ||
231a9800bebSGarrett D'Amore 	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
232a9800bebSGarrett D'Amore 		kern_update = 1;
233a9800bebSGarrett D'Amore 	}
2346a573d82SSukumar Swaminathan 
2356a573d82SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
2366a573d82SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
2376a573d82SSukumar Swaminathan 	hba->fc_edtov = FF_DEF_EDTOV;
2386a573d82SSukumar Swaminathan 	hba->fc_ratov = FF_DEF_RATOV;
2396a573d82SSukumar Swaminathan 	hba->fc_altov = FF_DEF_ALTOV;
2406a573d82SSukumar Swaminathan 	hba->fc_arbtov = FF_DEF_ARBTOV;
2416a573d82SSukumar Swaminathan 
242a9800bebSGarrett D'Amore 	/*
243a9800bebSGarrett D'Amore 	 * Get a buffer which will be used repeatedly for mailbox commands
244a9800bebSGarrett D'Amore 	 */
245a9800bebSGarrett D'Amore 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
2466a573d82SSukumar Swaminathan 
247a9800bebSGarrett D'Amore 	mb = (MAILBOX *)mbq;
2486a573d82SSukumar Swaminathan 
24982527734SSukumar Swaminathan 	/* Initialize sli mode based on configuration parameter */
25082527734SSukumar Swaminathan 	switch (cfg[CFG_SLI_MODE].current) {
25182527734SSukumar Swaminathan 	case 2:	/* SLI2 mode */
25282527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
25382527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
25482527734SSukumar Swaminathan 		break;
255291a2b48SSukumar Swaminathan 
25682527734SSukumar Swaminathan 	case 3:	/* SLI3 mode */
25782527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI3_MODE;
25882527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI3_MASK;
25982527734SSukumar Swaminathan 		break;
260291a2b48SSukumar Swaminathan 
26182527734SSukumar Swaminathan 	case 0:	/* Best available */
26282527734SSukumar Swaminathan 	case 1:	/* Best available */
26382527734SSukumar Swaminathan 	default:
26482527734SSukumar Swaminathan 		if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) {
26582527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
26682527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
26782527734SSukumar Swaminathan 		} else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) {
26882527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
26982527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
270*8f23e9faSHans Rosenfeld 		} else {
271*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
272*8f23e9faSHans Rosenfeld 			    "No SLI mode available.");
273*8f23e9faSHans Rosenfeld 			rval = EIO;
274*8f23e9faSHans Rosenfeld 			goto failed;
27582527734SSukumar Swaminathan 		}
276*8f23e9faSHans Rosenfeld 		break;
27782527734SSukumar Swaminathan 	}
27882527734SSukumar Swaminathan 	/* SBUS adapters only available in SLI2 */
27982527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
28082527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
28182527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
282291a2b48SSukumar Swaminathan 	}
283291a2b48SSukumar Swaminathan 
284*8f23e9faSHans Rosenfeld reset:
28582527734SSukumar Swaminathan 	/* Reset & Initialize the adapter */
28682527734SSukumar Swaminathan 	if (emlxs_sli3_hba_init(hba)) {
28782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
28882527734SSukumar Swaminathan 		    "Unable to init hba.");
289291a2b48SSukumar Swaminathan 
29082527734SSukumar Swaminathan 		rval = EIO;
29182527734SSukumar Swaminathan 		goto failed;
29282527734SSukumar Swaminathan 	}
293291a2b48SSukumar Swaminathan 
29482527734SSukumar Swaminathan #ifdef FMA_SUPPORT
29582527734SSukumar Swaminathan 	/* Access handle validation */
29682527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
29782527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
29882527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
29982527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
30082527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
30182527734SSukumar Swaminathan 	    != DDI_FM_OK)) {
30282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
30382527734SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
30482527734SSukumar Swaminathan 
30582527734SSukumar Swaminathan 		rval = EIO;
30682527734SSukumar Swaminathan 		goto failed;
307291a2b48SSukumar Swaminathan 	}
30882527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
309291a2b48SSukumar Swaminathan 
310*8f23e9faSHans Rosenfeld 	/* Check for PEGASUS (This is a special case) */
31182527734SSukumar Swaminathan 	/* We need to check for dual channel adapter */
312*8f23e9faSHans Rosenfeld 	if (hba->model_info.device_id == PCI_DEVICE_ID_PEGASUS) {
31382527734SSukumar Swaminathan 		/* Try to determine if this is a DC adapter */
31482527734SSukumar Swaminathan 		if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) {
31582527734SSukumar Swaminathan 			if (MaxRbusSize == REDUCED_SRAM_CFG) {
31682527734SSukumar Swaminathan 				/* LP9802DC */
31782527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
31882527734SSukumar Swaminathan 					if (emlxs_pci_model[i].id == LP9802DC) {
31982527734SSukumar Swaminathan 						bcopy(&emlxs_pci_model[i],
32082527734SSukumar Swaminathan 						    &hba->model_info,
32182527734SSukumar Swaminathan 						    sizeof (emlxs_model_t));
32282527734SSukumar Swaminathan 						break;
32382527734SSukumar Swaminathan 					}
32482527734SSukumar Swaminathan 				}
32582527734SSukumar Swaminathan 			} else if (hba->model_info.id != LP9802) {
32682527734SSukumar Swaminathan 				/* LP9802 */
32782527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
32882527734SSukumar Swaminathan 					if (emlxs_pci_model[i].id == LP9802) {
32982527734SSukumar Swaminathan 						bcopy(&emlxs_pci_model[i],
33082527734SSukumar Swaminathan 						    &hba->model_info,
33182527734SSukumar Swaminathan 						    sizeof (emlxs_model_t));
33282527734SSukumar Swaminathan 						break;
33382527734SSukumar Swaminathan 					}
33482527734SSukumar Swaminathan 				}
33582527734SSukumar Swaminathan 			}
33682527734SSukumar Swaminathan 		}
33782527734SSukumar Swaminathan 	}
338291a2b48SSukumar Swaminathan 
339291a2b48SSukumar Swaminathan 	/*
34082527734SSukumar Swaminathan 	 * Setup and issue mailbox READ REV command
341291a2b48SSukumar Swaminathan 	 */
34282527734SSukumar Swaminathan 	vpd->opFwRev = 0;
34382527734SSukumar Swaminathan 	vpd->postKernRev = 0;
34482527734SSukumar Swaminathan 	vpd->sli1FwRev = 0;
34582527734SSukumar Swaminathan 	vpd->sli2FwRev = 0;
34682527734SSukumar Swaminathan 	vpd->sli3FwRev = 0;
34782527734SSukumar Swaminathan 	vpd->sli4FwRev = 0;
34882527734SSukumar Swaminathan 
34982527734SSukumar Swaminathan 	vpd->postKernName[0] = 0;
35082527734SSukumar Swaminathan 	vpd->opFwName[0] = 0;
35182527734SSukumar Swaminathan 	vpd->sli1FwName[0] = 0;
35282527734SSukumar Swaminathan 	vpd->sli2FwName[0] = 0;
35382527734SSukumar Swaminathan 	vpd->sli3FwName[0] = 0;
35482527734SSukumar Swaminathan 	vpd->sli4FwName[0] = 0;
35582527734SSukumar Swaminathan 
35682527734SSukumar Swaminathan 	vpd->opFwLabel[0] = 0;
35782527734SSukumar Swaminathan 	vpd->sli1FwLabel[0] = 0;
35882527734SSukumar Swaminathan 	vpd->sli2FwLabel[0] = 0;
35982527734SSukumar Swaminathan 	vpd->sli3FwLabel[0] = 0;
36082527734SSukumar Swaminathan 	vpd->sli4FwLabel[0] = 0;
36182527734SSukumar Swaminathan 
36282527734SSukumar Swaminathan 	/* Sanity check */
36382527734SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
36482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
36582527734SSukumar Swaminathan 		    "Adapter / SLI mode mismatch mask:x%x",
36682527734SSukumar Swaminathan 		    hba->model_info.sli_mask);
36782527734SSukumar Swaminathan 
36882527734SSukumar Swaminathan 		rval = EIO;
36982527734SSukumar Swaminathan 		goto failed;
370291a2b48SSukumar Swaminathan 	}
371291a2b48SSukumar Swaminathan 
37282527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
37382527734SSukumar Swaminathan 	emlxs_mb_read_rev(hba, mbq, 0);
37482527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
37582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
37682527734SSukumar Swaminathan 		    "Unable to read rev. Mailbox cmd=%x status=%x",
37782527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
378291a2b48SSukumar Swaminathan 
37982527734SSukumar Swaminathan 		rval = EIO;
38082527734SSukumar Swaminathan 		goto failed;
381291a2b48SSukumar Swaminathan 	}
382291a2b48SSukumar Swaminathan 
38382527734SSukumar Swaminathan 	if (mb->un.varRdRev.rr == 0) {
38482527734SSukumar Swaminathan 		/* Old firmware */
38582527734SSukumar Swaminathan 		if (read_rev_reset == 0) {
38682527734SSukumar Swaminathan 			read_rev_reset = 1;
387291a2b48SSukumar Swaminathan 
38882527734SSukumar Swaminathan 			goto reset;
38982527734SSukumar Swaminathan 		} else {
39082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
39182527734SSukumar Swaminathan 			    "Outdated firmware detected.");
39282527734SSukumar Swaminathan 		}
393291a2b48SSukumar Swaminathan 
39482527734SSukumar Swaminathan 		vpd->rBit = 0;
39582527734SSukumar Swaminathan 	} else {
39682527734SSukumar Swaminathan 		if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) {
39782527734SSukumar Swaminathan 			if (read_rev_reset == 0) {
39882527734SSukumar Swaminathan 				read_rev_reset = 1;
399291a2b48SSukumar Swaminathan 
40082527734SSukumar Swaminathan 				goto reset;
40182527734SSukumar Swaminathan 			} else {
40282527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
40382527734SSukumar Swaminathan 				    "Non-operational firmware detected. "
40482527734SSukumar Swaminathan 				    "type=%x",
40582527734SSukumar Swaminathan 				    mb->un.varRdRev.un.b.ProgType);
40682527734SSukumar Swaminathan 			}
40782527734SSukumar Swaminathan 		}
408291a2b48SSukumar Swaminathan 
40982527734SSukumar Swaminathan 		vpd->rBit = 1;
41082527734SSukumar Swaminathan 		vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1;
41182527734SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel,
41282527734SSukumar Swaminathan 		    16);
41382527734SSukumar Swaminathan 		vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2;
41482527734SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel,
41582527734SSukumar Swaminathan 		    16);
416291a2b48SSukumar Swaminathan 
41782527734SSukumar Swaminathan 		/*
41882527734SSukumar Swaminathan 		 * Lets try to read the SLI3 version
41982527734SSukumar Swaminathan 		 * Setup and issue mailbox READ REV(v3) command
42082527734SSukumar Swaminathan 		 */
42182527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
42282527734SSukumar Swaminathan 
42382527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
42482527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
42582527734SSukumar Swaminathan 
42682527734SSukumar Swaminathan 		emlxs_mb_read_rev(hba, mbq, 1);
42782527734SSukumar Swaminathan 
42882527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
42982527734SSukumar Swaminathan 		    MBX_SUCCESS) {
43082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
43182527734SSukumar Swaminathan 			    "Unable to read rev (v3). Mailbox cmd=%x status=%x",
43282527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
43382527734SSukumar Swaminathan 
43482527734SSukumar Swaminathan 			rval = EIO;
43582527734SSukumar Swaminathan 			goto failed;
43682527734SSukumar Swaminathan 		}
43782527734SSukumar Swaminathan 
43882527734SSukumar Swaminathan 		if (mb->un.varRdRev.rf3) {
43982527734SSukumar Swaminathan 			/*
44082527734SSukumar Swaminathan 			 * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1;
44182527734SSukumar Swaminathan 			 * Not needed
44282527734SSukumar Swaminathan 			 */
44382527734SSukumar Swaminathan 			vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2;
44482527734SSukumar Swaminathan 			bcopy((char *)mb->un.varRdRev.sliFwName2,
44582527734SSukumar Swaminathan 			    vpd->sli3FwLabel, 16);
44682527734SSukumar Swaminathan 		}
447291a2b48SSukumar Swaminathan 	}
448291a2b48SSukumar Swaminathan 
44982527734SSukumar Swaminathan 	if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) {
45082527734SSukumar Swaminathan 		if (vpd->sli2FwRev) {
45182527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
45282527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
45382527734SSukumar Swaminathan 		} else {
45482527734SSukumar Swaminathan 			sli_mode = 0;
45582527734SSukumar Swaminathan 			sli_mode_mask = 0;
45682527734SSukumar Swaminathan 		}
457291a2b48SSukumar Swaminathan 	}
458291a2b48SSukumar Swaminathan 
45982527734SSukumar Swaminathan 	else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) {
46082527734SSukumar Swaminathan 		if (vpd->sli3FwRev) {
46182527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
46282527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
463291a2b48SSukumar Swaminathan 		} else {
46482527734SSukumar Swaminathan 			sli_mode = 0;
46582527734SSukumar Swaminathan 			sli_mode_mask = 0;
466291a2b48SSukumar Swaminathan 		}
467291a2b48SSukumar Swaminathan 	}
468291a2b48SSukumar Swaminathan 
46982527734SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & sli_mode_mask)) {
47082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
47182527734SSukumar Swaminathan 		    "Firmware not available. sli-mode=%d",
47282527734SSukumar Swaminathan 		    cfg[CFG_SLI_MODE].current);
473291a2b48SSukumar Swaminathan 
47482527734SSukumar Swaminathan 		rval = EIO;
47582527734SSukumar Swaminathan 		goto failed;
47682527734SSukumar Swaminathan 	}
477291a2b48SSukumar Swaminathan 
47882527734SSukumar Swaminathan 	/* Save information as VPD data */
47982527734SSukumar Swaminathan 	vpd->postKernRev = mb->un.varRdRev.postKernRev;
48082527734SSukumar Swaminathan 	vpd->opFwRev = mb->un.varRdRev.opFwRev;
48182527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16);
48282527734SSukumar Swaminathan 	vpd->biuRev = mb->un.varRdRev.biuRev;
48382527734SSukumar Swaminathan 	vpd->smRev = mb->un.varRdRev.smRev;
48482527734SSukumar Swaminathan 	vpd->smFwRev = mb->un.varRdRev.un.smFwRev;
48582527734SSukumar Swaminathan 	vpd->endecRev = mb->un.varRdRev.endecRev;
48682527734SSukumar Swaminathan 	vpd->fcphHigh = mb->un.varRdRev.fcphHigh;
48782527734SSukumar Swaminathan 	vpd->fcphLow = mb->un.varRdRev.fcphLow;
48882527734SSukumar Swaminathan 	vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh;
48982527734SSukumar Swaminathan 	vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow;
49082527734SSukumar Swaminathan 
49182527734SSukumar Swaminathan 	/* Decode FW names */
492*8f23e9faSHans Rosenfeld 	emlxs_decode_version(vpd->postKernRev, vpd->postKernName,
493*8f23e9faSHans Rosenfeld 	    sizeof (vpd->postKernName));
494*8f23e9faSHans Rosenfeld 	emlxs_decode_version(vpd->opFwRev, vpd->opFwName,
495*8f23e9faSHans Rosenfeld 	    sizeof (vpd->opFwName));
496*8f23e9faSHans Rosenfeld 	emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName,
497*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli1FwName));
498*8f23e9faSHans Rosenfeld 	emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName,
499*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli2FwName));
500*8f23e9faSHans Rosenfeld 	emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName,
501*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli3FwName));
502*8f23e9faSHans Rosenfeld 	emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName,
503*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli4FwName));
50482527734SSukumar Swaminathan 
50582527734SSukumar Swaminathan 	/* Decode FW labels */
506*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel, 1,
507*8f23e9faSHans Rosenfeld 	    sizeof (vpd->opFwLabel));
508*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel, 1,
509*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli1FwLabel));
510*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel, 1,
511*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli2FwLabel));
512*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel, 1,
513*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli3FwLabel));
514*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel, 1,
515*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli4FwLabel));
51682527734SSukumar Swaminathan 
51782527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
51882527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
51982527734SSukumar Swaminathan 
52082527734SSukumar Swaminathan 	key = emlxs_get_key(hba, mbq);
52182527734SSukumar Swaminathan 
52282527734SSukumar Swaminathan 	/* Get adapter VPD information */
52382527734SSukumar Swaminathan 	offset = 0;
52482527734SSukumar Swaminathan 	bzero(vpd_data, sizeof (vpd_data));
52582527734SSukumar Swaminathan 	vpd->port_index = (uint32_t)-1;
526291a2b48SSukumar Swaminathan 
52782527734SSukumar Swaminathan 	while (offset < DMP_VPD_SIZE) {
52882527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
52982527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
530291a2b48SSukumar Swaminathan 
53182527734SSukumar Swaminathan 		emlxs_mb_dump_vpd(hba, mbq, offset);
53282527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
53382527734SSukumar Swaminathan 		    MBX_SUCCESS) {
53482527734SSukumar Swaminathan 			/*
53582527734SSukumar Swaminathan 			 * Let it go through even if failed.
53682527734SSukumar Swaminathan 			 * Not all adapter's have VPD info and thus will
53782527734SSukumar Swaminathan 			 * fail here. This is not a problem
53882527734SSukumar Swaminathan 			 */
539291a2b48SSukumar Swaminathan 
54082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
54182527734SSukumar Swaminathan 			    "No VPD found. offset=%x status=%x", offset,
54282527734SSukumar Swaminathan 			    mb->mbxStatus);
54382527734SSukumar Swaminathan 			break;
54482527734SSukumar Swaminathan 		} else {
54582527734SSukumar Swaminathan 			if (mb->un.varDmp.ra == 1) {
54682527734SSukumar Swaminathan 				uint32_t *lp1, *lp2;
54782527734SSukumar Swaminathan 				uint32_t bsize;
54882527734SSukumar Swaminathan 				uint32_t wsize;
549291a2b48SSukumar Swaminathan 
55082527734SSukumar Swaminathan 				/*
55182527734SSukumar Swaminathan 				 * mb->un.varDmp.word_cnt is actually byte
55282527734SSukumar Swaminathan 				 * count for the dump reply
55382527734SSukumar Swaminathan 				 */
55482527734SSukumar Swaminathan 				bsize = mb->un.varDmp.word_cnt;
555291a2b48SSukumar Swaminathan 
55682527734SSukumar Swaminathan 				/* Stop if no data was received */
55782527734SSukumar Swaminathan 				if (bsize == 0) {
55882527734SSukumar Swaminathan 					break;
55982527734SSukumar Swaminathan 				}
560291a2b48SSukumar Swaminathan 
56182527734SSukumar Swaminathan 				/* Check limit on byte size */
56282527734SSukumar Swaminathan 				bsize = (bsize >
56382527734SSukumar Swaminathan 				    (sizeof (vpd_data) - offset)) ?
56482527734SSukumar Swaminathan 				    (sizeof (vpd_data) - offset) : bsize;
565291a2b48SSukumar Swaminathan 
56682527734SSukumar Swaminathan 				/*
56782527734SSukumar Swaminathan 				 * Convert size from bytes to words with
56882527734SSukumar Swaminathan 				 * minimum of 1 word
56982527734SSukumar Swaminathan 				 */
57082527734SSukumar Swaminathan 				wsize = (bsize > 4) ? (bsize >> 2) : 1;
571291a2b48SSukumar Swaminathan 
57282527734SSukumar Swaminathan 				/*
57382527734SSukumar Swaminathan 				 * Transfer data into vpd_data buffer one
57482527734SSukumar Swaminathan 				 * word at a time
57582527734SSukumar Swaminathan 				 */
57682527734SSukumar Swaminathan 				lp1 = (uint32_t *)&mb->un.varDmp.resp_offset;
57782527734SSukumar Swaminathan 				lp2 = (uint32_t *)&vpd_data[offset];
578291a2b48SSukumar Swaminathan 
57982527734SSukumar Swaminathan 				for (i = 0; i < wsize; i++) {
58082527734SSukumar Swaminathan 					status = *lp1++;
58182527734SSukumar Swaminathan 					*lp2++ = BE_SWAP32(status);
58282527734SSukumar Swaminathan 				}
583291a2b48SSukumar Swaminathan 
58482527734SSukumar Swaminathan 				/* Increment total byte count saved */
58582527734SSukumar Swaminathan 				offset += (wsize << 2);
586291a2b48SSukumar Swaminathan 
58782527734SSukumar Swaminathan 				/*
58882527734SSukumar Swaminathan 				 * Stop if less than a full transfer was
58982527734SSukumar Swaminathan 				 * received
59082527734SSukumar Swaminathan 				 */
59182527734SSukumar Swaminathan 				if (wsize < DMP_VPD_DUMP_WCOUNT) {
59282527734SSukumar Swaminathan 					break;
59382527734SSukumar Swaminathan 				}
594291a2b48SSukumar Swaminathan 
59582527734SSukumar Swaminathan 			} else {
59682527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
59782527734SSukumar Swaminathan 				    &emlxs_init_debug_msg,
59882527734SSukumar Swaminathan 				    "No VPD acknowledgment. offset=%x",
59982527734SSukumar Swaminathan 				    offset);
60082527734SSukumar Swaminathan 				break;
60182527734SSukumar Swaminathan 			}
60282527734SSukumar Swaminathan 		}
603291a2b48SSukumar Swaminathan 
604291a2b48SSukumar Swaminathan 	}
605291a2b48SSukumar Swaminathan 
60682527734SSukumar Swaminathan 	if (vpd_data[0]) {
60782527734SSukumar Swaminathan 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset);
608291a2b48SSukumar Swaminathan 
60982527734SSukumar Swaminathan 		/*
61082527734SSukumar Swaminathan 		 * If there is a VPD part number, and it does not
61182527734SSukumar Swaminathan 		 * match the current default HBA model info,
61282527734SSukumar Swaminathan 		 * replace the default data with an entry that
61382527734SSukumar Swaminathan 		 * does match.
61482527734SSukumar Swaminathan 		 *
61582527734SSukumar Swaminathan 		 * After emlxs_parse_vpd model holds the VPD value
61682527734SSukumar Swaminathan 		 * for V2 and part_num hold the value for PN. These
61782527734SSukumar Swaminathan 		 * 2 values are NOT necessarily the same.
61882527734SSukumar Swaminathan 		 */
619291a2b48SSukumar Swaminathan 
62082527734SSukumar Swaminathan 		rval = 0;
62182527734SSukumar Swaminathan 		if ((vpd->model[0] != 0) &&
62282527734SSukumar Swaminathan 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
623291a2b48SSukumar Swaminathan 
62482527734SSukumar Swaminathan 			/* First scan for a V2 match */
625291a2b48SSukumar Swaminathan 
62682527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
62782527734SSukumar Swaminathan 				if (strcmp(&vpd->model[0],
62882527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
62982527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
63082527734SSukumar Swaminathan 					    &hba->model_info,
63182527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
63282527734SSukumar Swaminathan 					rval = 1;
63382527734SSukumar Swaminathan 					break;
63482527734SSukumar Swaminathan 				}
63582527734SSukumar Swaminathan 			}
63682527734SSukumar Swaminathan 		}
637291a2b48SSukumar Swaminathan 
63882527734SSukumar Swaminathan 		if (!rval && (vpd->part_num[0] != 0) &&
63982527734SSukumar Swaminathan 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
640291a2b48SSukumar Swaminathan 
64182527734SSukumar Swaminathan 			/* Next scan for a PN match */
642291a2b48SSukumar Swaminathan 
64382527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
64482527734SSukumar Swaminathan 				if (strcmp(&vpd->part_num[0],
64582527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
64682527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
64782527734SSukumar Swaminathan 					    &hba->model_info,
64882527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
64982527734SSukumar Swaminathan 					break;
65082527734SSukumar Swaminathan 				}
65182527734SSukumar Swaminathan 			}
65282527734SSukumar Swaminathan 		}
653291a2b48SSukumar Swaminathan 
65482527734SSukumar Swaminathan 		/*
65582527734SSukumar Swaminathan 		 * Now lets update hba->model_info with the real
65682527734SSukumar Swaminathan 		 * VPD data, if any.
65782527734SSukumar Swaminathan 		 */
658291a2b48SSukumar Swaminathan 
65982527734SSukumar Swaminathan 		/*
66082527734SSukumar Swaminathan 		 * Replace the default model description with vpd data
66182527734SSukumar Swaminathan 		 */
66282527734SSukumar Swaminathan 		if (vpd->model_desc[0] != 0) {
663*8f23e9faSHans Rosenfeld 			(void) strncpy(hba->model_info.model_desc,
664*8f23e9faSHans Rosenfeld 			    vpd->model_desc,
665*8f23e9faSHans Rosenfeld 			    (sizeof (hba->model_info.model_desc)-1));
666291a2b48SSukumar Swaminathan 		}
667291a2b48SSukumar Swaminathan 
66882527734SSukumar Swaminathan 		/* Replace the default model with vpd data */
66982527734SSukumar Swaminathan 		if (vpd->model[0] != 0) {
670*8f23e9faSHans Rosenfeld 			(void) strncpy(hba->model_info.model, vpd->model,
671*8f23e9faSHans Rosenfeld 			    (sizeof (hba->model_info.model)-1));
67282527734SSukumar Swaminathan 		}
67382527734SSukumar Swaminathan 
67482527734SSukumar Swaminathan 		/* Replace the default program types with vpd data */
67582527734SSukumar Swaminathan 		if (vpd->prog_types[0] != 0) {
67682527734SSukumar Swaminathan 			emlxs_parse_prog_types(hba, vpd->prog_types);
67782527734SSukumar Swaminathan 		}
678291a2b48SSukumar Swaminathan 	}
679291a2b48SSukumar Swaminathan 
680291a2b48SSukumar Swaminathan 	/*
68182527734SSukumar Swaminathan 	 * Since the adapter model may have changed with the vpd data
68282527734SSukumar Swaminathan 	 * lets double check if adapter is not supported
683291a2b48SSukumar Swaminathan 	 */
68482527734SSukumar Swaminathan 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
68582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
68682527734SSukumar Swaminathan 		    "Unsupported adapter found.  "
68782527734SSukumar Swaminathan 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
68882527734SSukumar Swaminathan 		    hba->model_info.id, hba->model_info.device_id,
68982527734SSukumar Swaminathan 		    hba->model_info.ssdid, hba->model_info.model);
69082527734SSukumar Swaminathan 
69182527734SSukumar Swaminathan 		rval = EIO;
69282527734SSukumar Swaminathan 		goto failed;
69382527734SSukumar Swaminathan 	}
694291a2b48SSukumar Swaminathan 
69582527734SSukumar Swaminathan 	/* Read the adapter's wakeup parms */
69682527734SSukumar Swaminathan 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
69782527734SSukumar Swaminathan 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
698*8f23e9faSHans Rosenfeld 	    vpd->boot_version, sizeof (vpd->boot_version));
699291a2b48SSukumar Swaminathan 
70082527734SSukumar Swaminathan 	/* Get fcode version property */
70182527734SSukumar Swaminathan 	emlxs_get_fcode_version(hba);
702291a2b48SSukumar Swaminathan 
70382527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
70482527734SSukumar Swaminathan 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
70582527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->sli1FwRev);
706291a2b48SSukumar Swaminathan 
70782527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
70882527734SSukumar Swaminathan 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
70982527734SSukumar Swaminathan 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
710291a2b48SSukumar Swaminathan 
71182527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
71282527734SSukumar Swaminathan 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
713291a2b48SSukumar Swaminathan 
71482527734SSukumar Swaminathan 	/*
71582527734SSukumar Swaminathan 	 * If firmware checking is enabled and the adapter model indicates
71682527734SSukumar Swaminathan 	 * a firmware image, then perform firmware version check
71782527734SSukumar Swaminathan 	 */
7186a573d82SSukumar Swaminathan 	hba->fw_flag = 0;
7196a573d82SSukumar Swaminathan 	hba->fw_timer = 0;
7206a573d82SSukumar Swaminathan 
721*8f23e9faSHans Rosenfeld 	if (((fw_check & 0x1) &&
722*8f23e9faSHans Rosenfeld 	    (hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
7236a573d82SSukumar Swaminathan 	    hba->model_info.fwid) || ((fw_check & 0x2) &&
72482527734SSukumar Swaminathan 	    hba->model_info.fwid)) {
72582527734SSukumar Swaminathan 		emlxs_firmware_t *fw;
72682527734SSukumar Swaminathan 
72782527734SSukumar Swaminathan 		/* Find firmware image indicated by adapter model */
72882527734SSukumar Swaminathan 		fw = NULL;
72982527734SSukumar Swaminathan 		for (i = 0; i < emlxs_fw_count; i++) {
73082527734SSukumar Swaminathan 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
73182527734SSukumar Swaminathan 				fw = &emlxs_fw_table[i];
73282527734SSukumar Swaminathan 				break;
73382527734SSukumar Swaminathan 			}
734291a2b48SSukumar Swaminathan 		}
735291a2b48SSukumar Swaminathan 
736291a2b48SSukumar Swaminathan 		/*
73782527734SSukumar Swaminathan 		 * If the image was found, then verify current firmware
73882527734SSukumar Swaminathan 		 * versions of adapter
739291a2b48SSukumar Swaminathan 		 */
74082527734SSukumar Swaminathan 		if (fw) {
7416a573d82SSukumar Swaminathan 			if (!kern_update &&
7426a573d82SSukumar Swaminathan 			    ((fw->kern && (vpd->postKernRev != fw->kern)) ||
7436a573d82SSukumar Swaminathan 			    (fw->stub && (vpd->opFwRev != fw->stub)))) {
7446a573d82SSukumar Swaminathan 
7456a573d82SSukumar Swaminathan 				hba->fw_flag |= FW_UPDATE_NEEDED;
7466a573d82SSukumar Swaminathan 
7476a573d82SSukumar Swaminathan 			} else if ((fw->kern && (vpd->postKernRev !=
7486a573d82SSukumar Swaminathan 			    fw->kern)) ||
74982527734SSukumar Swaminathan 			    (fw->stub && (vpd->opFwRev != fw->stub)) ||
75082527734SSukumar Swaminathan 			    (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) ||
75182527734SSukumar Swaminathan 			    (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) ||
75282527734SSukumar Swaminathan 			    (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) ||
75382527734SSukumar Swaminathan 			    (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) {
75482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
75582527734SSukumar Swaminathan 				    "Firmware update needed. "
75682527734SSukumar Swaminathan 				    "Updating. id=%d fw=%d",
75782527734SSukumar Swaminathan 				    hba->model_info.id, hba->model_info.fwid);
75882527734SSukumar Swaminathan 
75982527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
76082527734SSukumar Swaminathan 				/*
76182527734SSukumar Swaminathan 				 * Load the firmware image now
76282527734SSukumar Swaminathan 				 * If MODFW_SUPPORT is not defined, the
76382527734SSukumar Swaminathan 				 * firmware image will already be defined
76482527734SSukumar Swaminathan 				 * in the emlxs_fw_table
76582527734SSukumar Swaminathan 				 */
76682527734SSukumar Swaminathan 				emlxs_fw_load(hba, fw);
76782527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
768291a2b48SSukumar Swaminathan 
76982527734SSukumar Swaminathan 				if (fw->image && fw->size) {
770*8f23e9faSHans Rosenfeld 					uint32_t rc;
771*8f23e9faSHans Rosenfeld 
772*8f23e9faSHans Rosenfeld 					rc = emlxs_fw_download(hba,
773*8f23e9faSHans Rosenfeld 					    (char *)fw->image, fw->size, 0);
774*8f23e9faSHans Rosenfeld 					if ((rc != FC_SUCCESS) &&
775*8f23e9faSHans Rosenfeld 					    (rc != EMLXS_REBOOT_REQUIRED)) {
77682527734SSukumar Swaminathan 						EMLXS_MSGF(EMLXS_CONTEXT,
77782527734SSukumar Swaminathan 						    &emlxs_init_msg,
77882527734SSukumar Swaminathan 						    "Firmware update failed.");
7796a573d82SSukumar Swaminathan 						hba->fw_flag |=
7806a573d82SSukumar Swaminathan 						    FW_UPDATE_NEEDED;
78182527734SSukumar Swaminathan 					}
78282527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
78382527734SSukumar Swaminathan 					/*
78482527734SSukumar Swaminathan 					 * Unload the firmware image from
78582527734SSukumar Swaminathan 					 * kernel memory
78682527734SSukumar Swaminathan 					 */
78782527734SSukumar Swaminathan 					emlxs_fw_unload(hba, fw);
78882527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
789291a2b48SSukumar Swaminathan 
79082527734SSukumar Swaminathan 					fw_check = 0;
79182527734SSukumar Swaminathan 
79282527734SSukumar Swaminathan 					goto reset;
79382527734SSukumar Swaminathan 				}
79482527734SSukumar Swaminathan 
795*8f23e9faSHans Rosenfeld 				hba->fw_flag |= FW_UPDATE_NEEDED;
796*8f23e9faSHans Rosenfeld 
79782527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
79882527734SSukumar Swaminathan 				    "Firmware image unavailable.");
79982527734SSukumar Swaminathan 			} else {
80082527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
80182527734SSukumar Swaminathan 				    "Firmware update not needed.");
80282527734SSukumar Swaminathan 			}
80382527734SSukumar Swaminathan 		} else {
80482527734SSukumar Swaminathan 			/* This should not happen */
80582527734SSukumar Swaminathan 
80682527734SSukumar Swaminathan 			/*
80782527734SSukumar Swaminathan 			 * This means either the adapter database is not
80882527734SSukumar Swaminathan 			 * correct or a firmware image is missing from the
80982527734SSukumar Swaminathan 			 * compile
81082527734SSukumar Swaminathan 			 */
81182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
81282527734SSukumar Swaminathan 			    "Firmware image unavailable. id=%d fw=%d",
81382527734SSukumar Swaminathan 			    hba->model_info.id, hba->model_info.fwid);
814291a2b48SSukumar Swaminathan 		}
815291a2b48SSukumar Swaminathan 	}
816291a2b48SSukumar Swaminathan 
81782527734SSukumar Swaminathan 	/*
81882527734SSukumar Swaminathan 	 * Add our interrupt routine to kernel's interrupt chain & enable it
81982527734SSukumar Swaminathan 	 * If MSI is enabled this will cause Solaris to program the MSI address
82082527734SSukumar Swaminathan 	 * and data registers in PCI config space
82182527734SSukumar Swaminathan 	 */
82282527734SSukumar Swaminathan 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
82382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
82482527734SSukumar Swaminathan 		    "Unable to add interrupt(s).");
8254baa2c25SSukumar Swaminathan 
82682527734SSukumar Swaminathan 		rval = EIO;
82782527734SSukumar Swaminathan 		goto failed;
82882527734SSukumar Swaminathan 	}
829291a2b48SSukumar Swaminathan 
83082527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
831291a2b48SSukumar Swaminathan 
83282527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
83382527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
834291a2b48SSukumar Swaminathan 
83582527734SSukumar Swaminathan 	(void) emlxs_mb_config_port(hba, mbq, sli_mode, key);
83682527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
83782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
83882527734SSukumar Swaminathan 		    "Unable to configure port. "
83982527734SSukumar Swaminathan 		    "Mailbox cmd=%x status=%x slimode=%d key=%x",
84082527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus, sli_mode, key);
841291a2b48SSukumar Swaminathan 
84282527734SSukumar Swaminathan 		for (sli_mode--; sli_mode > 0; sli_mode--) {
84382527734SSukumar Swaminathan 			/* Check if sli_mode is supported by this adapter */
84482527734SSukumar Swaminathan 			if (hba->model_info.sli_mask &
84582527734SSukumar Swaminathan 			    EMLXS_SLI_MASK(sli_mode)) {
84682527734SSukumar Swaminathan 				sli_mode_mask = EMLXS_SLI_MASK(sli_mode);
84782527734SSukumar Swaminathan 				break;
84882527734SSukumar Swaminathan 			}
84982527734SSukumar Swaminathan 		}
8504baa2c25SSukumar Swaminathan 
85182527734SSukumar Swaminathan 		if (sli_mode) {
85282527734SSukumar Swaminathan 			fw_check = 0;
8534baa2c25SSukumar Swaminathan 
85482527734SSukumar Swaminathan 			goto reset;
85582527734SSukumar Swaminathan 		}
856291a2b48SSukumar Swaminathan 
85782527734SSukumar Swaminathan 		hba->flag &= ~FC_SLIM2_MODE;
85882527734SSukumar Swaminathan 
85982527734SSukumar Swaminathan 		rval = EIO;
86082527734SSukumar Swaminathan 		goto failed;
861291a2b48SSukumar Swaminathan 	}
862291a2b48SSukumar Swaminathan 
86382527734SSukumar Swaminathan 	/* Check if SLI3 mode was achieved */
86482527734SSukumar Swaminathan 	if (mb->un.varCfgPort.rMA &&
86582527734SSukumar Swaminathan 	    (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) {
866291a2b48SSukumar Swaminathan 
86782527734SSukumar Swaminathan 		if (mb->un.varCfgPort.vpi_max > 1) {
86882527734SSukumar Swaminathan 			hba->flag |= FC_NPIV_ENABLED;
869291a2b48SSukumar Swaminathan 
87082527734SSukumar Swaminathan 			if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
87182527734SSukumar Swaminathan 				hba->vpi_max =
87282527734SSukumar Swaminathan 				    min(mb->un.varCfgPort.vpi_max,
87382527734SSukumar Swaminathan 				    MAX_VPORTS - 1);
87482527734SSukumar Swaminathan 			} else {
87582527734SSukumar Swaminathan 				hba->vpi_max =
87682527734SSukumar Swaminathan 				    min(mb->un.varCfgPort.vpi_max,
87782527734SSukumar Swaminathan 				    MAX_VPORTS_LIMITED - 1);
87882527734SSukumar Swaminathan 			}
87982527734SSukumar Swaminathan 		}
880291a2b48SSukumar Swaminathan 
88182527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5)
88282527734SSukumar Swaminathan 		hba->fca_tran->fca_num_npivports =
88382527734SSukumar Swaminathan 		    (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0;
88482527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */
88582527734SSukumar Swaminathan 
88682527734SSukumar Swaminathan 		if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) {
88782527734SSukumar Swaminathan 			hba->flag |= FC_HBQ_ENABLED;
888291a2b48SSukumar Swaminathan 		}
88982527734SSukumar Swaminathan 
89082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
89182527734SSukumar Swaminathan 		    "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max);
89282527734SSukumar Swaminathan 	} else {
89382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
89482527734SSukumar Swaminathan 		    "SLI2 mode: flag=%x", hba->flag);
89582527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
89682527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
89782527734SSukumar Swaminathan 		hba->sli_mode = sli_mode;
898*8f23e9faSHans Rosenfeld #if (EMLXS_MODREV >= EMLXS_MODREV5)
899*8f23e9faSHans Rosenfeld 		hba->fca_tran->fca_num_npivports = 0;
900*8f23e9faSHans Rosenfeld #endif /* >= EMLXS_MODREV5 */
901*8f23e9faSHans Rosenfeld 
902291a2b48SSukumar Swaminathan 	}
903291a2b48SSukumar Swaminathan 
90482527734SSukumar Swaminathan 	/* Get and save the current firmware version (based on sli_mode) */
90582527734SSukumar Swaminathan 	emlxs_decode_firmware_rev(hba, vpd);
906291a2b48SSukumar Swaminathan 
90782527734SSukumar Swaminathan 	emlxs_pcix_mxr_update(hba, 0);
908291a2b48SSukumar Swaminathan 
90982527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
91082527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
911291a2b48SSukumar Swaminathan 
91282527734SSukumar Swaminathan 	emlxs_mb_read_config(hba, mbq);
91382527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
91482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
91582527734SSukumar Swaminathan 		    "Unable to read configuration.  Mailbox cmd=%x status=%x",
91682527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
917291a2b48SSukumar Swaminathan 
91882527734SSukumar Swaminathan 		rval = EIO;
91982527734SSukumar Swaminathan 		goto failed;
92082527734SSukumar Swaminathan 	}
921291a2b48SSukumar Swaminathan 
92282527734SSukumar Swaminathan 	/* Save the link speed capabilities */
923a9800bebSGarrett D'Amore 	vpd->link_speed = (uint16_t)mb->un.varRdConfig.lmt;
92482527734SSukumar Swaminathan 	emlxs_process_link_speed(hba);
925291a2b48SSukumar Swaminathan 
92682527734SSukumar Swaminathan 	/* Set the max node count */
92782527734SSukumar Swaminathan 	if (cfg[CFG_NUM_NODES].current > 0) {
92882527734SSukumar Swaminathan 		hba->max_nodes =
92982527734SSukumar Swaminathan 		    min(cfg[CFG_NUM_NODES].current,
93082527734SSukumar Swaminathan 		    mb->un.varRdConfig.max_rpi);
93182527734SSukumar Swaminathan 	} else {
93282527734SSukumar Swaminathan 		hba->max_nodes = mb->un.varRdConfig.max_rpi;
93382527734SSukumar Swaminathan 	}
934291a2b48SSukumar Swaminathan 
93582527734SSukumar Swaminathan 	/* Set the io throttle */
93682527734SSukumar Swaminathan 	hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE;
937*8f23e9faSHans Rosenfeld 
938*8f23e9faSHans Rosenfeld 	/* Set max_iotag */
939*8f23e9faSHans Rosenfeld 	if (cfg[CFG_NUM_IOTAGS].current) {
940*8f23e9faSHans Rosenfeld 		hba->max_iotag = (uint16_t)cfg[CFG_NUM_IOTAGS].current;
941*8f23e9faSHans Rosenfeld 	} else {
942*8f23e9faSHans Rosenfeld 		hba->max_iotag = mb->un.varRdConfig.max_xri;
943*8f23e9faSHans Rosenfeld 	}
944*8f23e9faSHans Rosenfeld 
945*8f23e9faSHans Rosenfeld 	/* Set out-of-range iotag base */
946*8f23e9faSHans Rosenfeld 	hba->fc_oor_iotag = hba->max_iotag;
947291a2b48SSukumar Swaminathan 
94882527734SSukumar Swaminathan 	/*
94982527734SSukumar Swaminathan 	 * Allocate some memory for buffers
95082527734SSukumar Swaminathan 	 */
95182527734SSukumar Swaminathan 	if (emlxs_mem_alloc_buffer(hba) == 0) {
95282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
95382527734SSukumar Swaminathan 		    "Unable to allocate memory buffers.");
954291a2b48SSukumar Swaminathan 
95582527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
95682527734SSukumar Swaminathan 		return (ENOMEM);
95782527734SSukumar Swaminathan 	}
958291a2b48SSukumar Swaminathan 
95982527734SSukumar Swaminathan 	/*
96082527734SSukumar Swaminathan 	 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
96182527734SSukumar Swaminathan 	 */
962*8f23e9faSHans Rosenfeld 	if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) ||
963*8f23e9faSHans Rosenfeld 	    ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0)) {
96482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
96582527734SSukumar Swaminathan 		    "Unable to allocate diag buffers.");
96682527734SSukumar Swaminathan 
96782527734SSukumar Swaminathan 		rval = ENOMEM;
96882527734SSukumar Swaminathan 		goto failed;
969291a2b48SSukumar Swaminathan 	}
970291a2b48SSukumar Swaminathan 
97182527734SSukumar Swaminathan 	bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
97282527734SSukumar Swaminathan 	    MEM_ELSBUF_SIZE);
97382527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
97482527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
975291a2b48SSukumar Swaminathan 
97682527734SSukumar Swaminathan 	bzero(mp1->virt, MEM_ELSBUF_SIZE);
97782527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
97882527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
979291a2b48SSukumar Swaminathan 
98082527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
98182527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
982291a2b48SSukumar Swaminathan 
98382527734SSukumar Swaminathan 	(void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys);
98482527734SSukumar Swaminathan 
98582527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
98682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
98782527734SSukumar Swaminathan 		    "Unable to run BIU diag.  Mailbox cmd=%x status=%x",
98882527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
98982527734SSukumar Swaminathan 
99082527734SSukumar Swaminathan 		rval = EIO;
99182527734SSukumar Swaminathan 		goto failed;
992291a2b48SSukumar Swaminathan 	}
993291a2b48SSukumar Swaminathan 
99482527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
99582527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
996291a2b48SSukumar Swaminathan 
997b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
998b3660a96SSukumar Swaminathan 	if (mp->dma_handle) {
999b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
1000b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
1001b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
1002b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
1003*8f23e9faSHans Rosenfeld 			    "sli3_online: hdl=%p",
1004b3660a96SSukumar Swaminathan 			    mp->dma_handle);
1005b3660a96SSukumar Swaminathan 			rval = EIO;
1006b3660a96SSukumar Swaminathan 			goto failed;
1007b3660a96SSukumar Swaminathan 		}
1008b3660a96SSukumar Swaminathan 	}
1009b3660a96SSukumar Swaminathan 
1010b3660a96SSukumar Swaminathan 	if (mp1->dma_handle) {
1011b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle)
1012b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
1013b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
1014b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
1015*8f23e9faSHans Rosenfeld 			    "sli3_online: hdl=%p",
1016b3660a96SSukumar Swaminathan 			    mp1->dma_handle);
1017b3660a96SSukumar Swaminathan 			rval = EIO;
1018b3660a96SSukumar Swaminathan 			goto failed;
1019b3660a96SSukumar Swaminathan 		}
1020b3660a96SSukumar Swaminathan 	}
1021b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1022b3660a96SSukumar Swaminathan 
102382527734SSukumar Swaminathan 	outptr = mp->virt;
102482527734SSukumar Swaminathan 	inptr = mp1->virt;
102582527734SSukumar Swaminathan 
102682527734SSukumar Swaminathan 	for (i = 0; i < MEM_ELSBUF_SIZE; i++) {
102782527734SSukumar Swaminathan 		if (*outptr++ != *inptr++) {
102882527734SSukumar Swaminathan 			outptr--;
102982527734SSukumar Swaminathan 			inptr--;
103082527734SSukumar Swaminathan 
103182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
103282527734SSukumar Swaminathan 			    "BIU diagnostic failed. "
103382527734SSukumar Swaminathan 			    "offset %x value %x should be %x.",
103482527734SSukumar Swaminathan 			    i, (uint32_t)*inptr, (uint32_t)*outptr);
103582527734SSukumar Swaminathan 
103682527734SSukumar Swaminathan 			rval = EIO;
103782527734SSukumar Swaminathan 			goto failed;
103882527734SSukumar Swaminathan 		}
1039291a2b48SSukumar Swaminathan 	}
1040291a2b48SSukumar Swaminathan 
1041fe199829SSukumar Swaminathan 	/* Free the buffers since we were polling */
1042a9800bebSGarrett D'Amore 	emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1043fe199829SSukumar Swaminathan 	mp = NULL;
1044a9800bebSGarrett D'Amore 	emlxs_mem_put(hba, MEM_BUF, (void *)mp1);
1045fe199829SSukumar Swaminathan 	mp1 = NULL;
1046fe199829SSukumar Swaminathan 
104782527734SSukumar Swaminathan 	hba->channel_fcp = FC_FCP_RING;
104882527734SSukumar Swaminathan 	hba->channel_els = FC_ELS_RING;
104982527734SSukumar Swaminathan 	hba->channel_ip = FC_IP_RING;
105082527734SSukumar Swaminathan 	hba->channel_ct = FC_CT_RING;
105182527734SSukumar Swaminathan 	hba->sli.sli3.ring_count = MAX_RINGS;
1052291a2b48SSukumar Swaminathan 
105382527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
105482527734SSukumar Swaminathan 	hba->io_count = 0;
105582527734SSukumar Swaminathan 	hba->fc_iotag = 1;
1056291a2b48SSukumar Swaminathan 
105782527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
105882527734SSukumar Swaminathan 		cp = &hba->chan[i];
1059291a2b48SSukumar Swaminathan 
106082527734SSukumar Swaminathan 		/* 1 to 1 mapping between ring and channel */
106182527734SSukumar Swaminathan 		cp->iopath = (void *)&hba->sli.sli3.ring[i];
1062291a2b48SSukumar Swaminathan 
106382527734SSukumar Swaminathan 		cp->hba = hba;
106482527734SSukumar Swaminathan 		cp->channelno = i;
1065291a2b48SSukumar Swaminathan 	}
1066291a2b48SSukumar Swaminathan 
106782527734SSukumar Swaminathan 	/*
106882527734SSukumar Swaminathan 	 * Setup and issue mailbox CONFIGURE RING command
106982527734SSukumar Swaminathan 	 */
107082527734SSukumar Swaminathan 	for (i = 0; i < (uint32_t)hba->sli.sli3.ring_count; i++) {
107182527734SSukumar Swaminathan 		/*
107282527734SSukumar Swaminathan 		 * Initialize cmd/rsp ring pointers
107382527734SSukumar Swaminathan 		 */
107482527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[i];
1075291a2b48SSukumar Swaminathan 
107682527734SSukumar Swaminathan 		/* 1 to 1 mapping between ring and channel */
107782527734SSukumar Swaminathan 		rp->channelp = &hba->chan[i];
1078291a2b48SSukumar Swaminathan 
107982527734SSukumar Swaminathan 		rp->hba = hba;
108082527734SSukumar Swaminathan 		rp->ringno = (uint8_t)i;
108182527734SSukumar Swaminathan 
108282527734SSukumar Swaminathan 		rp->fc_cmdidx = 0;
108382527734SSukumar Swaminathan 		rp->fc_rspidx = 0;
108482527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_CFGRING);
108582527734SSukumar Swaminathan 
108682527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
108782527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
108882527734SSukumar Swaminathan 
108982527734SSukumar Swaminathan 		emlxs_mb_config_ring(hba, i, mbq);
109082527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
109182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
109282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
109382527734SSukumar Swaminathan 			    "Unable to configure ring. "
109482527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
109582527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
109682527734SSukumar Swaminathan 
109782527734SSukumar Swaminathan 			rval = EIO;
109882527734SSukumar Swaminathan 			goto failed;
109982527734SSukumar Swaminathan 		}
1100291a2b48SSukumar Swaminathan 	}
1101291a2b48SSukumar Swaminathan 
110282527734SSukumar Swaminathan 	/*
110382527734SSukumar Swaminathan 	 * Setup link timers
110482527734SSukumar Swaminathan 	 */
110582527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
1106291a2b48SSukumar Swaminathan 
110782527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
110882527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
1109291a2b48SSukumar Swaminathan 
111082527734SSukumar Swaminathan 	emlxs_mb_config_link(hba, mbq);
111182527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
111282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
111382527734SSukumar Swaminathan 		    "Unable to configure link. Mailbox cmd=%x status=%x",
111482527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1115291a2b48SSukumar Swaminathan 
111682527734SSukumar Swaminathan 		rval = EIO;
111782527734SSukumar Swaminathan 		goto failed;
111882527734SSukumar Swaminathan 	}
1119291a2b48SSukumar Swaminathan 
112082527734SSukumar Swaminathan #ifdef MAX_RRDY_SUPPORT
112182527734SSukumar Swaminathan 	/* Set MAX_RRDY if one is provided */
112282527734SSukumar Swaminathan 	if (cfg[CFG_MAX_RRDY].current) {
1123291a2b48SSukumar Swaminathan 
112482527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
112582527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
112682527734SSukumar Swaminathan 
112782527734SSukumar Swaminathan 		emlxs_mb_set_var(hba, (MAILBOX *)mbq, 0x00060412,
112882527734SSukumar Swaminathan 		    cfg[CFG_MAX_RRDY].current);
112982527734SSukumar Swaminathan 
113082527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
113182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
113282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
113382527734SSukumar Swaminathan 			    "MAX_RRDY: Unable to set.  status=%x " \
113482527734SSukumar Swaminathan 			    "value=%d",
113582527734SSukumar Swaminathan 			    mb->mbxStatus, cfg[CFG_MAX_RRDY].current);
113682527734SSukumar Swaminathan 		} else {
113782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
113882527734SSukumar Swaminathan 			    "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current);
113982527734SSukumar Swaminathan 		}
114082527734SSukumar Swaminathan 	}
114182527734SSukumar Swaminathan #endif /* MAX_RRDY_SUPPORT */
114282527734SSukumar Swaminathan 
114382527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
114482527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
114582527734SSukumar Swaminathan 
114682527734SSukumar Swaminathan 	/*
114782527734SSukumar Swaminathan 	 * We need to get login parameters for NID
114882527734SSukumar Swaminathan 	 */
114982527734SSukumar Swaminathan 	(void) emlxs_mb_read_sparam(hba, mbq);
1150a9800bebSGarrett D'Amore 	mp = (MATCHMAP *)mbq->bp;
115182527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
115282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
115382527734SSukumar Swaminathan 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
115482527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
115582527734SSukumar Swaminathan 
115682527734SSukumar Swaminathan 		rval = EIO;
115782527734SSukumar Swaminathan 		goto failed;
115882527734SSukumar Swaminathan 	}
115982527734SSukumar Swaminathan 
116082527734SSukumar Swaminathan 	/* Free the buffer since we were polling */
1161a9800bebSGarrett D'Amore 	emlxs_mem_put(hba, MEM_BUF, (void *)mp);
116282527734SSukumar Swaminathan 	mp = NULL;
116382527734SSukumar Swaminathan 
116482527734SSukumar Swaminathan 	/* If no serial number in VPD data, then use the WWPN */
116582527734SSukumar Swaminathan 	if (vpd->serial_num[0] == 0) {
116682527734SSukumar Swaminathan 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
116782527734SSukumar Swaminathan 		for (i = 0; i < 12; i++) {
116882527734SSukumar Swaminathan 			status = *outptr++;
116982527734SSukumar Swaminathan 			j = ((status & 0xf0) >> 4);
117082527734SSukumar Swaminathan 			if (j <= 9) {
117182527734SSukumar Swaminathan 				vpd->serial_num[i] =
117282527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
117382527734SSukumar Swaminathan 			} else {
117482527734SSukumar Swaminathan 				vpd->serial_num[i] =
117582527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
117682527734SSukumar Swaminathan 			}
117782527734SSukumar Swaminathan 
117882527734SSukumar Swaminathan 			i++;
117982527734SSukumar Swaminathan 			j = (status & 0xf);
118082527734SSukumar Swaminathan 			if (j <= 9) {
118182527734SSukumar Swaminathan 				vpd->serial_num[i] =
118282527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
118382527734SSukumar Swaminathan 			} else {
118482527734SSukumar Swaminathan 				vpd->serial_num[i] =
118582527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
1186291a2b48SSukumar Swaminathan 			}
1187291a2b48SSukumar Swaminathan 		}
118882527734SSukumar Swaminathan 
1189291a2b48SSukumar Swaminathan 		/*
119082527734SSukumar Swaminathan 		 * Set port number and port index to zero
119182527734SSukumar Swaminathan 		 * The WWN's are unique to each port and therefore port_num
119282527734SSukumar Swaminathan 		 * must equal zero. This effects the hba_fru_details structure
119382527734SSukumar Swaminathan 		 * in fca_bind_port()
1194291a2b48SSukumar Swaminathan 		 */
119582527734SSukumar Swaminathan 		vpd->port_num[0] = 0;
119682527734SSukumar Swaminathan 		vpd->port_index = 0;
119782527734SSukumar Swaminathan 	}
1198291a2b48SSukumar Swaminathan 
119982527734SSukumar Swaminathan 	/*
120082527734SSukumar Swaminathan 	 * Make first attempt to set a port index
120182527734SSukumar Swaminathan 	 * Check if this is a multifunction adapter
120282527734SSukumar Swaminathan 	 */
1203a9800bebSGarrett D'Amore 	if ((vpd->port_index == (uint32_t)-1) &&
120482527734SSukumar Swaminathan 	    (hba->model_info.chip >= EMLXS_THOR_CHIP)) {
120582527734SSukumar Swaminathan 		char *buffer;
120682527734SSukumar Swaminathan 		int32_t i;
1207291a2b48SSukumar Swaminathan 
120882527734SSukumar Swaminathan 		/*
120982527734SSukumar Swaminathan 		 * The port address looks like this:
121082527734SSukumar Swaminathan 		 * 1	- for port index 0
121182527734SSukumar Swaminathan 		 * 1,1	- for port index 1
121282527734SSukumar Swaminathan 		 * 1,2	- for port index 2
121382527734SSukumar Swaminathan 		 */
121482527734SSukumar Swaminathan 		buffer = ddi_get_name_addr(hba->dip);
1215291a2b48SSukumar Swaminathan 
121682527734SSukumar Swaminathan 		if (buffer) {
121782527734SSukumar Swaminathan 			vpd->port_index = 0;
1218291a2b48SSukumar Swaminathan 
121982527734SSukumar Swaminathan 			/* Reverse scan for a comma */
122082527734SSukumar Swaminathan 			for (i = strlen(buffer) - 1; i > 0; i--) {
122182527734SSukumar Swaminathan 				if (buffer[i] == ',') {
122282527734SSukumar Swaminathan 					/* Comma found - set index now */
122382527734SSukumar Swaminathan 					vpd->port_index =
122482527734SSukumar Swaminathan 					    emlxs_strtol(&buffer[i + 1], 10);
122582527734SSukumar Swaminathan 					break;
122682527734SSukumar Swaminathan 				}
122782527734SSukumar Swaminathan 			}
122882527734SSukumar Swaminathan 		}
122982527734SSukumar Swaminathan 	}
1230291a2b48SSukumar Swaminathan 
123182527734SSukumar Swaminathan 	/* Make final attempt to set a port index */
1232a9800bebSGarrett D'Amore 	if (vpd->port_index == (uint32_t)-1) {
123382527734SSukumar Swaminathan 		dev_info_t *p_dip;
123482527734SSukumar Swaminathan 		dev_info_t *c_dip;
1235291a2b48SSukumar Swaminathan 
123682527734SSukumar Swaminathan 		p_dip = ddi_get_parent(hba->dip);
123782527734SSukumar Swaminathan 		c_dip = ddi_get_child(p_dip);
1238291a2b48SSukumar Swaminathan 
123982527734SSukumar Swaminathan 		vpd->port_index = 0;
124082527734SSukumar Swaminathan 		while (c_dip && (hba->dip != c_dip)) {
124182527734SSukumar Swaminathan 			c_dip = ddi_get_next_sibling(c_dip);
124282527734SSukumar Swaminathan 			vpd->port_index++;
1243291a2b48SSukumar Swaminathan 		}
124482527734SSukumar Swaminathan 	}
1245291a2b48SSukumar Swaminathan 
124682527734SSukumar Swaminathan 	if (vpd->port_num[0] == 0) {
1247*8f23e9faSHans Rosenfeld 		if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) {
1248*8f23e9faSHans Rosenfeld 			(void) snprintf(vpd->port_num,
1249*8f23e9faSHans Rosenfeld 			    (sizeof (vpd->port_num)-1),
1250*8f23e9faSHans Rosenfeld 			    "%d", vpd->port_index);
125182527734SSukumar Swaminathan 		}
125282527734SSukumar Swaminathan 	}
1253291a2b48SSukumar Swaminathan 
125482527734SSukumar Swaminathan 	if (vpd->id[0] == 0) {
1255*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->id, hba->model_info.model_desc,
1256*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->id)-1));
125782527734SSukumar Swaminathan 	}
1258291a2b48SSukumar Swaminathan 
125982527734SSukumar Swaminathan 	if (vpd->manufacturer[0] == 0) {
1260*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->manufacturer, hba->model_info.manufacturer,
1261*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->manufacturer)-1));
126282527734SSukumar Swaminathan 	}
1263291a2b48SSukumar Swaminathan 
126482527734SSukumar Swaminathan 	if (vpd->part_num[0] == 0) {
1265*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->part_num, hba->model_info.model,
1266*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->part_num)-1));
126782527734SSukumar Swaminathan 	}
1268291a2b48SSukumar Swaminathan 
126982527734SSukumar Swaminathan 	if (vpd->model_desc[0] == 0) {
1270*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->model_desc, hba->model_info.model_desc,
1271*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->model_desc)-1));
127282527734SSukumar Swaminathan 	}
1273291a2b48SSukumar Swaminathan 
127482527734SSukumar Swaminathan 	if (vpd->model[0] == 0) {
1275*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->model, hba->model_info.model,
1276*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->model)-1));
127782527734SSukumar Swaminathan 	}
1278291a2b48SSukumar Swaminathan 
127982527734SSukumar Swaminathan 	if (vpd->prog_types[0] == 0) {
1280*8f23e9faSHans Rosenfeld 		emlxs_build_prog_types(hba, vpd);
1281291a2b48SSukumar Swaminathan 	}
1282291a2b48SSukumar Swaminathan 
128382527734SSukumar Swaminathan 	/* Create the symbolic names */
1284*8f23e9faSHans Rosenfeld 	(void) snprintf(hba->snn, (sizeof (hba->snn)-1),
1285*8f23e9faSHans Rosenfeld 	    "Emulex %s FV%s DV%s %s",
128682527734SSukumar Swaminathan 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
128782527734SSukumar Swaminathan 	    (char *)utsname.nodename);
1288291a2b48SSukumar Swaminathan 
1289*8f23e9faSHans Rosenfeld 	(void) snprintf(hba->spn, (sizeof (hba->spn)-1),
129082527734SSukumar Swaminathan 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
129182527734SSukumar Swaminathan 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
129282527734SSukumar Swaminathan 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
129382527734SSukumar Swaminathan 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1294291a2b48SSukumar Swaminathan 
129582527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
129682527734SSukumar Swaminathan 		if ((hba->sparam.portName.nameType != NAME_IEEE) ||
129782527734SSukumar Swaminathan 		    (hba->sparam.portName.IEEEextMsn != 0) ||
129882527734SSukumar Swaminathan 		    (hba->sparam.portName.IEEEextLsb != 0)) {
1299291a2b48SSukumar Swaminathan 
130082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1301*8f23e9faSHans Rosenfeld 			    "WWPN doesn't conform to IP profile: "
1302*8f23e9faSHans Rosenfeld 			    "nameType=%x. Disabling networking.",
130382527734SSukumar Swaminathan 			    hba->sparam.portName.nameType);
1304*8f23e9faSHans Rosenfeld 
1305*8f23e9faSHans Rosenfeld 			cfg[CFG_NETWORK_ON].current = 0;
130682527734SSukumar Swaminathan 		}
1307*8f23e9faSHans Rosenfeld 	}
1308291a2b48SSukumar Swaminathan 
1309*8f23e9faSHans Rosenfeld 	if (cfg[CFG_NETWORK_ON].current) {
131082527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
131182527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1312291a2b48SSukumar Swaminathan 
131382527734SSukumar Swaminathan 		/* Issue CONFIG FARP */
131482527734SSukumar Swaminathan 		emlxs_mb_config_farp(hba, mbq);
131582527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
131682527734SSukumar Swaminathan 		    MBX_SUCCESS) {
131782527734SSukumar Swaminathan 			/*
131882527734SSukumar Swaminathan 			 * Let it go through even if failed.
131982527734SSukumar Swaminathan 			 */
132082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
132182527734SSukumar Swaminathan 			    "Unable to configure FARP. "
132282527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
132382527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
132482527734SSukumar Swaminathan 		}
1325291a2b48SSukumar Swaminathan 	}
132682527734SSukumar Swaminathan #ifdef MSI_SUPPORT
132782527734SSukumar Swaminathan 	/* Configure MSI map if required */
132882527734SSukumar Swaminathan 	if (hba->intr_count > 1) {
1329a9800bebSGarrett D'Amore 
1330a9800bebSGarrett D'Amore 		if (hba->intr_type == DDI_INTR_TYPE_MSIX) {
1331a9800bebSGarrett D'Amore 			/* always start from 0 */
1332a9800bebSGarrett D'Amore 			hba->last_msiid = 0;
1333a9800bebSGarrett D'Amore 		}
1334a9800bebSGarrett D'Amore 
133582527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
133682527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1337291a2b48SSukumar Swaminathan 
133882527734SSukumar Swaminathan 		emlxs_mb_config_msix(hba, mbq, hba->intr_map, hba->intr_count);
1339291a2b48SSukumar Swaminathan 
134082527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) ==
134182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
134282527734SSukumar Swaminathan 			goto msi_configured;
134382527734SSukumar Swaminathan 		}
1344291a2b48SSukumar Swaminathan 
134582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
134682527734SSukumar Swaminathan 		    "Unable to config MSIX.  Mailbox cmd=0x%x status=0x%x",
134782527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1348291a2b48SSukumar Swaminathan 
134982527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
135082527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1351291a2b48SSukumar Swaminathan 
135282527734SSukumar Swaminathan 		emlxs_mb_config_msi(hba, mbq, hba->intr_map, hba->intr_count);
1353291a2b48SSukumar Swaminathan 
135482527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) ==
135582527734SSukumar Swaminathan 		    MBX_SUCCESS) {
135682527734SSukumar Swaminathan 			goto msi_configured;
1357291a2b48SSukumar Swaminathan 		}
1358291a2b48SSukumar Swaminathan 
1359291a2b48SSukumar Swaminathan 
136082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
136182527734SSukumar Swaminathan 		    "Unable to config MSI.  Mailbox cmd=0x%x status=0x%x",
136282527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1363291a2b48SSukumar Swaminathan 
136482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
136582527734SSukumar Swaminathan 		    "Attempting single interrupt mode...");
1366291a2b48SSukumar Swaminathan 
136782527734SSukumar Swaminathan 		/* First cleanup old interrupts */
136882527734SSukumar Swaminathan 		(void) emlxs_msi_remove(hba);
136982527734SSukumar Swaminathan 		(void) emlxs_msi_uninit(hba);
1370291a2b48SSukumar Swaminathan 
137182527734SSukumar Swaminathan 		status = emlxs_msi_init(hba, 1);
1372291a2b48SSukumar Swaminathan 
137382527734SSukumar Swaminathan 		if (status != DDI_SUCCESS) {
137482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
137582527734SSukumar Swaminathan 			    "Unable to initialize interrupt. status=%d",
137682527734SSukumar Swaminathan 			    status);
1377291a2b48SSukumar Swaminathan 
137882527734SSukumar Swaminathan 			rval = EIO;
137982527734SSukumar Swaminathan 			goto failed;
1380291a2b48SSukumar Swaminathan 		}
1381291a2b48SSukumar Swaminathan 
138282527734SSukumar Swaminathan 		/*
138382527734SSukumar Swaminathan 		 * Reset adapter - The adapter needs to be reset because
138482527734SSukumar Swaminathan 		 * the bus cannot handle the MSI change without handshaking
138582527734SSukumar Swaminathan 		 * with the adapter again
138682527734SSukumar Swaminathan 		 */
1387291a2b48SSukumar Swaminathan 
138882527734SSukumar Swaminathan 		(void) emlxs_mem_free_buffer(hba);
138982527734SSukumar Swaminathan 		fw_check = 0;
139082527734SSukumar Swaminathan 		goto reset;
139182527734SSukumar Swaminathan 	}
1392291a2b48SSukumar Swaminathan 
139382527734SSukumar Swaminathan msi_configured:
1394291a2b48SSukumar Swaminathan 
139582527734SSukumar Swaminathan 
1396a9800bebSGarrett D'Amore 	if ((hba->intr_count >= 1) &&
1397a9800bebSGarrett D'Amore 	    (hba->sli_mode == EMLXS_HBA_SLI3_MODE)) {
1398a9800bebSGarrett D'Amore 		/* intr_count is a sequence of msi id */
1399a9800bebSGarrett D'Amore 		/* Setup msi2chan[msi_id] */
1400a9800bebSGarrett D'Amore 		for (i = 0; i < hba->intr_count; i ++) {
1401a9800bebSGarrett D'Amore 			hba->msi2chan[i] = i;
1402a9800bebSGarrett D'Amore 			if (i >= hba->chan_count)
1403a9800bebSGarrett D'Amore 				hba->msi2chan[i] = (i - hba->chan_count);
1404a9800bebSGarrett D'Amore 		}
1405a9800bebSGarrett D'Amore 	}
140682527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
140782527734SSukumar Swaminathan 
140882527734SSukumar Swaminathan 	/*
140982527734SSukumar Swaminathan 	 * We always disable the firmware traffic cop feature
141082527734SSukumar Swaminathan 	 */
141182527734SSukumar Swaminathan 	if (emlxs_disable_traffic_cop) {
141282527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
141382527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
141482527734SSukumar Swaminathan 
141582527734SSukumar Swaminathan 		emlxs_disable_tc(hba, mbq);
141682527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
141782527734SSukumar Swaminathan 		    MBX_SUCCESS) {
141882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
141982527734SSukumar Swaminathan 			    "Unable to disable traffic cop. "
142082527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
142182527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
142282527734SSukumar Swaminathan 
142382527734SSukumar Swaminathan 			rval = EIO;
142482527734SSukumar Swaminathan 			goto failed;
1425291a2b48SSukumar Swaminathan 		}
142682527734SSukumar Swaminathan 	}
1427291a2b48SSukumar Swaminathan 
142882527734SSukumar Swaminathan 
142982527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
143082527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
143182527734SSukumar Swaminathan 
143282527734SSukumar Swaminathan 	/* Register for async events */
143382527734SSukumar Swaminathan 	emlxs_mb_async_event(hba, mbq);
143482527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
143582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
143682527734SSukumar Swaminathan 		    "Async events disabled. Mailbox status=%x",
143782527734SSukumar Swaminathan 		    mb->mbxStatus);
143882527734SSukumar Swaminathan 	} else {
143982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
144082527734SSukumar Swaminathan 		    "Async events enabled.");
144182527734SSukumar Swaminathan 		hba->flag |= FC_ASYNC_EVENTS;
1442291a2b48SSukumar Swaminathan 	}
1443291a2b48SSukumar Swaminathan 
144482527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
1445291a2b48SSukumar Swaminathan 
144682527734SSukumar Swaminathan 	emlxs_sli3_enable_intr(hba);
1447291a2b48SSukumar Swaminathan 
144882527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
1449*8f23e9faSHans Rosenfeld 		if (port->flag & EMLXS_TGT_ENABLED) {
145082527734SSukumar Swaminathan 			if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) {
145182527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
145282527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
145382527734SSukumar Swaminathan 				    "Unable to setup FCT HBQ.");
1454291a2b48SSukumar Swaminathan 
145582527734SSukumar Swaminathan 				rval = ENOMEM;
1456*8f23e9faSHans Rosenfeld 
1457*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
1458*8f23e9faSHans Rosenfeld 				/* Check if we can fall back to just */
1459*8f23e9faSHans Rosenfeld 				/* initiator mode */
1460*8f23e9faSHans Rosenfeld 				if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
1461*8f23e9faSHans Rosenfeld 				    (port->flag & EMLXS_INI_ENABLED) &&
1462*8f23e9faSHans Rosenfeld 				    (cfg[CFG_DTM_ENABLE].current == 1) &&
1463*8f23e9faSHans Rosenfeld 				    (cfg[CFG_TARGET_MODE].current == 0)) {
1464*8f23e9faSHans Rosenfeld 
1465*8f23e9faSHans Rosenfeld 					cfg[CFG_DTM_ENABLE].current = 0;
1466*8f23e9faSHans Rosenfeld 
1467*8f23e9faSHans Rosenfeld 					EMLXS_MSGF(EMLXS_CONTEXT,
1468*8f23e9faSHans Rosenfeld 					    &emlxs_init_failed_msg,
1469*8f23e9faSHans Rosenfeld 					    "Disabling dynamic target mode. "
1470*8f23e9faSHans Rosenfeld 					    "Enabling initiator mode only.");
1471*8f23e9faSHans Rosenfeld 
1472*8f23e9faSHans Rosenfeld 					/* This will trigger the driver to */
1473*8f23e9faSHans Rosenfeld 					/* reattach */
1474*8f23e9faSHans Rosenfeld 					rval = EAGAIN;
1475*8f23e9faSHans Rosenfeld 				}
1476*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
147782527734SSukumar Swaminathan 				goto failed;
147882527734SSukumar Swaminathan 			}
147982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
148082527734SSukumar Swaminathan 			    "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
148182527734SSukumar Swaminathan 		}
1482291a2b48SSukumar Swaminathan 
148382527734SSukumar Swaminathan 		if (cfg[CFG_NETWORK_ON].current) {
148482527734SSukumar Swaminathan 			if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) {
148582527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
148682527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
148782527734SSukumar Swaminathan 				    "Unable to setup IP HBQ.");
1488291a2b48SSukumar Swaminathan 
148982527734SSukumar Swaminathan 				rval = ENOMEM;
149082527734SSukumar Swaminathan 				goto failed;
149182527734SSukumar Swaminathan 			}
149282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
149382527734SSukumar Swaminathan 			    "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
149482527734SSukumar Swaminathan 		}
1495291a2b48SSukumar Swaminathan 
149682527734SSukumar Swaminathan 		if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) {
149782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
149882527734SSukumar Swaminathan 			    "Unable to setup ELS HBQ.");
149982527734SSukumar Swaminathan 			rval = ENOMEM;
150082527734SSukumar Swaminathan 			goto failed;
150182527734SSukumar Swaminathan 		}
150282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
150382527734SSukumar Swaminathan 		    "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1504291a2b48SSukumar Swaminathan 
150582527734SSukumar Swaminathan 		if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) {
150682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
150782527734SSukumar Swaminathan 			    "Unable to setup CT HBQ.");
1508291a2b48SSukumar Swaminathan 
150982527734SSukumar Swaminathan 			rval = ENOMEM;
151082527734SSukumar Swaminathan 			goto failed;
151182527734SSukumar Swaminathan 		}
151282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
151382527734SSukumar Swaminathan 		    "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
151482527734SSukumar Swaminathan 	} else {
1515*8f23e9faSHans Rosenfeld 		if (port->flag & EMLXS_TGT_ENABLED) {
151682527734SSukumar Swaminathan 			/* Post the FCT unsol buffers */
151782527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[FC_FCT_RING];
151882527734SSukumar Swaminathan 			for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) {
151982527734SSukumar Swaminathan 				(void) emlxs_post_buffer(hba, rp, 2);
152082527734SSukumar Swaminathan 			}
152182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
152282527734SSukumar Swaminathan 			    "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
152382527734SSukumar Swaminathan 		}
1524291a2b48SSukumar Swaminathan 
152582527734SSukumar Swaminathan 		if (cfg[CFG_NETWORK_ON].current) {
152682527734SSukumar Swaminathan 			/* Post the IP unsol buffers */
152782527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[FC_IP_RING];
152882527734SSukumar Swaminathan 			for (j = 0; j < MEM_IPBUF_COUNT; j += 2) {
152982527734SSukumar Swaminathan 				(void) emlxs_post_buffer(hba, rp, 2);
153082527734SSukumar Swaminathan 			}
153182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
153282527734SSukumar Swaminathan 			    "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
153382527734SSukumar Swaminathan 		}
1534291a2b48SSukumar Swaminathan 
153582527734SSukumar Swaminathan 		/* Post the ELS unsol buffers */
153682527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[FC_ELS_RING];
153782527734SSukumar Swaminathan 		for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) {
153882527734SSukumar Swaminathan 			(void) emlxs_post_buffer(hba, rp, 2);
153982527734SSukumar Swaminathan 		}
154082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
154182527734SSukumar Swaminathan 		    "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1542291a2b48SSukumar Swaminathan 
154382527734SSukumar Swaminathan 
154482527734SSukumar Swaminathan 		/* Post the CT unsol buffers */
154582527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[FC_CT_RING];
154682527734SSukumar Swaminathan 		for (j = 0; j < MEM_CTBUF_COUNT; j += 2) {
154782527734SSukumar Swaminathan 			(void) emlxs_post_buffer(hba, rp, 2);
154882527734SSukumar Swaminathan 		}
154982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
155082527734SSukumar Swaminathan 		    "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1551291a2b48SSukumar Swaminathan 	}
1552291a2b48SSukumar Swaminathan 
1553a9800bebSGarrett D'Amore 	(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1554291a2b48SSukumar Swaminathan 
1555*8f23e9faSHans Rosenfeld 	/* Check persist-linkdown */
1556*8f23e9faSHans Rosenfeld 	if (cfg[CFG_PERSIST_LINKDOWN].current) {
1557*8f23e9faSHans Rosenfeld 		EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1558*8f23e9faSHans Rosenfeld 		return (0);
1559*8f23e9faSHans Rosenfeld 	}
1560*8f23e9faSHans Rosenfeld 
1561*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
1562*8f23e9faSHans Rosenfeld 	if ((port->mode == MODE_TARGET) &&
1563*8f23e9faSHans Rosenfeld 	    !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1564*8f23e9faSHans Rosenfeld 		emlxs_enable_latt(hba);
1565*8f23e9faSHans Rosenfeld 		return (0);
1566*8f23e9faSHans Rosenfeld 	}
1567*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
1568*8f23e9faSHans Rosenfeld 
156982527734SSukumar Swaminathan 	/*
157082527734SSukumar Swaminathan 	 * Setup and issue mailbox INITIALIZE LINK command
157182527734SSukumar Swaminathan 	 * At this point, the interrupt will be generated by the HW
157282527734SSukumar Swaminathan 	 */
1573*8f23e9faSHans Rosenfeld 	mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX);
1574*8f23e9faSHans Rosenfeld 	if (mbq == NULL) {
1575*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1576*8f23e9faSHans Rosenfeld 		    "Unable to allocate mailbox buffer.");
1577a9800bebSGarrett D'Amore 
1578*8f23e9faSHans Rosenfeld 		rval = EIO;
1579*8f23e9faSHans Rosenfeld 		goto failed;
1580*8f23e9faSHans Rosenfeld 	}
1581*8f23e9faSHans Rosenfeld 	mb = (MAILBOX *)mbq;
1582a9800bebSGarrett D'Amore 
1583*8f23e9faSHans Rosenfeld 	emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current,
1584*8f23e9faSHans Rosenfeld 	    cfg[CFG_LINK_SPEED].current);
1585291a2b48SSukumar Swaminathan 
1586*8f23e9faSHans Rosenfeld 	rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
1587*8f23e9faSHans Rosenfeld 	if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) {
1588*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1589*8f23e9faSHans Rosenfeld 		    "Unable to initialize link. " \
1590*8f23e9faSHans Rosenfeld 		    "Mailbox cmd=%x status=%x",
1591*8f23e9faSHans Rosenfeld 		    mb->mbxCommand, mb->mbxStatus);
1592*8f23e9faSHans Rosenfeld 
1593*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
1594*8f23e9faSHans Rosenfeld 		mbq = NULL;
1595*8f23e9faSHans Rosenfeld 		rval = EIO;
1596*8f23e9faSHans Rosenfeld 		goto failed;
1597*8f23e9faSHans Rosenfeld 	}
1598*8f23e9faSHans Rosenfeld 
1599*8f23e9faSHans Rosenfeld 	/*
1600*8f23e9faSHans Rosenfeld 	 * Enable link attention interrupt
1601*8f23e9faSHans Rosenfeld 	 */
1602*8f23e9faSHans Rosenfeld 	emlxs_enable_latt(hba);
1603*8f23e9faSHans Rosenfeld 
1604*8f23e9faSHans Rosenfeld 	/* Wait for link to come up */
1605*8f23e9faSHans Rosenfeld 	i = cfg[CFG_LINKUP_DELAY].current;
1606*8f23e9faSHans Rosenfeld 	while (i && (hba->state < FC_LINK_UP)) {
1607*8f23e9faSHans Rosenfeld 		/* Check for hardware error */
1608*8f23e9faSHans Rosenfeld 		if (hba->state == FC_ERROR) {
1609*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
1610*8f23e9faSHans Rosenfeld 			    &emlxs_init_failed_msg,
1611*8f23e9faSHans Rosenfeld 			    "Adapter error.");
1612291a2b48SSukumar Swaminathan 
1613a9800bebSGarrett D'Amore 			mbq = NULL;
161482527734SSukumar Swaminathan 			rval = EIO;
161582527734SSukumar Swaminathan 			goto failed;
161682527734SSukumar Swaminathan 		}
1617291a2b48SSukumar Swaminathan 
1618*8f23e9faSHans Rosenfeld 		BUSYWAIT_MS(1000);
1619*8f23e9faSHans Rosenfeld 		i--;
162082527734SSukumar Swaminathan 	}
162182527734SSukumar Swaminathan 
162282527734SSukumar Swaminathan 	/*
162382527734SSukumar Swaminathan 	 * The leadvile driver will now handle the FLOGI at the driver level
162482527734SSukumar Swaminathan 	 */
1625291a2b48SSukumar Swaminathan 
1626291a2b48SSukumar Swaminathan 	return (0);
1627291a2b48SSukumar Swaminathan 
162882527734SSukumar Swaminathan failed:
1629291a2b48SSukumar Swaminathan 
163082527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1631291a2b48SSukumar Swaminathan 
163282527734SSukumar Swaminathan 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
163382527734SSukumar Swaminathan 		(void) EMLXS_INTR_REMOVE(hba);
163482527734SSukumar Swaminathan 	}
1635291a2b48SSukumar Swaminathan 
163682527734SSukumar Swaminathan 	if (mp) {
1637a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
163882527734SSukumar Swaminathan 		mp = NULL;
163982527734SSukumar Swaminathan 	}
1640291a2b48SSukumar Swaminathan 
164182527734SSukumar Swaminathan 	if (mp1) {
1642a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_BUF, (void *)mp1);
164382527734SSukumar Swaminathan 		mp1 = NULL;
164482527734SSukumar Swaminathan 	}
1645291a2b48SSukumar Swaminathan 
164682527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
1647291a2b48SSukumar Swaminathan 
164882527734SSukumar Swaminathan 	if (mbq) {
164982527734SSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
165082527734SSukumar Swaminathan 		mbq = NULL;
165182527734SSukumar Swaminathan 		mb = NULL;
1652291a2b48SSukumar Swaminathan 	}
1653291a2b48SSukumar Swaminathan 
165482527734SSukumar Swaminathan 	if (rval == 0) {
165582527734SSukumar Swaminathan 		rval = EIO;
165682527734SSukumar Swaminathan 	}
1657291a2b48SSukumar Swaminathan 
165882527734SSukumar Swaminathan 	return (rval);
1659291a2b48SSukumar Swaminathan 
166082527734SSukumar Swaminathan } /* emlxs_sli3_online() */
1661291a2b48SSukumar Swaminathan 
1662291a2b48SSukumar Swaminathan 
1663*8f23e9faSHans Rosenfeld /*ARGSUSED*/
166482527734SSukumar Swaminathan static void
1665*8f23e9faSHans Rosenfeld emlxs_sli3_offline(emlxs_hba_t *hba, uint32_t reset_requested)
166682527734SSukumar Swaminathan {
166782527734SSukumar Swaminathan 	/* Reverse emlxs_sli3_online */
1668291a2b48SSukumar Swaminathan 
166982527734SSukumar Swaminathan 	/* Kill the adapter */
167082527734SSukumar Swaminathan 	emlxs_sli3_hba_kill(hba);
1671291a2b48SSukumar Swaminathan 
167282527734SSukumar Swaminathan 	/* Free driver shared memory */
167382527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
1674291a2b48SSukumar Swaminathan 
167582527734SSukumar Swaminathan } /* emlxs_sli3_offline() */
1676291a2b48SSukumar Swaminathan 
1677291a2b48SSukumar Swaminathan 
167882527734SSukumar Swaminathan static int
167982527734SSukumar Swaminathan emlxs_sli3_map_hdw(emlxs_hba_t *hba)
1680291a2b48SSukumar Swaminathan {
168182527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
168282527734SSukumar Swaminathan 	dev_info_t		*dip;
168382527734SSukumar Swaminathan 	ddi_device_acc_attr_t	dev_attr;
168482527734SSukumar Swaminathan 	int			status;
1685291a2b48SSukumar Swaminathan 
168682527734SSukumar Swaminathan 	dip = (dev_info_t *)hba->dip;
168782527734SSukumar Swaminathan 	dev_attr = emlxs_dev_acc_attr;
1688291a2b48SSukumar Swaminathan 
168982527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
1690291a2b48SSukumar Swaminathan 
169182527734SSukumar Swaminathan 		if (hba->sli.sli3.slim_acc_handle == 0) {
169282527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip,
169382527734SSukumar Swaminathan 			    SBUS_DFLY_SLIM_RINDEX,
169482527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.slim_addr,
169582527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle);
169682527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
169782527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
169882527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
169982527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup SLIM failed. "
170082527734SSukumar Swaminathan 				    "status=%x", status);
170182527734SSukumar Swaminathan 				goto failed;
170282527734SSukumar Swaminathan 			}
170382527734SSukumar Swaminathan 		}
170482527734SSukumar Swaminathan 		if (hba->sli.sli3.csr_acc_handle == 0) {
170582527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip,
170682527734SSukumar Swaminathan 			    SBUS_DFLY_CSR_RINDEX,
170782527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.csr_addr,
170882527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle);
170982527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
171082527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
171182527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
171282527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup DFLY CSR "
171382527734SSukumar Swaminathan 				    "failed. status=%x", status);
171482527734SSukumar Swaminathan 				goto failed;
171582527734SSukumar Swaminathan 			}
171682527734SSukumar Swaminathan 		}
171782527734SSukumar Swaminathan 		if (hba->sli.sli3.sbus_flash_acc_handle == 0) {
171882527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, SBUS_FLASH_RDWR,
171982527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.sbus_flash_addr, 0, 0,
172082527734SSukumar Swaminathan 			    &dev_attr, &hba->sli.sli3.sbus_flash_acc_handle);
172182527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
172282527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
172382527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
172482527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup Fcode Flash "
172582527734SSukumar Swaminathan 				    "failed. status=%x", status);
172682527734SSukumar Swaminathan 				goto failed;
172782527734SSukumar Swaminathan 			}
172882527734SSukumar Swaminathan 		}
172982527734SSukumar Swaminathan 		if (hba->sli.sli3.sbus_core_acc_handle == 0) {
173082527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, SBUS_TITAN_CORE_RINDEX,
173182527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.sbus_core_addr, 0, 0,
173282527734SSukumar Swaminathan 			    &dev_attr, &hba->sli.sli3.sbus_core_acc_handle);
173382527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
173482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
173582527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
173682527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup TITAN CORE "
173782527734SSukumar Swaminathan 				    "failed. status=%x", status);
173882527734SSukumar Swaminathan 				goto failed;
173982527734SSukumar Swaminathan 			}
1740291a2b48SSukumar Swaminathan 		}
1741291a2b48SSukumar Swaminathan 
174282527734SSukumar Swaminathan 		if (hba->sli.sli3.sbus_csr_handle == 0) {
174382527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, SBUS_TITAN_CSR_RINDEX,
174482527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.sbus_csr_addr,
174582527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.sbus_csr_handle);
174682527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
174782527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
174882527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
174982527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup TITAN CSR "
175082527734SSukumar Swaminathan 				    "failed. status=%x", status);
175182527734SSukumar Swaminathan 				goto failed;
1752291a2b48SSukumar Swaminathan 			}
1753291a2b48SSukumar Swaminathan 		}
175482527734SSukumar Swaminathan 	} else {	/* ****** PCI ****** */
1755291a2b48SSukumar Swaminathan 
175682527734SSukumar Swaminathan 		if (hba->sli.sli3.slim_acc_handle == 0) {
175782527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, PCI_SLIM_RINDEX,
175882527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.slim_addr,
175982527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle);
176082527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
176182527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
176282527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
176382527734SSukumar Swaminathan 				    "(PCI) ddi_regs_map_setup SLIM failed. "
176482527734SSukumar Swaminathan 				    "stat=%d mem=%p attr=%p hdl=%p",
176582527734SSukumar Swaminathan 				    status, &hba->sli.sli3.slim_addr, &dev_attr,
176682527734SSukumar Swaminathan 				    &hba->sli.sli3.slim_acc_handle);
176782527734SSukumar Swaminathan 				goto failed;
176882527734SSukumar Swaminathan 			}
1769291a2b48SSukumar Swaminathan 		}
1770291a2b48SSukumar Swaminathan 
177182527734SSukumar Swaminathan 		/*
177282527734SSukumar Swaminathan 		 * Map in control registers, using memory-mapped version of
177382527734SSukumar Swaminathan 		 * the registers rather than the I/O space-mapped registers.
177482527734SSukumar Swaminathan 		 */
177582527734SSukumar Swaminathan 		if (hba->sli.sli3.csr_acc_handle == 0) {
177682527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, PCI_CSR_RINDEX,
177782527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.csr_addr,
177882527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle);
177982527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
178082527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
178182527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
178282527734SSukumar Swaminathan 				    "ddi_regs_map_setup CSR failed. status=%x",
178382527734SSukumar Swaminathan 				    status);
178482527734SSukumar Swaminathan 				goto failed;
178582527734SSukumar Swaminathan 			}
178682527734SSukumar Swaminathan 		}
1787291a2b48SSukumar Swaminathan 	}
1788291a2b48SSukumar Swaminathan 
178982527734SSukumar Swaminathan 	if (hba->sli.sli3.slim2.virt == 0) {
179082527734SSukumar Swaminathan 		MBUF_INFO	*buf_info;
179182527734SSukumar Swaminathan 		MBUF_INFO	bufinfo;
1792291a2b48SSukumar Swaminathan 
179382527734SSukumar Swaminathan 		buf_info = &bufinfo;
1794291a2b48SSukumar Swaminathan 
179582527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
179682527734SSukumar Swaminathan 		buf_info->size = SLI_SLIM2_SIZE;
179782527734SSukumar Swaminathan 		buf_info->flags =
179882527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
179982527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(dip, 1L);
1800291a2b48SSukumar Swaminathan 
180182527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
1802291a2b48SSukumar Swaminathan 
180382527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
180482527734SSukumar Swaminathan 			goto failed;
1805291a2b48SSukumar Swaminathan 		}
180682527734SSukumar Swaminathan 
1807a9800bebSGarrett D'Amore 		hba->sli.sli3.slim2.virt = buf_info->virt;
180882527734SSukumar Swaminathan 		hba->sli.sli3.slim2.phys = buf_info->phys;
180982527734SSukumar Swaminathan 		hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE;
181082527734SSukumar Swaminathan 		hba->sli.sli3.slim2.data_handle = buf_info->data_handle;
181182527734SSukumar Swaminathan 		hba->sli.sli3.slim2.dma_handle = buf_info->dma_handle;
181282527734SSukumar Swaminathan 		bzero((char *)hba->sli.sli3.slim2.virt, SLI_SLIM2_SIZE);
1813291a2b48SSukumar Swaminathan 	}
1814291a2b48SSukumar Swaminathan 
181582527734SSukumar Swaminathan 	/* offset from beginning of register space */
181682527734SSukumar Swaminathan 	hba->sli.sli3.ha_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
181782527734SSukumar Swaminathan 	    (sizeof (uint32_t) * HA_REG_OFFSET));
181882527734SSukumar Swaminathan 	hba->sli.sli3.ca_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
181982527734SSukumar Swaminathan 	    (sizeof (uint32_t) * CA_REG_OFFSET));
182082527734SSukumar Swaminathan 	hba->sli.sli3.hs_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
182182527734SSukumar Swaminathan 	    (sizeof (uint32_t) * HS_REG_OFFSET));
182282527734SSukumar Swaminathan 	hba->sli.sli3.hc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
182382527734SSukumar Swaminathan 	    (sizeof (uint32_t) * HC_REG_OFFSET));
182482527734SSukumar Swaminathan 	hba->sli.sli3.bc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
182582527734SSukumar Swaminathan 	    (sizeof (uint32_t) * BC_REG_OFFSET));
1826291a2b48SSukumar Swaminathan 
182782527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
182882527734SSukumar Swaminathan 		/* offset from beginning of register space */
182982527734SSukumar Swaminathan 		/* for TITAN registers */
183082527734SSukumar Swaminathan 		hba->sli.sli3.shc_reg_addr =
183182527734SSukumar Swaminathan 		    (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
183282527734SSukumar Swaminathan 		    (sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET));
183382527734SSukumar Swaminathan 		hba->sli.sli3.shs_reg_addr =
183482527734SSukumar Swaminathan 		    (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
183582527734SSukumar Swaminathan 		    (sizeof (uint32_t) * SBUS_STAT_REG_OFFSET));
183682527734SSukumar Swaminathan 		hba->sli.sli3.shu_reg_addr =
183782527734SSukumar Swaminathan 		    (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
183882527734SSukumar Swaminathan 		    (sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET));
183982527734SSukumar Swaminathan 	}
184082527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
1841291a2b48SSukumar Swaminathan 
184282527734SSukumar Swaminathan 	return (0);
1843291a2b48SSukumar Swaminathan 
184482527734SSukumar Swaminathan failed:
1845291a2b48SSukumar Swaminathan 
184682527734SSukumar Swaminathan 	emlxs_sli3_unmap_hdw(hba);
184782527734SSukumar Swaminathan 	return (ENOMEM);
1848291a2b48SSukumar Swaminathan 
184982527734SSukumar Swaminathan } /* emlxs_sli3_map_hdw() */
1850291a2b48SSukumar Swaminathan 
1851291a2b48SSukumar Swaminathan 
185282527734SSukumar Swaminathan static void
185382527734SSukumar Swaminathan emlxs_sli3_unmap_hdw(emlxs_hba_t *hba)
185482527734SSukumar Swaminathan {
185582527734SSukumar Swaminathan 	MBUF_INFO	bufinfo;
185682527734SSukumar Swaminathan 	MBUF_INFO	*buf_info = &bufinfo;
1857291a2b48SSukumar Swaminathan 
185882527734SSukumar Swaminathan 	if (hba->sli.sli3.csr_acc_handle) {
185982527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.csr_acc_handle);
186082527734SSukumar Swaminathan 		hba->sli.sli3.csr_acc_handle = 0;
186182527734SSukumar Swaminathan 	}
1862291a2b48SSukumar Swaminathan 
186382527734SSukumar Swaminathan 	if (hba->sli.sli3.slim_acc_handle) {
186482527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.slim_acc_handle);
186582527734SSukumar Swaminathan 		hba->sli.sli3.slim_acc_handle = 0;
186682527734SSukumar Swaminathan 	}
1867291a2b48SSukumar Swaminathan 
186882527734SSukumar Swaminathan 	if (hba->sli.sli3.sbus_flash_acc_handle) {
186982527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.sbus_flash_acc_handle);
187082527734SSukumar Swaminathan 		hba->sli.sli3.sbus_flash_acc_handle = 0;
187182527734SSukumar Swaminathan 	}
1872291a2b48SSukumar Swaminathan 
187382527734SSukumar Swaminathan 	if (hba->sli.sli3.sbus_core_acc_handle) {
187482527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.sbus_core_acc_handle);
187582527734SSukumar Swaminathan 		hba->sli.sli3.sbus_core_acc_handle = 0;
187682527734SSukumar Swaminathan 	}
1877291a2b48SSukumar Swaminathan 
187882527734SSukumar Swaminathan 	if (hba->sli.sli3.sbus_csr_handle) {
187982527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.sbus_csr_handle);
188082527734SSukumar Swaminathan 		hba->sli.sli3.sbus_csr_handle = 0;
188182527734SSukumar Swaminathan 	}
1882291a2b48SSukumar Swaminathan 
188382527734SSukumar Swaminathan 	if (hba->sli.sli3.slim2.virt) {
188482527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1885291a2b48SSukumar Swaminathan 
188682527734SSukumar Swaminathan 		if (hba->sli.sli3.slim2.phys) {
188782527734SSukumar Swaminathan 			buf_info->phys = hba->sli.sli3.slim2.phys;
188882527734SSukumar Swaminathan 			buf_info->data_handle = hba->sli.sli3.slim2.data_handle;
188982527734SSukumar Swaminathan 			buf_info->dma_handle = hba->sli.sli3.slim2.dma_handle;
189082527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
189182527734SSukumar Swaminathan 		}
1892291a2b48SSukumar Swaminathan 
1893a9800bebSGarrett D'Amore 		buf_info->virt = hba->sli.sli3.slim2.virt;
189482527734SSukumar Swaminathan 		buf_info->size = hba->sli.sli3.slim2.size;
189582527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
1896291a2b48SSukumar Swaminathan 
1897a9800bebSGarrett D'Amore 		hba->sli.sli3.slim2.virt = NULL;
1898291a2b48SSukumar Swaminathan 	}
1899291a2b48SSukumar Swaminathan 
1900291a2b48SSukumar Swaminathan 
190182527734SSukumar Swaminathan 	return;
1902291a2b48SSukumar Swaminathan 
190382527734SSukumar Swaminathan } /* emlxs_sli3_unmap_hdw() */
1904291a2b48SSukumar Swaminathan 
1905291a2b48SSukumar Swaminathan 
190682527734SSukumar Swaminathan static uint32_t
190782527734SSukumar Swaminathan emlxs_sli3_hba_init(emlxs_hba_t *hba)
190882527734SSukumar Swaminathan {
190982527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
191082527734SSukumar Swaminathan 	emlxs_port_t *vport;
191182527734SSukumar Swaminathan 	emlxs_config_t *cfg;
1912a9800bebSGarrett D'Amore 	uint16_t i;
1913*8f23e9faSHans Rosenfeld 	VPIobj_t *vpip;
19144baa2c25SSukumar Swaminathan 
191582527734SSukumar Swaminathan 	cfg = &CFG;
191682527734SSukumar Swaminathan 	i = 0;
1917291a2b48SSukumar Swaminathan 
191882527734SSukumar Swaminathan 	/* Restart the adapter */
191982527734SSukumar Swaminathan 	if (emlxs_sli3_hba_reset(hba, 1, 0, 0)) {
192082527734SSukumar Swaminathan 		return (1);
192182527734SSukumar Swaminathan 	}
1922291a2b48SSukumar Swaminathan 
192382527734SSukumar Swaminathan 	hba->channel_fcp = FC_FCP_RING;
192482527734SSukumar Swaminathan 	hba->channel_els = FC_ELS_RING;
192582527734SSukumar Swaminathan 	hba->channel_ip = FC_IP_RING;
192682527734SSukumar Swaminathan 	hba->channel_ct = FC_CT_RING;
192782527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
192882527734SSukumar Swaminathan 	hba->sli.sli3.ring_count = MAX_RINGS;
1929291a2b48SSukumar Swaminathan 
1930291a2b48SSukumar Swaminathan 	/*
193182527734SSukumar Swaminathan 	 * WARNING: There is a max of 6 ring masks allowed
1932291a2b48SSukumar Swaminathan 	 */
193382527734SSukumar Swaminathan 	/* RING 0 - FCP */
1934*8f23e9faSHans Rosenfeld 	if (port->flag & EMLXS_TGT_ENABLED) {
193582527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_FCP_RING] = 1;
193682527734SSukumar Swaminathan 		hba->sli.sli3.ring_rval[i] = FC_FCP_CMND;
193782527734SSukumar Swaminathan 		hba->sli.sli3.ring_rmask[i] = 0;
1938*8f23e9faSHans Rosenfeld 		hba->sli.sli3.ring_tval[i] = FC_TYPE_SCSI_FCP;
193982527734SSukumar Swaminathan 		hba->sli.sli3.ring_tmask[i++] = 0xFF;
194082527734SSukumar Swaminathan 	} else {
194182527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_FCP_RING] = 0;
1942291a2b48SSukumar Swaminathan 	}
1943291a2b48SSukumar Swaminathan 
194482527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES;
194582527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES;
1946291a2b48SSukumar Swaminathan 
194782527734SSukumar Swaminathan 	/* RING 1 - IP */
194882527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
194982527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_IP_RING] = 1;
195082527734SSukumar Swaminathan 		hba->sli.sli3.ring_rval[i] = FC_UNSOL_DATA; /* Unsol Data */
195182527734SSukumar Swaminathan 		hba->sli.sli3.ring_rmask[i] = 0xFF;
1952*8f23e9faSHans Rosenfeld 		hba->sli.sli3.ring_tval[i] = FC_TYPE_IS8802_SNAP; /* LLC/SNAP */
195382527734SSukumar Swaminathan 		hba->sli.sli3.ring_tmask[i++] = 0xFF;
1954291a2b48SSukumar Swaminathan 	} else {
195582527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_IP_RING] = 0;
1956291a2b48SSukumar Swaminathan 	}
1957291a2b48SSukumar Swaminathan 
195882527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES;
195982527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES;
19604baa2c25SSukumar Swaminathan 
196182527734SSukumar Swaminathan 	/* RING 2 - ELS */
196282527734SSukumar Swaminathan 	hba->sli.sli3.ring_masks[FC_ELS_RING] = 1;
196382527734SSukumar Swaminathan 	hba->sli.sli3.ring_rval[i] = FC_ELS_REQ;	/* ELS request/rsp */
196482527734SSukumar Swaminathan 	hba->sli.sli3.ring_rmask[i] = 0xFE;
1965*8f23e9faSHans Rosenfeld 	hba->sli.sli3.ring_tval[i] = FC_TYPE_EXTENDED_LS;	/* ELS */
196682527734SSukumar Swaminathan 	hba->sli.sli3.ring_tmask[i++] = 0xFF;
1967291a2b48SSukumar Swaminathan 
196882527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES;
196982527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES;
1970291a2b48SSukumar Swaminathan 
197182527734SSukumar Swaminathan 	/* RING 3 - CT */
197282527734SSukumar Swaminathan 	hba->sli.sli3.ring_masks[FC_CT_RING] = 1;
197382527734SSukumar Swaminathan 	hba->sli.sli3.ring_rval[i] = FC_UNSOL_CTL;	/* CT request/rsp */
197482527734SSukumar Swaminathan 	hba->sli.sli3.ring_rmask[i] = 0xFE;
1975*8f23e9faSHans Rosenfeld 	hba->sli.sli3.ring_tval[i] = FC_TYPE_FC_SERVICES;	/* CT */
197682527734SSukumar Swaminathan 	hba->sli.sli3.ring_tmask[i++] = 0xFF;
1977291a2b48SSukumar Swaminathan 
197882527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES;
197982527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES;
1980291a2b48SSukumar Swaminathan 
198182527734SSukumar Swaminathan 	if (i > 6) {
198282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
1983*8f23e9faSHans Rosenfeld 		    "hba_init: Too many ring masks defined. cnt=%d", i);
198482527734SSukumar Swaminathan 		return (1);
198582527734SSukumar Swaminathan 	}
198682527734SSukumar Swaminathan 
198782527734SSukumar Swaminathan 	/* Initialize all the port objects */
198882527734SSukumar Swaminathan 	hba->vpi_max = 0;
198982527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
199082527734SSukumar Swaminathan 		vport = &VPORT(i);
199182527734SSukumar Swaminathan 		vport->hba = hba;
199282527734SSukumar Swaminathan 		vport->vpi = i;
1993*8f23e9faSHans Rosenfeld 
1994*8f23e9faSHans Rosenfeld 		vpip = &vport->VPIobj;
1995*8f23e9faSHans Rosenfeld 		vpip->index = i;
1996*8f23e9faSHans Rosenfeld 		vpip->VPI = i;
1997*8f23e9faSHans Rosenfeld 		vpip->port = vport;
1998*8f23e9faSHans Rosenfeld 		vpip->state = VPI_STATE_OFFLINE;
1999*8f23e9faSHans Rosenfeld 		vport->vpip = vpip;
200082527734SSukumar Swaminathan 	}
200182527734SSukumar Swaminathan 
200282527734SSukumar Swaminathan 	/*
200382527734SSukumar Swaminathan 	 * Initialize the max_node count to a default value if needed
200482527734SSukumar Swaminathan 	 * This determines how many node objects we preallocate in the pool
200582527734SSukumar Swaminathan 	 * The actual max_nodes will be set later based on adapter info
200682527734SSukumar Swaminathan 	 */
200782527734SSukumar Swaminathan 	if (hba->max_nodes == 0) {
200882527734SSukumar Swaminathan 		if (cfg[CFG_NUM_NODES].current > 0) {
200982527734SSukumar Swaminathan 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
201082527734SSukumar Swaminathan 		} else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
201182527734SSukumar Swaminathan 			hba->max_nodes = 4096;
201282527734SSukumar Swaminathan 		} else {
201382527734SSukumar Swaminathan 			hba->max_nodes = 512;
201482527734SSukumar Swaminathan 		}
201582527734SSukumar Swaminathan 	}
2016291a2b48SSukumar Swaminathan 
201782527734SSukumar Swaminathan 	return (0);
2018291a2b48SSukumar Swaminathan 
201982527734SSukumar Swaminathan } /* emlxs_sli3_hba_init() */
2020291a2b48SSukumar Swaminathan 
2021291a2b48SSukumar Swaminathan 
202282527734SSukumar Swaminathan /*
202382527734SSukumar Swaminathan  * 0: quiesce indicates the call is not from quiesce routine.
202482527734SSukumar Swaminathan  * 1: quiesce indicates the call is from quiesce routine.
202582527734SSukumar Swaminathan  */
202682527734SSukumar Swaminathan static uint32_t
202782527734SSukumar Swaminathan emlxs_sli3_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
202882527734SSukumar Swaminathan 	uint32_t quiesce)
2029291a2b48SSukumar Swaminathan {
203082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
203182527734SSukumar Swaminathan 	MAILBOX *swpmb;
203282527734SSukumar Swaminathan 	MAILBOX *mb;
203382527734SSukumar Swaminathan 	uint32_t word0;
203482527734SSukumar Swaminathan 	uint16_t cfg_value;
2035*8f23e9faSHans Rosenfeld 	uint32_t status = 0;
203682527734SSukumar Swaminathan 	uint32_t status1;
203782527734SSukumar Swaminathan 	uint32_t status2;
203882527734SSukumar Swaminathan 	uint32_t i;
203982527734SSukumar Swaminathan 	uint32_t ready;
204082527734SSukumar Swaminathan 	emlxs_port_t *vport;
204182527734SSukumar Swaminathan 	RING *rp;
204282527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
2043291a2b48SSukumar Swaminathan 
204482527734SSukumar Swaminathan 	if (!cfg[CFG_RESET_ENABLE].current) {
204582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
204682527734SSukumar Swaminathan 		    "Adapter reset disabled.");
204782527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
2048291a2b48SSukumar Swaminathan 
204982527734SSukumar Swaminathan 		return (1);
2050291a2b48SSukumar Swaminathan 	}
2051291a2b48SSukumar Swaminathan 
205282527734SSukumar Swaminathan 	/* Kill the adapter first */
205382527734SSukumar Swaminathan 	if (quiesce == 0) {
205482527734SSukumar Swaminathan 		emlxs_sli3_hba_kill(hba);
205582527734SSukumar Swaminathan 	} else {
205682527734SSukumar Swaminathan 		emlxs_sli3_hba_kill4quiesce(hba);
2057291a2b48SSukumar Swaminathan 	}
2058291a2b48SSukumar Swaminathan 
205982527734SSukumar Swaminathan 	if (restart) {
206082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
206182527734SSukumar Swaminathan 		    "Restarting.");
206282527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_START);
2063291a2b48SSukumar Swaminathan 
206482527734SSukumar Swaminathan 		ready = (HS_FFRDY | HS_MBRDY);
206582527734SSukumar Swaminathan 	} else {
206682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
206782527734SSukumar Swaminathan 		    "Resetting.");
206882527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_WARM_START);
2069291a2b48SSukumar Swaminathan 
207082527734SSukumar Swaminathan 		ready = HS_MBRDY;
2071291a2b48SSukumar Swaminathan 	}
2072291a2b48SSukumar Swaminathan 
207382527734SSukumar Swaminathan 	hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR);
2074291a2b48SSukumar Swaminathan 
207582527734SSukumar Swaminathan 	mb = FC_SLIM1_MAILBOX(hba);
207682527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
2077291a2b48SSukumar Swaminathan 
207882527734SSukumar Swaminathan reset:
2079291a2b48SSukumar Swaminathan 
2080*8f23e9faSHans Rosenfeld 	i = 0;
2081*8f23e9faSHans Rosenfeld 
208282527734SSukumar Swaminathan 	/* Save reset time */
208382527734SSukumar Swaminathan 	HBASTATS.ResetTime = hba->timer_tics;
2084291a2b48SSukumar Swaminathan 
208582527734SSukumar Swaminathan 	if (restart) {
208682527734SSukumar Swaminathan 		/* First put restart command in mailbox */
208782527734SSukumar Swaminathan 		word0 = 0;
208882527734SSukumar Swaminathan 		swpmb->mbxCommand = MBX_RESTART;
208982527734SSukumar Swaminathan 		swpmb->mbxHc = 1;
209082527734SSukumar Swaminathan 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb), word0);
209182527734SSukumar Swaminathan 
209282527734SSukumar Swaminathan 		/* Only skip post after emlxs_sli3_online is completed */
209382527734SSukumar Swaminathan 		if (skip_post) {
209482527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1),
209582527734SSukumar Swaminathan 			    1);
209682527734SSukumar Swaminathan 		} else {
209782527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1),
209882527734SSukumar Swaminathan 			    0);
2099291a2b48SSukumar Swaminathan 		}
2100291a2b48SSukumar Swaminathan 
210182527734SSukumar Swaminathan 	}
2102291a2b48SSukumar Swaminathan 
210382527734SSukumar Swaminathan 	/*
210482527734SSukumar Swaminathan 	 * Turn off SERR, PERR in PCI cmd register
210582527734SSukumar Swaminathan 	 */
210682527734SSukumar Swaminathan 	cfg_value = ddi_get16(hba->pci_acc_handle,
210782527734SSukumar Swaminathan 	    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER));
2108291a2b48SSukumar Swaminathan 
210982527734SSukumar Swaminathan 	ddi_put16(hba->pci_acc_handle,
211082527734SSukumar Swaminathan 	    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
211182527734SSukumar Swaminathan 	    (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL)));
2112291a2b48SSukumar Swaminathan 
211382527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = HC_INITFF;
211482527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
2115291a2b48SSukumar Swaminathan 
211682527734SSukumar Swaminathan 	/* Wait 1 msec before restoring PCI config */
2117*8f23e9faSHans Rosenfeld 	BUSYWAIT_MS(1);
2118291a2b48SSukumar Swaminathan 
211982527734SSukumar Swaminathan 	/* Restore PCI cmd register */
212082527734SSukumar Swaminathan 	ddi_put16(hba->pci_acc_handle,
212182527734SSukumar Swaminathan 	    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
212282527734SSukumar Swaminathan 	    (uint16_t)cfg_value);
2123291a2b48SSukumar Swaminathan 
212482527734SSukumar Swaminathan 	/* Wait 3 seconds before checking */
2125*8f23e9faSHans Rosenfeld 	BUSYWAIT_MS(3000);
212682527734SSukumar Swaminathan 	i += 3;
2127291a2b48SSukumar Swaminathan 
212882527734SSukumar Swaminathan 	/* Wait for reset completion */
212982527734SSukumar Swaminathan 	while (i < 30) {
213082527734SSukumar Swaminathan 		/* Check status register to see what current state is */
213182527734SSukumar Swaminathan 		status = READ_CSR_REG(hba, FC_HS_REG(hba));
2132291a2b48SSukumar Swaminathan 
213382527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
213482527734SSukumar Swaminathan 		if (status & HS_FFERM) {
213582527734SSukumar Swaminathan 			status1 = READ_SLIM_ADDR(hba, ((volatile uint8_t *)
213682527734SSukumar Swaminathan 			    hba->sli.sli3.slim_addr + 0xa8));
213782527734SSukumar Swaminathan 			status2 = READ_SLIM_ADDR(hba, ((volatile uint8_t *)
213882527734SSukumar Swaminathan 			    hba->sli.sli3.slim_addr + 0xac));
2139291a2b48SSukumar Swaminathan 
214082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
214182527734SSukumar Swaminathan 			    "HS_FFERM: status=0x%x status1=0x%x status2=0x%x",
214282527734SSukumar Swaminathan 			    status, status1, status2);
2143291a2b48SSukumar Swaminathan 
214482527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
214582527734SSukumar Swaminathan 			return (1);
2146291a2b48SSukumar Swaminathan 		}
2147291a2b48SSukumar Swaminathan 
214882527734SSukumar Swaminathan 		if ((status & ready) == ready) {
214982527734SSukumar Swaminathan 			/* Reset Done !! */
215082527734SSukumar Swaminathan 			goto done;
215182527734SSukumar Swaminathan 		}
2152291a2b48SSukumar Swaminathan 
215382527734SSukumar Swaminathan 		/*
215482527734SSukumar Swaminathan 		 * Check every 1 second for 15 seconds, then reset board
215582527734SSukumar Swaminathan 		 * again (w/post), then check every 1 second for 15 * seconds.
215682527734SSukumar Swaminathan 		 */
2157*8f23e9faSHans Rosenfeld 		BUSYWAIT_MS(1000);
215882527734SSukumar Swaminathan 		i++;
2159291a2b48SSukumar Swaminathan 
216082527734SSukumar Swaminathan 		/* Reset again (w/post) at 15 seconds */
216182527734SSukumar Swaminathan 		if (i == 15) {
216282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
216382527734SSukumar Swaminathan 			    "Reset failed. Retrying...");
2164291a2b48SSukumar Swaminathan 
216582527734SSukumar Swaminathan 			goto reset;
2166291a2b48SSukumar Swaminathan 		}
2167291a2b48SSukumar Swaminathan 	}
2168291a2b48SSukumar Swaminathan 
216982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
217082527734SSukumar Swaminathan reset_fail:
217182527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
2172291a2b48SSukumar Swaminathan 
217382527734SSukumar Swaminathan 	/* Timeout occurred */
217482527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
217582527734SSukumar Swaminathan 	    "Timeout: status=0x%x", status);
217682527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
2177291a2b48SSukumar Swaminathan 
217882527734SSukumar Swaminathan 	/* Log a dump event */
217982527734SSukumar Swaminathan 	emlxs_log_dump_event(port, NULL, 0);
2180291a2b48SSukumar Swaminathan 
218182527734SSukumar Swaminathan 	return (1);
2182291a2b48SSukumar Swaminathan 
218382527734SSukumar Swaminathan done:
2184291a2b48SSukumar Swaminathan 
218582527734SSukumar Swaminathan 	/* Initialize hc_copy */
218682527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba));
2187291a2b48SSukumar Swaminathan 
21884baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
21894baa2c25SSukumar Swaminathan 	/* Access handle validation */
219082527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
21914baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) ||
219282527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
219382527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
219482527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
21954baa2c25SSukumar Swaminathan 	    != DDI_FM_OK)) {
21964baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
21974baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
219882527734SSukumar Swaminathan 		goto reset_fail;
21994baa2c25SSukumar Swaminathan 	}
22004baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
22014baa2c25SSukumar Swaminathan 
220282527734SSukumar Swaminathan 	/* Reset the hba structure */
220382527734SSukumar Swaminathan 	hba->flag &= FC_RESET_MASK;
220482527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
220582527734SSukumar Swaminathan 	hba->io_count = 0;
220682527734SSukumar Swaminathan 	hba->iodone_count = 0;
220782527734SSukumar Swaminathan 	hba->topology = 0;
220882527734SSukumar Swaminathan 	hba->linkspeed = 0;
220982527734SSukumar Swaminathan 	hba->heartbeat_active = 0;
221082527734SSukumar Swaminathan 	hba->discovery_timer = 0;
221182527734SSukumar Swaminathan 	hba->linkup_timer = 0;
221282527734SSukumar Swaminathan 	hba->loopback_tics = 0;
2213291a2b48SSukumar Swaminathan 
221482527734SSukumar Swaminathan 	/* Reset the ring objects */
221582527734SSukumar Swaminathan 	for (i = 0; i < MAX_RINGS; i++) {
221682527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[i];
221782527734SSukumar Swaminathan 		rp->fc_mpon = 0;
221882527734SSukumar Swaminathan 		rp->fc_mpoff = 0;
221982527734SSukumar Swaminathan 	}
2220291a2b48SSukumar Swaminathan 
222182527734SSukumar Swaminathan 	/* Reset the port objects */
222282527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
222382527734SSukumar Swaminathan 		vport = &VPORT(i);
2224291a2b48SSukumar Swaminathan 
222582527734SSukumar Swaminathan 		vport->flag &= EMLXS_PORT_RESET_MASK;
222682527734SSukumar Swaminathan 		vport->did = 0;
222782527734SSukumar Swaminathan 		vport->prev_did = 0;
222882527734SSukumar Swaminathan 		vport->lip_type = 0;
222982527734SSukumar Swaminathan 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
2230a9800bebSGarrett D'Amore 		bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
223182527734SSukumar Swaminathan 
223282527734SSukumar Swaminathan 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
223382527734SSukumar Swaminathan 		vport->node_base.nlp_Rpi = 0;
223482527734SSukumar Swaminathan 		vport->node_base.nlp_DID = 0xffffff;
223582527734SSukumar Swaminathan 		vport->node_base.nlp_list_next = NULL;
223682527734SSukumar Swaminathan 		vport->node_base.nlp_list_prev = NULL;
223782527734SSukumar Swaminathan 		vport->node_base.nlp_active = 1;
223882527734SSukumar Swaminathan 		vport->node_count = 0;
223982527734SSukumar Swaminathan 
224082527734SSukumar Swaminathan 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
224182527734SSukumar Swaminathan 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
2242291a2b48SSukumar Swaminathan 		}
224382527734SSukumar Swaminathan 	}
2244291a2b48SSukumar Swaminathan 
224582527734SSukumar Swaminathan 	return (0);
2246291a2b48SSukumar Swaminathan 
224782527734SSukumar Swaminathan } /* emlxs_sli3_hba_reset */
2248291a2b48SSukumar Swaminathan 
2249291a2b48SSukumar Swaminathan 
225082527734SSukumar Swaminathan #define	BPL_CMD		0
225182527734SSukumar Swaminathan #define	BPL_RESP	1
225282527734SSukumar Swaminathan #define	BPL_DATA	2
2253291a2b48SSukumar Swaminathan 
225482527734SSukumar Swaminathan static ULP_BDE64 *
2255*8f23e9faSHans Rosenfeld emlxs_pkt_to_bpl(fc_packet_t *pkt, ULP_BDE64 *bpl, uint32_t bpl_type)
225682527734SSukumar Swaminathan {
225782527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp;
225882527734SSukumar Swaminathan 	uint_t	i;
225982527734SSukumar Swaminathan 	int32_t	size;
226082527734SSukumar Swaminathan 	uint_t	cookie_cnt;
2261*8f23e9faSHans Rosenfeld 	uint8_t bdeFlags;
2262291a2b48SSukumar Swaminathan 
226382527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
226482527734SSukumar Swaminathan 	switch (bpl_type) {
226582527734SSukumar Swaminathan 	case BPL_CMD:
226682527734SSukumar Swaminathan 		cp = pkt->pkt_cmd_cookie;
226782527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
226882527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
2269*8f23e9faSHans Rosenfeld 		bdeFlags = 0;
227082527734SSukumar Swaminathan 		break;
2271291a2b48SSukumar Swaminathan 
227282527734SSukumar Swaminathan 	case BPL_RESP:
227382527734SSukumar Swaminathan 		cp = pkt->pkt_resp_cookie;
227482527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
227582527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
2276*8f23e9faSHans Rosenfeld 		bdeFlags = BUFF_USE_RCV;
227782527734SSukumar Swaminathan 		break;
2278291a2b48SSukumar Swaminathan 
2279291a2b48SSukumar Swaminathan 
228082527734SSukumar Swaminathan 	case BPL_DATA:
228182527734SSukumar Swaminathan 		cp = pkt->pkt_data_cookie;
228282527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_data_cookie_cnt;
228382527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
2284*8f23e9faSHans Rosenfeld 		bdeFlags = (pkt->pkt_tran_type == FC_PKT_FCP_READ) ?
2285*8f23e9faSHans Rosenfeld 		    BUFF_USE_RCV : 0;
228682527734SSukumar Swaminathan 		break;
2287*8f23e9faSHans Rosenfeld 
2288*8f23e9faSHans Rosenfeld 	default:
2289*8f23e9faSHans Rosenfeld 		return (NULL);
229082527734SSukumar Swaminathan 	}
2291291a2b48SSukumar Swaminathan 
229282527734SSukumar Swaminathan #else
229382527734SSukumar Swaminathan 	switch (bpl_type) {
229482527734SSukumar Swaminathan 	case BPL_CMD:
229582527734SSukumar Swaminathan 		cp = &pkt->pkt_cmd_cookie;
229682527734SSukumar Swaminathan 		cookie_cnt = 1;
229782527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
2298*8f23e9faSHans Rosenfeld 		bdeFlags = 0;
229982527734SSukumar Swaminathan 		break;
2300291a2b48SSukumar Swaminathan 
230182527734SSukumar Swaminathan 	case BPL_RESP:
230282527734SSukumar Swaminathan 		cp = &pkt->pkt_resp_cookie;
230382527734SSukumar Swaminathan 		cookie_cnt = 1;
230482527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
2305*8f23e9faSHans Rosenfeld 		bdeFlags = BUFF_USE_RCV;
230682527734SSukumar Swaminathan 		break;
2307291a2b48SSukumar Swaminathan 
2308291a2b48SSukumar Swaminathan 
230982527734SSukumar Swaminathan 	case BPL_DATA:
231082527734SSukumar Swaminathan 		cp = &pkt->pkt_data_cookie;
231182527734SSukumar Swaminathan 		cookie_cnt = 1;
231282527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
2313*8f23e9faSHans Rosenfeld 		bdeFlags = (pkt->pkt_tran_type == FC_PKT_FCP_READ) ?
2314*8f23e9faSHans Rosenfeld 		    BUFF_USE_RCV : 0;
231582527734SSukumar Swaminathan 		break;
2316*8f23e9faSHans Rosenfeld 
2317*8f23e9faSHans Rosenfeld 	default:
2318*8f23e9faSHans Rosenfeld 		return (NULL);
231982527734SSukumar Swaminathan 	}
232082527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2321291a2b48SSukumar Swaminathan 
232282527734SSukumar Swaminathan 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
232382527734SSukumar Swaminathan 		bpl->addrHigh =
232482527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_HI(cp->dmac_laddress));
232582527734SSukumar Swaminathan 		bpl->addrLow =
232682527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_LO(cp->dmac_laddress));
232782527734SSukumar Swaminathan 		bpl->tus.f.bdeSize = MIN(size, cp->dmac_size);
232882527734SSukumar Swaminathan 		bpl->tus.f.bdeFlags = bdeFlags;
232982527734SSukumar Swaminathan 		bpl->tus.w = BE_SWAP32(bpl->tus.w);
2330291a2b48SSukumar Swaminathan 
233182527734SSukumar Swaminathan 		bpl++;
233282527734SSukumar Swaminathan 		size -= cp->dmac_size;
233382527734SSukumar Swaminathan 	}
2334291a2b48SSukumar Swaminathan 
233582527734SSukumar Swaminathan 	return (bpl);
2336291a2b48SSukumar Swaminathan 
233782527734SSukumar Swaminathan } /* emlxs_pkt_to_bpl */
2338291a2b48SSukumar Swaminathan 
2339291a2b48SSukumar Swaminathan 
234082527734SSukumar Swaminathan static uint32_t
234182527734SSukumar Swaminathan emlxs_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
234282527734SSukumar Swaminathan {
234382527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
234482527734SSukumar Swaminathan 	fc_packet_t	*pkt;
234582527734SSukumar Swaminathan 	MATCHMAP	*bmp;
234682527734SSukumar Swaminathan 	ULP_BDE64	*bpl;
234782527734SSukumar Swaminathan 	uint64_t	bp;
234882527734SSukumar Swaminathan 	IOCB		*iocb;
234982527734SSukumar Swaminathan 	IOCBQ		*iocbq;
235082527734SSukumar Swaminathan 	CHANNEL	*cp;
235182527734SSukumar Swaminathan 	uint32_t	data_cookie_cnt;
2352*8f23e9faSHans Rosenfeld 	uint32_t	channelno;
2353291a2b48SSukumar Swaminathan 
235482527734SSukumar Swaminathan 	cp = sbp->channel;
235582527734SSukumar Swaminathan 	iocb = (IOCB *) & sbp->iocbq;
235682527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
2357291a2b48SSukumar Swaminathan 
2358*8f23e9faSHans Rosenfeld 	if (hba->sli.sli3.bpl_table) {
2359*8f23e9faSHans Rosenfeld 		bmp = hba->sli.sli3.bpl_table[sbp->iotag];
2360*8f23e9faSHans Rosenfeld 	} else {
2361*8f23e9faSHans Rosenfeld 		bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL);
2362*8f23e9faSHans Rosenfeld 	}
2363291a2b48SSukumar Swaminathan 
236482527734SSukumar Swaminathan 	if (!bmp) {
236582527734SSukumar Swaminathan 		return (1);
236682527734SSukumar Swaminathan 	}
2367291a2b48SSukumar Swaminathan 
236882527734SSukumar Swaminathan 	sbp->bmp = bmp;
236982527734SSukumar Swaminathan 	bpl = (ULP_BDE64 *)bmp->virt;
237082527734SSukumar Swaminathan 	bp = bmp->phys;
2371291a2b48SSukumar Swaminathan 
237282527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
237382527734SSukumar Swaminathan 	data_cookie_cnt = pkt->pkt_data_cookie_cnt;
237482527734SSukumar Swaminathan #else
237582527734SSukumar Swaminathan 	data_cookie_cnt = 1;
237682527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2377291a2b48SSukumar Swaminathan 
237882527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
237982527734SSukumar Swaminathan 
2380*8f23e9faSHans Rosenfeld 	channelno = (iocbq->flag & IOCB_FCP_CMD)? FC_FCP_RING:cp->channelno;
2381*8f23e9faSHans Rosenfeld 	switch (channelno) {
2382*8f23e9faSHans Rosenfeld 		case FC_FCP_RING:
2383*8f23e9faSHans Rosenfeld 
238482527734SSukumar Swaminathan 		/* CMD payload */
2385*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2386*8f23e9faSHans Rosenfeld 		if (! bpl) {
2387*8f23e9faSHans Rosenfeld 			return (1);
2388*8f23e9faSHans Rosenfeld 		}
2389*8f23e9faSHans Rosenfeld 
2390*8f23e9faSHans Rosenfeld 		/* Check if response & data payloads are needed */
2391*8f23e9faSHans Rosenfeld 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2392*8f23e9faSHans Rosenfeld 			break;
2393*8f23e9faSHans Rosenfeld 		}
2394*8f23e9faSHans Rosenfeld 
2395*8f23e9faSHans Rosenfeld 		/* RSP payload */
2396*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP);
2397*8f23e9faSHans Rosenfeld 		if (! bpl) {
2398*8f23e9faSHans Rosenfeld 			return (1);
2399*8f23e9faSHans Rosenfeld 		}
2400*8f23e9faSHans Rosenfeld 
2401*8f23e9faSHans Rosenfeld 		/* Check if data payload is needed */
2402*8f23e9faSHans Rosenfeld 		if ((pkt->pkt_datalen == 0) ||
2403*8f23e9faSHans Rosenfeld 		    (data_cookie_cnt == 0)) {
2404*8f23e9faSHans Rosenfeld 			break;
2405291a2b48SSukumar Swaminathan 		}
2406291a2b48SSukumar Swaminathan 
2407*8f23e9faSHans Rosenfeld 		/* DATA payload */
2408*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_DATA);
2409*8f23e9faSHans Rosenfeld 		if (! bpl) {
2410*8f23e9faSHans Rosenfeld 			return (1);
2411*8f23e9faSHans Rosenfeld 		}
241282527734SSukumar Swaminathan 		break;
2413291a2b48SSukumar Swaminathan 
241482527734SSukumar Swaminathan 	case FC_IP_RING:
241582527734SSukumar Swaminathan 
241682527734SSukumar Swaminathan 		/* CMD payload */
2417*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2418*8f23e9faSHans Rosenfeld 		if (! bpl) {
2419*8f23e9faSHans Rosenfeld 			return (1);
2420*8f23e9faSHans Rosenfeld 		}
2421291a2b48SSukumar Swaminathan 		break;
2422291a2b48SSukumar Swaminathan 
242382527734SSukumar Swaminathan 	case FC_ELS_RING:
2424291a2b48SSukumar Swaminathan 
242582527734SSukumar Swaminathan 		/* CMD payload */
2426*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2427*8f23e9faSHans Rosenfeld 		if (! bpl) {
2428*8f23e9faSHans Rosenfeld 			return (1);
2429*8f23e9faSHans Rosenfeld 		}
2430291a2b48SSukumar Swaminathan 
2431*8f23e9faSHans Rosenfeld 		/* Check if response payload is needed */
2432*8f23e9faSHans Rosenfeld 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2433*8f23e9faSHans Rosenfeld 			break;
243482527734SSukumar Swaminathan 		}
2435291a2b48SSukumar Swaminathan 
2436*8f23e9faSHans Rosenfeld 		/* RSP payload */
2437*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP);
2438*8f23e9faSHans Rosenfeld 		if (! bpl) {
2439*8f23e9faSHans Rosenfeld 			return (1);
2440*8f23e9faSHans Rosenfeld 		}
244182527734SSukumar Swaminathan 		break;
2442291a2b48SSukumar Swaminathan 
244382527734SSukumar Swaminathan 	case FC_CT_RING:
2444291a2b48SSukumar Swaminathan 
244582527734SSukumar Swaminathan 		/* CMD payload */
2446*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2447*8f23e9faSHans Rosenfeld 		if (! bpl) {
2448*8f23e9faSHans Rosenfeld 			return (1);
2449*8f23e9faSHans Rosenfeld 		}
2450291a2b48SSukumar Swaminathan 
2451*8f23e9faSHans Rosenfeld 		/* Check if response payload is needed */
2452*8f23e9faSHans Rosenfeld 		if ((pkt->pkt_tran_type == FC_PKT_OUTBOUND) &&
2453*8f23e9faSHans Rosenfeld 		    (pkt->pkt_cmd_fhdr.type != EMLXS_MENLO_TYPE)) {
2454*8f23e9faSHans Rosenfeld 			break;
245582527734SSukumar Swaminathan 		}
2456291a2b48SSukumar Swaminathan 
2457*8f23e9faSHans Rosenfeld 		/* RSP payload */
2458*8f23e9faSHans Rosenfeld 		bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP);
2459*8f23e9faSHans Rosenfeld 		if (! bpl) {
2460*8f23e9faSHans Rosenfeld 			return (1);
2461*8f23e9faSHans Rosenfeld 		}
246282527734SSukumar Swaminathan 		break;
2463291a2b48SSukumar Swaminathan 
2464291a2b48SSukumar Swaminathan 	}
2465291a2b48SSukumar Swaminathan 
246682527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
246782527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.addrHigh = PADDR_HI(bp);
246882527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.addrLow  = PADDR_LO(bp);
2469*8f23e9faSHans Rosenfeld 	iocb->un.genreq64.bdl.bdeSize  =
2470*8f23e9faSHans Rosenfeld 	    (uint32_t)(((uintptr_t)bpl - (uintptr_t)bmp->virt) & 0xFFFFFFFF);
247182527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 1;
247282527734SSukumar Swaminathan 	iocb->ULPLE = 1;
2473291a2b48SSukumar Swaminathan 
247482527734SSukumar Swaminathan 	return (0);
2475291a2b48SSukumar Swaminathan 
247682527734SSukumar Swaminathan } /* emlxs_sli2_bde_setup */
2477291a2b48SSukumar Swaminathan 
2478291a2b48SSukumar Swaminathan 
247982527734SSukumar Swaminathan static uint32_t
248082527734SSukumar Swaminathan emlxs_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
248182527734SSukumar Swaminathan {
248282527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
248382527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_resp;
248482527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_data;
248582527734SSukumar Swaminathan 	fc_packet_t	*pkt;
248682527734SSukumar Swaminathan 	ULP_BDE64	*bde;
248782527734SSukumar Swaminathan 	int		data_cookie_cnt;
248882527734SSukumar Swaminathan 	uint32_t	i;
2489*8f23e9faSHans Rosenfeld 	uint32_t	channelno;
249082527734SSukumar Swaminathan 	IOCB		*iocb;
249182527734SSukumar Swaminathan 	IOCBQ		*iocbq;
249282527734SSukumar Swaminathan 	CHANNEL		*cp;
2493291a2b48SSukumar Swaminathan 
249482527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
249582527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
249682527734SSukumar Swaminathan 	if ((pkt->pkt_cmd_cookie_cnt > 1) ||
249782527734SSukumar Swaminathan 	    (pkt->pkt_resp_cookie_cnt > 1) ||
249882527734SSukumar Swaminathan 	    ((pkt->pkt_cmd_cookie_cnt + pkt->pkt_resp_cookie_cnt +
249982527734SSukumar Swaminathan 	    pkt->pkt_data_cookie_cnt) > SLI3_MAX_BDE)) {
250082527734SSukumar Swaminathan 		i = emlxs_sli2_bde_setup(port, sbp);
250182527734SSukumar Swaminathan 		return (i);
250282527734SSukumar Swaminathan 	}
2503291a2b48SSukumar Swaminathan 
250482527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
250582527734SSukumar Swaminathan 	cp_resp = pkt->pkt_resp_cookie;
250682527734SSukumar Swaminathan 	cp_data = pkt->pkt_data_cookie;
250782527734SSukumar Swaminathan 	data_cookie_cnt = pkt->pkt_data_cookie_cnt;
250882527734SSukumar Swaminathan #else
250982527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
251082527734SSukumar Swaminathan 	cp_resp = &pkt->pkt_resp_cookie;
251182527734SSukumar Swaminathan 	cp_data = &pkt->pkt_data_cookie;
251282527734SSukumar Swaminathan 	data_cookie_cnt = 1;
251382527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2514291a2b48SSukumar Swaminathan 
2515*8f23e9faSHans Rosenfeld 	cp = sbp->channel;
251682527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
2517*8f23e9faSHans Rosenfeld 	iocb = (IOCB *)iocbq;
2518*8f23e9faSHans Rosenfeld 	iocb->unsli3.ext_iocb.ebde_count = 0;
2519291a2b48SSukumar Swaminathan 
2520*8f23e9faSHans Rosenfeld 	channelno = (iocbq->flag & IOCB_FCP_CMD)? FC_FCP_RING:cp->channelno;
2521*8f23e9faSHans Rosenfeld 	switch (channelno) {
252282527734SSukumar Swaminathan 	case FC_FCP_RING:
252382527734SSukumar Swaminathan 		/* CMD payload */
252482527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.addrHigh =
252582527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
252682527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.addrLow =
252782527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
252882527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.bdeSize  = pkt->pkt_cmdlen;
252982527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.bdeFlags = 0;
2530291a2b48SSukumar Swaminathan 
2531*8f23e9faSHans Rosenfeld 		/* Check if a response & data payload are needed */
2532*8f23e9faSHans Rosenfeld 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2533*8f23e9faSHans Rosenfeld 			break;
253482527734SSukumar Swaminathan 		}
2535*8f23e9faSHans Rosenfeld 
2536*8f23e9faSHans Rosenfeld 		/* RSP payload */
2537*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.addrHigh =
2538*8f23e9faSHans Rosenfeld 		    PADDR_HI(cp_resp->dmac_laddress);
2539*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.addrLow =
2540*8f23e9faSHans Rosenfeld 		    PADDR_LO(cp_resp->dmac_laddress);
2541*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen;
2542*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 0;
2543*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde_count = 1;
2544*8f23e9faSHans Rosenfeld 
2545*8f23e9faSHans Rosenfeld 		/* Check if a data payload is needed */
2546*8f23e9faSHans Rosenfeld 		if ((pkt->pkt_datalen == 0) ||
2547*8f23e9faSHans Rosenfeld 		    (data_cookie_cnt == 0)) {
2548*8f23e9faSHans Rosenfeld 			break;
2549*8f23e9faSHans Rosenfeld 		}
2550*8f23e9faSHans Rosenfeld 
2551*8f23e9faSHans Rosenfeld 		/* DATA payload */
2552*8f23e9faSHans Rosenfeld 		bde = (ULP_BDE64 *)&iocb->unsli3.ext_iocb.ebde2;
2553*8f23e9faSHans Rosenfeld 		for (i = 0; i < data_cookie_cnt; i++) {
2554*8f23e9faSHans Rosenfeld 			bde->addrHigh = PADDR_HI(cp_data->dmac_laddress);
2555*8f23e9faSHans Rosenfeld 			bde->addrLow = PADDR_LO(cp_data->dmac_laddress);
2556*8f23e9faSHans Rosenfeld 			bde->tus.f.bdeSize = cp_data->dmac_size;
2557*8f23e9faSHans Rosenfeld 			bde->tus.f.bdeFlags = 0;
2558*8f23e9faSHans Rosenfeld 			cp_data++;
2559*8f23e9faSHans Rosenfeld 			bde++;
2560*8f23e9faSHans Rosenfeld 		}
2561*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde_count += data_cookie_cnt;
2562291a2b48SSukumar Swaminathan 
256382527734SSukumar Swaminathan 		break;
2564291a2b48SSukumar Swaminathan 
256582527734SSukumar Swaminathan 	case FC_IP_RING:
256682527734SSukumar Swaminathan 		/* CMD payload */
256782527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.addrHigh =
256882527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
256982527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.addrLow =
257082527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
257182527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.bdeSize  = pkt->pkt_cmdlen;
257282527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.bdeFlags = 0;
2573291a2b48SSukumar Swaminathan 
257482527734SSukumar Swaminathan 		break;
2575291a2b48SSukumar Swaminathan 
257682527734SSukumar Swaminathan 	case FC_ELS_RING:
2577291a2b48SSukumar Swaminathan 
257882527734SSukumar Swaminathan 		/* CMD payload */
257982527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.addrHigh =
258082527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
258182527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.addrLow =
258282527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
258382527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeSize  = pkt->pkt_cmdlen;
258482527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeFlags = 0;
2585291a2b48SSukumar Swaminathan 
2586*8f23e9faSHans Rosenfeld 		/* Check if a response payload is needed */
2587*8f23e9faSHans Rosenfeld 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2588*8f23e9faSHans Rosenfeld 			break;
258982527734SSukumar Swaminathan 		}
2590291a2b48SSukumar Swaminathan 
2591*8f23e9faSHans Rosenfeld 		/* RSP payload */
2592*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.addrHigh =
2593*8f23e9faSHans Rosenfeld 		    PADDR_HI(cp_resp->dmac_laddress);
2594*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.addrLow =
2595*8f23e9faSHans Rosenfeld 		    PADDR_LO(cp_resp->dmac_laddress);
2596*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen;
2597*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = BUFF_USE_RCV;
2598*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde_count = 1;
259982527734SSukumar Swaminathan 		break;
2600291a2b48SSukumar Swaminathan 
260182527734SSukumar Swaminathan 	case FC_CT_RING:
2602291a2b48SSukumar Swaminathan 
260382527734SSukumar Swaminathan 		/* CMD payload */
260482527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.addrHigh =
260582527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
260682527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.addrLow =
260782527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
260882527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.bdeSize  = pkt->pkt_cmdlen;
260982527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.bdeFlags = 0;
2610291a2b48SSukumar Swaminathan 
2611*8f23e9faSHans Rosenfeld 		/* Check if a response payload is needed */
2612*8f23e9faSHans Rosenfeld 		if ((pkt->pkt_tran_type == FC_PKT_OUTBOUND) &&
2613*8f23e9faSHans Rosenfeld 		    (pkt->pkt_cmd_fhdr.type != EMLXS_MENLO_TYPE)) {
2614*8f23e9faSHans Rosenfeld 			break;
261582527734SSukumar Swaminathan 		}
2616291a2b48SSukumar Swaminathan 
2617*8f23e9faSHans Rosenfeld 		/* RSP payload */
2618*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.addrHigh =
2619*8f23e9faSHans Rosenfeld 		    PADDR_HI(cp_resp->dmac_laddress);
2620*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.addrLow =
2621*8f23e9faSHans Rosenfeld 		    PADDR_LO(cp_resp->dmac_laddress);
2622*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen;
2623*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = BUFF_USE_RCV;
2624*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_iocb.ebde_count = 1;
262582527734SSukumar Swaminathan 		break;
2626291a2b48SSukumar Swaminathan 	}
2627291a2b48SSukumar Swaminathan 
262882527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 0;
262982527734SSukumar Swaminathan 	iocb->ULPLE = 0;
2630291a2b48SSukumar Swaminathan 
263182527734SSukumar Swaminathan 	return (0);
2632291a2b48SSukumar Swaminathan 
263382527734SSukumar Swaminathan } /* emlxs_sli3_bde_setup */
2634291a2b48SSukumar Swaminathan 
2635291a2b48SSukumar Swaminathan 
263682527734SSukumar Swaminathan /* Only used for FCP Data xfers */
263782527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
263882527734SSukumar Swaminathan /*ARGSUSED*/
263982527734SSukumar Swaminathan static uint32_t
264082527734SSukumar Swaminathan emlxs_sli2_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
264182527734SSukumar Swaminathan {
264282527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
264382527734SSukumar Swaminathan 	scsi_task_t *fct_task;
264482527734SSukumar Swaminathan 	MATCHMAP *bmp;
264582527734SSukumar Swaminathan 	ULP_BDE64 *bpl;
264682527734SSukumar Swaminathan 	uint64_t bp;
264782527734SSukumar Swaminathan 	uint8_t bdeFlags;
264882527734SSukumar Swaminathan 	IOCB *iocb;
264982527734SSukumar Swaminathan 	uint32_t size;
2650*8f23e9faSHans Rosenfeld 	MATCHMAP *mp;
2651291a2b48SSukumar Swaminathan 
2652*8f23e9faSHans Rosenfeld 	iocb = (IOCB *)&sbp->iocbq.iocb;
265382527734SSukumar Swaminathan 	sbp->bmp = NULL;
2654291a2b48SSukumar Swaminathan 
265582527734SSukumar Swaminathan 	if (!sbp->fct_buf) {
265682527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrHigh = 0;
265782527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrLow = 0;
265882527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeSize = 0;
265982527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeFlags = 0;
266082527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Offset = 0;
266182527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Length = 0;
266282527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 0;
266382527734SSukumar Swaminathan 		iocb->ULPLE = 1;
266482527734SSukumar Swaminathan 		return (0);
2665291a2b48SSukumar Swaminathan 	}
2666*8f23e9faSHans Rosenfeld 
2667*8f23e9faSHans Rosenfeld 	if (hba->sli.sli3.bpl_table) {
2668*8f23e9faSHans Rosenfeld 		bmp = hba->sli.sli3.bpl_table[sbp->iotag];
2669*8f23e9faSHans Rosenfeld 	} else {
2670*8f23e9faSHans Rosenfeld 		bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL);
2671*8f23e9faSHans Rosenfeld 	}
2672291a2b48SSukumar Swaminathan 
267382527734SSukumar Swaminathan 	if (!bmp) {
267482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2675*8f23e9faSHans Rosenfeld 		    "fct_sli2_bde_setup: Unable to BPL buffer. iotag=%d",
267682527734SSukumar Swaminathan 		    sbp->iotag);
2677291a2b48SSukumar Swaminathan 
267882527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrHigh = 0;
267982527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrLow = 0;
268082527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeSize = 0;
268182527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeFlags = 0;
268282527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Offset = 0;
268382527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Length = 0;
268482527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 0;
268582527734SSukumar Swaminathan 		iocb->ULPLE = 1;
268682527734SSukumar Swaminathan 		return (1);
268782527734SSukumar Swaminathan 	}
2688291a2b48SSukumar Swaminathan 
268982527734SSukumar Swaminathan 	bpl = (ULP_BDE64 *)bmp->virt;
269082527734SSukumar Swaminathan 	bp = bmp->phys;
2691291a2b48SSukumar Swaminathan 
269282527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
2693291a2b48SSukumar Swaminathan 
269482527734SSukumar Swaminathan 	size = sbp->fct_buf->db_data_size;
2695*8f23e9faSHans Rosenfeld 	mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2696291a2b48SSukumar Swaminathan 
269782527734SSukumar Swaminathan 	bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
2698291a2b48SSukumar Swaminathan 
269982527734SSukumar Swaminathan 	/* Init the buffer list */
2700*8f23e9faSHans Rosenfeld 	bpl->addrHigh = BE_SWAP32(PADDR_HI(mp->phys));
2701*8f23e9faSHans Rosenfeld 	bpl->addrLow = BE_SWAP32(PADDR_LO(mp->phys));
2702*8f23e9faSHans Rosenfeld 	bpl->tus.f.bdeSize = size;
2703*8f23e9faSHans Rosenfeld 	bpl->tus.f.bdeFlags = bdeFlags;
2704*8f23e9faSHans Rosenfeld 	bpl->tus.w = BE_SWAP32(bpl->tus.w);
2705291a2b48SSukumar Swaminathan 
270682527734SSukumar Swaminathan 	/* Init the IOCB */
270782527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bp);
270882527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bp);
2709*8f23e9faSHans Rosenfeld 	iocb->un.fcpt64.bdl.bdeSize = sizeof (ULP_BDE64);
271082527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL;
2711291a2b48SSukumar Swaminathan 
271282527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Length =
271382527734SSukumar Swaminathan 	    (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
271482527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Offset = 0;
2715291a2b48SSukumar Swaminathan 
271682527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 1;
271782527734SSukumar Swaminathan 	iocb->ULPLE = 1;
271882527734SSukumar Swaminathan 	sbp->bmp = bmp;
2719291a2b48SSukumar Swaminathan 
272082527734SSukumar Swaminathan 	return (0);
2721291a2b48SSukumar Swaminathan 
272282527734SSukumar Swaminathan } /* emlxs_sli2_fct_bde_setup */
272382527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2724291a2b48SSukumar Swaminathan 
2725291a2b48SSukumar Swaminathan 
272682527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
272782527734SSukumar Swaminathan /*ARGSUSED*/
272882527734SSukumar Swaminathan static uint32_t
272982527734SSukumar Swaminathan emlxs_sli3_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
273082527734SSukumar Swaminathan {
273182527734SSukumar Swaminathan 	scsi_task_t *fct_task;
273282527734SSukumar Swaminathan 	IOCB *iocb;
2733*8f23e9faSHans Rosenfeld 	MATCHMAP *mp;
273482527734SSukumar Swaminathan 	uint32_t bdeFlags;
2735*8f23e9faSHans Rosenfeld 	uint32_t size;
2736291a2b48SSukumar Swaminathan 
273782527734SSukumar Swaminathan 	iocb = (IOCB *)&sbp->iocbq;
2738291a2b48SSukumar Swaminathan 
273982527734SSukumar Swaminathan 	if (!sbp->fct_buf) {
274082527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrHigh = 0;
274182527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrLow = 0;
274282527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeSize = 0;
274382527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeFlags = 0;
274482527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Offset = 0;
274582527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Length = 0;
274682527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 0;
274782527734SSukumar Swaminathan 		iocb->ULPLE = 0;
274882527734SSukumar Swaminathan 		iocb->unsli3.ext_iocb.ebde_count = 0;
274982527734SSukumar Swaminathan 		return (0);
2750291a2b48SSukumar Swaminathan 	}
2751291a2b48SSukumar Swaminathan 
275282527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
2753291a2b48SSukumar Swaminathan 
275482527734SSukumar Swaminathan 	size = sbp->fct_buf->db_data_size;
2755*8f23e9faSHans Rosenfeld 	mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2756291a2b48SSukumar Swaminathan 
275782527734SSukumar Swaminathan 	bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
2758291a2b48SSukumar Swaminathan 
275982527734SSukumar Swaminathan 	/* Init first BDE */
2760*8f23e9faSHans Rosenfeld 	iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(mp->phys);
2761*8f23e9faSHans Rosenfeld 	iocb->un.fcpt64.bdl.addrLow = PADDR_LO(mp->phys);
2762*8f23e9faSHans Rosenfeld 	iocb->un.fcpt64.bdl.bdeSize = size;
276382527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.bdeFlags = bdeFlags;
2764291a2b48SSukumar Swaminathan 
2765*8f23e9faSHans Rosenfeld 	iocb->unsli3.ext_iocb.ebde_count = 0;
276682527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Length =
276782527734SSukumar Swaminathan 	    (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
276882527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Offset = 0;
2769291a2b48SSukumar Swaminathan 
277082527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 0;
277182527734SSukumar Swaminathan 	iocb->ULPLE = 0;
2772291a2b48SSukumar Swaminathan 
277382527734SSukumar Swaminathan 	return (0);
2774291a2b48SSukumar Swaminathan 
277582527734SSukumar Swaminathan } /* emlxs_sli3_fct_bde_setup */
277682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2777291a2b48SSukumar Swaminathan 
2778291a2b48SSukumar Swaminathan 
277982527734SSukumar Swaminathan static void
278082527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2781291a2b48SSukumar Swaminathan {
278282527734SSukumar Swaminathan #ifdef FMA_SUPPORT
278382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
278482527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
278582527734SSukumar Swaminathan 	PGP *pgp;
278682527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
278782527734SSukumar Swaminathan 	SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
2788291a2b48SSukumar Swaminathan 	RING *rp;
278982527734SSukumar Swaminathan 	uint32_t nextIdx;
279082527734SSukumar Swaminathan 	uint32_t status;
279182527734SSukumar Swaminathan 	void *ioa2;
279282527734SSukumar Swaminathan 	off_t offset;
279382527734SSukumar Swaminathan 	uint32_t count = 0;
279482527734SSukumar Swaminathan 	uint32_t flag;
279582527734SSukumar Swaminathan 	uint32_t channelno;
279682527734SSukumar Swaminathan 	int32_t throttle;
2797*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
2798*8f23e9faSHans Rosenfeld 	int32_t node_throttle;
2799*8f23e9faSHans Rosenfeld 	NODELIST *marked_node = NULL;
2800*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
2801291a2b48SSukumar Swaminathan 
280282527734SSukumar Swaminathan 	channelno = cp->channelno;
280382527734SSukumar Swaminathan 	rp = (RING *)cp->iopath;
2804291a2b48SSukumar Swaminathan 
280582527734SSukumar Swaminathan 	throttle = 0;
2806291a2b48SSukumar Swaminathan 
280782527734SSukumar Swaminathan 	/* Check if FCP ring and adapter is not ready */
280882527734SSukumar Swaminathan 	/* We may use any ring for FCP_CMD */
280982527734SSukumar Swaminathan 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
281082527734SSukumar Swaminathan 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
2811*8f23e9faSHans Rosenfeld 		    (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) {
281282527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
281382527734SSukumar Swaminathan 			return;
281482527734SSukumar Swaminathan 		}
2815291a2b48SSukumar Swaminathan 	}
2816291a2b48SSukumar Swaminathan 
281782527734SSukumar Swaminathan 	/* Attempt to acquire CMD_RING lock */
281882527734SSukumar Swaminathan 	if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) {
281982527734SSukumar Swaminathan 		/* Queue it for later */
282082527734SSukumar Swaminathan 		if (iocbq) {
282182527734SSukumar Swaminathan 			if ((hba->io_count -
282282527734SSukumar Swaminathan 			    hba->channel_tx_count) > 10) {
282382527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
282482527734SSukumar Swaminathan 				return;
282582527734SSukumar Swaminathan 			} else {
2826291a2b48SSukumar Swaminathan 
282782527734SSukumar Swaminathan 				/*
282882527734SSukumar Swaminathan 				 * EMLXS_MSGF(EMLXS_CONTEXT,
282982527734SSukumar Swaminathan 				 * &emlxs_ring_watchdog_msg,
283082527734SSukumar Swaminathan 				 * "%s host=%d port=%d cnt=%d,%d  RACE
283182527734SSukumar Swaminathan 				 * CONDITION3 DETECTED.",
283282527734SSukumar Swaminathan 				 * emlxs_ring_xlate(channelno),
283382527734SSukumar Swaminathan 				 * rp->fc_cmdidx, rp->fc_port_cmdidx,
283482527734SSukumar Swaminathan 				 * hba->channel_tx_count,
283582527734SSukumar Swaminathan 				 * hba->io_count);
283682527734SSukumar Swaminathan 				 */
283782527734SSukumar Swaminathan 				mutex_enter(&EMLXS_CMD_RING_LOCK(channelno));
283882527734SSukumar Swaminathan 			}
283982527734SSukumar Swaminathan 		} else {
284082527734SSukumar Swaminathan 			return;
284182527734SSukumar Swaminathan 		}
2842291a2b48SSukumar Swaminathan 	}
284382527734SSukumar Swaminathan 	/* CMD_RING_LOCK acquired */
2844291a2b48SSukumar Swaminathan 
284582527734SSukumar Swaminathan 	/* Throttle check only applies to non special iocb */
284682527734SSukumar Swaminathan 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
284782527734SSukumar Swaminathan 		/* Check if HBA is full */
284882527734SSukumar Swaminathan 		throttle = hba->io_throttle - hba->io_active;
284982527734SSukumar Swaminathan 		if (throttle <= 0) {
285082527734SSukumar Swaminathan 			/* Hitting adapter throttle limit */
285182527734SSukumar Swaminathan 			/* Queue it for later */
285282527734SSukumar Swaminathan 			if (iocbq) {
285382527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
2854291a2b48SSukumar Swaminathan 			}
285582527734SSukumar Swaminathan 
285682527734SSukumar Swaminathan 			goto busy;
2857291a2b48SSukumar Swaminathan 		}
2858291a2b48SSukumar Swaminathan 	}
2859291a2b48SSukumar Swaminathan 
286082527734SSukumar Swaminathan 	/* Read adapter's get index */
286182527734SSukumar Swaminathan 	pgp = (PGP *)
286282527734SSukumar Swaminathan 	    &((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[channelno];
286382527734SSukumar Swaminathan 	offset =
286482527734SSukumar Swaminathan 	    (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) -
286582527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
286682527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
286782527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
286882527734SSukumar Swaminathan 	rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2869291a2b48SSukumar Swaminathan 
287082527734SSukumar Swaminathan 	/* Calculate the next put index */
287182527734SSukumar Swaminathan 	nextIdx =
287282527734SSukumar Swaminathan 	    (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
2873291a2b48SSukumar Swaminathan 
287482527734SSukumar Swaminathan 	/* Check if ring is full */
287582527734SSukumar Swaminathan 	if (nextIdx == rp->fc_port_cmdidx) {
287682527734SSukumar Swaminathan 		/* Try one more time */
287782527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
287882527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
287982527734SSukumar Swaminathan 		rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2880291a2b48SSukumar Swaminathan 
288182527734SSukumar Swaminathan 		if (nextIdx == rp->fc_port_cmdidx) {
288282527734SSukumar Swaminathan 			/* Queue it for later */
288382527734SSukumar Swaminathan 			if (iocbq) {
288482527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
288582527734SSukumar Swaminathan 			}
2886291a2b48SSukumar Swaminathan 
288782527734SSukumar Swaminathan 			goto busy;
288882527734SSukumar Swaminathan 		}
2889291a2b48SSukumar Swaminathan 	}
2890291a2b48SSukumar Swaminathan 
289182527734SSukumar Swaminathan 	/*
289282527734SSukumar Swaminathan 	 * We have a command ring slot available
289382527734SSukumar Swaminathan 	 * Make sure we have an iocb to send
289482527734SSukumar Swaminathan 	 */
289582527734SSukumar Swaminathan 	if (iocbq) {
289682527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2897291a2b48SSukumar Swaminathan 
289882527734SSukumar Swaminathan 		/* Check if the ring already has iocb's waiting */
289982527734SSukumar Swaminathan 		if (cp->nodeq.q_first != NULL) {
290082527734SSukumar Swaminathan 			/* Put the current iocbq on the tx queue */
290182527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 0);
2902291a2b48SSukumar Swaminathan 
290382527734SSukumar Swaminathan 			/*
290482527734SSukumar Swaminathan 			 * Attempt to replace it with the next iocbq
290582527734SSukumar Swaminathan 			 * in the tx queue
290682527734SSukumar Swaminathan 			 */
290782527734SSukumar Swaminathan 			iocbq = emlxs_tx_get(cp, 0);
290882527734SSukumar Swaminathan 		}
2909291a2b48SSukumar Swaminathan 
291082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2911291a2b48SSukumar Swaminathan 	} else {
291282527734SSukumar Swaminathan 		/* Try to get the next iocb on the tx queue */
291382527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
2914291a2b48SSukumar Swaminathan 	}
2915291a2b48SSukumar Swaminathan 
291682527734SSukumar Swaminathan sendit:
291782527734SSukumar Swaminathan 	count = 0;
2918291a2b48SSukumar Swaminathan 
291982527734SSukumar Swaminathan 	/* Process each iocbq */
292082527734SSukumar Swaminathan 	while (iocbq) {
292182527734SSukumar Swaminathan 		sbp = iocbq->sbp;
2922*8f23e9faSHans Rosenfeld 
2923*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
2924*8f23e9faSHans Rosenfeld 		if (sbp && sbp->node && sbp->node->io_throttle) {
2925*8f23e9faSHans Rosenfeld 			node_throttle = sbp->node->io_throttle -
2926*8f23e9faSHans Rosenfeld 			    sbp->node->io_active;
2927*8f23e9faSHans Rosenfeld 			if (node_throttle <= 0) {
2928*8f23e9faSHans Rosenfeld 				/* Node is busy */
2929*8f23e9faSHans Rosenfeld 				/* Queue this iocb and get next iocb from */
2930*8f23e9faSHans Rosenfeld 				/* channel */
2931*8f23e9faSHans Rosenfeld 
2932*8f23e9faSHans Rosenfeld 				if (!marked_node) {
2933*8f23e9faSHans Rosenfeld 					marked_node = sbp->node;
2934*8f23e9faSHans Rosenfeld 				}
2935*8f23e9faSHans Rosenfeld 
2936*8f23e9faSHans Rosenfeld 				mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2937*8f23e9faSHans Rosenfeld 				emlxs_tx_put(iocbq, 0);
2938*8f23e9faSHans Rosenfeld 
2939*8f23e9faSHans Rosenfeld 				if (cp->nodeq.q_first == marked_node) {
2940*8f23e9faSHans Rosenfeld 					mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2941*8f23e9faSHans Rosenfeld 					goto busy;
2942*8f23e9faSHans Rosenfeld 				}
2943*8f23e9faSHans Rosenfeld 
2944*8f23e9faSHans Rosenfeld 				iocbq = emlxs_tx_get(cp, 0);
2945*8f23e9faSHans Rosenfeld 				mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2946*8f23e9faSHans Rosenfeld 				continue;
2947*8f23e9faSHans Rosenfeld 			}
2948*8f23e9faSHans Rosenfeld 		}
2949*8f23e9faSHans Rosenfeld 		marked_node = 0;
2950*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
2951*8f23e9faSHans Rosenfeld 
295282527734SSukumar Swaminathan 		if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) {
295382527734SSukumar Swaminathan 			/*
295482527734SSukumar Swaminathan 			 * Update adapter if needed, since we are about to
295582527734SSukumar Swaminathan 			 * delay here
295682527734SSukumar Swaminathan 			 */
295782527734SSukumar Swaminathan 			if (count) {
295882527734SSukumar Swaminathan 				count = 0;
2959291a2b48SSukumar Swaminathan 
296082527734SSukumar Swaminathan 				/* Update the adapter's cmd put index */
296182527734SSukumar Swaminathan 				if (hba->bus_type == SBUS_FC) {
296282527734SSukumar Swaminathan 					slim2p->mbx.us.s2.host[channelno].
296382527734SSukumar Swaminathan 					    cmdPutInx =
296482527734SSukumar Swaminathan 					    BE_SWAP32(rp->fc_cmdidx);
2965291a2b48SSukumar Swaminathan 
296682527734SSukumar Swaminathan 					/* DMA sync the index for the adapter */
296782527734SSukumar Swaminathan 					offset = (off_t)
296882527734SSukumar Swaminathan 					    ((uint64_t)
296982527734SSukumar Swaminathan 					    ((unsigned long)&(slim2p->mbx.us.
297082527734SSukumar Swaminathan 					    s2.host[channelno].cmdPutInx)) -
297182527734SSukumar Swaminathan 					    (uint64_t)((unsigned long)slim2p));
297282527734SSukumar Swaminathan 					EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.
297382527734SSukumar Swaminathan 					    dma_handle, offset, 4,
297482527734SSukumar Swaminathan 					    DDI_DMA_SYNC_FORDEV);
297582527734SSukumar Swaminathan 				} else {
297682527734SSukumar Swaminathan 					ioa2 = (void *)
297782527734SSukumar Swaminathan 					    ((char *)hba->sli.sli3.slim_addr +
297882527734SSukumar Swaminathan 					    hba->sli.sli3.hgp_ring_offset +
297982527734SSukumar Swaminathan 					    ((channelno * 2) *
298082527734SSukumar Swaminathan 					    sizeof (uint32_t)));
298182527734SSukumar Swaminathan 					WRITE_SLIM_ADDR(hba,
298282527734SSukumar Swaminathan 					    (volatile uint32_t *)ioa2,
298382527734SSukumar Swaminathan 					    rp->fc_cmdidx);
298482527734SSukumar Swaminathan 				}
2985291a2b48SSukumar Swaminathan 
298682527734SSukumar Swaminathan 				status = (CA_R0ATT << (channelno * 4));
298782527734SSukumar Swaminathan 				WRITE_CSR_REG(hba, FC_CA_REG(hba),
298882527734SSukumar Swaminathan 				    (volatile uint32_t)status);
2989291a2b48SSukumar Swaminathan 
299082527734SSukumar Swaminathan 			}
299182527734SSukumar Swaminathan 			/* Perform delay */
299282527734SSukumar Swaminathan 			if ((channelno == FC_ELS_RING) &&
299382527734SSukumar Swaminathan 			    !(iocbq->flag & IOCB_FCP_CMD)) {
299482527734SSukumar Swaminathan 				drv_usecwait(100000);
299582527734SSukumar Swaminathan 			} else {
299682527734SSukumar Swaminathan 				drv_usecwait(20000);
299782527734SSukumar Swaminathan 			}
299882527734SSukumar Swaminathan 		}
299982527734SSukumar Swaminathan 
300082527734SSukumar Swaminathan 		/*
300182527734SSukumar Swaminathan 		 * At this point, we have a command ring slot available
300282527734SSukumar Swaminathan 		 * and an iocb to send
300382527734SSukumar Swaminathan 		 */
300482527734SSukumar Swaminathan 		flag =  iocbq->flag;
3005291a2b48SSukumar Swaminathan 
300682527734SSukumar Swaminathan 		/* Send the iocb */
300782527734SSukumar Swaminathan 		emlxs_sli3_issue_iocb(hba, rp, iocbq);
300882527734SSukumar Swaminathan 		/*
300982527734SSukumar Swaminathan 		 * After this, the sbp / iocb should not be
301082527734SSukumar Swaminathan 		 * accessed in the xmit path.
301182527734SSukumar Swaminathan 		 */
3012291a2b48SSukumar Swaminathan 
301382527734SSukumar Swaminathan 		count++;
301482527734SSukumar Swaminathan 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
301582527734SSukumar Swaminathan 			/* Check if HBA is full */
301682527734SSukumar Swaminathan 			throttle = hba->io_throttle - hba->io_active;
301782527734SSukumar Swaminathan 			if (throttle <= 0) {
301882527734SSukumar Swaminathan 				goto busy;
301982527734SSukumar Swaminathan 			}
302082527734SSukumar Swaminathan 		}
3021291a2b48SSukumar Swaminathan 
302282527734SSukumar Swaminathan 		/* Calculate the next put index */
302382527734SSukumar Swaminathan 		nextIdx =
302482527734SSukumar Swaminathan 		    (rp->fc_cmdidx + 1 >=
302582527734SSukumar Swaminathan 		    rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
3026291a2b48SSukumar Swaminathan 
302782527734SSukumar Swaminathan 		/* Check if ring is full */
302882527734SSukumar Swaminathan 		if (nextIdx == rp->fc_port_cmdidx) {
302982527734SSukumar Swaminathan 			/* Try one more time */
303082527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
303182527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORKERNEL);
303282527734SSukumar Swaminathan 			rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
3033291a2b48SSukumar Swaminathan 
303482527734SSukumar Swaminathan 			if (nextIdx == rp->fc_port_cmdidx) {
303582527734SSukumar Swaminathan 				goto busy;
303682527734SSukumar Swaminathan 			}
303782527734SSukumar Swaminathan 		}
3038291a2b48SSukumar Swaminathan 
303982527734SSukumar Swaminathan 		/* Get the next iocb from the tx queue if there is one */
304082527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
3041291a2b48SSukumar Swaminathan 	}
3042291a2b48SSukumar Swaminathan 
304382527734SSukumar Swaminathan 	if (count) {
304482527734SSukumar Swaminathan 		/* Update the adapter's cmd put index */
304582527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
304682527734SSukumar Swaminathan 			slim2p->mbx.us.s2.host[channelno].
304782527734SSukumar Swaminathan 			    cmdPutInx = BE_SWAP32(rp->fc_cmdidx);
3048291a2b48SSukumar Swaminathan 
304982527734SSukumar Swaminathan 			/* DMA sync the index for the adapter */
305082527734SSukumar Swaminathan 			offset = (off_t)
305182527734SSukumar Swaminathan 			    ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
305282527734SSukumar Swaminathan 			    host[channelno].cmdPutInx)) -
305382527734SSukumar Swaminathan 			    (uint64_t)((unsigned long)slim2p));
305482527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
305582527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORDEV);
305682527734SSukumar Swaminathan 		} else {
305782527734SSukumar Swaminathan 			ioa2 =
305882527734SSukumar Swaminathan 			    (void *)((char *)hba->sli.sli3.slim_addr +
305982527734SSukumar Swaminathan 			    hba->sli.sli3.hgp_ring_offset +
306082527734SSukumar Swaminathan 			    ((channelno * 2) * sizeof (uint32_t)));
306182527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
306282527734SSukumar Swaminathan 			    rp->fc_cmdidx);
306382527734SSukumar Swaminathan 		}
3064291a2b48SSukumar Swaminathan 
306582527734SSukumar Swaminathan 		status = (CA_R0ATT << (channelno * 4));
306682527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_CA_REG(hba),
306782527734SSukumar Swaminathan 		    (volatile uint32_t)status);
3068291a2b48SSukumar Swaminathan 
306982527734SSukumar Swaminathan 		/* Check tx queue one more time before releasing */
307082527734SSukumar Swaminathan 		if ((iocbq = emlxs_tx_get(cp, 1))) {
307182527734SSukumar Swaminathan 			/*
307282527734SSukumar Swaminathan 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg,
307382527734SSukumar Swaminathan 			 * "%s host=%d port=%d   RACE CONDITION1
307482527734SSukumar Swaminathan 			 * DETECTED.", emlxs_ring_xlate(channelno),
307582527734SSukumar Swaminathan 			 * rp->fc_cmdidx, rp->fc_port_cmdidx);
307682527734SSukumar Swaminathan 			 */
307782527734SSukumar Swaminathan 			goto sendit;
307882527734SSukumar Swaminathan 		}
3079291a2b48SSukumar Swaminathan 	}
3080291a2b48SSukumar Swaminathan 
308182527734SSukumar Swaminathan #ifdef FMA_SUPPORT
308282527734SSukumar Swaminathan 	/* Access handle validation */
308382527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
308482527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
308582527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3086291a2b48SSukumar Swaminathan 
308782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
3088291a2b48SSukumar Swaminathan 
308982527734SSukumar Swaminathan 	return;
3090291a2b48SSukumar Swaminathan 
309182527734SSukumar Swaminathan busy:
3092291a2b48SSukumar Swaminathan 
3093291a2b48SSukumar Swaminathan 	/*
309482527734SSukumar Swaminathan 	 * Set ring to SET R0CE_REQ in Chip Att register.
309582527734SSukumar Swaminathan 	 * Chip will tell us when an entry is freed.
3096291a2b48SSukumar Swaminathan 	 */
309782527734SSukumar Swaminathan 	if (count) {
309882527734SSukumar Swaminathan 		/* Update the adapter's cmd put index */
309982527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
310082527734SSukumar Swaminathan 			slim2p->mbx.us.s2.host[channelno].cmdPutInx =
310182527734SSukumar Swaminathan 			    BE_SWAP32(rp->fc_cmdidx);
3102291a2b48SSukumar Swaminathan 
310382527734SSukumar Swaminathan 			/* DMA sync the index for the adapter */
310482527734SSukumar Swaminathan 			offset = (off_t)
310582527734SSukumar Swaminathan 			    ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
310682527734SSukumar Swaminathan 			    host[channelno].cmdPutInx)) -
310782527734SSukumar Swaminathan 			    (uint64_t)((unsigned long)slim2p));
310882527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
310982527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORDEV);
311082527734SSukumar Swaminathan 		} else {
311182527734SSukumar Swaminathan 			ioa2 =
311282527734SSukumar Swaminathan 			    (void *)((char *)hba->sli.sli3.slim_addr +
311382527734SSukumar Swaminathan 			    hba->sli.sli3.hgp_ring_offset +
311482527734SSukumar Swaminathan 			    ((channelno * 2) * sizeof (uint32_t)));
311582527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
311682527734SSukumar Swaminathan 			    rp->fc_cmdidx);
3117291a2b48SSukumar Swaminathan 		}
311882527734SSukumar Swaminathan 	}
3119291a2b48SSukumar Swaminathan 
312082527734SSukumar Swaminathan 	status = ((CA_R0ATT | CA_R0CE_REQ) << (channelno * 4));
312182527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), (volatile uint32_t)status);
312282527734SSukumar Swaminathan 
312382527734SSukumar Swaminathan 	if (throttle <= 0) {
312482527734SSukumar Swaminathan 		HBASTATS.IocbThrottled++;
312582527734SSukumar Swaminathan 	} else {
312682527734SSukumar Swaminathan 		HBASTATS.IocbRingFull[channelno]++;
3127291a2b48SSukumar Swaminathan 	}
3128291a2b48SSukumar Swaminathan 
312982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
313082527734SSukumar Swaminathan 	/* Access handle validation */
313182527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
313282527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
313382527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3134291a2b48SSukumar Swaminathan 
313582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
3136291a2b48SSukumar Swaminathan 
3137291a2b48SSukumar Swaminathan 	return;
3138291a2b48SSukumar Swaminathan 
313982527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb_cmd() */
3140291a2b48SSukumar Swaminathan 
3141291a2b48SSukumar Swaminathan 
314282527734SSukumar Swaminathan /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */
314382527734SSukumar Swaminathan /* MBX_WAIT   - returns MBX_TIMEOUT or mailbox_status */
314482527734SSukumar Swaminathan /* MBX_SLEEP  - returns MBX_TIMEOUT or mailbox_status */
314582527734SSukumar Swaminathan /* MBX_POLL   - returns MBX_TIMEOUT or mailbox_status */
3146291a2b48SSukumar Swaminathan 
314782527734SSukumar Swaminathan static uint32_t
314882527734SSukumar Swaminathan emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
314982527734SSukumar Swaminathan     uint32_t tmo)
3150291a2b48SSukumar Swaminathan {
3151a9800bebSGarrett D'Amore 	emlxs_port_t		*port;
315282527734SSukumar Swaminathan 	SLIM2			*slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
315382527734SSukumar Swaminathan 	MAILBOX			*mbox;
315482527734SSukumar Swaminathan 	MAILBOX			*mb;
315582527734SSukumar Swaminathan 	volatile uint32_t	word0;
315682527734SSukumar Swaminathan 	volatile uint32_t	ldata;
315782527734SSukumar Swaminathan 	off_t			offset;
315882527734SSukumar Swaminathan 	MATCHMAP		*mbox_bp;
315982527734SSukumar Swaminathan 	uint32_t		tmo_local;
316082527734SSukumar Swaminathan 	MAILBOX			*swpmb;
3161291a2b48SSukumar Swaminathan 
3162a9800bebSGarrett D'Amore 	if (!mbq->port) {
3163a9800bebSGarrett D'Amore 		mbq->port = &PPORT;
3164a9800bebSGarrett D'Amore 	}
3165a9800bebSGarrett D'Amore 
3166a9800bebSGarrett D'Amore 	port = (emlxs_port_t *)mbq->port;
3167a9800bebSGarrett D'Amore 
316882527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
316982527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
3170291a2b48SSukumar Swaminathan 
317182527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
3172291a2b48SSukumar Swaminathan 
317382527734SSukumar Swaminathan 	/* Check for minimum timeouts */
317482527734SSukumar Swaminathan 	switch (mb->mbxCommand) {
317582527734SSukumar Swaminathan 	/* Mailbox commands that erase/write flash */
317682527734SSukumar Swaminathan 	case MBX_DOWN_LOAD:
317782527734SSukumar Swaminathan 	case MBX_UPDATE_CFG:
317882527734SSukumar Swaminathan 	case MBX_LOAD_AREA:
317982527734SSukumar Swaminathan 	case MBX_LOAD_EXP_ROM:
318082527734SSukumar Swaminathan 	case MBX_WRITE_NV:
318182527734SSukumar Swaminathan 	case MBX_FLASH_WR_ULA:
318282527734SSukumar Swaminathan 	case MBX_DEL_LD_ENTRY:
318382527734SSukumar Swaminathan 	case MBX_LOAD_SM:
318482527734SSukumar Swaminathan 		if (tmo < 300) {
318582527734SSukumar Swaminathan 			tmo = 300;
3186291a2b48SSukumar Swaminathan 		}
318782527734SSukumar Swaminathan 		break;
3188291a2b48SSukumar Swaminathan 
318982527734SSukumar Swaminathan 	default:
319082527734SSukumar Swaminathan 		if (tmo < 30) {
319182527734SSukumar Swaminathan 			tmo = 30;
319282527734SSukumar Swaminathan 		}
319382527734SSukumar Swaminathan 		break;
319482527734SSukumar Swaminathan 	}
3195291a2b48SSukumar Swaminathan 
319682527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
319782527734SSukumar Swaminathan 	tmo_local = tmo * 100;
3198291a2b48SSukumar Swaminathan 
319982527734SSukumar Swaminathan 	/* Adjust wait flag */
320082527734SSukumar Swaminathan 	if (flag != MBX_NOWAIT) {
320182527734SSukumar Swaminathan 		/* If interrupt is enabled, use sleep, otherwise poll */
320282527734SSukumar Swaminathan 		if (hba->sli.sli3.hc_copy & HC_MBINT_ENA) {
320382527734SSukumar Swaminathan 			flag = MBX_SLEEP;
3204291a2b48SSukumar Swaminathan 		} else {
320582527734SSukumar Swaminathan 			flag = MBX_POLL;
3206291a2b48SSukumar Swaminathan 		}
320782527734SSukumar Swaminathan 	}
3208291a2b48SSukumar Swaminathan 
320982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
3210291a2b48SSukumar Swaminathan 
321182527734SSukumar Swaminathan 	/* Check for hardware error */
321282527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
321382527734SSukumar Swaminathan 		mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ?
321482527734SSukumar Swaminathan 		    MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR;
3215291a2b48SSukumar Swaminathan 
321682527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
3217291a2b48SSukumar Swaminathan 
321882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
321982527734SSukumar Swaminathan 		    "Hardware error reported. %s failed. status=%x mb=%p",
3220*8f23e9faSHans Rosenfeld 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb);
3221291a2b48SSukumar Swaminathan 
322282527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
3223291a2b48SSukumar Swaminathan 	}
3224291a2b48SSukumar Swaminathan 
322582527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
322682527734SSukumar Swaminathan 		/* If we are not polling, then queue it for later */
322782527734SSukumar Swaminathan 		if (flag == MBX_NOWAIT) {
322882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
322982527734SSukumar Swaminathan 			    "Busy.      %s: mb=%p NoWait.",
323082527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3231291a2b48SSukumar Swaminathan 
323282527734SSukumar Swaminathan 			emlxs_mb_put(hba, mbq);
3233291a2b48SSukumar Swaminathan 
323482527734SSukumar Swaminathan 			HBASTATS.MboxBusy++;
3235291a2b48SSukumar Swaminathan 
323682527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
3237291a2b48SSukumar Swaminathan 
323882527734SSukumar Swaminathan 			return (MBX_BUSY);
323982527734SSukumar Swaminathan 		}
3240291a2b48SSukumar Swaminathan 
324182527734SSukumar Swaminathan 		while (hba->mbox_queue_flag) {
324282527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
3243291a2b48SSukumar Swaminathan 
324482527734SSukumar Swaminathan 			if (tmo_local-- == 0) {
324582527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
324682527734SSukumar Swaminathan 				    &emlxs_mbox_event_msg,
324782527734SSukumar Swaminathan 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
324882527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
324982527734SSukumar Swaminathan 				    tmo);
3250291a2b48SSukumar Swaminathan 
325182527734SSukumar Swaminathan 				/* Non-lethalStatus mailbox timeout */
325282527734SSukumar Swaminathan 				/* Does not indicate a hardware error */
325382527734SSukumar Swaminathan 				mb->mbxStatus = MBX_TIMEOUT;
325482527734SSukumar Swaminathan 				return (MBX_TIMEOUT);
325582527734SSukumar Swaminathan 			}
3256291a2b48SSukumar Swaminathan 
3257*8f23e9faSHans Rosenfeld 			BUSYWAIT_MS(10);
325882527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
3259*8f23e9faSHans Rosenfeld 
3260*8f23e9faSHans Rosenfeld 			/* Check for hardware error */
3261*8f23e9faSHans Rosenfeld 			if (hba->flag & FC_HARDWARE_ERROR) {
3262*8f23e9faSHans Rosenfeld 				mb->mbxStatus =
3263*8f23e9faSHans Rosenfeld 				    (hba->flag & FC_OVERTEMP_EVENT) ?
3264*8f23e9faSHans Rosenfeld 				    MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR;
3265*8f23e9faSHans Rosenfeld 
3266*8f23e9faSHans Rosenfeld 				mutex_exit(&EMLXS_PORT_LOCK);
3267*8f23e9faSHans Rosenfeld 
3268*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
3269*8f23e9faSHans Rosenfeld 				    &emlxs_mbox_detail_msg,
3270*8f23e9faSHans Rosenfeld 				    "Hardware error reported. %s failed. "
3271*8f23e9faSHans Rosenfeld 				    "status=%x mb=%p",
3272*8f23e9faSHans Rosenfeld 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3273*8f23e9faSHans Rosenfeld 				    mb->mbxStatus, mb);
3274*8f23e9faSHans Rosenfeld 
3275*8f23e9faSHans Rosenfeld 				return (MBX_HARDWARE_ERROR);
3276*8f23e9faSHans Rosenfeld 			}
32774baa2c25SSukumar Swaminathan 		}
3278291a2b48SSukumar Swaminathan 	}
3279291a2b48SSukumar Swaminathan 
328082527734SSukumar Swaminathan 	/* Initialize mailbox area */
328182527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
3282291a2b48SSukumar Swaminathan 
328382527734SSukumar Swaminathan 	switch (flag) {
328482527734SSukumar Swaminathan 	case MBX_NOWAIT:
3285291a2b48SSukumar Swaminathan 
328682527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_HEARTBEAT) {
328782527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD &&
328882527734SSukumar Swaminathan 			    mb->mbxCommand != MBX_DUMP_MEMORY) {
328982527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
329082527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
329182527734SSukumar Swaminathan 				    "Sending.   %s: mb=%p NoWait.",
329282527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
329382527734SSukumar Swaminathan 			}
329482527734SSukumar Swaminathan 		}
3295291a2b48SSukumar Swaminathan 
329682527734SSukumar Swaminathan 		break;
3297291a2b48SSukumar Swaminathan 
329882527734SSukumar Swaminathan 	case MBX_SLEEP:
329982527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD &&
330082527734SSukumar Swaminathan 		    mb->mbxCommand != MBX_DUMP_MEMORY) {
330182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
330282527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Sleep.",
330382527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
330482527734SSukumar Swaminathan 		}
3305291a2b48SSukumar Swaminathan 
330682527734SSukumar Swaminathan 		break;
3307291a2b48SSukumar Swaminathan 
330882527734SSukumar Swaminathan 	case MBX_POLL:
330982527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD &&
331082527734SSukumar Swaminathan 		    mb->mbxCommand != MBX_DUMP_MEMORY) {
331182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
331282527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Polled.",
331382527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
331482527734SSukumar Swaminathan 		}
331582527734SSukumar Swaminathan 		break;
331682527734SSukumar Swaminathan 	}
3317291a2b48SSukumar Swaminathan 
331882527734SSukumar Swaminathan 	mb->mbxOwner = OWN_CHIP;
3319291a2b48SSukumar Swaminathan 
332082527734SSukumar Swaminathan 	/* Clear the attention bit */
332182527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT);
3322291a2b48SSukumar Swaminathan 
332382527734SSukumar Swaminathan 	if (hba->flag & FC_SLIM2_MODE) {
332482527734SSukumar Swaminathan 		/* First copy command data */
332582527734SSukumar Swaminathan 		mbox = FC_SLIM2_MAILBOX(hba);
332682527734SSukumar Swaminathan 		offset =
332782527734SSukumar Swaminathan 		    (off_t)((uint64_t)((unsigned long)mbox)
332882527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)slim2p));
3329291a2b48SSukumar Swaminathan 
333082527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
333182527734SSukumar Swaminathan 		if (mbq->extbuf) {
333282527734SSukumar Swaminathan 			uint32_t *mbox_ext =
333382527734SSukumar Swaminathan 			    (uint32_t *)((uint8_t *)mbox +
333482527734SSukumar Swaminathan 			    MBOX_EXTENSION_OFFSET);
333582527734SSukumar Swaminathan 			off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
3336291a2b48SSukumar Swaminathan 
333782527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)mbq->extbuf,
333882527734SSukumar Swaminathan 			    (uint8_t *)mbox_ext, mbq->extsize);
3339291a2b48SSukumar Swaminathan 
334082527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
334182527734SSukumar Swaminathan 			    offset_ext, mbq->extsize,
334282527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORDEV);
3343291a2b48SSukumar Swaminathan 		}
334482527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
3345291a2b48SSukumar Swaminathan 
334682527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox,
334782527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE);
3348291a2b48SSukumar Swaminathan 
334982527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
335082527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
335182527734SSukumar Swaminathan 	} else {	/* SLIM 1 */
3352291a2b48SSukumar Swaminathan 
335382527734SSukumar Swaminathan 		mbox = FC_SLIM1_MAILBOX(hba);
3354291a2b48SSukumar Swaminathan 
335582527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
335682527734SSukumar Swaminathan 		if (mbq->extbuf) {
335782527734SSukumar Swaminathan 			uint32_t *mbox_ext =
335882527734SSukumar Swaminathan 			    (uint32_t *)((uint8_t *)mbox +
335982527734SSukumar Swaminathan 			    MBOX_EXTENSION_OFFSET);
336082527734SSukumar Swaminathan 			WRITE_SLIM_COPY(hba, (uint32_t *)mbq->extbuf,
336182527734SSukumar Swaminathan 			    mbox_ext, (mbq->extsize / 4));
336282527734SSukumar Swaminathan 		}
336382527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
3364291a2b48SSukumar Swaminathan 
336582527734SSukumar Swaminathan 		/* First copy command data */
336682527734SSukumar Swaminathan 		WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords,
336782527734SSukumar Swaminathan 		    (MAILBOX_CMD_WSIZE - 1));
3368291a2b48SSukumar Swaminathan 
336982527734SSukumar Swaminathan 		/* copy over last word, with mbxOwner set */
337082527734SSukumar Swaminathan 		ldata = *((volatile uint32_t *)mb);
337182527734SSukumar Swaminathan 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata);
3372291a2b48SSukumar Swaminathan 	}
3373291a2b48SSukumar Swaminathan 
337482527734SSukumar Swaminathan 	/* Interrupt board to do it right away */
337582527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
3376291a2b48SSukumar Swaminathan 
337782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
3378291a2b48SSukumar Swaminathan 
33794baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
33804baa2c25SSukumar Swaminathan 	/* Access handle validation */
338182527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
338282527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
338382527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
33844baa2c25SSukumar Swaminathan 	    != DDI_FM_OK)) {
33854baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
33864baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
338782527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
33884baa2c25SSukumar Swaminathan 	}
33894baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
33904baa2c25SSukumar Swaminathan 
339182527734SSukumar Swaminathan 	switch (flag) {
339282527734SSukumar Swaminathan 	case MBX_NOWAIT:
339382527734SSukumar Swaminathan 		return (MBX_SUCCESS);
3394291a2b48SSukumar Swaminathan 
339582527734SSukumar Swaminathan 	case MBX_SLEEP:
33964baa2c25SSukumar Swaminathan 
339782527734SSukumar Swaminathan 		/* Wait for completion */
339882527734SSukumar Swaminathan 		/* The driver clock is timing the mailbox. */
339982527734SSukumar Swaminathan 		/* emlxs_mb_fini() will be called externally. */
3400291a2b48SSukumar Swaminathan 
340182527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
340282527734SSukumar Swaminathan 		while (!(mbq->flag & MBQ_COMPLETED)) {
340382527734SSukumar Swaminathan 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
340482527734SSukumar Swaminathan 		}
340582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
3406291a2b48SSukumar Swaminathan 
340782527734SSukumar Swaminathan 		if (mb->mbxStatus == MBX_TIMEOUT) {
340882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
340982527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%d. Sleep.",
341082527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
341182527734SSukumar Swaminathan 		} else {
341282527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD &&
341382527734SSukumar Swaminathan 			    mb->mbxCommand != MBX_DUMP_MEMORY) {
341482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
341582527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
341682527734SSukumar Swaminathan 				    "Completed. %s: mb=%p status=%x Sleep.",
341782527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
341882527734SSukumar Swaminathan 				    mb->mbxStatus);
341982527734SSukumar Swaminathan 			}
342082527734SSukumar Swaminathan 		}
3421291a2b48SSukumar Swaminathan 
342282527734SSukumar Swaminathan 		break;
3423291a2b48SSukumar Swaminathan 
342482527734SSukumar Swaminathan 	case MBX_POLL:
3425291a2b48SSukumar Swaminathan 
342682527734SSukumar Swaminathan 		/* Convert tmo seconds to 500 usec tics */
342782527734SSukumar Swaminathan 		tmo_local = tmo * 2000;
3428291a2b48SSukumar Swaminathan 
342982527734SSukumar Swaminathan 		/* Get first word of mailbox */
343082527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
343182527734SSukumar Swaminathan 			mbox = FC_SLIM2_MAILBOX(hba);
343282527734SSukumar Swaminathan 			offset = (off_t)((uint64_t)((unsigned long)mbox) -
343382527734SSukumar Swaminathan 			    (uint64_t)((unsigned long)slim2p));
3434291a2b48SSukumar Swaminathan 
343582527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
343682527734SSukumar Swaminathan 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
343782527734SSukumar Swaminathan 			word0 = *((volatile uint32_t *)mbox);
343882527734SSukumar Swaminathan 			word0 = BE_SWAP32(word0);
343982527734SSukumar Swaminathan 		} else {
344082527734SSukumar Swaminathan 			mbox = FC_SLIM1_MAILBOX(hba);
344182527734SSukumar Swaminathan 			word0 =
344282527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
34434baa2c25SSukumar Swaminathan 		}
34444baa2c25SSukumar Swaminathan 
344582527734SSukumar Swaminathan 		/* Wait for command to complete */
344682527734SSukumar Swaminathan 		while ((swpmb->mbxOwner == OWN_CHIP) &&
344782527734SSukumar Swaminathan 		    !(mbq->flag & MBQ_COMPLETED)) {
344882527734SSukumar Swaminathan 			if (!hba->timer_id && (tmo_local-- == 0)) {
344982527734SSukumar Swaminathan 				/* self time */
345082527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
345182527734SSukumar Swaminathan 				    &emlxs_mbox_timeout_msg,
3452*8f23e9faSHans Rosenfeld 				    "%s: mb=%p tmo=%d Polled.",
3453*8f23e9faSHans Rosenfeld 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3454*8f23e9faSHans Rosenfeld 				    mb, tmo);
3455291a2b48SSukumar Swaminathan 
345682527734SSukumar Swaminathan 				hba->flag |= FC_MBOX_TIMEOUT;
345782527734SSukumar Swaminathan 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
345882527734SSukumar Swaminathan 				emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3459291a2b48SSukumar Swaminathan 
346082527734SSukumar Swaminathan 				break;
346182527734SSukumar Swaminathan 			}
3462291a2b48SSukumar Swaminathan 
3463*8f23e9faSHans Rosenfeld 			BUSYWAIT_US(500);
3464291a2b48SSukumar Swaminathan 
346582527734SSukumar Swaminathan 			/* Get first word of mailbox */
346682527734SSukumar Swaminathan 			if (hba->flag & FC_SLIM2_MODE) {
346782527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(
346882527734SSukumar Swaminathan 				    hba->sli.sli3.slim2.dma_handle, offset,
346982527734SSukumar Swaminathan 				    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
347082527734SSukumar Swaminathan 				word0 = *((volatile uint32_t *)mbox);
347182527734SSukumar Swaminathan 				word0 = BE_SWAP32(word0);
347282527734SSukumar Swaminathan 			} else {
347382527734SSukumar Swaminathan 				word0 =
347482527734SSukumar Swaminathan 				    READ_SLIM_ADDR(hba,
347582527734SSukumar Swaminathan 				    ((volatile uint32_t *)mbox));
347682527734SSukumar Swaminathan 			}
3477291a2b48SSukumar Swaminathan 
347882527734SSukumar Swaminathan 		}	/* while */
3479291a2b48SSukumar Swaminathan 
348082527734SSukumar Swaminathan 		if (mb->mbxStatus == MBX_TIMEOUT) {
348182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
348282527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%d. Polled.",
348382527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
348482527734SSukumar Swaminathan 
348582527734SSukumar Swaminathan 			break;
3486291a2b48SSukumar Swaminathan 		}
3487291a2b48SSukumar Swaminathan 
3488*8f23e9faSHans Rosenfeld 		/* Check for config port command */
3489*8f23e9faSHans Rosenfeld 		if ((swpmb->mbxCommand == MBX_CONFIG_PORT) &&
3490*8f23e9faSHans Rosenfeld 		    (swpmb->mbxStatus == MBX_SUCCESS)) {
3491*8f23e9faSHans Rosenfeld 			/* Setup host mbox for cmpl */
3492*8f23e9faSHans Rosenfeld 			mbox = FC_SLIM2_MAILBOX(hba);
3493*8f23e9faSHans Rosenfeld 			offset = (off_t)((uint64_t)((unsigned long)mbox)
3494*8f23e9faSHans Rosenfeld 			    - (uint64_t)((unsigned long)slim2p));
3495*8f23e9faSHans Rosenfeld 
3496*8f23e9faSHans Rosenfeld 			hba->flag |= FC_SLIM2_MODE;
3497*8f23e9faSHans Rosenfeld 		}
3498*8f23e9faSHans Rosenfeld 
3499*8f23e9faSHans Rosenfeld 		/* copy results back to user */
3500*8f23e9faSHans Rosenfeld 		if (hba->flag & FC_SLIM2_MODE) {
3501*8f23e9faSHans Rosenfeld 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
350282527734SSukumar Swaminathan 			    offset, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
3503291a2b48SSukumar Swaminathan 
350482527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb,
350582527734SSukumar Swaminathan 			    MAILBOX_CMD_BSIZE);
350682527734SSukumar Swaminathan 		} else {
350782527734SSukumar Swaminathan 			READ_SLIM_COPY(hba, (uint32_t *)mb,
350882527734SSukumar Swaminathan 			    (uint32_t *)mbox, MAILBOX_CMD_WSIZE);
350982527734SSukumar Swaminathan 		}
3510291a2b48SSukumar Swaminathan 
351182527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
351282527734SSukumar Swaminathan 		if (mbq->extbuf) {
351382527734SSukumar Swaminathan 			uint32_t *mbox_ext =
351482527734SSukumar Swaminathan 			    (uint32_t *)((uint8_t *)mbox +
351582527734SSukumar Swaminathan 			    MBOX_EXTENSION_OFFSET);
351682527734SSukumar Swaminathan 			off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
3517291a2b48SSukumar Swaminathan 
351882527734SSukumar Swaminathan 			if (hba->flag & FC_SLIM2_MODE) {
351982527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(
352082527734SSukumar Swaminathan 				    hba->sli.sli3.slim2.dma_handle, offset_ext,
352182527734SSukumar Swaminathan 				    mbq->extsize, DDI_DMA_SYNC_FORKERNEL);
3522291a2b48SSukumar Swaminathan 
352382527734SSukumar Swaminathan 				BE_SWAP32_BCOPY((uint8_t *)mbox_ext,
352482527734SSukumar Swaminathan 				    (uint8_t *)mbq->extbuf, mbq->extsize);
352582527734SSukumar Swaminathan 			} else {
352682527734SSukumar Swaminathan 				READ_SLIM_COPY(hba,
352782527734SSukumar Swaminathan 				    (uint32_t *)mbq->extbuf, mbox_ext,
352882527734SSukumar Swaminathan 				    (mbq->extsize / 4));
352982527734SSukumar Swaminathan 			}
353082527734SSukumar Swaminathan 		}
353182527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
3532291a2b48SSukumar Swaminathan 
353382527734SSukumar Swaminathan 		/* Sync the memory buffer */
353482527734SSukumar Swaminathan 		if (mbq->bp) {
353582527734SSukumar Swaminathan 			mbox_bp = (MATCHMAP *)mbq->bp;
353682527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0,
353782527734SSukumar Swaminathan 			    mbox_bp->size, DDI_DMA_SYNC_FORKERNEL);
353882527734SSukumar Swaminathan 		}
3539291a2b48SSukumar Swaminathan 
354082527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD &&
354182527734SSukumar Swaminathan 		    mb->mbxCommand != MBX_DUMP_MEMORY) {
354282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
354382527734SSukumar Swaminathan 			    "Completed. %s: mb=%p status=%x Polled.",
354482527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
354582527734SSukumar Swaminathan 			    mb->mbxStatus);
354682527734SSukumar Swaminathan 		}
3547291a2b48SSukumar Swaminathan 
354882527734SSukumar Swaminathan 		/* Process the result */
354982527734SSukumar Swaminathan 		if (!(mbq->flag & MBQ_PASSTHRU)) {
355082527734SSukumar Swaminathan 			if (mbq->mbox_cmpl) {
355182527734SSukumar Swaminathan 				(void) (mbq->mbox_cmpl)(hba, mbq);
355282527734SSukumar Swaminathan 			}
355382527734SSukumar Swaminathan 		}
3554291a2b48SSukumar Swaminathan 
355582527734SSukumar Swaminathan 		/* Clear the attention bit */
355682527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT);
35574baa2c25SSukumar Swaminathan 
355882527734SSukumar Swaminathan 		/* Clean up the mailbox area */
355982527734SSukumar Swaminathan 		emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3560291a2b48SSukumar Swaminathan 
356182527734SSukumar Swaminathan 		break;
3562291a2b48SSukumar Swaminathan 
356382527734SSukumar Swaminathan 	}	/* switch (flag) */
356482527734SSukumar Swaminathan 
356582527734SSukumar Swaminathan 	return (mb->mbxStatus);
356682527734SSukumar Swaminathan 
356782527734SSukumar Swaminathan } /* emlxs_sli3_issue_mbox_cmd() */
356882527734SSukumar Swaminathan 
356982527734SSukumar Swaminathan 
357082527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
3571*8f23e9faSHans Rosenfeld /*ARGSUSED*/
357282527734SSukumar Swaminathan static uint32_t
357382527734SSukumar Swaminathan emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp,
357482527734SSukumar Swaminathan 	int channel)
3575291a2b48SSukumar Swaminathan {
357682527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
357782527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
357882527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd;
357982527734SSukumar Swaminathan 	stmf_data_buf_t *dbuf;
358082527734SSukumar Swaminathan 	scsi_task_t *fct_task;
3581*8f23e9faSHans Rosenfeld 	fc_packet_t *pkt;
358282527734SSukumar Swaminathan 	uint32_t did;
358382527734SSukumar Swaminathan 	IOCBQ *iocbq;
358482527734SSukumar Swaminathan 	IOCB *iocb;
358582527734SSukumar Swaminathan 	uint32_t timeout;
358682527734SSukumar Swaminathan 	uint32_t iotag;
358782527734SSukumar Swaminathan 	emlxs_node_t *ndlp;
358882527734SSukumar Swaminathan 	CHANNEL *cp;
3589*8f23e9faSHans Rosenfeld 	ddi_dma_cookie_t *cp_cmd;
3590291a2b48SSukumar Swaminathan 
3591*8f23e9faSHans Rosenfeld 	pkt = PRIV2PKT(cmd_sbp);
3592291a2b48SSukumar Swaminathan 
359382527734SSukumar Swaminathan 	cp = (CHANNEL *)cmd_sbp->channel;
3594291a2b48SSukumar Swaminathan 
359582527734SSukumar Swaminathan 	iocbq = &cmd_sbp->iocbq;
359682527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3597291a2b48SSukumar Swaminathan 
3598291a2b48SSukumar Swaminathan 
359982527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
360082527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, cmd_sbp);
3601291a2b48SSukumar Swaminathan 
360282527734SSukumar Swaminathan 	if (!iotag) {
360382527734SSukumar Swaminathan 		/* No more command slots available, retry later */
360482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3605*8f23e9faSHans Rosenfeld 		    "Adapter Busy. Unable to allocate iotag. did=0x%x",
3606*8f23e9faSHans Rosenfeld 		    cmd_sbp->did);
36074baa2c25SSukumar Swaminathan 
360882527734SSukumar Swaminathan 		return (IOERR_NO_RESOURCES);
3609291a2b48SSukumar Swaminathan 	}
3610291a2b48SSukumar Swaminathan 
3611291a2b48SSukumar Swaminathan 
3612*8f23e9faSHans Rosenfeld 	/* Point of no return */
3613*8f23e9faSHans Rosenfeld 
3614*8f23e9faSHans Rosenfeld 	if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) {
3615*8f23e9faSHans Rosenfeld 
3616*8f23e9faSHans Rosenfeld 		ndlp = cmd_sbp->node;
3617*8f23e9faSHans Rosenfeld 		cp->ulpSendCmd++;
3618*8f23e9faSHans Rosenfeld 
3619*8f23e9faSHans Rosenfeld 		/* Initalize iocbq */
3620*8f23e9faSHans Rosenfeld 		iocbq->port = (void *)port;
3621*8f23e9faSHans Rosenfeld 		iocbq->node = (void *)ndlp;
3622*8f23e9faSHans Rosenfeld 		iocbq->channel = (void *)cp;
3623*8f23e9faSHans Rosenfeld 
3624*8f23e9faSHans Rosenfeld 		/*
3625*8f23e9faSHans Rosenfeld 		 * Don't give the abort priority, we want the IOCB
3626*8f23e9faSHans Rosenfeld 		 * we are aborting to be processed first.
3627*8f23e9faSHans Rosenfeld 		 */
3628*8f23e9faSHans Rosenfeld 		iocbq->flag |= IOCB_SPECIAL;
3629*8f23e9faSHans Rosenfeld 
3630*8f23e9faSHans Rosenfeld 		iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id;
3631*8f23e9faSHans Rosenfeld 		iocb->ULPIOTAG = (uint16_t)iotag;
3632*8f23e9faSHans Rosenfeld 		iocb->ULPLE = 1;
3633*8f23e9faSHans Rosenfeld 		iocb->ULPCLASS = cmd_sbp->class;
3634*8f23e9faSHans Rosenfeld 		iocb->ULPOWNER = OWN_CHIP;
3635291a2b48SSukumar Swaminathan 
3636*8f23e9faSHans Rosenfeld 		if (hba->state >= FC_LINK_UP) {
3637*8f23e9faSHans Rosenfeld 			/* Create the abort IOCB */
3638*8f23e9faSHans Rosenfeld 			iocb->un.acxri.abortType = ABORT_TYPE_ABTS;
3639*8f23e9faSHans Rosenfeld 			iocb->ULPCOMMAND = CMD_ABORT_XRI_CX;
3640*8f23e9faSHans Rosenfeld 
3641*8f23e9faSHans Rosenfeld 		} else {
3642*8f23e9faSHans Rosenfeld 			/* Create the close IOCB */
3643*8f23e9faSHans Rosenfeld 			iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX;
3644*8f23e9faSHans Rosenfeld 
3645*8f23e9faSHans Rosenfeld 		}
3646*8f23e9faSHans Rosenfeld 
3647*8f23e9faSHans Rosenfeld 		iocb->ULPRSVDBYTE =
3648*8f23e9faSHans Rosenfeld 		    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3649*8f23e9faSHans Rosenfeld 		/* Set the pkt timer */
3650*8f23e9faSHans Rosenfeld 		cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3651*8f23e9faSHans Rosenfeld 		    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3652*8f23e9faSHans Rosenfeld 
3653*8f23e9faSHans Rosenfeld 		return (IOERR_SUCCESS);
3654*8f23e9faSHans Rosenfeld 
3655*8f23e9faSHans Rosenfeld 	} else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) {
3656*8f23e9faSHans Rosenfeld 
3657*8f23e9faSHans Rosenfeld 		ndlp = cmd_sbp->node;
3658*8f23e9faSHans Rosenfeld 		cp->ulpSendCmd++;
3659*8f23e9faSHans Rosenfeld 
3660*8f23e9faSHans Rosenfeld 		/* Initalize iocbq */
3661*8f23e9faSHans Rosenfeld 		iocbq->port = (void *)port;
3662*8f23e9faSHans Rosenfeld 		iocbq->node = (void *)ndlp;
3663*8f23e9faSHans Rosenfeld 		iocbq->channel = (void *)cp;
3664*8f23e9faSHans Rosenfeld 
3665*8f23e9faSHans Rosenfeld #if (EMLXS_MODREV >= EMLXS_MODREV3)
3666*8f23e9faSHans Rosenfeld 		cp_cmd = pkt->pkt_cmd_cookie;
3667*8f23e9faSHans Rosenfeld #else
3668*8f23e9faSHans Rosenfeld 		cp_cmd  = &pkt->pkt_cmd_cookie;
3669*8f23e9faSHans Rosenfeld #endif	/* >= EMLXS_MODREV3 */
3670*8f23e9faSHans Rosenfeld 
3671*8f23e9faSHans Rosenfeld 		iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
3672*8f23e9faSHans Rosenfeld 		iocb->un.fcpt64.bdl.addrLow = PADDR_LO(cp_cmd->dmac_laddress);
3673*8f23e9faSHans Rosenfeld 		iocb->un.fcpt64.bdl.bdeSize = pkt->pkt_cmdlen;
3674*8f23e9faSHans Rosenfeld 		iocb->un.fcpt64.bdl.bdeFlags = 0;
3675*8f23e9faSHans Rosenfeld 
3676*8f23e9faSHans Rosenfeld 		if (hba->sli_mode < 3) {
3677*8f23e9faSHans Rosenfeld 			iocb->ULPBDECOUNT = 1;
3678*8f23e9faSHans Rosenfeld 			iocb->ULPLE = 1;
3679*8f23e9faSHans Rosenfeld 		} else {	/* SLI3 */
3680*8f23e9faSHans Rosenfeld 
3681*8f23e9faSHans Rosenfeld 			iocb->ULPBDECOUNT = 0;
3682*8f23e9faSHans Rosenfeld 			iocb->ULPLE = 0;
3683*8f23e9faSHans Rosenfeld 			iocb->unsli3.ext_iocb.ebde_count = 0;
3684*8f23e9faSHans Rosenfeld 		}
3685*8f23e9faSHans Rosenfeld 
3686*8f23e9faSHans Rosenfeld 		/* Initalize iocb */
3687*8f23e9faSHans Rosenfeld 		iocb->ULPCONTEXT = (uint16_t)pkt->pkt_cmd_fhdr.rx_id;
3688*8f23e9faSHans Rosenfeld 		iocb->ULPIOTAG = (uint16_t)iotag;
3689*8f23e9faSHans Rosenfeld 		iocb->ULPRSVDBYTE =
3690*8f23e9faSHans Rosenfeld 		    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3691*8f23e9faSHans Rosenfeld 		iocb->ULPOWNER = OWN_CHIP;
3692*8f23e9faSHans Rosenfeld 		iocb->ULPCLASS = cmd_sbp->class;
3693*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX;
3694*8f23e9faSHans Rosenfeld 
3695*8f23e9faSHans Rosenfeld 		/* Set the pkt timer */
3696*8f23e9faSHans Rosenfeld 		cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3697*8f23e9faSHans Rosenfeld 		    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3698*8f23e9faSHans Rosenfeld 
3699*8f23e9faSHans Rosenfeld 		if (pkt->pkt_cmdlen) {
3700*8f23e9faSHans Rosenfeld 			EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
3701*8f23e9faSHans Rosenfeld 			    DDI_DMA_SYNC_FORDEV);
3702*8f23e9faSHans Rosenfeld 		}
3703*8f23e9faSHans Rosenfeld 
3704*8f23e9faSHans Rosenfeld 		return (IOERR_SUCCESS);
3705*8f23e9faSHans Rosenfeld 	}
3706*8f23e9faSHans Rosenfeld 
3707*8f23e9faSHans Rosenfeld 	dbuf = cmd_sbp->fct_buf;
3708*8f23e9faSHans Rosenfeld 	fct_cmd = cmd_sbp->fct_cmd;
3709*8f23e9faSHans Rosenfeld 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
3710*8f23e9faSHans Rosenfeld 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
3711*8f23e9faSHans Rosenfeld 	did = fct_cmd->cmd_rportid;
3712291a2b48SSukumar Swaminathan 
371382527734SSukumar Swaminathan 	iocbq->channel = (void *)cmd_sbp->channel;
3714291a2b48SSukumar Swaminathan 
371582527734SSukumar Swaminathan 	if (emlxs_fct_bde_setup(port, cmd_sbp)) {
371682527734SSukumar Swaminathan 		/* Unregister the packet */
371782527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cmd_sbp->channel, iotag, 0);
3718291a2b48SSukumar Swaminathan 
371982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
372082527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
3721291a2b48SSukumar Swaminathan 
372282527734SSukumar Swaminathan 		return (IOERR_INTERNAL_ERROR);
372382527734SSukumar Swaminathan 	}
3724*8f23e9faSHans Rosenfeld 
3725*8f23e9faSHans Rosenfeld 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
3726*8f23e9faSHans Rosenfeld 		timeout =
3727*8f23e9faSHans Rosenfeld 		    ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
3728*8f23e9faSHans Rosenfeld 	} else {
3729*8f23e9faSHans Rosenfeld 		timeout = 0x80000000;
3730*8f23e9faSHans Rosenfeld 	}
3731*8f23e9faSHans Rosenfeld 
3732*8f23e9faSHans Rosenfeld 	cmd_sbp->ticks =
3733*8f23e9faSHans Rosenfeld 	    hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10);
3734*8f23e9faSHans Rosenfeld 
3735*8f23e9faSHans Rosenfeld 	/* Initalize iocbq */
3736*8f23e9faSHans Rosenfeld 	iocbq->port = (void *)port;
3737*8f23e9faSHans Rosenfeld 	iocbq->node = (void *)ndlp;
3738291a2b48SSukumar Swaminathan 
373982527734SSukumar Swaminathan 	/* Initalize iocb */
374082527734SSukumar Swaminathan 	iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid;
3741a9800bebSGarrett D'Amore 	iocb->ULPIOTAG = (uint16_t)iotag;
374282527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout);
374382527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
374482527734SSukumar Swaminathan 	iocb->ULPCLASS = cmd_sbp->class;
3745291a2b48SSukumar Swaminathan 
374682527734SSukumar Swaminathan 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
374782527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset;
3748291a2b48SSukumar Swaminathan 
374982527734SSukumar Swaminathan 	if (fct_task->task_flags & TF_WRITE_DATA) {
375082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX;
375182527734SSukumar Swaminathan 	} else {	/* TF_READ_DATA */
3752291a2b48SSukumar Swaminathan 
375382527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
3754291a2b48SSukumar Swaminathan 
37556a573d82SSukumar Swaminathan 		if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) &&
3756*8f23e9faSHans Rosenfeld 		    (dbuf->db_data_size >=
3757a9800bebSGarrett D'Amore 		    fct_task->task_expected_xfer_length)) {
375882527734SSukumar Swaminathan 			iocb->ULPCT = 0x1;
375982527734SSukumar Swaminathan 			/* enable auto-rsp AP feature */
3760a9800bebSGarrett D'Amore 		}
376182527734SSukumar Swaminathan 	}
3762291a2b48SSukumar Swaminathan 
376382527734SSukumar Swaminathan 	return (IOERR_SUCCESS);
3764291a2b48SSukumar Swaminathan 
376582527734SSukumar Swaminathan } /* emlxs_sli3_prep_fct_iocb() */
3766291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3767291a2b48SSukumar Swaminathan 
376882527734SSukumar Swaminathan /* ARGSUSED */
376982527734SSukumar Swaminathan static uint32_t
377082527734SSukumar Swaminathan emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
377182527734SSukumar Swaminathan {
377282527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
377382527734SSukumar Swaminathan 	fc_packet_t *pkt;
377482527734SSukumar Swaminathan 	CHANNEL *cp;
377582527734SSukumar Swaminathan 	IOCBQ *iocbq;
377682527734SSukumar Swaminathan 	IOCB *iocb;
377782527734SSukumar Swaminathan 	NODELIST *ndlp;
377882527734SSukumar Swaminathan 	uint16_t iotag;
377982527734SSukumar Swaminathan 	uint32_t did;
378082527734SSukumar Swaminathan 
378182527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
378282527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
378382527734SSukumar Swaminathan 	cp = &hba->chan[FC_FCP_RING];
378482527734SSukumar Swaminathan 
378582527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
378682527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
378782527734SSukumar Swaminathan 
378882527734SSukumar Swaminathan 	/* Find target node object */
378982527734SSukumar Swaminathan 	ndlp = (NODELIST *)iocbq->node;
379082527734SSukumar Swaminathan 
379182527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
379282527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
379382527734SSukumar Swaminathan 
379482527734SSukumar Swaminathan 	if (!iotag) {
379582527734SSukumar Swaminathan 		/*
379682527734SSukumar Swaminathan 		 * No more command slots available, retry later
379782527734SSukumar Swaminathan 		 */
379882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
379982527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag: did=0x%x", did);
380082527734SSukumar Swaminathan 
380182527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
380282527734SSukumar Swaminathan 	}
380382527734SSukumar Swaminathan 
380482527734SSukumar Swaminathan 	/* Initalize iocbq */
380582527734SSukumar Swaminathan 	iocbq->port = (void *) port;
380682527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
380782527734SSukumar Swaminathan 
380882527734SSukumar Swaminathan 	/* Indicate this is a FCP cmd */
380982527734SSukumar Swaminathan 	iocbq->flag |= IOCB_FCP_CMD;
381082527734SSukumar Swaminathan 
381182527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
381282527734SSukumar Swaminathan 		/* Unregister the packet */
381382527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
381482527734SSukumar Swaminathan 
381582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
381682527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
381782527734SSukumar Swaminathan 
381882527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
381982527734SSukumar Swaminathan 	}
382082527734SSukumar Swaminathan 	/* Point of no return */
382182527734SSukumar Swaminathan 
382282527734SSukumar Swaminathan 	/* Initalize iocb */
382382527734SSukumar Swaminathan 	iocb->ULPCONTEXT = ndlp->nlp_Rpi;
382482527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
382582527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
382682527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
382782527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
382882527734SSukumar Swaminathan 
382982527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
383082527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
383182527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
383282527734SSukumar Swaminathan 		break;
383382527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
383482527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
383582527734SSukumar Swaminathan 		/* iocb->ULPCLASS = CLASS3; */
383682527734SSukumar Swaminathan 		break;
383782527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
383882527734SSukumar Swaminathan 	default:
383982527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
384082527734SSukumar Swaminathan 		break;
384182527734SSukumar Swaminathan 	}
384282527734SSukumar Swaminathan 
384382527734SSukumar Swaminathan 	/* if device is FCP-2 device, set the following bit */
384482527734SSukumar Swaminathan 	/* that says to run the FC-TAPE protocol. */
384582527734SSukumar Swaminathan 	if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
384682527734SSukumar Swaminathan 		iocb->ULPFCP2RCVY = 1;
384782527734SSukumar Swaminathan 	}
384882527734SSukumar Swaminathan 
384982527734SSukumar Swaminathan 	if (pkt->pkt_datalen == 0) {
385082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR;
385182527734SSukumar Swaminathan 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
385282527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR;
3853*8f23e9faSHans Rosenfeld 		iocb->ULPPU = PARM_XFER_CHECK;
385482527734SSukumar Swaminathan 		iocb->un.fcpi64.fcpi_parm = pkt->pkt_datalen;
385582527734SSukumar Swaminathan 	} else {
385682527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR;
385782527734SSukumar Swaminathan 	}
385882527734SSukumar Swaminathan 
385982527734SSukumar Swaminathan 	return (FC_SUCCESS);
386082527734SSukumar Swaminathan 
386182527734SSukumar Swaminathan } /* emlxs_sli3_prep_fcp_iocb() */
386282527734SSukumar Swaminathan 
386382527734SSukumar Swaminathan 
386482527734SSukumar Swaminathan static uint32_t
386582527734SSukumar Swaminathan emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
386682527734SSukumar Swaminathan {
386782527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
386882527734SSukumar Swaminathan 	fc_packet_t *pkt;
386982527734SSukumar Swaminathan 	IOCBQ *iocbq;
387082527734SSukumar Swaminathan 	IOCB *iocb;
387182527734SSukumar Swaminathan 	CHANNEL *cp;
387282527734SSukumar Swaminathan 	NODELIST *ndlp;
387382527734SSukumar Swaminathan 	uint16_t iotag;
387482527734SSukumar Swaminathan 	uint32_t did;
387582527734SSukumar Swaminathan 
387682527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
387782527734SSukumar Swaminathan 	cp = &hba->chan[FC_IP_RING];
387882527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
387982527734SSukumar Swaminathan 
388082527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
388182527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
388282527734SSukumar Swaminathan 	ndlp = (NODELIST *)iocbq->node;
388382527734SSukumar Swaminathan 
388482527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
388582527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
388682527734SSukumar Swaminathan 
388782527734SSukumar Swaminathan 	if (!iotag) {
388882527734SSukumar Swaminathan 		/*
388982527734SSukumar Swaminathan 		 * No more command slots available, retry later
389082527734SSukumar Swaminathan 		 */
389182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
389282527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag: did=0x%x", did);
389382527734SSukumar Swaminathan 
389482527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
389582527734SSukumar Swaminathan 	}
389682527734SSukumar Swaminathan 
389782527734SSukumar Swaminathan 	/* Initalize iocbq */
389882527734SSukumar Swaminathan 	iocbq->port = (void *) port;
389982527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
390082527734SSukumar Swaminathan 
390182527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
390282527734SSukumar Swaminathan 		/* Unregister the packet */
390382527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
390482527734SSukumar Swaminathan 
390582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
390682527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
390782527734SSukumar Swaminathan 
390882527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
390982527734SSukumar Swaminathan 	}
391082527734SSukumar Swaminathan 	/* Point of no return */
391182527734SSukumar Swaminathan 
391282527734SSukumar Swaminathan 	/* Initalize iocb */
391382527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Fctl = 0;
391482527734SSukumar Swaminathan 
391582527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_FIRST_SEQ) {
391682527734SSukumar Swaminathan 		iocb->un.xseq64.w5.hcsw.Fctl |= FSEQ;
391782527734SSukumar Swaminathan 	}
391882527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
391982527734SSukumar Swaminathan 		iocb->un.xseq64.w5.hcsw.Fctl |= SI;
392082527734SSukumar Swaminathan 	}
392182527734SSukumar Swaminathan 
392282527734SSukumar Swaminathan 	/* network headers */
392382527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl;
392482527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
392582527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type;
392682527734SSukumar Swaminathan 
392782527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
392882527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
392982527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
393082527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
393182527734SSukumar Swaminathan 
393282527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_BROADCAST) {
393382527734SSukumar Swaminathan 		HBASTATS.IpBcastIssued++;
393482527734SSukumar Swaminathan 
393582527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN;
393682527734SSukumar Swaminathan 		iocb->ULPCONTEXT = 0;
393782527734SSukumar Swaminathan 
3938a9800bebSGarrett D'Amore 		if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
393982527734SSukumar Swaminathan 			if (hba->topology != TOPOLOGY_LOOP) {
394082527734SSukumar Swaminathan 				iocb->ULPCT = 0x1;
394182527734SSukumar Swaminathan 			}
394282527734SSukumar Swaminathan 			iocb->ULPCONTEXT = port->vpi;
394382527734SSukumar Swaminathan 		}
394482527734SSukumar Swaminathan 	} else {
394582527734SSukumar Swaminathan 		HBASTATS.IpSeqIssued++;
394682527734SSukumar Swaminathan 
394782527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
394882527734SSukumar Swaminathan 		iocb->ULPCONTEXT = ndlp->nlp_Xri;
394982527734SSukumar Swaminathan 	}
395082527734SSukumar Swaminathan 
395182527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
395282527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
395382527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
395482527734SSukumar Swaminathan 		break;
395582527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
395682527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
395782527734SSukumar Swaminathan 		break;
395882527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
395982527734SSukumar Swaminathan 	default:
396082527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
396182527734SSukumar Swaminathan 		break;
396282527734SSukumar Swaminathan 	}
396382527734SSukumar Swaminathan 
396482527734SSukumar Swaminathan 	return (FC_SUCCESS);
396582527734SSukumar Swaminathan 
396682527734SSukumar Swaminathan } /* emlxs_sli3_prep_ip_iocb() */
396782527734SSukumar Swaminathan 
396882527734SSukumar Swaminathan 
396982527734SSukumar Swaminathan static uint32_t
397082527734SSukumar Swaminathan emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
397182527734SSukumar Swaminathan {
397282527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
397382527734SSukumar Swaminathan 	fc_packet_t *pkt;
397482527734SSukumar Swaminathan 	IOCBQ *iocbq;
397582527734SSukumar Swaminathan 	IOCB *iocb;
397682527734SSukumar Swaminathan 	CHANNEL *cp;
397782527734SSukumar Swaminathan 	uint16_t iotag;
397882527734SSukumar Swaminathan 	uint32_t did;
397982527734SSukumar Swaminathan 	uint32_t cmd;
398082527734SSukumar Swaminathan 
398182527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
398282527734SSukumar Swaminathan 	cp = &hba->chan[FC_ELS_RING];
398382527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
398482527734SSukumar Swaminathan 
398582527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
398682527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
398782527734SSukumar Swaminathan 
398882527734SSukumar Swaminathan 
398982527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
399082527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
399182527734SSukumar Swaminathan 
399282527734SSukumar Swaminathan 	if (!iotag) {
399382527734SSukumar Swaminathan 		/*
399482527734SSukumar Swaminathan 		 * No more command slots available, retry later
399582527734SSukumar Swaminathan 		 */
399682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
399782527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
399882527734SSukumar Swaminathan 
399982527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
400082527734SSukumar Swaminathan 	}
400182527734SSukumar Swaminathan 	/* Initalize iocbq */
400282527734SSukumar Swaminathan 	iocbq->port = (void *) port;
400382527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
400482527734SSukumar Swaminathan 
400582527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
400682527734SSukumar Swaminathan 		/* Unregister the packet */
400782527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
400882527734SSukumar Swaminathan 
400982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
401082527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
401182527734SSukumar Swaminathan 
401282527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
401382527734SSukumar Swaminathan 	}
401482527734SSukumar Swaminathan 	/* Point of no return */
401582527734SSukumar Swaminathan 
401682527734SSukumar Swaminathan 	/* Initalize iocb */
401782527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
401882527734SSukumar Swaminathan 		/* ELS Response */
401982527734SSukumar Swaminathan 		iocb->ULPCONTEXT = (volatile uint16_t) pkt->pkt_cmd_fhdr.rx_id;
402082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX;
402182527734SSukumar Swaminathan 	} else {
402282527734SSukumar Swaminathan 		/* ELS Request */
402382527734SSukumar Swaminathan 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
402482527734SSukumar Swaminathan 		iocb->ULPCONTEXT =
402582527734SSukumar Swaminathan 		    (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0;
402682527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR;
402782527734SSukumar Swaminathan 
4028a9800bebSGarrett D'Amore 		if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
4029a9800bebSGarrett D'Amore 			if (hba->topology != TOPOLOGY_LOOP) {
4030a9800bebSGarrett D'Amore 				cmd = *((uint32_t *)pkt->pkt_cmd);
4031a9800bebSGarrett D'Amore 				cmd &= ELS_CMD_MASK;
403282527734SSukumar Swaminathan 
4033a9800bebSGarrett D'Amore 				if ((cmd == ELS_CMD_FLOGI) ||
4034a9800bebSGarrett D'Amore 				    (cmd == ELS_CMD_FDISC)) {
4035a9800bebSGarrett D'Amore 					iocb->ULPCT = 0x2;
4036a9800bebSGarrett D'Amore 				} else {
4037a9800bebSGarrett D'Amore 					iocb->ULPCT = 0x1;
4038a9800bebSGarrett D'Amore 				}
403982527734SSukumar Swaminathan 			}
4040a9800bebSGarrett D'Amore 			iocb->ULPCONTEXT = port->vpi;
404182527734SSukumar Swaminathan 		}
404282527734SSukumar Swaminathan 	}
404382527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
404482527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
404582527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
404682527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
404782527734SSukumar Swaminathan 
404882527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
404982527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
405082527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
405182527734SSukumar Swaminathan 		break;
405282527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
405382527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
405482527734SSukumar Swaminathan 		break;
405582527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
405682527734SSukumar Swaminathan 	default:
405782527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
405882527734SSukumar Swaminathan 		break;
405982527734SSukumar Swaminathan 	}
406082527734SSukumar Swaminathan 	sbp->class = iocb->ULPCLASS;
406182527734SSukumar Swaminathan 
406282527734SSukumar Swaminathan 	return (FC_SUCCESS);
406382527734SSukumar Swaminathan 
406482527734SSukumar Swaminathan } /* emlxs_sli3_prep_els_iocb() */
406582527734SSukumar Swaminathan 
406682527734SSukumar Swaminathan 
406782527734SSukumar Swaminathan static uint32_t
406882527734SSukumar Swaminathan emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
406982527734SSukumar Swaminathan {
407082527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
407182527734SSukumar Swaminathan 	fc_packet_t *pkt;
407282527734SSukumar Swaminathan 	IOCBQ *iocbq;
407382527734SSukumar Swaminathan 	IOCB *iocb;
407482527734SSukumar Swaminathan 	CHANNEL *cp;
407582527734SSukumar Swaminathan 	NODELIST *ndlp;
407682527734SSukumar Swaminathan 	uint16_t iotag;
407782527734SSukumar Swaminathan 	uint32_t did;
407882527734SSukumar Swaminathan 
407982527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
408082527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
408182527734SSukumar Swaminathan 	cp = &hba->chan[FC_CT_RING];
408282527734SSukumar Swaminathan 
408382527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
408482527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
408582527734SSukumar Swaminathan 	ndlp = (NODELIST *)iocbq->node;
408682527734SSukumar Swaminathan 
408782527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
408882527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
408982527734SSukumar Swaminathan 
409082527734SSukumar Swaminathan 	if (!iotag) {
409182527734SSukumar Swaminathan 		/*
409282527734SSukumar Swaminathan 		 * No more command slots available, retry later
409382527734SSukumar Swaminathan 		 */
409482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
409582527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
409682527734SSukumar Swaminathan 
409782527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
409882527734SSukumar Swaminathan 	}
409982527734SSukumar Swaminathan 
410082527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
410182527734SSukumar Swaminathan 		/* Unregister the packet */
410282527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
410382527734SSukumar Swaminathan 
410482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
410582527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
410682527734SSukumar Swaminathan 
410782527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
410882527734SSukumar Swaminathan 	}
410982527734SSukumar Swaminathan 
411082527734SSukumar Swaminathan 	/* Point of no return */
411182527734SSukumar Swaminathan 
411282527734SSukumar Swaminathan 	/* Initalize iocbq */
411382527734SSukumar Swaminathan 	iocbq->port = (void *) port;
411482527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
411582527734SSukumar Swaminathan 
411682527734SSukumar Swaminathan 	/* Fill in rest of iocb */
411782527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Fctl = LA;
411882527734SSukumar Swaminathan 
411982527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
412082527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Fctl |= LSEQ;
412182527734SSukumar Swaminathan 	}
412282527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
412382527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Fctl |= SI;
412482527734SSukumar Swaminathan 	}
412582527734SSukumar Swaminathan 
412682527734SSukumar Swaminathan 	/* Initalize iocb */
412782527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
412882527734SSukumar Swaminathan 		/* CT Response */
412982527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
413082527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
413182527734SSukumar Swaminathan 		iocb->ULPCONTEXT  = pkt->pkt_cmd_fhdr.rx_id;
413282527734SSukumar Swaminathan 	} else {
413382527734SSukumar Swaminathan 		/* CT Request */
413482527734SSukumar Swaminathan 		iocb->ULPCOMMAND  = CMD_GEN_REQUEST64_CR;
413582527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Dfctl = 0;
413682527734SSukumar Swaminathan 		iocb->ULPCONTEXT  = ndlp->nlp_Rpi;
413782527734SSukumar Swaminathan 	}
413882527734SSukumar Swaminathan 
413982527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
414082527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
414182527734SSukumar Swaminathan 
414282527734SSukumar Swaminathan 	iocb->ULPIOTAG    = iotag;
414382527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
414482527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
414582527734SSukumar Swaminathan 	iocb->ULPOWNER    = OWN_CHIP;
414682527734SSukumar Swaminathan 
414782527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
414882527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
414982527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
415082527734SSukumar Swaminathan 		break;
415182527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
415282527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
415382527734SSukumar Swaminathan 		break;
415482527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
415582527734SSukumar Swaminathan 	default:
415682527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
415782527734SSukumar Swaminathan 		break;
415882527734SSukumar Swaminathan 	}
415982527734SSukumar Swaminathan 
416082527734SSukumar Swaminathan 	return (FC_SUCCESS);
416182527734SSukumar Swaminathan 
416282527734SSukumar Swaminathan } /* emlxs_sli3_prep_ct_iocb() */
416382527734SSukumar Swaminathan 
416482527734SSukumar Swaminathan 
4165291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
416682527734SSukumar Swaminathan static uint32_t
416782527734SSukumar Swaminathan emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
416882527734SSukumar Swaminathan {
416982527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
417082527734SSukumar Swaminathan 	uint32_t rval;
417182527734SSukumar Swaminathan 
4172*8f23e9faSHans Rosenfeld 	if (sbp->fct_buf->db_sglist_length != 1) {
417382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4174*8f23e9faSHans Rosenfeld 		    "fct_bde_setup: Only 1 sglist entry supported: %d",
4175*8f23e9faSHans Rosenfeld 		    sbp->fct_buf->db_sglist_length);
417682527734SSukumar Swaminathan 		return (1);
417782527734SSukumar Swaminathan 	}
417882527734SSukumar Swaminathan 
4179*8f23e9faSHans Rosenfeld 	if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) {
418082527734SSukumar Swaminathan 		rval = emlxs_sli2_fct_bde_setup(port, sbp);
418182527734SSukumar Swaminathan 	} else {
418282527734SSukumar Swaminathan 		rval = emlxs_sli3_fct_bde_setup(port, sbp);
418382527734SSukumar Swaminathan 	}
418482527734SSukumar Swaminathan 
418582527734SSukumar Swaminathan 	return (rval);
418682527734SSukumar Swaminathan 
418782527734SSukumar Swaminathan } /* emlxs_fct_bde_setup() */
4188291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4189291a2b48SSukumar Swaminathan 
4190*8f23e9faSHans Rosenfeld 
419182527734SSukumar Swaminathan static uint32_t
419282527734SSukumar Swaminathan emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
419382527734SSukumar Swaminathan {
419482527734SSukumar Swaminathan 	uint32_t	rval;
419582527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
419682527734SSukumar Swaminathan 
4197a9800bebSGarrett D'Amore 	if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) {
419882527734SSukumar Swaminathan 		rval = emlxs_sli2_bde_setup(port, sbp);
419982527734SSukumar Swaminathan 	} else {
420082527734SSukumar Swaminathan 		rval = emlxs_sli3_bde_setup(port, sbp);
420182527734SSukumar Swaminathan 	}
420282527734SSukumar Swaminathan 
420382527734SSukumar Swaminathan 	return (rval);
420482527734SSukumar Swaminathan 
420582527734SSukumar Swaminathan } /* emlxs_bde_setup() */
420682527734SSukumar Swaminathan 
420782527734SSukumar Swaminathan 
420882527734SSukumar Swaminathan static void
4209*8f23e9faSHans Rosenfeld emlxs_sli3_poll_intr(emlxs_hba_t *hba)
421082527734SSukumar Swaminathan {
421182527734SSukumar Swaminathan 	uint32_t ha_copy;
421282527734SSukumar Swaminathan 
4213*8f23e9faSHans Rosenfeld 	/* Check attention bits once and process if required */
421482527734SSukumar Swaminathan 
4215*8f23e9faSHans Rosenfeld 	ha_copy = emlxs_check_attention(hba);
421682527734SSukumar Swaminathan 
4217*8f23e9faSHans Rosenfeld 	if (ha_copy == 0) {
4218*8f23e9faSHans Rosenfeld 		return;
421982527734SSukumar Swaminathan 	}
422082527734SSukumar Swaminathan 
422182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
422282527734SSukumar Swaminathan 	ha_copy = emlxs_get_attention(hba, -1);
422382527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
422482527734SSukumar Swaminathan 
422582527734SSukumar Swaminathan 	emlxs_proc_attention(hba, ha_copy);
422682527734SSukumar Swaminathan 
422782527734SSukumar Swaminathan 	return;
422882527734SSukumar Swaminathan 
422982527734SSukumar Swaminathan } /* emlxs_sli3_poll_intr() */
423082527734SSukumar Swaminathan 
4231*8f23e9faSHans Rosenfeld 
423282527734SSukumar Swaminathan #ifdef MSI_SUPPORT
423382527734SSukumar Swaminathan static uint32_t
423482527734SSukumar Swaminathan emlxs_sli3_msi_intr(char *arg1, char *arg2)
423582527734SSukumar Swaminathan {
423682527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
423782527734SSukumar Swaminathan #ifdef FMA_SUPPORT
423882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
423982527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
424082527734SSukumar Swaminathan 	uint16_t msgid;
424182527734SSukumar Swaminathan 	uint32_t hc_copy;
424282527734SSukumar Swaminathan 	uint32_t ha_copy;
424382527734SSukumar Swaminathan 	uint32_t restore = 0;
4244291a2b48SSukumar Swaminathan 
424582527734SSukumar Swaminathan 	/*
424682527734SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
4247*8f23e9faSHans Rosenfeld 	 * "sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2);
424882527734SSukumar Swaminathan 	 */
4249291a2b48SSukumar Swaminathan 
425082527734SSukumar Swaminathan 	/* Check for legacy interrupt handling */
425182527734SSukumar Swaminathan 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
425282527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
4253291a2b48SSukumar Swaminathan 
425482527734SSukumar Swaminathan 		if (hba->flag & FC_OFFLINE_MODE) {
425582527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
4256291a2b48SSukumar Swaminathan 
425782527734SSukumar Swaminathan 			if (hba->bus_type == SBUS_FC) {
425882527734SSukumar Swaminathan 				return (DDI_INTR_CLAIMED);
425982527734SSukumar Swaminathan 			} else {
426082527734SSukumar Swaminathan 				return (DDI_INTR_UNCLAIMED);
426182527734SSukumar Swaminathan 			}
4262291a2b48SSukumar Swaminathan 		}
4263291a2b48SSukumar Swaminathan 
426482527734SSukumar Swaminathan 		/* Get host attention bits */
426582527734SSukumar Swaminathan 		ha_copy = emlxs_get_attention(hba, -1);
4266291a2b48SSukumar Swaminathan 
426782527734SSukumar Swaminathan 		if (ha_copy == 0) {
426882527734SSukumar Swaminathan 			if (hba->intr_unclaimed) {
426982527734SSukumar Swaminathan 				mutex_exit(&EMLXS_PORT_LOCK);
427082527734SSukumar Swaminathan 				return (DDI_INTR_UNCLAIMED);
427182527734SSukumar Swaminathan 			}
4272291a2b48SSukumar Swaminathan 
427382527734SSukumar Swaminathan 			hba->intr_unclaimed = 1;
427482527734SSukumar Swaminathan 		} else {
427582527734SSukumar Swaminathan 			hba->intr_unclaimed = 0;
4276291a2b48SSukumar Swaminathan 		}
4277291a2b48SSukumar Swaminathan 
427882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4279291a2b48SSukumar Swaminathan 
428082527734SSukumar Swaminathan 		/* Process the interrupt */
428182527734SSukumar Swaminathan 		emlxs_proc_attention(hba, ha_copy);
4282291a2b48SSukumar Swaminathan 
428382527734SSukumar Swaminathan 		return (DDI_INTR_CLAIMED);
428482527734SSukumar Swaminathan 	}
4285291a2b48SSukumar Swaminathan 
428682527734SSukumar Swaminathan 	/* DDI_INTR_TYPE_MSI  */
428782527734SSukumar Swaminathan 	/* DDI_INTR_TYPE_MSIX */
4288291a2b48SSukumar Swaminathan 
428982527734SSukumar Swaminathan 	/* Get MSI message id */
429082527734SSukumar Swaminathan 	msgid = (uint16_t)((unsigned long)arg2);
4291291a2b48SSukumar Swaminathan 
429282527734SSukumar Swaminathan 	/* Validate the message id */
429382527734SSukumar Swaminathan 	if (msgid >= hba->intr_count) {
429482527734SSukumar Swaminathan 		msgid = 0;
429582527734SSukumar Swaminathan 	}
4296291a2b48SSukumar Swaminathan 
429782527734SSukumar Swaminathan 	mutex_enter(&EMLXS_INTR_LOCK(msgid));
4298291a2b48SSukumar Swaminathan 
429982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
430082527734SSukumar Swaminathan 
430182527734SSukumar Swaminathan 	/* Check if adapter is offline */
430282527734SSukumar Swaminathan 	if (hba->flag & FC_OFFLINE_MODE) {
430382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
430482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_INTR_LOCK(msgid));
430582527734SSukumar Swaminathan 
430682527734SSukumar Swaminathan 		/* Always claim an MSI interrupt */
430782527734SSukumar Swaminathan 		return (DDI_INTR_CLAIMED);
430882527734SSukumar Swaminathan 	}
430982527734SSukumar Swaminathan 
431082527734SSukumar Swaminathan 	/* Disable interrupts associated with this msgid */
431182527734SSukumar Swaminathan 	if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) {
431282527734SSukumar Swaminathan 		hc_copy = hba->sli.sli3.hc_copy & ~hba->intr_mask;
431382527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hc_copy);
431482527734SSukumar Swaminathan 		restore = 1;
431582527734SSukumar Swaminathan 	}
431682527734SSukumar Swaminathan 
431782527734SSukumar Swaminathan 	/* Get host attention bits */
431882527734SSukumar Swaminathan 	ha_copy = emlxs_get_attention(hba, msgid);
431982527734SSukumar Swaminathan 
432082527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
432182527734SSukumar Swaminathan 
432282527734SSukumar Swaminathan 	/* Process the interrupt */
432382527734SSukumar Swaminathan 	emlxs_proc_attention(hba, ha_copy);
432482527734SSukumar Swaminathan 
432582527734SSukumar Swaminathan 	/* Restore interrupts */
432682527734SSukumar Swaminathan 	if (restore) {
432782527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
432882527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
432982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
433082527734SSukumar Swaminathan 		/* Access handle validation */
433182527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
433282527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
433382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
433482527734SSukumar Swaminathan 	}
433582527734SSukumar Swaminathan 
433682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_INTR_LOCK(msgid));
433782527734SSukumar Swaminathan 
433882527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
433982527734SSukumar Swaminathan 
434082527734SSukumar Swaminathan } /* emlxs_sli3_msi_intr() */
434182527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
434282527734SSukumar Swaminathan 
434382527734SSukumar Swaminathan 
434482527734SSukumar Swaminathan static int
434582527734SSukumar Swaminathan emlxs_sli3_intx_intr(char *arg)
434682527734SSukumar Swaminathan {
434782527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
434882527734SSukumar Swaminathan 	uint32_t ha_copy = 0;
434982527734SSukumar Swaminathan 
435082527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
435182527734SSukumar Swaminathan 
435282527734SSukumar Swaminathan 	if (hba->flag & FC_OFFLINE_MODE) {
435382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
435482527734SSukumar Swaminathan 
435582527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
435682527734SSukumar Swaminathan 			return (DDI_INTR_CLAIMED);
435782527734SSukumar Swaminathan 		} else {
435882527734SSukumar Swaminathan 			return (DDI_INTR_UNCLAIMED);
4359291a2b48SSukumar Swaminathan 		}
436082527734SSukumar Swaminathan 	}
4361291a2b48SSukumar Swaminathan 
436282527734SSukumar Swaminathan 	/* Get host attention bits */
436382527734SSukumar Swaminathan 	ha_copy = emlxs_get_attention(hba, -1);
4364291a2b48SSukumar Swaminathan 
436582527734SSukumar Swaminathan 	if (ha_copy == 0) {
436682527734SSukumar Swaminathan 		if (hba->intr_unclaimed) {
436782527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
436882527734SSukumar Swaminathan 			return (DDI_INTR_UNCLAIMED);
4369291a2b48SSukumar Swaminathan 		}
4370291a2b48SSukumar Swaminathan 
437182527734SSukumar Swaminathan 		hba->intr_unclaimed = 1;
437282527734SSukumar Swaminathan 	} else {
437382527734SSukumar Swaminathan 		hba->intr_unclaimed = 0;
437482527734SSukumar Swaminathan 	}
437582527734SSukumar Swaminathan 
437682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
437782527734SSukumar Swaminathan 
437882527734SSukumar Swaminathan 	/* Process the interrupt */
437982527734SSukumar Swaminathan 	emlxs_proc_attention(hba, ha_copy);
438082527734SSukumar Swaminathan 
438182527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
438282527734SSukumar Swaminathan 
438382527734SSukumar Swaminathan } /* emlxs_sli3_intx_intr() */
438482527734SSukumar Swaminathan 
438582527734SSukumar Swaminathan 
438682527734SSukumar Swaminathan /* EMLXS_PORT_LOCK must be held when call this routine */
438782527734SSukumar Swaminathan static uint32_t
4388a9800bebSGarrett D'Amore emlxs_get_attention(emlxs_hba_t *hba, int32_t msgid)
438982527734SSukumar Swaminathan {
439082527734SSukumar Swaminathan #ifdef FMA_SUPPORT
439182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
439282527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
439382527734SSukumar Swaminathan 	uint32_t ha_copy = 0;
439482527734SSukumar Swaminathan 	uint32_t ha_copy2;
439582527734SSukumar Swaminathan 	uint32_t mask = hba->sli.sli3.hc_copy;
439682527734SSukumar Swaminathan 
439782527734SSukumar Swaminathan #ifdef MSI_SUPPORT
439882527734SSukumar Swaminathan 
439982527734SSukumar Swaminathan read_ha_register:
440082527734SSukumar Swaminathan 
440182527734SSukumar Swaminathan 	/* Check for default MSI interrupt */
440282527734SSukumar Swaminathan 	if (msgid == 0) {
440382527734SSukumar Swaminathan 		/* Read host attention register to determine interrupt source */
440482527734SSukumar Swaminathan 		ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
440582527734SSukumar Swaminathan 
440682527734SSukumar Swaminathan 		/* Filter out MSI non-default attention bits */
440782527734SSukumar Swaminathan 		ha_copy2 &= ~(hba->intr_cond);
440882527734SSukumar Swaminathan 	}
440982527734SSukumar Swaminathan 
441082527734SSukumar Swaminathan 	/* Check for polled or fixed type interrupt */
441182527734SSukumar Swaminathan 	else if (msgid == -1) {
441282527734SSukumar Swaminathan 		/* Read host attention register to determine interrupt source */
441382527734SSukumar Swaminathan 		ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
441482527734SSukumar Swaminathan 	}
441582527734SSukumar Swaminathan 
441682527734SSukumar Swaminathan 	/* Otherwise, assume a mapped MSI interrupt */
441782527734SSukumar Swaminathan 	else {
441882527734SSukumar Swaminathan 		/* Convert MSI msgid to mapped attention bits */
441982527734SSukumar Swaminathan 		ha_copy2 = hba->intr_map[msgid];
442082527734SSukumar Swaminathan 	}
442182527734SSukumar Swaminathan 
442282527734SSukumar Swaminathan #else /* !MSI_SUPPORT */
442382527734SSukumar Swaminathan 
442482527734SSukumar Swaminathan 	/* Read host attention register to determine interrupt source */
442582527734SSukumar Swaminathan 	ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
442682527734SSukumar Swaminathan 
442782527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
442882527734SSukumar Swaminathan 
442982527734SSukumar Swaminathan 	/* Check if Hardware error interrupt is enabled */
443082527734SSukumar Swaminathan 	if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) {
443182527734SSukumar Swaminathan 		ha_copy2 &= ~HA_ERATT;
443282527734SSukumar Swaminathan 	}
443382527734SSukumar Swaminathan 
443482527734SSukumar Swaminathan 	/* Check if link interrupt is enabled */
443582527734SSukumar Swaminathan 	if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) {
443682527734SSukumar Swaminathan 		ha_copy2 &= ~HA_LATT;
443782527734SSukumar Swaminathan 	}
443882527734SSukumar Swaminathan 
443982527734SSukumar Swaminathan 	/* Check if Mailbox interrupt is enabled */
444082527734SSukumar Swaminathan 	if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) {
444182527734SSukumar Swaminathan 		ha_copy2 &= ~HA_MBATT;
444282527734SSukumar Swaminathan 	}
444382527734SSukumar Swaminathan 
444482527734SSukumar Swaminathan 	/* Check if ring0 interrupt is enabled */
444582527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) {
444682527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R0ATT;
444782527734SSukumar Swaminathan 	}
444882527734SSukumar Swaminathan 
444982527734SSukumar Swaminathan 	/* Check if ring1 interrupt is enabled */
445082527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) {
445182527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R1ATT;
445282527734SSukumar Swaminathan 	}
445382527734SSukumar Swaminathan 
445482527734SSukumar Swaminathan 	/* Check if ring2 interrupt is enabled */
445582527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) {
445682527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R2ATT;
445782527734SSukumar Swaminathan 	}
445882527734SSukumar Swaminathan 
445982527734SSukumar Swaminathan 	/* Check if ring3 interrupt is enabled */
446082527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) {
446182527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R3ATT;
446282527734SSukumar Swaminathan 	}
4463291a2b48SSukumar Swaminathan 
446482527734SSukumar Swaminathan 	/* Accumulate attention bits */
446582527734SSukumar Swaminathan 	ha_copy |= ha_copy2;
4466291a2b48SSukumar Swaminathan 
446782527734SSukumar Swaminathan 	/* Clear attentions except for error, link, and autoclear(MSIX) */
446882527734SSukumar Swaminathan 	ha_copy2 &= ~(HA_ERATT | HA_LATT);	/* | hba->intr_autoClear */
4469291a2b48SSukumar Swaminathan 
447082527734SSukumar Swaminathan 	if (ha_copy2) {
447182527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HA_REG(hba), ha_copy2);
447282527734SSukumar Swaminathan 	}
4473291a2b48SSukumar Swaminathan 
44744baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
447582527734SSukumar Swaminathan 	/* Access handle validation */
447682527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
44774baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4478291a2b48SSukumar Swaminathan 
447982527734SSukumar Swaminathan 	return (ha_copy);
4480291a2b48SSukumar Swaminathan 
448182527734SSukumar Swaminathan } /* emlxs_get_attention() */
4482291a2b48SSukumar Swaminathan 
4483291a2b48SSukumar Swaminathan 
448482527734SSukumar Swaminathan static void
448582527734SSukumar Swaminathan emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy)
448682527734SSukumar Swaminathan {
44874baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
448882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
44894baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
44904baa2c25SSukumar Swaminathan 
449182527734SSukumar Swaminathan 	/* ha_copy should be pre-filtered */
4492291a2b48SSukumar Swaminathan 
449382527734SSukumar Swaminathan 	/*
449482527734SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4495*8f23e9faSHans Rosenfeld 	 * "proc_attention: ha_copy=%x", ha_copy);
449682527734SSukumar Swaminathan 	 */
4497291a2b48SSukumar Swaminathan 
449882527734SSukumar Swaminathan 	if (hba->state < FC_WARM_START) {
449982527734SSukumar Swaminathan 		return;
4500291a2b48SSukumar Swaminathan 	}
4501291a2b48SSukumar Swaminathan 
450282527734SSukumar Swaminathan 	if (!ha_copy) {
450382527734SSukumar Swaminathan 		return;
450482527734SSukumar Swaminathan 	}
4505291a2b48SSukumar Swaminathan 
450682527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
450782527734SSukumar Swaminathan 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
450882527734SSukumar Swaminathan 	}
4509291a2b48SSukumar Swaminathan 
451082527734SSukumar Swaminathan 	/* Adapter error */
451182527734SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
451282527734SSukumar Swaminathan 		HBASTATS.IntrEvent[6]++;
451382527734SSukumar Swaminathan 		emlxs_handle_ff_error(hba);
451482527734SSukumar Swaminathan 		return;
451582527734SSukumar Swaminathan 	}
4516291a2b48SSukumar Swaminathan 
451782527734SSukumar Swaminathan 	/* Mailbox interrupt */
451882527734SSukumar Swaminathan 	if (ha_copy & HA_MBATT) {
451982527734SSukumar Swaminathan 		HBASTATS.IntrEvent[5]++;
452082527734SSukumar Swaminathan 		(void) emlxs_handle_mb_event(hba);
452182527734SSukumar Swaminathan 	}
4522291a2b48SSukumar Swaminathan 
452382527734SSukumar Swaminathan 	/* Link Attention interrupt */
452482527734SSukumar Swaminathan 	if (ha_copy & HA_LATT) {
452582527734SSukumar Swaminathan 		HBASTATS.IntrEvent[4]++;
452682527734SSukumar Swaminathan 		emlxs_sli3_handle_link_event(hba);
452782527734SSukumar Swaminathan 	}
4528291a2b48SSukumar Swaminathan 
452982527734SSukumar Swaminathan 	/* event on ring 0 - FCP Ring */
453082527734SSukumar Swaminathan 	if (ha_copy & HA_R0ATT) {
453182527734SSukumar Swaminathan 		HBASTATS.IntrEvent[0]++;
453282527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 0, ha_copy);
453382527734SSukumar Swaminathan 	}
4534291a2b48SSukumar Swaminathan 
453582527734SSukumar Swaminathan 	/* event on ring 1 - IP Ring */
453682527734SSukumar Swaminathan 	if (ha_copy & HA_R1ATT) {
453782527734SSukumar Swaminathan 		HBASTATS.IntrEvent[1]++;
453882527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 1, ha_copy);
453982527734SSukumar Swaminathan 	}
4540291a2b48SSukumar Swaminathan 
454182527734SSukumar Swaminathan 	/* event on ring 2 - ELS Ring */
454282527734SSukumar Swaminathan 	if (ha_copy & HA_R2ATT) {
454382527734SSukumar Swaminathan 		HBASTATS.IntrEvent[2]++;
454482527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 2, ha_copy);
454582527734SSukumar Swaminathan 	}
4546291a2b48SSukumar Swaminathan 
454782527734SSukumar Swaminathan 	/* event on ring 3 - CT Ring */
454882527734SSukumar Swaminathan 	if (ha_copy & HA_R3ATT) {
454982527734SSukumar Swaminathan 		HBASTATS.IntrEvent[3]++;
455082527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 3, ha_copy);
455182527734SSukumar Swaminathan 	}
4552291a2b48SSukumar Swaminathan 
455382527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
455482527734SSukumar Swaminathan 		WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), SBUS_STAT_IP);
4555291a2b48SSukumar Swaminathan 	}
4556291a2b48SSukumar Swaminathan 
455782527734SSukumar Swaminathan 	/* Set heartbeat flag to show activity */
455882527734SSukumar Swaminathan 	hba->heartbeat_flag = 1;
4559291a2b48SSukumar Swaminathan 
456082527734SSukumar Swaminathan #ifdef FMA_SUPPORT
456182527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
456282527734SSukumar Swaminathan 		/* Access handle validation */
456382527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle);
4564291a2b48SSukumar Swaminathan 	}
456582527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4566291a2b48SSukumar Swaminathan 
456782527734SSukumar Swaminathan 	return;
4568291a2b48SSukumar Swaminathan 
456982527734SSukumar Swaminathan } /* emlxs_proc_attention() */
4570291a2b48SSukumar Swaminathan 
4571291a2b48SSukumar Swaminathan 
457282527734SSukumar Swaminathan /*
457382527734SSukumar Swaminathan  * emlxs_handle_ff_error()
457482527734SSukumar Swaminathan  *
457582527734SSukumar Swaminathan  *    Description: Processes a FireFly error
457682527734SSukumar Swaminathan  *    Runs at Interrupt level
457782527734SSukumar Swaminathan  */
457882527734SSukumar Swaminathan static void
457982527734SSukumar Swaminathan emlxs_handle_ff_error(emlxs_hba_t *hba)
458082527734SSukumar Swaminathan {
458182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
458282527734SSukumar Swaminathan 	uint32_t status;
458382527734SSukumar Swaminathan 	uint32_t status1;
458482527734SSukumar Swaminathan 	uint32_t status2;
458582527734SSukumar Swaminathan 	int i = 0;
4586291a2b48SSukumar Swaminathan 
458782527734SSukumar Swaminathan 	/* do what needs to be done, get error from STATUS REGISTER */
458882527734SSukumar Swaminathan 	status = READ_CSR_REG(hba, FC_HS_REG(hba));
4589291a2b48SSukumar Swaminathan 
459082527734SSukumar Swaminathan 	/* Clear Chip error bit */
459182527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_ERATT);
4592291a2b48SSukumar Swaminathan 
459382527734SSukumar Swaminathan 	/* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */
459482527734SSukumar Swaminathan 	if (status & HS_FFER1) {
459582527734SSukumar Swaminathan 
459682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
459782527734SSukumar Swaminathan 		    "HS_FFER1 received");
459882527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
4599*8f23e9faSHans Rosenfeld 		(void) emlxs_offline(hba, 1);
460082527734SSukumar Swaminathan 		while ((status & HS_FFER1) && (i < 300)) {
460182527734SSukumar Swaminathan 			status =
460282527734SSukumar Swaminathan 			    READ_CSR_REG(hba, FC_HS_REG(hba));
4603*8f23e9faSHans Rosenfeld 			BUSYWAIT_MS(1000);
460482527734SSukumar Swaminathan 			i++;
4605291a2b48SSukumar Swaminathan 		}
460682527734SSukumar Swaminathan 	}
4607291a2b48SSukumar Swaminathan 
460882527734SSukumar Swaminathan 	if (i == 300) {
460982527734SSukumar Swaminathan 		/* 5 minutes is up, shutdown HBA */
461082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
461182527734SSukumar Swaminathan 		    "HS_FFER1 clear timeout");
4612291a2b48SSukumar Swaminathan 
461382527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
461482527734SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
4615291a2b48SSukumar Swaminathan 
461682527734SSukumar Swaminathan 		goto done;
4617291a2b48SSukumar Swaminathan 	}
4618291a2b48SSukumar Swaminathan 
461982527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
462082527734SSukumar Swaminathan 	    "HS_FFER1 cleared");
462182527734SSukumar Swaminathan 
462282527734SSukumar Swaminathan 	if (status & HS_OVERTEMP) {
462382527734SSukumar Swaminathan 		status1 =
462482527734SSukumar Swaminathan 		    READ_SLIM_ADDR(hba,
462582527734SSukumar Swaminathan 		    ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xb0));
462682527734SSukumar Swaminathan 
462782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
462882527734SSukumar Swaminathan 		    "Maximum adapter temperature exceeded (%d �C).", status1);
462982527734SSukumar Swaminathan 
463082527734SSukumar Swaminathan 		hba->temperature = status1;
463182527734SSukumar Swaminathan 		hba->flag |= FC_OVERTEMP_EVENT;
463282527734SSukumar Swaminathan 
463382527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
463482527734SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_shutdown_thread,
463582527734SSukumar Swaminathan 		    NULL, NULL);
463682527734SSukumar Swaminathan 
463782527734SSukumar Swaminathan 	} else {
463882527734SSukumar Swaminathan 		status1 =
463982527734SSukumar Swaminathan 		    READ_SLIM_ADDR(hba,
464082527734SSukumar Swaminathan 		    ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xa8));
464182527734SSukumar Swaminathan 		status2 =
464282527734SSukumar Swaminathan 		    READ_SLIM_ADDR(hba,
464382527734SSukumar Swaminathan 		    ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xac));
464482527734SSukumar Swaminathan 
464582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
464682527734SSukumar Swaminathan 		    "Host Error Attention: "
464782527734SSukumar Swaminathan 		    "status=0x%x status1=0x%x status2=0x%x",
464882527734SSukumar Swaminathan 		    status, status1, status2);
464982527734SSukumar Swaminathan 
465082527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
4651291a2b48SSukumar Swaminathan 
465282527734SSukumar Swaminathan 		if (status & HS_FFER6) {
465382527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_restart_thread,
465482527734SSukumar Swaminathan 			    NULL, NULL);
465582527734SSukumar Swaminathan 		} else {
465682527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_shutdown_thread,
465782527734SSukumar Swaminathan 			    NULL, NULL);
4658291a2b48SSukumar Swaminathan 		}
4659291a2b48SSukumar Swaminathan 	}
4660291a2b48SSukumar Swaminathan 
466182527734SSukumar Swaminathan done:
466282527734SSukumar Swaminathan #ifdef FMA_SUPPORT
466382527734SSukumar Swaminathan 	/* Access handle validation */
466482527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
466582527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
466682527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4667291a2b48SSukumar Swaminathan 
466882527734SSukumar Swaminathan 	return;
4669291a2b48SSukumar Swaminathan 
467082527734SSukumar Swaminathan } /* emlxs_handle_ff_error() */
4671291a2b48SSukumar Swaminathan 
4672291a2b48SSukumar Swaminathan 
467382527734SSukumar Swaminathan /*
467482527734SSukumar Swaminathan  *  emlxs_sli3_handle_link_event()
467582527734SSukumar Swaminathan  *
467682527734SSukumar Swaminathan  *    Description: Process a Link Attention.
467782527734SSukumar Swaminathan  */
467882527734SSukumar Swaminathan static void
467982527734SSukumar Swaminathan emlxs_sli3_handle_link_event(emlxs_hba_t *hba)
468082527734SSukumar Swaminathan {
468182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
468282527734SSukumar Swaminathan 	MAILBOXQ *mbq;
468382527734SSukumar Swaminathan 	int rc;
4684291a2b48SSukumar Swaminathan 
468582527734SSukumar Swaminathan 	HBASTATS.LinkEvent++;
4686291a2b48SSukumar Swaminathan 
468782527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, "event=%x",
468882527734SSukumar Swaminathan 	    HBASTATS.LinkEvent);
4689291a2b48SSukumar Swaminathan 
469082527734SSukumar Swaminathan 	/* Make sure link is declared down */
469182527734SSukumar Swaminathan 	emlxs_linkdown(hba);
4692291a2b48SSukumar Swaminathan 
469382527734SSukumar Swaminathan 	/* Get a buffer which will be used for mailbox commands */
4694*8f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
469582527734SSukumar Swaminathan 		/* Get link attention message */
469682527734SSukumar Swaminathan 		if (emlxs_mb_read_la(hba, mbq) == 0) {
469782527734SSukumar Swaminathan 			rc =  emlxs_sli3_issue_mbox_cmd(hba, mbq,
469882527734SSukumar Swaminathan 			    MBX_NOWAIT, 0);
469982527734SSukumar Swaminathan 			if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
4700a9800bebSGarrett D'Amore 				emlxs_mem_put(hba, MEM_MBOX,
4701a9800bebSGarrett D'Amore 				    (void *)mbq);
470282527734SSukumar Swaminathan 			}
4703291a2b48SSukumar Swaminathan 
470482527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
4705291a2b48SSukumar Swaminathan 
470682527734SSukumar Swaminathan 			/*
470782527734SSukumar Swaminathan 			 * Clear Link Attention in HA REG
470882527734SSukumar Swaminathan 			 */
470982527734SSukumar Swaminathan 			WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_LATT);
4710291a2b48SSukumar Swaminathan 
471182527734SSukumar Swaminathan #ifdef FMA_SUPPORT
471282527734SSukumar Swaminathan 			/* Access handle validation */
471382527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
471482527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4715291a2b48SSukumar Swaminathan 
471682527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
471782527734SSukumar Swaminathan 		} else {
4718a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4719291a2b48SSukumar Swaminathan 		}
4720291a2b48SSukumar Swaminathan 	}
4721291a2b48SSukumar Swaminathan 
472282527734SSukumar Swaminathan } /* emlxs_sli3_handle_link_event()  */
4723291a2b48SSukumar Swaminathan 
4724291a2b48SSukumar Swaminathan 
472582527734SSukumar Swaminathan /*
472682527734SSukumar Swaminathan  *  emlxs_sli3_handle_ring_event()
472782527734SSukumar Swaminathan  *
472882527734SSukumar Swaminathan  *    Description: Process a Ring Attention.
472982527734SSukumar Swaminathan  */
4730291a2b48SSukumar Swaminathan static void
473182527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
473282527734SSukumar Swaminathan     uint32_t ha_copy)
4733291a2b48SSukumar Swaminathan {
473482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
473582527734SSukumar Swaminathan 	SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
473682527734SSukumar Swaminathan 	CHANNEL *cp;
473782527734SSukumar Swaminathan 	RING *rp;
473882527734SSukumar Swaminathan 	IOCB *entry;
473982527734SSukumar Swaminathan 	IOCBQ *iocbq;
474082527734SSukumar Swaminathan 	IOCBQ local_iocbq;
474182527734SSukumar Swaminathan 	PGP *pgp;
474282527734SSukumar Swaminathan 	uint32_t count;
474382527734SSukumar Swaminathan 	volatile uint32_t chipatt;
474482527734SSukumar Swaminathan 	void *ioa2;
474582527734SSukumar Swaminathan 	uint32_t reg;
474682527734SSukumar Swaminathan 	uint32_t channel_no;
4747291a2b48SSukumar Swaminathan 	off_t offset;
474882527734SSukumar Swaminathan 	IOCBQ *rsp_head = NULL;
474982527734SSukumar Swaminathan 	IOCBQ *rsp_tail = NULL;
475082527734SSukumar Swaminathan 	emlxs_buf_t *sbp = NULL;
4751291a2b48SSukumar Swaminathan 
475282527734SSukumar Swaminathan 	count = 0;
475382527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[ring_no];
475482527734SSukumar Swaminathan 	cp = rp->channelp;
475582527734SSukumar Swaminathan 	channel_no = cp->channelno;
4756291a2b48SSukumar Swaminathan 
475782527734SSukumar Swaminathan 	/*
475882527734SSukumar Swaminathan 	 * Isolate this ring's host attention bits
475982527734SSukumar Swaminathan 	 * This makes all ring attention bits equal
476082527734SSukumar Swaminathan 	 * to Ring0 attention bits
476182527734SSukumar Swaminathan 	 */
476282527734SSukumar Swaminathan 	reg = (ha_copy >> (ring_no * 4)) & 0x0f;
4763291a2b48SSukumar Swaminathan 
476482527734SSukumar Swaminathan 	/*
476582527734SSukumar Swaminathan 	 * Gather iocb entries off response ring.
476682527734SSukumar Swaminathan 	 * Ensure entry is owned by the host.
476782527734SSukumar Swaminathan 	 */
476882527734SSukumar Swaminathan 	pgp = (PGP *)&slim2p->mbx.us.s2.port[ring_no];
476982527734SSukumar Swaminathan 	offset =
477082527734SSukumar Swaminathan 	    (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) -
477182527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)slim2p));
477282527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
477382527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
477482527734SSukumar Swaminathan 	rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx);
4775291a2b48SSukumar Swaminathan 
477682527734SSukumar Swaminathan 	/* While ring is not empty */
477782527734SSukumar Swaminathan 	while (rp->fc_rspidx != rp->fc_port_rspidx) {
477882527734SSukumar Swaminathan 		HBASTATS.IocbReceived[channel_no]++;
4779291a2b48SSukumar Swaminathan 
478082527734SSukumar Swaminathan 		/* Get the next response ring iocb */
478182527734SSukumar Swaminathan 		entry =
478282527734SSukumar Swaminathan 		    (IOCB *)(((char *)rp->fc_rspringaddr +
478382527734SSukumar Swaminathan 		    (rp->fc_rspidx * hba->sli.sli3.iocb_rsp_size)));
4784291a2b48SSukumar Swaminathan 
478582527734SSukumar Swaminathan 		/* DMA sync the response ring iocb for the adapter */
478682527734SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)entry)
478782527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)slim2p));
478882527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
478982527734SSukumar Swaminathan 		    hba->sli.sli3.iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL);
4790291a2b48SSukumar Swaminathan 
479182527734SSukumar Swaminathan 		count++;
4792291a2b48SSukumar Swaminathan 
479382527734SSukumar Swaminathan 		/* Copy word6 and word7 to local iocb for now */
479482527734SSukumar Swaminathan 		iocbq = &local_iocbq;
4795291a2b48SSukumar Swaminathan 
479682527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)entry + (sizeof (uint32_t) * 6),
479782527734SSukumar Swaminathan 		    (uint8_t *)iocbq + (sizeof (uint32_t) * 6),
479882527734SSukumar Swaminathan 		    (sizeof (uint32_t) * 2));
4799291a2b48SSukumar Swaminathan 
480082527734SSukumar Swaminathan 		/* when LE is not set, entire Command has not been received */
480182527734SSukumar Swaminathan 		if (!iocbq->iocb.ULPLE) {
480282527734SSukumar Swaminathan 			/* This should never happen */
480382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg,
480482527734SSukumar Swaminathan 			    "ulpLE is not set. "
4805*8f23e9faSHans Rosenfeld 			    "ring=%d iotag=%d cmd=%x status=%x",
480682527734SSukumar Swaminathan 			    channel_no, iocbq->iocb.ULPIOTAG,
480782527734SSukumar Swaminathan 			    iocbq->iocb.ULPCOMMAND, iocbq->iocb.ULPSTATUS);
4808291a2b48SSukumar Swaminathan 
480982527734SSukumar Swaminathan 			goto next;
4810291a2b48SSukumar Swaminathan 		}
4811291a2b48SSukumar Swaminathan 
4812*8f23e9faSHans Rosenfeld 		sbp = NULL;
481382527734SSukumar Swaminathan 		switch (iocbq->iocb.ULPCOMMAND) {
481482527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
481582527734SSukumar Swaminathan 		case CMD_CLOSE_XRI_CX:
481682527734SSukumar Swaminathan 		case CMD_CLOSE_XRI_CN:
481782527734SSukumar Swaminathan 		case CMD_ABORT_XRI_CX:
4818*8f23e9faSHans Rosenfeld 			if (port->mode == MODE_TARGET) {
4819*8f23e9faSHans Rosenfeld 				sbp = emlxs_unregister_pkt(cp,
4820*8f23e9faSHans Rosenfeld 				    iocbq->iocb.ULPIOTAG, 0);
482182527734SSukumar Swaminathan 			}
482282527734SSukumar Swaminathan 			break;
482382527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4824291a2b48SSukumar Swaminathan 
482582527734SSukumar Swaminathan 			/* Ring 0 registered commands */
482682527734SSukumar Swaminathan 		case CMD_FCP_ICMND_CR:
482782527734SSukumar Swaminathan 		case CMD_FCP_ICMND_CX:
482882527734SSukumar Swaminathan 		case CMD_FCP_IREAD_CR:
482982527734SSukumar Swaminathan 		case CMD_FCP_IREAD_CX:
483082527734SSukumar Swaminathan 		case CMD_FCP_IWRITE_CR:
483182527734SSukumar Swaminathan 		case CMD_FCP_IWRITE_CX:
483282527734SSukumar Swaminathan 		case CMD_FCP_ICMND64_CR:
483382527734SSukumar Swaminathan 		case CMD_FCP_ICMND64_CX:
483482527734SSukumar Swaminathan 		case CMD_FCP_IREAD64_CR:
483582527734SSukumar Swaminathan 		case CMD_FCP_IREAD64_CX:
483682527734SSukumar Swaminathan 		case CMD_FCP_IWRITE64_CR:
483782527734SSukumar Swaminathan 		case CMD_FCP_IWRITE64_CX:
483882527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
483982527734SSukumar Swaminathan 		case CMD_FCP_TSEND_CX:
484082527734SSukumar Swaminathan 		case CMD_FCP_TSEND64_CX:
484182527734SSukumar Swaminathan 		case CMD_FCP_TRECEIVE_CX:
484282527734SSukumar Swaminathan 		case CMD_FCP_TRECEIVE64_CX:
484382527734SSukumar Swaminathan 		case CMD_FCP_TRSP_CX:
484482527734SSukumar Swaminathan 		case CMD_FCP_TRSP64_CX:
484582527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4846291a2b48SSukumar Swaminathan 
484782527734SSukumar Swaminathan 			/* Ring 1 registered commands */
484882527734SSukumar Swaminathan 		case CMD_XMIT_BCAST_CN:
484982527734SSukumar Swaminathan 		case CMD_XMIT_BCAST_CX:
485082527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE_CX:
485182527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE_CR:
485282527734SSukumar Swaminathan 		case CMD_XMIT_BCAST64_CN:
485382527734SSukumar Swaminathan 		case CMD_XMIT_BCAST64_CX:
485482527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE64_CX:
485582527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE64_CR:
485682527734SSukumar Swaminathan 		case CMD_CREATE_XRI_CR:
485782527734SSukumar Swaminathan 		case CMD_CREATE_XRI_CX:
4858291a2b48SSukumar Swaminathan 
485982527734SSukumar Swaminathan 			/* Ring 2 registered commands */
486082527734SSukumar Swaminathan 		case CMD_ELS_REQUEST_CR:
486182527734SSukumar Swaminathan 		case CMD_ELS_REQUEST_CX:
486282527734SSukumar Swaminathan 		case CMD_XMIT_ELS_RSP_CX:
486382527734SSukumar Swaminathan 		case CMD_ELS_REQUEST64_CR:
486482527734SSukumar Swaminathan 		case CMD_ELS_REQUEST64_CX:
486582527734SSukumar Swaminathan 		case CMD_XMIT_ELS_RSP64_CX:
4866291a2b48SSukumar Swaminathan 
486782527734SSukumar Swaminathan 			/* Ring 3 registered commands */
486882527734SSukumar Swaminathan 		case CMD_GEN_REQUEST64_CR:
486982527734SSukumar Swaminathan 		case CMD_GEN_REQUEST64_CX:
4870291a2b48SSukumar Swaminathan 
487182527734SSukumar Swaminathan 			sbp =
487282527734SSukumar Swaminathan 			    emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0);
487382527734SSukumar Swaminathan 			break;
487482527734SSukumar Swaminathan 		}
4875291a2b48SSukumar Swaminathan 
487682527734SSukumar Swaminathan 		/* If packet is stale, then drop it. */
487782527734SSukumar Swaminathan 		if (sbp == STALE_PACKET) {
487882527734SSukumar Swaminathan 			cp->hbaCmplCmd_sbp++;
487982527734SSukumar Swaminathan 			/* Copy entry to the local iocbq */
488082527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)entry,
488182527734SSukumar Swaminathan 			    (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4882291a2b48SSukumar Swaminathan 
488382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
488482527734SSukumar Swaminathan 			    "channelno=%d iocb=%p cmd=%x status=%x "
4885*8f23e9faSHans Rosenfeld 			    "error=%x iotag=%d context=%x info=%x",
488682527734SSukumar Swaminathan 			    channel_no, iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
488782527734SSukumar Swaminathan 			    iocbq->iocb.ULPSTATUS,
488882527734SSukumar Swaminathan 			    (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
488982527734SSukumar Swaminathan 			    (uint16_t)iocbq->iocb.ULPIOTAG,
489082527734SSukumar Swaminathan 			    (uint16_t)iocbq->iocb.ULPCONTEXT,
489182527734SSukumar Swaminathan 			    (uint8_t)iocbq->iocb.ULPRSVDBYTE);
4892291a2b48SSukumar Swaminathan 
489382527734SSukumar Swaminathan 			goto next;
4894291a2b48SSukumar Swaminathan 		}
4895291a2b48SSukumar Swaminathan 
489682527734SSukumar Swaminathan 		/*
489782527734SSukumar Swaminathan 		 * If a packet was found, then queue the packet's
489882527734SSukumar Swaminathan 		 * iocb for deferred processing
489982527734SSukumar Swaminathan 		 */
490082527734SSukumar Swaminathan 		else if (sbp) {
490182527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
490282527734SSukumar Swaminathan 			fct_cmd_t *fct_cmd;
490382527734SSukumar Swaminathan 			emlxs_buf_t *cmd_sbp;
4904291a2b48SSukumar Swaminathan 
490582527734SSukumar Swaminathan 			fct_cmd = sbp->fct_cmd;
490682527734SSukumar Swaminathan 			if (fct_cmd) {
490782527734SSukumar Swaminathan 				cmd_sbp =
490882527734SSukumar Swaminathan 				    (emlxs_buf_t *)fct_cmd->cmd_fca_private;
490982527734SSukumar Swaminathan 				mutex_enter(&cmd_sbp->fct_mtx);
491082527734SSukumar Swaminathan 				EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
491182527734SSukumar Swaminathan 				    EMLXS_FCT_IOCB_COMPLETE);
491282527734SSukumar Swaminathan 				mutex_exit(&cmd_sbp->fct_mtx);
491382527734SSukumar Swaminathan 			}
491482527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
491582527734SSukumar Swaminathan 			cp->hbaCmplCmd_sbp++;
49161a5e258fSJosef 'Jeff' Sipek 			atomic_dec_32(&hba->io_active);
4917*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
4918*8f23e9faSHans Rosenfeld 			if (sbp->node) {
4919*8f23e9faSHans Rosenfeld 				atomic_dec_32(&sbp->node->io_active);
4920*8f23e9faSHans Rosenfeld 			}
4921*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
4922291a2b48SSukumar Swaminathan 
492382527734SSukumar Swaminathan 			/* Copy entry to sbp's iocbq */
492482527734SSukumar Swaminathan 			iocbq = &sbp->iocbq;
492582527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)entry,
492682527734SSukumar Swaminathan 			    (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4927291a2b48SSukumar Swaminathan 
492882527734SSukumar Swaminathan 			iocbq->next = NULL;
4929291a2b48SSukumar Swaminathan 
493082527734SSukumar Swaminathan 			/*
493182527734SSukumar Swaminathan 			 * If this is NOT a polled command completion
493282527734SSukumar Swaminathan 			 * or a driver allocated pkt, then defer pkt
493382527734SSukumar Swaminathan 			 * completion.
493482527734SSukumar Swaminathan 			 */
493582527734SSukumar Swaminathan 			if (!(sbp->pkt_flags &
493682527734SSukumar Swaminathan 			    (PACKET_POLLED | PACKET_ALLOCATED))) {
493782527734SSukumar Swaminathan 				/* Add the IOCB to the local list */
493882527734SSukumar Swaminathan 				if (!rsp_head) {
493982527734SSukumar Swaminathan 					rsp_head = iocbq;
494082527734SSukumar Swaminathan 				} else {
494182527734SSukumar Swaminathan 					rsp_tail->next = iocbq;
494282527734SSukumar Swaminathan 				}
4943291a2b48SSukumar Swaminathan 
494482527734SSukumar Swaminathan 				rsp_tail = iocbq;
4945291a2b48SSukumar Swaminathan 
494682527734SSukumar Swaminathan 				goto next;
494782527734SSukumar Swaminathan 			}
494882527734SSukumar Swaminathan 		} else {
494982527734SSukumar Swaminathan 			cp->hbaCmplCmd++;
495082527734SSukumar Swaminathan 			/* Copy entry to the local iocbq */
495182527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)entry,
495282527734SSukumar Swaminathan 			    (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4953291a2b48SSukumar Swaminathan 
495482527734SSukumar Swaminathan 			iocbq->next = NULL;
495582527734SSukumar Swaminathan 			iocbq->bp = NULL;
495682527734SSukumar Swaminathan 			iocbq->port = &PPORT;
495782527734SSukumar Swaminathan 			iocbq->channel = cp;
495882527734SSukumar Swaminathan 			iocbq->node = NULL;
495982527734SSukumar Swaminathan 			iocbq->sbp = NULL;
496082527734SSukumar Swaminathan 			iocbq->flag = 0;
496182527734SSukumar Swaminathan 		}
4962291a2b48SSukumar Swaminathan 
496382527734SSukumar Swaminathan 		/* process the channel event now */
496482527734SSukumar Swaminathan 		emlxs_proc_channel_event(hba, cp, iocbq);
4965291a2b48SSukumar Swaminathan 
496682527734SSukumar Swaminathan next:
496782527734SSukumar Swaminathan 		/* Increment the driver's local response get index */
496882527734SSukumar Swaminathan 		if (++rp->fc_rspidx >= rp->fc_numRiocb) {
496982527734SSukumar Swaminathan 			rp->fc_rspidx = 0;
497082527734SSukumar Swaminathan 		}
4971291a2b48SSukumar Swaminathan 
497282527734SSukumar Swaminathan 	}	/* while (TRUE) */
4973291a2b48SSukumar Swaminathan 
497482527734SSukumar Swaminathan 	if (rsp_head) {
497582527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
497682527734SSukumar Swaminathan 		if (cp->rsp_head == NULL) {
497782527734SSukumar Swaminathan 			cp->rsp_head = rsp_head;
497882527734SSukumar Swaminathan 			cp->rsp_tail = rsp_tail;
497982527734SSukumar Swaminathan 		} else {
498082527734SSukumar Swaminathan 			cp->rsp_tail->next = rsp_head;
498182527734SSukumar Swaminathan 			cp->rsp_tail = rsp_tail;
498282527734SSukumar Swaminathan 		}
498382527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
4984291a2b48SSukumar Swaminathan 
498582527734SSukumar Swaminathan 		emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp);
498682527734SSukumar Swaminathan 	}
4987291a2b48SSukumar Swaminathan 
498882527734SSukumar Swaminathan 	/* Check if at least one response entry was processed */
498982527734SSukumar Swaminathan 	if (count) {
499082527734SSukumar Swaminathan 		/* Update response get index for the adapter */
499182527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
499282527734SSukumar Swaminathan 			slim2p->mbx.us.s2.host[channel_no].rspGetInx
499382527734SSukumar Swaminathan 			    = BE_SWAP32(rp->fc_rspidx);
4994291a2b48SSukumar Swaminathan 
499582527734SSukumar Swaminathan 			/* DMA sync the index for the adapter */
499682527734SSukumar Swaminathan 			offset = (off_t)
499782527734SSukumar Swaminathan 			    ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
499882527734SSukumar Swaminathan 			    host[channel_no].rspGetInx))
499982527734SSukumar Swaminathan 			    - (uint64_t)((unsigned long)slim2p));
500082527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
500182527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORDEV);
500282527734SSukumar Swaminathan 		} else {
500382527734SSukumar Swaminathan 			ioa2 =
500482527734SSukumar Swaminathan 			    (void *)((char *)hba->sli.sli3.slim_addr +
500582527734SSukumar Swaminathan 			    hba->sli.sli3.hgp_ring_offset + (((channel_no * 2) +
500682527734SSukumar Swaminathan 			    1) * sizeof (uint32_t)));
500782527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
500882527734SSukumar Swaminathan 			    rp->fc_rspidx);
500982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
501082527734SSukumar Swaminathan 			/* Access handle validation */
501182527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
501282527734SSukumar Swaminathan 			    hba->sli.sli3.slim_acc_handle);
501382527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5014291a2b48SSukumar Swaminathan 		}
5015291a2b48SSukumar Swaminathan 
501682527734SSukumar Swaminathan 		if (reg & HA_R0RE_REQ) {
501782527734SSukumar Swaminathan 			/* HBASTATS.chipRingFree++; */
5018291a2b48SSukumar Swaminathan 
501982527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
5020291a2b48SSukumar Swaminathan 
502182527734SSukumar Swaminathan 			/* Tell the adapter we serviced the ring */
502282527734SSukumar Swaminathan 			chipatt = ((CA_R0ATT | CA_R0RE_RSP) <<
502382527734SSukumar Swaminathan 			    (channel_no * 4));
502482527734SSukumar Swaminathan 			WRITE_CSR_REG(hba, FC_CA_REG(hba), chipatt);
5025291a2b48SSukumar Swaminathan 
502682527734SSukumar Swaminathan #ifdef FMA_SUPPORT
502782527734SSukumar Swaminathan 			/* Access handle validation */
502882527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
502982527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
503082527734SSukumar Swaminathan 
503182527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
5032291a2b48SSukumar Swaminathan 		}
503382527734SSukumar Swaminathan 	}
5034291a2b48SSukumar Swaminathan 
503582527734SSukumar Swaminathan 	if ((reg & HA_R0CE_RSP) || hba->channel_tx_count) {
503682527734SSukumar Swaminathan 		/* HBASTATS.hostRingFree++; */
5037291a2b48SSukumar Swaminathan 
503882527734SSukumar Swaminathan 		/* Cmd ring may be available. Try sending more iocbs */
503982527734SSukumar Swaminathan 		emlxs_sli3_issue_iocb_cmd(hba, cp, 0);
5040291a2b48SSukumar Swaminathan 	}
5041291a2b48SSukumar Swaminathan 
504282527734SSukumar Swaminathan 	/* HBASTATS.ringEvent++; */
5043291a2b48SSukumar Swaminathan 
504482527734SSukumar Swaminathan 	return;
5045291a2b48SSukumar Swaminathan 
504682527734SSukumar Swaminathan } /* emlxs_sli3_handle_ring_event() */
5047291a2b48SSukumar Swaminathan 
5048291a2b48SSukumar Swaminathan 
504982527734SSukumar Swaminathan extern int
505082527734SSukumar Swaminathan emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
505182527734SSukumar Swaminathan {
505282527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
505382527734SSukumar Swaminathan 	IOCB *iocb;
505482527734SSukumar Swaminathan 	RING *rp;
505582527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
505682527734SSukumar Swaminathan 	uint64_t bdeAddr;
505782527734SSukumar Swaminathan 	uint32_t vpi = 0;
505882527734SSukumar Swaminathan 	uint32_t channelno;
505982527734SSukumar Swaminathan 	uint32_t size = 0;
506082527734SSukumar Swaminathan 	uint32_t *RcvError;
506182527734SSukumar Swaminathan 	uint32_t *RcvDropped;
506282527734SSukumar Swaminathan 	uint32_t *UbPosted;
506382527734SSukumar Swaminathan 	emlxs_msg_t *dropped_msg;
506482527734SSukumar Swaminathan 	char error_str[64];
506582527734SSukumar Swaminathan 	uint32_t buf_type;
506682527734SSukumar Swaminathan 	uint32_t *word;
5067291a2b48SSukumar Swaminathan 
506882527734SSukumar Swaminathan 	channelno = cp->channelno;
506982527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[channelno];
5070291a2b48SSukumar Swaminathan 
507182527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
507282527734SSukumar Swaminathan 	word = (uint32_t *)iocb;
5073291a2b48SSukumar Swaminathan 
507482527734SSukumar Swaminathan 	switch (channelno) {
507582527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
507682527734SSukumar Swaminathan 	case FC_FCT_RING:
507782527734SSukumar Swaminathan 		HBASTATS.FctRingEvent++;
507882527734SSukumar Swaminathan 		RcvError = &HBASTATS.FctRingError;
507982527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.FctRingDropped;
508082527734SSukumar Swaminathan 		UbPosted = &HBASTATS.FctUbPosted;
508182527734SSukumar Swaminathan 		dropped_msg = &emlxs_fct_detail_msg;
508282527734SSukumar Swaminathan 		buf_type = MEM_FCTBUF;
508382527734SSukumar Swaminathan 		break;
508482527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5085291a2b48SSukumar Swaminathan 
508682527734SSukumar Swaminathan 	case FC_IP_RING:
508782527734SSukumar Swaminathan 		HBASTATS.IpRcvEvent++;
508882527734SSukumar Swaminathan 		RcvError = &HBASTATS.IpDropped;
508982527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.IpDropped;
509082527734SSukumar Swaminathan 		UbPosted = &HBASTATS.IpUbPosted;
509182527734SSukumar Swaminathan 		dropped_msg = &emlxs_unsol_ip_dropped_msg;
509282527734SSukumar Swaminathan 		buf_type = MEM_IPBUF;
509382527734SSukumar Swaminathan 		break;
5094291a2b48SSukumar Swaminathan 
509582527734SSukumar Swaminathan 	case FC_ELS_RING:
509682527734SSukumar Swaminathan 		HBASTATS.ElsRcvEvent++;
509782527734SSukumar Swaminathan 		RcvError = &HBASTATS.ElsRcvError;
509882527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.ElsRcvDropped;
509982527734SSukumar Swaminathan 		UbPosted = &HBASTATS.ElsUbPosted;
510082527734SSukumar Swaminathan 		dropped_msg = &emlxs_unsol_els_dropped_msg;
510182527734SSukumar Swaminathan 		buf_type = MEM_ELSBUF;
510282527734SSukumar Swaminathan 		break;
510382527734SSukumar Swaminathan 
510482527734SSukumar Swaminathan 	case FC_CT_RING:
510582527734SSukumar Swaminathan 		HBASTATS.CtRcvEvent++;
510682527734SSukumar Swaminathan 		RcvError = &HBASTATS.CtRcvError;
510782527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.CtRcvDropped;
510882527734SSukumar Swaminathan 		UbPosted = &HBASTATS.CtUbPosted;
510982527734SSukumar Swaminathan 		dropped_msg = &emlxs_unsol_ct_dropped_msg;
511082527734SSukumar Swaminathan 		buf_type = MEM_CTBUF;
511182527734SSukumar Swaminathan 		break;
511282527734SSukumar Swaminathan 
511382527734SSukumar Swaminathan 	default:
511482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
511582527734SSukumar Swaminathan 		    "channel=%d cmd=%x  %s %x %x %x %x",
511682527734SSukumar Swaminathan 		    channelno, iocb->ULPCOMMAND,
511782527734SSukumar Swaminathan 		    emlxs_state_xlate(iocb->ULPSTATUS), word[4], word[5],
511882527734SSukumar Swaminathan 		    word[6], word[7]);
511982527734SSukumar Swaminathan 		return (1);
512082527734SSukumar Swaminathan 	}
512182527734SSukumar Swaminathan 
512282527734SSukumar Swaminathan 	if (iocb->ULPSTATUS) {
512382527734SSukumar Swaminathan 		if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
512482527734SSukumar Swaminathan 		    (iocb->un.grsp.perr.statLocalError ==
512582527734SSukumar Swaminathan 		    IOERR_RCV_BUFFER_TIMEOUT)) {
5126*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "Out of posted buffers:",
5127*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
5128*8f23e9faSHans Rosenfeld 			iocb->ULPBDECOUNT = 0;
512982527734SSukumar Swaminathan 		} else if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
513082527734SSukumar Swaminathan 		    (iocb->un.grsp.perr.statLocalError ==
513182527734SSukumar Swaminathan 		    IOERR_RCV_BUFFER_WAITING)) {
5132*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "Buffer waiting:",
5133*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
5134*8f23e9faSHans Rosenfeld 			iocb->ULPBDECOUNT = 0;
513582527734SSukumar Swaminathan 			goto done;
513682527734SSukumar Swaminathan 		} else if (iocb->ULPSTATUS == IOSTAT_NEED_BUFF_ENTRY) {
5137*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "Need Buffer Entry:",
5138*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
5139*8f23e9faSHans Rosenfeld 			iocb->ULPBDECOUNT = 0;
514082527734SSukumar Swaminathan 			goto done;
514182527734SSukumar Swaminathan 		} else {
5142*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "General error:",
5143*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
5144291a2b48SSukumar Swaminathan 		}
5145291a2b48SSukumar Swaminathan 
514682527734SSukumar Swaminathan 		goto failed;
5147291a2b48SSukumar Swaminathan 	}
5148291a2b48SSukumar Swaminathan 
514982527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
515082527734SSukumar Swaminathan 		HBQ_INIT_t *hbq;
515182527734SSukumar Swaminathan 		HBQE_t *hbqE;
515282527734SSukumar Swaminathan 		uint32_t hbqe_tag;
5153*8f23e9faSHans Rosenfeld 		uint32_t hbq_id;
5154291a2b48SSukumar Swaminathan 
515582527734SSukumar Swaminathan 		(*UbPosted)--;
5156291a2b48SSukumar Swaminathan 
515782527734SSukumar Swaminathan 		hbqE = (HBQE_t *)iocb;
515882527734SSukumar Swaminathan 		hbq_id = hbqE->unt.ext.HBQ_tag;
515982527734SSukumar Swaminathan 		hbqe_tag = hbqE->unt.ext.HBQE_tag;
5160291a2b48SSukumar Swaminathan 
516182527734SSukumar Swaminathan 		hbq = &hba->sli.sli3.hbq_table[hbq_id];
5162291a2b48SSukumar Swaminathan 
516382527734SSukumar Swaminathan 		if (hbqe_tag >= hbq->HBQ_numEntries) {
5164*8f23e9faSHans Rosenfeld 			(void) snprintf(error_str, sizeof (error_str),
5165*8f23e9faSHans Rosenfeld 			    "Invalid HBQE iotag=%d:", hbqe_tag);
516682527734SSukumar Swaminathan 			goto dropped;
516782527734SSukumar Swaminathan 		}
5168291a2b48SSukumar Swaminathan 
516982527734SSukumar Swaminathan 		mp = hba->sli.sli3.hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag];
5170291a2b48SSukumar Swaminathan 
517182527734SSukumar Swaminathan 		size = iocb->unsli3.ext_rcv.seq_len;
517282527734SSukumar Swaminathan 	} else {
517382527734SSukumar Swaminathan 		bdeAddr =
517482527734SSukumar Swaminathan 		    PADDR(iocb->un.cont64[0].addrHigh,
517582527734SSukumar Swaminathan 		    iocb->un.cont64[0].addrLow);
5176291a2b48SSukumar Swaminathan 
517782527734SSukumar Swaminathan 		/* Check for invalid buffer */
517882527734SSukumar Swaminathan 		if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) {
5179*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "Invalid buffer:",
5180*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
518182527734SSukumar Swaminathan 			goto dropped;
5182291a2b48SSukumar Swaminathan 		}
5183291a2b48SSukumar Swaminathan 
518482527734SSukumar Swaminathan 		mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr);
5185291a2b48SSukumar Swaminathan 
518682527734SSukumar Swaminathan 		size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize;
5187291a2b48SSukumar Swaminathan 	}
5188291a2b48SSukumar Swaminathan 
518982527734SSukumar Swaminathan 	if (!mp) {
5190*8f23e9faSHans Rosenfeld 		(void) strlcpy(error_str, "Buffer not mapped:",
5191*8f23e9faSHans Rosenfeld 		    sizeof (error_str));
519282527734SSukumar Swaminathan 		goto dropped;
519382527734SSukumar Swaminathan 	}
5194291a2b48SSukumar Swaminathan 
5195b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5196b3660a96SSukumar Swaminathan 	if (mp->dma_handle) {
5197b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
5198b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
5199b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
5200b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
5201*8f23e9faSHans Rosenfeld 			    "handle_rcv_seq: hdl=%p",
5202b3660a96SSukumar Swaminathan 			    mp->dma_handle);
5203b3660a96SSukumar Swaminathan 			goto dropped;
5204b3660a96SSukumar Swaminathan 		}
5205b3660a96SSukumar Swaminathan 	}
5206b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5207b3660a96SSukumar Swaminathan 
520882527734SSukumar Swaminathan 	if (!size) {
5209*8f23e9faSHans Rosenfeld 		(void) strlcpy(error_str, "Buffer empty:", sizeof (error_str));
521082527734SSukumar Swaminathan 		goto dropped;
521182527734SSukumar Swaminathan 	}
5212291a2b48SSukumar Swaminathan 
521382527734SSukumar Swaminathan 	/* To avoid we drop the broadcast packets */
521482527734SSukumar Swaminathan 	if (channelno != FC_IP_RING) {
521582527734SSukumar Swaminathan 		/* Get virtual port */
521682527734SSukumar Swaminathan 		if (hba->flag & FC_NPIV_ENABLED) {
521782527734SSukumar Swaminathan 			vpi = iocb->unsli3.ext_rcv.vpi;
521882527734SSukumar Swaminathan 			if (vpi >= hba->vpi_max) {
5219*8f23e9faSHans Rosenfeld 				(void) snprintf(error_str, sizeof (error_str),
522082527734SSukumar Swaminathan 				"Invalid VPI=%d:", vpi);
522182527734SSukumar Swaminathan 				goto dropped;
522282527734SSukumar Swaminathan 			}
5223291a2b48SSukumar Swaminathan 
522482527734SSukumar Swaminathan 			port = &VPORT(vpi);
522582527734SSukumar Swaminathan 		}
52264baa2c25SSukumar Swaminathan 	}
52274baa2c25SSukumar Swaminathan 
522882527734SSukumar Swaminathan 	/* Process request */
522982527734SSukumar Swaminathan 	switch (channelno) {
523082527734SSukumar Swaminathan 	case FC_FCT_RING:
5231*8f23e9faSHans Rosenfeld 		if (port->mode == MODE_INITIATOR) {
5232*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "Target mode disabled:",
5233*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
5234*8f23e9faSHans Rosenfeld 			goto dropped;
5235*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
5236*8f23e9faSHans Rosenfeld 		} else if (port->mode == MODE_TARGET) {
5237*8f23e9faSHans Rosenfeld 			(void) emlxs_fct_handle_unsol_req(port, cp, iocbq, mp,
5238*8f23e9faSHans Rosenfeld 			    size);
523982527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5240*8f23e9faSHans Rosenfeld 		} else {
5241*8f23e9faSHans Rosenfeld 			(void) snprintf(error_str, sizeof (error_str),
5242*8f23e9faSHans Rosenfeld 			    "Invalid mode=%x:", port->mode);
5243*8f23e9faSHans Rosenfeld 			goto dropped;
5244*8f23e9faSHans Rosenfeld 		}
5245*8f23e9faSHans Rosenfeld 		break;
5246291a2b48SSukumar Swaminathan 
524782527734SSukumar Swaminathan 	case FC_IP_RING:
5248*8f23e9faSHans Rosenfeld 		if (port->mode == MODE_INITIATOR) {
5249*8f23e9faSHans Rosenfeld 			(void) emlxs_ip_handle_unsol_req(port, cp, iocbq,
5250*8f23e9faSHans Rosenfeld 			    mp, size);
5251*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
5252*8f23e9faSHans Rosenfeld 		} else if (port->mode == MODE_TARGET) {
5253*8f23e9faSHans Rosenfeld 			(void) strlcpy(error_str, "Initiator mode disabled:",
5254*8f23e9faSHans Rosenfeld 			    sizeof (error_str));
5255*8f23e9faSHans Rosenfeld 			goto dropped;
5256*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
5257*8f23e9faSHans Rosenfeld 		} else {
5258*8f23e9faSHans Rosenfeld 			(void) snprintf(error_str, sizeof (error_str),
5259*8f23e9faSHans Rosenfeld 			    "Invalid mode=%x:", port->mode);
5260*8f23e9faSHans Rosenfeld 			goto dropped;
5261*8f23e9faSHans Rosenfeld 		}
526282527734SSukumar Swaminathan 		break;
5263291a2b48SSukumar Swaminathan 
526482527734SSukumar Swaminathan 	case FC_ELS_RING:
5265*8f23e9faSHans Rosenfeld 		if (port->mode == MODE_INITIATOR) {
526682527734SSukumar Swaminathan 			(void) emlxs_els_handle_unsol_req(port, cp, iocbq, mp,
526782527734SSukumar Swaminathan 			    size);
526882527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
5269*8f23e9faSHans Rosenfeld 		} else if (port->mode == MODE_TARGET) {
527082527734SSukumar Swaminathan 			(void) emlxs_fct_handle_unsol_els(port, cp, iocbq, mp,
527182527734SSukumar Swaminathan 			    size);
527282527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5273*8f23e9faSHans Rosenfeld 		} else {
5274*8f23e9faSHans Rosenfeld 			(void) snprintf(error_str, sizeof (error_str),
5275*8f23e9faSHans Rosenfeld 			    "Invalid mode=%x:", port->mode);
5276*8f23e9faSHans Rosenfeld 			goto dropped;
5277*8f23e9faSHans Rosenfeld 		}
527882527734SSukumar Swaminathan 		break;
5279291a2b48SSukumar Swaminathan 
528082527734SSukumar Swaminathan 	case FC_CT_RING:
528182527734SSukumar Swaminathan 		(void) emlxs_ct_handle_unsol_req(port, cp, iocbq, mp, size);
528282527734SSukumar Swaminathan 		break;
528382527734SSukumar Swaminathan 	}
5284291a2b48SSukumar Swaminathan 
528582527734SSukumar Swaminathan 	goto done;
5286291a2b48SSukumar Swaminathan 
528782527734SSukumar Swaminathan dropped:
528882527734SSukumar Swaminathan 	(*RcvDropped)++;
5289291a2b48SSukumar Swaminathan 
529082527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg,
529182527734SSukumar Swaminathan 	    "%s: cmd=%x  %s %x %x %x %x",
529282527734SSukumar Swaminathan 	    error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS),
529382527734SSukumar Swaminathan 	    word[4], word[5], word[6], word[7]);
5294291a2b48SSukumar Swaminathan 
529582527734SSukumar Swaminathan 	if (channelno == FC_FCT_RING) {
529682527734SSukumar Swaminathan 		uint32_t sid;
5297291a2b48SSukumar Swaminathan 
5298*8f23e9faSHans Rosenfeld 		if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
529982527734SSukumar Swaminathan 			emlxs_node_t *ndlp;
530082527734SSukumar Swaminathan 			ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
5301*8f23e9faSHans Rosenfeld 			if (! ndlp) {
5302*8f23e9faSHans Rosenfeld 				goto done;
5303*8f23e9faSHans Rosenfeld 			}
530482527734SSukumar Swaminathan 			sid = ndlp->nlp_DID;
530582527734SSukumar Swaminathan 		} else {
530682527734SSukumar Swaminathan 			sid = iocb->un.ulpWord[4] & 0xFFFFFF;
530782527734SSukumar Swaminathan 		}
5308291a2b48SSukumar Swaminathan 
530982527734SSukumar Swaminathan 		emlxs_send_logo(port, sid);
5310291a2b48SSukumar Swaminathan 	}
5311291a2b48SSukumar Swaminathan 
531282527734SSukumar Swaminathan 	goto done;
5313291a2b48SSukumar Swaminathan 
531482527734SSukumar Swaminathan failed:
531582527734SSukumar Swaminathan 	(*RcvError)++;
5316291a2b48SSukumar Swaminathan 
531782527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg,
531882527734SSukumar Swaminathan 	    "%s: cmd=%x %s  %x %x %x %x  hba:%x %x",
531982527734SSukumar Swaminathan 	    error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS),
532082527734SSukumar Swaminathan 	    word[4], word[5], word[6], word[7], hba->state, hba->flag);
5321291a2b48SSukumar Swaminathan 
532282527734SSukumar Swaminathan done:
5323291a2b48SSukumar Swaminathan 
532482527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
5325*8f23e9faSHans Rosenfeld 		if (iocb->ULPBDECOUNT) {
5326*8f23e9faSHans Rosenfeld 			HBQE_t *hbqE;
5327*8f23e9faSHans Rosenfeld 			uint32_t hbq_id;
5328*8f23e9faSHans Rosenfeld 
5329*8f23e9faSHans Rosenfeld 			hbqE = (HBQE_t *)iocb;
5330*8f23e9faSHans Rosenfeld 			hbq_id = hbqE->unt.ext.HBQ_tag;
5331*8f23e9faSHans Rosenfeld 
5332*8f23e9faSHans Rosenfeld 			emlxs_update_HBQ_index(hba, hbq_id);
5333*8f23e9faSHans Rosenfeld 		}
533482527734SSukumar Swaminathan 	} else {
533582527734SSukumar Swaminathan 		if (mp) {
5336a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, buf_type, (void *)mp);
5337291a2b48SSukumar Swaminathan 		}
5338*8f23e9faSHans Rosenfeld 
5339*8f23e9faSHans Rosenfeld 		if (iocb->ULPBDECOUNT) {
5340*8f23e9faSHans Rosenfeld 			(void) emlxs_post_buffer(hba, rp, 1);
5341*8f23e9faSHans Rosenfeld 		}
5342291a2b48SSukumar Swaminathan 	}
5343291a2b48SSukumar Swaminathan 
534482527734SSukumar Swaminathan 	return (0);
5345291a2b48SSukumar Swaminathan 
534682527734SSukumar Swaminathan } /* emlxs_handle_rcv_seq() */
5347291a2b48SSukumar Swaminathan 
5348291a2b48SSukumar Swaminathan 
534982527734SSukumar Swaminathan /* EMLXS_CMD_RING_LOCK must be held when calling this function */
535082527734SSukumar Swaminathan static void
535182527734SSukumar Swaminathan emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
5352291a2b48SSukumar Swaminathan {
535382527734SSukumar Swaminathan 	emlxs_port_t *port;
535482527734SSukumar Swaminathan 	IOCB *icmd;
535582527734SSukumar Swaminathan 	IOCB *iocb;
535682527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
535782527734SSukumar Swaminathan 	off_t offset;
535882527734SSukumar Swaminathan 	uint32_t ringno;
5359291a2b48SSukumar Swaminathan 
536082527734SSukumar Swaminathan 	ringno = rp->ringno;
536182527734SSukumar Swaminathan 	sbp = iocbq->sbp;
536282527734SSukumar Swaminathan 	icmd = &iocbq->iocb;
536382527734SSukumar Swaminathan 	port = iocbq->port;
5364291a2b48SSukumar Swaminathan 
536582527734SSukumar Swaminathan 	HBASTATS.IocbIssued[ringno]++;
5366291a2b48SSukumar Swaminathan 
536782527734SSukumar Swaminathan 	/* Check for ULP pkt request */
536882527734SSukumar Swaminathan 	if (sbp) {
536982527734SSukumar Swaminathan 		mutex_enter(&sbp->mtx);
5370291a2b48SSukumar Swaminathan 
537182527734SSukumar Swaminathan 		if (sbp->node == NULL) {
537282527734SSukumar Swaminathan 			/* Set node to base node by default */
537382527734SSukumar Swaminathan 			iocbq->node = (void *)&port->node_base;
537482527734SSukumar Swaminathan 			sbp->node = (void *)&port->node_base;
537582527734SSukumar Swaminathan 		}
5376291a2b48SSukumar Swaminathan 
537782527734SSukumar Swaminathan 		sbp->pkt_flags |= PACKET_IN_CHIPQ;
537882527734SSukumar Swaminathan 		mutex_exit(&sbp->mtx);
5379291a2b48SSukumar Swaminathan 
53801a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32(&hba->io_active);
5381*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
5382*8f23e9faSHans Rosenfeld 		if (sbp->node) {
5383*8f23e9faSHans Rosenfeld 			atomic_inc_32(&sbp->node->io_active);
5384*8f23e9faSHans Rosenfeld 		}
5385*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
5386291a2b48SSukumar Swaminathan 
538782527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
538882527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
538982527734SSukumar Swaminathan 		if (sbp->fct_cmd) {
539082527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
539182527734SSukumar Swaminathan 			    EMLXS_FCT_IOCB_ISSUED);
539282527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
539382527734SSukumar Swaminathan 			    icmd->ULPCOMMAND);
539482527734SSukumar Swaminathan 		}
539582527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
539682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5397291a2b48SSukumar Swaminathan 
539882527734SSukumar Swaminathan 		rp->channelp->hbaSendCmd_sbp++;
539982527734SSukumar Swaminathan 		iocbq->channel = rp->channelp;
5400291a2b48SSukumar Swaminathan 	} else {
540182527734SSukumar Swaminathan 		rp->channelp->hbaSendCmd++;
5402291a2b48SSukumar Swaminathan 	}
5403291a2b48SSukumar Swaminathan 
540482527734SSukumar Swaminathan 	/* get the next available command ring iocb */
540582527734SSukumar Swaminathan 	iocb =
540682527734SSukumar Swaminathan 	    (IOCB *)(((char *)rp->fc_cmdringaddr +
540782527734SSukumar Swaminathan 	    (rp->fc_cmdidx * hba->sli.sli3.iocb_cmd_size)));
5408291a2b48SSukumar Swaminathan 
540982527734SSukumar Swaminathan 	/* Copy the local iocb to the command ring iocb */
541082527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)icmd, (uint8_t *)iocb,
541182527734SSukumar Swaminathan 	    hba->sli.sli3.iocb_cmd_size);
5412291a2b48SSukumar Swaminathan 
541382527734SSukumar Swaminathan 	/* DMA sync the command ring iocb for the adapter */
541482527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)iocb)
541582527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
541682527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
541782527734SSukumar Swaminathan 	    hba->sli.sli3.iocb_cmd_size, DDI_DMA_SYNC_FORDEV);
5418291a2b48SSukumar Swaminathan 
541982527734SSukumar Swaminathan 	/*
542082527734SSukumar Swaminathan 	 * After this, the sbp / iocb should not be
542182527734SSukumar Swaminathan 	 * accessed in the xmit path.
542282527734SSukumar Swaminathan 	 */
542382527734SSukumar Swaminathan 
542482527734SSukumar Swaminathan 	/* Free the local iocb if there is no sbp tracking it */
542582527734SSukumar Swaminathan 	if (!sbp) {
5426a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
5427291a2b48SSukumar Swaminathan 	}
5428291a2b48SSukumar Swaminathan 
542982527734SSukumar Swaminathan 	/* update local ring index to next available ring index */
543082527734SSukumar Swaminathan 	rp->fc_cmdidx =
543182527734SSukumar Swaminathan 	    (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
5432291a2b48SSukumar Swaminathan 
5433291a2b48SSukumar Swaminathan 
543482527734SSukumar Swaminathan 	return;
54354baa2c25SSukumar Swaminathan 
543682527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb() */
5437291a2b48SSukumar Swaminathan 
5438291a2b48SSukumar Swaminathan 
543982527734SSukumar Swaminathan static void
544082527734SSukumar Swaminathan emlxs_sli3_hba_kill(emlxs_hba_t *hba)
544182527734SSukumar Swaminathan {
544282527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
544382527734SSukumar Swaminathan 	MAILBOX *swpmb;
544482527734SSukumar Swaminathan 	MAILBOX *mb2;
544582527734SSukumar Swaminathan 	MAILBOX *mb1;
544682527734SSukumar Swaminathan 	uint32_t word0;
544782527734SSukumar Swaminathan 	uint32_t j;
544882527734SSukumar Swaminathan 	uint32_t interlock_failed;
544982527734SSukumar Swaminathan 	uint32_t ha_copy;
545082527734SSukumar Swaminathan 	uint32_t value;
545182527734SSukumar Swaminathan 	off_t offset;
545282527734SSukumar Swaminathan 	uint32_t size;
5453291a2b48SSukumar Swaminathan 
545482527734SSukumar Swaminathan 	/* Perform adapter interlock to kill adapter */
545582527734SSukumar Swaminathan 	interlock_failed = 0;
5456291a2b48SSukumar Swaminathan 
545782527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
545882527734SSukumar Swaminathan 	if (hba->flag & FC_INTERLOCKED) {
545982527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5460291a2b48SSukumar Swaminathan 
546182527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5462291a2b48SSukumar Swaminathan 
546382527734SSukumar Swaminathan 		return;
546482527734SSukumar Swaminathan 	}
5465291a2b48SSukumar Swaminathan 
546682527734SSukumar Swaminathan 	j = 0;
546782527734SSukumar Swaminathan 	while (j++ < 10000) {
546882527734SSukumar Swaminathan 		if (hba->mbox_queue_flag == 0) {
546982527734SSukumar Swaminathan 			break;
547082527734SSukumar Swaminathan 		}
5471291a2b48SSukumar Swaminathan 
547282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5473*8f23e9faSHans Rosenfeld 		BUSYWAIT_US(100);
547482527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
547582527734SSukumar Swaminathan 	}
5476291a2b48SSukumar Swaminathan 
547782527734SSukumar Swaminathan 	if (hba->mbox_queue_flag != 0) {
547882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
547982527734SSukumar Swaminathan 		    "Interlock failed. Mailbox busy.");
548082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
548182527734SSukumar Swaminathan 		return;
548282527734SSukumar Swaminathan 	}
5483291a2b48SSukumar Swaminathan 
548482527734SSukumar Swaminathan 	hba->flag |= FC_INTERLOCKED;
548582527734SSukumar Swaminathan 	hba->mbox_queue_flag = 1;
5486291a2b48SSukumar Swaminathan 
548782527734SSukumar Swaminathan 	/* Disable all host interrupts */
548882527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
548982527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
549082527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff);
5491291a2b48SSukumar Swaminathan 
549282527734SSukumar Swaminathan 	mb2 = FC_SLIM2_MAILBOX(hba);
549382527734SSukumar Swaminathan 	mb1 = FC_SLIM1_MAILBOX(hba);
549482527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
5495291a2b48SSukumar Swaminathan 
549682527734SSukumar Swaminathan 	if (!(hba->flag & FC_SLIM2_MODE)) {
549782527734SSukumar Swaminathan 		goto mode_B;
549882527734SSukumar Swaminathan 	}
5499291a2b48SSukumar Swaminathan 
550082527734SSukumar Swaminathan mode_A:
5501291a2b48SSukumar Swaminathan 
550282527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
550382527734SSukumar Swaminathan 	    "Attempting SLIM2 Interlock...");
5504291a2b48SSukumar Swaminathan 
550582527734SSukumar Swaminathan interlock_A:
5506291a2b48SSukumar Swaminathan 
5507a9800bebSGarrett D'Amore 	value = 0x55555555;
550882527734SSukumar Swaminathan 	word0 = 0;
550982527734SSukumar Swaminathan 	swpmb->mbxCommand = MBX_KILL_BOARD;
551082527734SSukumar Swaminathan 	swpmb->mbxOwner = OWN_CHIP;
5511291a2b48SSukumar Swaminathan 
551282527734SSukumar Swaminathan 	/* Write value to SLIM */
551382527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
551482527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0);
5515291a2b48SSukumar Swaminathan 
551682527734SSukumar Swaminathan 	/* Send Kill board request */
551782527734SSukumar Swaminathan 	mb2->un.varWords[0] = value;
551882527734SSukumar Swaminathan 	mb2->mbxCommand = MBX_KILL_BOARD;
551982527734SSukumar Swaminathan 	mb2->mbxOwner = OWN_CHIP;
5520291a2b48SSukumar Swaminathan 
552182527734SSukumar Swaminathan 	/* Sync the memory */
552282527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)mb2)
552382527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
552482527734SSukumar Swaminathan 	size = (sizeof (uint32_t) * 2);
5525291a2b48SSukumar Swaminathan 
552682527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size);
5527291a2b48SSukumar Swaminathan 
552882527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size,
552982527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
5530291a2b48SSukumar Swaminathan 
553182527734SSukumar Swaminathan 	/* interrupt board to do it right away */
553282527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5533291a2b48SSukumar Swaminathan 
553482527734SSukumar Swaminathan 	/* First wait for command acceptence */
553582527734SSukumar Swaminathan 	j = 0;
553682527734SSukumar Swaminathan 	while (j++ < 1000) {
553782527734SSukumar Swaminathan 		value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5538291a2b48SSukumar Swaminathan 
5539a9800bebSGarrett D'Amore 		if (value == 0xAAAAAAAA) {
554082527734SSukumar Swaminathan 			break;
5541291a2b48SSukumar Swaminathan 		}
5542291a2b48SSukumar Swaminathan 
5543*8f23e9faSHans Rosenfeld 		BUSYWAIT_US(50);
554482527734SSukumar Swaminathan 	}
5545291a2b48SSukumar Swaminathan 
5546a9800bebSGarrett D'Amore 	if (value == 0xAAAAAAAA) {
554782527734SSukumar Swaminathan 		/* Now wait for mailbox ownership to clear */
554882527734SSukumar Swaminathan 		while (j++ < 10000) {
554982527734SSukumar Swaminathan 			word0 =
555082527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5551291a2b48SSukumar Swaminathan 
555282527734SSukumar Swaminathan 			if (swpmb->mbxOwner == 0) {
555382527734SSukumar Swaminathan 				break;
55544baa2c25SSukumar Swaminathan 			}
555582527734SSukumar Swaminathan 
5556*8f23e9faSHans Rosenfeld 			BUSYWAIT_US(50);
5557291a2b48SSukumar Swaminathan 		}
5558291a2b48SSukumar Swaminathan 
555982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
556082527734SSukumar Swaminathan 		    "Interlock succeeded.");
5561291a2b48SSukumar Swaminathan 
556282527734SSukumar Swaminathan 		goto done;
556382527734SSukumar Swaminathan 	}
5564291a2b48SSukumar Swaminathan 
556582527734SSukumar Swaminathan 	/* Interlock failed !!! */
556682527734SSukumar Swaminathan 	interlock_failed = 1;
5567291a2b48SSukumar Swaminathan 
556882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Interlock failed.");
5569291a2b48SSukumar Swaminathan 
557082527734SSukumar Swaminathan mode_B:
5571291a2b48SSukumar Swaminathan 
557282527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
557382527734SSukumar Swaminathan 	    "Attempting SLIM1 Interlock...");
5574291a2b48SSukumar Swaminathan 
557582527734SSukumar Swaminathan interlock_B:
55764baa2c25SSukumar Swaminathan 
5577a9800bebSGarrett D'Amore 	value = 0x55555555;
557882527734SSukumar Swaminathan 	word0 = 0;
557982527734SSukumar Swaminathan 	swpmb->mbxCommand = MBX_KILL_BOARD;
558082527734SSukumar Swaminathan 	swpmb->mbxOwner = OWN_CHIP;
55814baa2c25SSukumar Swaminathan 
558282527734SSukumar Swaminathan 	/* Write KILL BOARD to mailbox */
558382527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
558482527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb1), word0);
5585291a2b48SSukumar Swaminathan 
558682527734SSukumar Swaminathan 	/* interrupt board to do it right away */
558782527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5588291a2b48SSukumar Swaminathan 
558982527734SSukumar Swaminathan 	/* First wait for command acceptence */
559082527734SSukumar Swaminathan 	j = 0;
559182527734SSukumar Swaminathan 	while (j++ < 1000) {
559282527734SSukumar Swaminathan 		value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5593291a2b48SSukumar Swaminathan 
5594a9800bebSGarrett D'Amore 		if (value == 0xAAAAAAAA) {
559582527734SSukumar Swaminathan 			break;
5596291a2b48SSukumar Swaminathan 		}
559782527734SSukumar Swaminathan 
5598*8f23e9faSHans Rosenfeld 		BUSYWAIT_US(50);
5599291a2b48SSukumar Swaminathan 	}
5600291a2b48SSukumar Swaminathan 
5601a9800bebSGarrett D'Amore 	if (value == 0xAAAAAAAA) {
560282527734SSukumar Swaminathan 		/* Now wait for mailbox ownership to clear */
560382527734SSukumar Swaminathan 		while (j++ < 10000) {
560482527734SSukumar Swaminathan 			word0 =
560582527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5606291a2b48SSukumar Swaminathan 
560782527734SSukumar Swaminathan 			if (swpmb->mbxOwner == 0) {
560882527734SSukumar Swaminathan 				break;
560982527734SSukumar Swaminathan 			}
5610291a2b48SSukumar Swaminathan 
5611*8f23e9faSHans Rosenfeld 			BUSYWAIT_US(50);
5612291a2b48SSukumar Swaminathan 		}
5613291a2b48SSukumar Swaminathan 
561482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
561582527734SSukumar Swaminathan 		    "Interlock succeeded.");
5616291a2b48SSukumar Swaminathan 
561782527734SSukumar Swaminathan 		goto done;
561882527734SSukumar Swaminathan 	}
5619291a2b48SSukumar Swaminathan 
562082527734SSukumar Swaminathan 	/* Interlock failed !!! */
5621291a2b48SSukumar Swaminathan 
562282527734SSukumar Swaminathan 	/* If this is the first time then try again */
562382527734SSukumar Swaminathan 	if (interlock_failed == 0) {
562482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
562582527734SSukumar Swaminathan 		    "Interlock failed. Retrying...");
5626291a2b48SSukumar Swaminathan 
562782527734SSukumar Swaminathan 		/* Try again */
562882527734SSukumar Swaminathan 		interlock_failed = 1;
562982527734SSukumar Swaminathan 		goto interlock_B;
5630291a2b48SSukumar Swaminathan 	}
5631291a2b48SSukumar Swaminathan 
5632291a2b48SSukumar Swaminathan 	/*
563382527734SSukumar Swaminathan 	 * Now check for error attention to indicate the board has
563482527734SSukumar Swaminathan 	 * been kiilled
5635291a2b48SSukumar Swaminathan 	 */
563682527734SSukumar Swaminathan 	j = 0;
563782527734SSukumar Swaminathan 	while (j++ < 10000) {
563882527734SSukumar Swaminathan 		ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
5639bb63f56eSSukumar Swaminathan 
564082527734SSukumar Swaminathan 		if (ha_copy & HA_ERATT) {
564182527734SSukumar Swaminathan 			break;
564282527734SSukumar Swaminathan 		}
56433be114edSSukumar Swaminathan 
5644*8f23e9faSHans Rosenfeld 		BUSYWAIT_US(50);
564582527734SSukumar Swaminathan 	}
5646291a2b48SSukumar Swaminathan 
564782527734SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
564882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
564982527734SSukumar Swaminathan 		    "Interlock failed. Board killed.");
565082527734SSukumar Swaminathan 	} else {
565182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
565282527734SSukumar Swaminathan 		    "Interlock failed. Board not killed.");
565382527734SSukumar Swaminathan 	}
5654291a2b48SSukumar Swaminathan 
565582527734SSukumar Swaminathan done:
5656291a2b48SSukumar Swaminathan 
565782527734SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
5658291a2b48SSukumar Swaminathan 
565982527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5660291a2b48SSukumar Swaminathan 
566182527734SSukumar Swaminathan #ifdef FMA_SUPPORT
566282527734SSukumar Swaminathan 	/* Access handle validation */
566382527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
566482527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
566582527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5666291a2b48SSukumar Swaminathan 
566782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
5668291a2b48SSukumar Swaminathan 
566982527734SSukumar Swaminathan 	return;
5670291a2b48SSukumar Swaminathan 
567182527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill() */
5672291a2b48SSukumar Swaminathan 
5673291a2b48SSukumar Swaminathan 
567482527734SSukumar Swaminathan static void
567582527734SSukumar Swaminathan emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba)
567682527734SSukumar Swaminathan {
567782527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
567882527734SSukumar Swaminathan 	MAILBOX *swpmb;
567982527734SSukumar Swaminathan 	MAILBOX *mb2;
568082527734SSukumar Swaminathan 	MAILBOX *mb1;
568182527734SSukumar Swaminathan 	uint32_t word0;
568282527734SSukumar Swaminathan 	off_t offset;
568382527734SSukumar Swaminathan 	uint32_t j;
568482527734SSukumar Swaminathan 	uint32_t value;
568582527734SSukumar Swaminathan 	uint32_t size;
5686291a2b48SSukumar Swaminathan 
568782527734SSukumar Swaminathan 	/* Disable all host interrupts */
568882527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
568982527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
569082527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff);
5691291a2b48SSukumar Swaminathan 
569282527734SSukumar Swaminathan 	mb2 = FC_SLIM2_MAILBOX(hba);
569382527734SSukumar Swaminathan 	mb1 = FC_SLIM1_MAILBOX(hba);
569482527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
5695291a2b48SSukumar Swaminathan 
5696a9800bebSGarrett D'Amore 	value = 0x55555555;
569782527734SSukumar Swaminathan 	word0 = 0;
569882527734SSukumar Swaminathan 	swpmb->mbxCommand = MBX_KILL_BOARD;
569982527734SSukumar Swaminathan 	swpmb->mbxOwner = OWN_CHIP;
5700291a2b48SSukumar Swaminathan 
570182527734SSukumar Swaminathan 	/* Write value to SLIM */
570282527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
570382527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0);
5704291a2b48SSukumar Swaminathan 
570582527734SSukumar Swaminathan 	/* Send Kill board request */
570682527734SSukumar Swaminathan 	mb2->un.varWords[0] = value;
570782527734SSukumar Swaminathan 	mb2->mbxCommand = MBX_KILL_BOARD;
570882527734SSukumar Swaminathan 	mb2->mbxOwner = OWN_CHIP;
5709291a2b48SSukumar Swaminathan 
571082527734SSukumar Swaminathan 	/* Sync the memory */
571182527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)mb2)
571282527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
571382527734SSukumar Swaminathan 	size = (sizeof (uint32_t) * 2);
5714291a2b48SSukumar Swaminathan 
571582527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size);
5716291a2b48SSukumar Swaminathan 
571782527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size,
571882527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
5719291a2b48SSukumar Swaminathan 
572082527734SSukumar Swaminathan 	/* interrupt board to do it right away */
572182527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5722291a2b48SSukumar Swaminathan 
572382527734SSukumar Swaminathan 	/* First wait for command acceptence */
572482527734SSukumar Swaminathan 	j = 0;
572582527734SSukumar Swaminathan 	while (j++ < 1000) {
572682527734SSukumar Swaminathan 		value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5727291a2b48SSukumar Swaminathan 
5728a9800bebSGarrett D'Amore 		if (value == 0xAAAAAAAA) {
572982527734SSukumar Swaminathan 			break;
573082527734SSukumar Swaminathan 		}
5731*8f23e9faSHans Rosenfeld 		BUSYWAIT_US(50);
573282527734SSukumar Swaminathan 	}
5733a9800bebSGarrett D'Amore 	if (value == 0xAAAAAAAA) {
573482527734SSukumar Swaminathan 		/* Now wait for mailbox ownership to clear */
573582527734SSukumar Swaminathan 		while (j++ < 10000) {
573682527734SSukumar Swaminathan 			word0 =
573782527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
573882527734SSukumar Swaminathan 			if (swpmb->mbxOwner == 0) {
573982527734SSukumar Swaminathan 				break;
5740291a2b48SSukumar Swaminathan 			}
5741*8f23e9faSHans Rosenfeld 			BUSYWAIT_US(50);
5742291a2b48SSukumar Swaminathan 		}
574382527734SSukumar Swaminathan 		goto done;
574482527734SSukumar Swaminathan 	}
5745291a2b48SSukumar Swaminathan 
574682527734SSukumar Swaminathan done:
574782527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5748291a2b48SSukumar Swaminathan 
574982527734SSukumar Swaminathan #ifdef FMA_SUPPORT
575082527734SSukumar Swaminathan 	/* Access handle validation */
575182527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
575282527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
575382527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
575482527734SSukumar Swaminathan 	return;
5755291a2b48SSukumar Swaminathan 
575682527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill4quiesce */
5757291a2b48SSukumar Swaminathan 
5758291a2b48SSukumar Swaminathan 
5759291a2b48SSukumar Swaminathan 
5760291a2b48SSukumar Swaminathan 
576182527734SSukumar Swaminathan /*
576282527734SSukumar Swaminathan  * emlxs_handle_mb_event
576382527734SSukumar Swaminathan  *
576482527734SSukumar Swaminathan  * Description: Process a Mailbox Attention.
576582527734SSukumar Swaminathan  * Called from host_interrupt to process MBATT
576682527734SSukumar Swaminathan  *
576782527734SSukumar Swaminathan  *   Returns:
576882527734SSukumar Swaminathan  *
576982527734SSukumar Swaminathan  */
577082527734SSukumar Swaminathan static uint32_t
577182527734SSukumar Swaminathan emlxs_handle_mb_event(emlxs_hba_t *hba)
577282527734SSukumar Swaminathan {
577382527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
577482527734SSukumar Swaminathan 	MAILBOX			*mb;
577582527734SSukumar Swaminathan 	MAILBOX			*swpmb;
577682527734SSukumar Swaminathan 	MAILBOX			*mbox;
5777a9800bebSGarrett D'Amore 	MAILBOXQ		*mbq = NULL;
577882527734SSukumar Swaminathan 	volatile uint32_t	word0;
577982527734SSukumar Swaminathan 	MATCHMAP		*mbox_bp;
578082527734SSukumar Swaminathan 	off_t			offset;
578182527734SSukumar Swaminathan 	uint32_t		i;
578282527734SSukumar Swaminathan 	int			rc;
578382527734SSukumar Swaminathan 
578482527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
5785291a2b48SSukumar Swaminathan 
5786a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_PORT_LOCK);
578782527734SSukumar Swaminathan 	switch (hba->mbox_queue_flag) {
578882527734SSukumar Swaminathan 	case 0:
578982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
579082527734SSukumar Swaminathan 		    "No mailbox active.");
5791a9800bebSGarrett D'Amore 
5792a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
579382527734SSukumar Swaminathan 		return (0);
5794291a2b48SSukumar Swaminathan 
579582527734SSukumar Swaminathan 	case MBX_POLL:
5796291a2b48SSukumar Swaminathan 
579782527734SSukumar Swaminathan 		/* Mark mailbox complete, this should wake up any polling */
579882527734SSukumar Swaminathan 		/* threads. This can happen if interrupts are enabled while */
579982527734SSukumar Swaminathan 		/* a polled mailbox command is outstanding. If we don't set */
580082527734SSukumar Swaminathan 		/* MBQ_COMPLETED here, the polling thread may wait until */
580182527734SSukumar Swaminathan 		/* timeout error occurs */
5802291a2b48SSukumar Swaminathan 
580382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
580482527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
580582527734SSukumar Swaminathan 		if (mbq) {
5806a9800bebSGarrett D'Amore 			port = (emlxs_port_t *)mbq->port;
580782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
580882527734SSukumar Swaminathan 			    "Mailbox event. Completing Polled command.");
580982527734SSukumar Swaminathan 			mbq->flag |= MBQ_COMPLETED;
581082527734SSukumar Swaminathan 		}
5811a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_MBOX_LOCK);
5812291a2b48SSukumar Swaminathan 
5813a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
581482527734SSukumar Swaminathan 		return (0);
5815291a2b48SSukumar Swaminathan 
581682527734SSukumar Swaminathan 	case MBX_SLEEP:
581782527734SSukumar Swaminathan 	case MBX_NOWAIT:
5818a9800bebSGarrett D'Amore 		/* Check mbox_timer, it acts as a service flag too */
5819a9800bebSGarrett D'Amore 		/* The first to service the mbox queue will clear the timer */
5820a9800bebSGarrett D'Amore 		if (hba->mbox_timer) {
5821a9800bebSGarrett D'Amore 			hba->mbox_timer = 0;
5822a9800bebSGarrett D'Amore 
5823a9800bebSGarrett D'Amore 			mutex_enter(&EMLXS_MBOX_LOCK);
5824a9800bebSGarrett D'Amore 			mbq = (MAILBOXQ *)hba->mbox_mbq;
5825a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_MBOX_LOCK);
5826a9800bebSGarrett D'Amore 		}
5827a9800bebSGarrett D'Amore 
5828a9800bebSGarrett D'Amore 		if (!mbq) {
5829a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5830a9800bebSGarrett D'Amore 			    "Mailbox event. No service required.");
5831a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_PORT_LOCK);
5832a9800bebSGarrett D'Amore 			return (0);
5833a9800bebSGarrett D'Amore 		}
5834a9800bebSGarrett D'Amore 
583582527734SSukumar Swaminathan 		mb = (MAILBOX *)mbq;
5836a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
583782527734SSukumar Swaminathan 		break;
5838291a2b48SSukumar Swaminathan 
583982527734SSukumar Swaminathan 	default:
584082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
584182527734SSukumar Swaminathan 		    "Invalid Mailbox flag (%x).");
5842a9800bebSGarrett D'Amore 
5843a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
584482527734SSukumar Swaminathan 		return (0);
584582527734SSukumar Swaminathan 	}
5846291a2b48SSukumar Swaminathan 
5847a9800bebSGarrett D'Amore 	/* Set port context */
5848a9800bebSGarrett D'Amore 	port = (emlxs_port_t *)mbq->port;
5849a9800bebSGarrett D'Amore 
585082527734SSukumar Swaminathan 	/* Get first word of mailbox */
585182527734SSukumar Swaminathan 	if (hba->flag & FC_SLIM2_MODE) {
585282527734SSukumar Swaminathan 		mbox = FC_SLIM2_MAILBOX(hba);
585382527734SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)mbox)
585482527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5855291a2b48SSukumar Swaminathan 
585682527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
585782527734SSukumar Swaminathan 		    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
585882527734SSukumar Swaminathan 		word0 = *((volatile uint32_t *)mbox);
585982527734SSukumar Swaminathan 		word0 = BE_SWAP32(word0);
586082527734SSukumar Swaminathan 	} else {
586182527734SSukumar Swaminathan 		mbox = FC_SLIM1_MAILBOX(hba);
586282527734SSukumar Swaminathan 		word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
586382527734SSukumar Swaminathan 	}
5864291a2b48SSukumar Swaminathan 
586582527734SSukumar Swaminathan 	i = 0;
586682527734SSukumar Swaminathan 	while (swpmb->mbxOwner == OWN_CHIP) {
586782527734SSukumar Swaminathan 		if (i++ > 10000) {
586882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
586982527734SSukumar Swaminathan 			    "OWN_CHIP: %s: status=%x",
587082527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
587182527734SSukumar Swaminathan 			    swpmb->mbxStatus);
5872291a2b48SSukumar Swaminathan 
587382527734SSukumar Swaminathan 			return (1);
587482527734SSukumar Swaminathan 		}
5875291a2b48SSukumar Swaminathan 
587682527734SSukumar Swaminathan 		/* Get first word of mailbox */
587782527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
587882527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
587982527734SSukumar Swaminathan 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
588082527734SSukumar Swaminathan 			word0 = *((volatile uint32_t *)mbox);
588182527734SSukumar Swaminathan 			word0 = BE_SWAP32(word0);
588282527734SSukumar Swaminathan 		} else {
588382527734SSukumar Swaminathan 			word0 =
588482527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
588582527734SSukumar Swaminathan 		}
5886a9800bebSGarrett D'Amore 	}
5887291a2b48SSukumar Swaminathan 
588882527734SSukumar Swaminathan 	/* Now that we are the owner, DMA Sync entire mailbox if needed */
588982527734SSukumar Swaminathan 	if (hba->flag & FC_SLIM2_MODE) {
589082527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
589182527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
5892291a2b48SSukumar Swaminathan 
589382527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb,
589482527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE);
589582527734SSukumar Swaminathan 	} else {
589682527734SSukumar Swaminathan 		READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox,
589782527734SSukumar Swaminathan 		    MAILBOX_CMD_WSIZE);
589882527734SSukumar Swaminathan 	}
5899291a2b48SSukumar Swaminathan 
590082527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
590182527734SSukumar Swaminathan 	if (mbq->extbuf) {
590282527734SSukumar Swaminathan 		uint32_t *mbox_ext =
590382527734SSukumar Swaminathan 		    (uint32_t *)((uint8_t *)mbox + MBOX_EXTENSION_OFFSET);
590482527734SSukumar Swaminathan 		off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
5905291a2b48SSukumar Swaminathan 
590682527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
590782527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
590882527734SSukumar Swaminathan 			    offset_ext, mbq->extsize,
590982527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
591082527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)mbox_ext,
591182527734SSukumar Swaminathan 			    (uint8_t *)mbq->extbuf, mbq->extsize);
591282527734SSukumar Swaminathan 		} else {
591382527734SSukumar Swaminathan 			READ_SLIM_COPY(hba, (uint32_t *)mbq->extbuf,
591482527734SSukumar Swaminathan 			    mbox_ext, (mbq->extsize / 4));
5915291a2b48SSukumar Swaminathan 		}
591682527734SSukumar Swaminathan 	}
591782527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
5918291a2b48SSukumar Swaminathan 
59194baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
592082527734SSukumar Swaminathan 	if (!(hba->flag & FC_SLIM2_MODE)) {
592182527734SSukumar Swaminathan 		/* Access handle validation */
592282527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
592382527734SSukumar Swaminathan 	}
59244baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5925291a2b48SSukumar Swaminathan 
592682527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
592782527734SSukumar Swaminathan 	if (mbq->bp) {
592882527734SSukumar Swaminathan 		mbox_bp = (MATCHMAP *)mbq->bp;
592982527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
593082527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
593182527734SSukumar Swaminathan 	}
5932291a2b48SSukumar Swaminathan 
593382527734SSukumar Swaminathan 	/* Mailbox has been completely received at this point */
5934291a2b48SSukumar Swaminathan 
593582527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_HEARTBEAT) {
593682527734SSukumar Swaminathan 		hba->heartbeat_active = 0;
593782527734SSukumar Swaminathan 		goto done;
5938291a2b48SSukumar Swaminathan 	}
5939291a2b48SSukumar Swaminathan 
594082527734SSukumar Swaminathan 	if (hba->mbox_queue_flag == MBX_SLEEP) {
594182527734SSukumar Swaminathan 		if (swpmb->mbxCommand != MBX_DOWN_LOAD &&
594282527734SSukumar Swaminathan 		    swpmb->mbxCommand != MBX_DUMP_MEMORY) {
594382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
594482527734SSukumar Swaminathan 			    "Received.  %s: status=%x Sleep.",
594582527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
594682527734SSukumar Swaminathan 			    swpmb->mbxStatus);
5947291a2b48SSukumar Swaminathan 		}
594882527734SSukumar Swaminathan 	} else {
594982527734SSukumar Swaminathan 		if (swpmb->mbxCommand != MBX_DOWN_LOAD &&
595082527734SSukumar Swaminathan 		    swpmb->mbxCommand != MBX_DUMP_MEMORY) {
595182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
595282527734SSukumar Swaminathan 			    "Completed. %s: status=%x",
595382527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
595482527734SSukumar Swaminathan 			    swpmb->mbxStatus);
5955291a2b48SSukumar Swaminathan 		}
595682527734SSukumar Swaminathan 	}
5957291a2b48SSukumar Swaminathan 
595882527734SSukumar Swaminathan 	/* Filter out passthru mailbox */
595982527734SSukumar Swaminathan 	if (mbq->flag & MBQ_PASSTHRU) {
596082527734SSukumar Swaminathan 		goto done;
596182527734SSukumar Swaminathan 	}
5962291a2b48SSukumar Swaminathan 
596382527734SSukumar Swaminathan 	if (mb->mbxStatus) {
596482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
596582527734SSukumar Swaminathan 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
596682527734SSukumar Swaminathan 		    (uint32_t)mb->mbxStatus);
596782527734SSukumar Swaminathan 	}
5968291a2b48SSukumar Swaminathan 
596982527734SSukumar Swaminathan 	if (mbq->mbox_cmpl) {
597082527734SSukumar Swaminathan 		rc = (mbq->mbox_cmpl)(hba, mbq);
597182527734SSukumar Swaminathan 		/* If mbox was retried, return immediately */
597282527734SSukumar Swaminathan 		if (rc) {
597382527734SSukumar Swaminathan 			return (0);
597482527734SSukumar Swaminathan 		}
597582527734SSukumar Swaminathan 	}
5976291a2b48SSukumar Swaminathan 
597782527734SSukumar Swaminathan done:
5978291a2b48SSukumar Swaminathan 
597982527734SSukumar Swaminathan 	/* Clean up the mailbox area */
598082527734SSukumar Swaminathan 	emlxs_mb_fini(hba, mb, mb->mbxStatus);
598182527734SSukumar Swaminathan 
598282527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
598382527734SSukumar Swaminathan 	if (mbq) {
598482527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
598582527734SSukumar Swaminathan 		rc =  emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
598682527734SSukumar Swaminathan 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
5987a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5988291a2b48SSukumar Swaminathan 		}
598982527734SSukumar Swaminathan 	}
599082527734SSukumar Swaminathan 	return (0);
5991291a2b48SSukumar Swaminathan 
599282527734SSukumar Swaminathan } /* emlxs_handle_mb_event() */
5993291a2b48SSukumar Swaminathan 
5994291a2b48SSukumar Swaminathan 
5995*8f23e9faSHans Rosenfeld static void
599682527734SSukumar Swaminathan emlxs_sli3_timer(emlxs_hba_t *hba)
599782527734SSukumar Swaminathan {
599882527734SSukumar Swaminathan 	/* Perform SLI3 level timer checks */
5999291a2b48SSukumar Swaminathan 
600082527734SSukumar Swaminathan 	emlxs_sli3_timer_check_mbox(hba);
6001291a2b48SSukumar Swaminathan 
600282527734SSukumar Swaminathan } /* emlxs_sli3_timer() */
6003291a2b48SSukumar Swaminathan 
600482527734SSukumar Swaminathan 
600582527734SSukumar Swaminathan static void
600682527734SSukumar Swaminathan emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba)
6007291a2b48SSukumar Swaminathan {
6008291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6009291a2b48SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
601082527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
6011291a2b48SSukumar Swaminathan 	uint32_t word0;
6012291a2b48SSukumar Swaminathan 	uint32_t offset;
6013291a2b48SSukumar Swaminathan 	uint32_t ha_copy = 0;
6014291a2b48SSukumar Swaminathan 
6015291a2b48SSukumar Swaminathan 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
6016291a2b48SSukumar Swaminathan 		return;
6017291a2b48SSukumar Swaminathan 	}
6018291a2b48SSukumar Swaminathan 
6019291a2b48SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
6020291a2b48SSukumar Swaminathan 
6021291a2b48SSukumar Swaminathan 	/* Return if timer hasn't expired */
6022291a2b48SSukumar Swaminathan 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
6023291a2b48SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
6024291a2b48SSukumar Swaminathan 		return;
6025291a2b48SSukumar Swaminathan 	}
6026291a2b48SSukumar Swaminathan 
6027291a2b48SSukumar Swaminathan 	/* Mailbox timed out, first check for error attention */
6028291a2b48SSukumar Swaminathan 	ha_copy = emlxs_check_attention(hba);
6029291a2b48SSukumar Swaminathan 
6030291a2b48SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
6031a9800bebSGarrett D'Amore 		hba->mbox_timer = 0;
6032291a2b48SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
6033291a2b48SSukumar Swaminathan 		emlxs_handle_ff_error(hba);
6034291a2b48SSukumar Swaminathan 		return;
6035291a2b48SSukumar Swaminathan 	}
6036291a2b48SSukumar Swaminathan 
6037291a2b48SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
6038291a2b48SSukumar Swaminathan 		/* Get first word of mailbox */
6039291a2b48SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
6040291a2b48SSukumar Swaminathan 			mb = FC_SLIM2_MAILBOX(hba);
604182527734SSukumar Swaminathan 			offset =
604282527734SSukumar Swaminathan 			    (off_t)((uint64_t)((unsigned long)mb) - (uint64_t)
604382527734SSukumar Swaminathan 			    ((unsigned long)hba->sli.sli3.slim2.virt));
6044291a2b48SSukumar Swaminathan 
604582527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
604682527734SSukumar Swaminathan 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
6047291a2b48SSukumar Swaminathan 			word0 = *((volatile uint32_t *)mb);
604882527734SSukumar Swaminathan 			word0 = BE_SWAP32(word0);
6049291a2b48SSukumar Swaminathan 		} else {
6050291a2b48SSukumar Swaminathan 			mb = FC_SLIM1_MAILBOX(hba);
6051291a2b48SSukumar Swaminathan 			word0 =
6052291a2b48SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb));
60534baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
60544baa2c25SSukumar Swaminathan 			/* Access handle validation */
605582527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
605682527734SSukumar Swaminathan 			    hba->sli.sli3.slim_acc_handle);
60574baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6058291a2b48SSukumar Swaminathan 		}
6059291a2b48SSukumar Swaminathan 
6060291a2b48SSukumar Swaminathan 		mb = (MAILBOX *)&word0;
6061291a2b48SSukumar Swaminathan 
6062291a2b48SSukumar Swaminathan 		/* Check if mailbox has actually completed */
6063291a2b48SSukumar Swaminathan 		if (mb->mbxOwner == OWN_HOST) {
6064291a2b48SSukumar Swaminathan 			/* Read host attention register to determine */
6065291a2b48SSukumar Swaminathan 			/* interrupt source */
6066291a2b48SSukumar Swaminathan 			uint32_t ha_copy = emlxs_check_attention(hba);
6067291a2b48SSukumar Swaminathan 
6068291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
6069291a2b48SSukumar Swaminathan 			    "Mailbox attention missed: %s. Forcing event. "
6070291a2b48SSukumar Swaminathan 			    "hc=%x ha=%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
607182527734SSukumar Swaminathan 			    hba->sli.sli3.hc_copy, ha_copy);
6072291a2b48SSukumar Swaminathan 
6073291a2b48SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
6074291a2b48SSukumar Swaminathan 
6075291a2b48SSukumar Swaminathan 			(void) emlxs_handle_mb_event(hba);
6076291a2b48SSukumar Swaminathan 
6077291a2b48SSukumar Swaminathan 			return;
6078291a2b48SSukumar Swaminathan 		}
6079291a2b48SSukumar Swaminathan 
6080a9800bebSGarrett D'Amore 		/* The first to service the mbox queue will clear the timer */
6081a9800bebSGarrett D'Amore 		/* We will service the mailbox here */
6082a9800bebSGarrett D'Amore 		hba->mbox_timer = 0;
6083a9800bebSGarrett D'Amore 
6084a9800bebSGarrett D'Amore 		mutex_enter(&EMLXS_MBOX_LOCK);
6085a9800bebSGarrett D'Amore 		mb = (MAILBOX *)hba->mbox_mbq;
6086a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_MBOX_LOCK);
6087291a2b48SSukumar Swaminathan 	}
6088291a2b48SSukumar Swaminathan 
608982527734SSukumar Swaminathan 	if (mb) {
609082527734SSukumar Swaminathan 		switch (hba->mbox_queue_flag) {
609182527734SSukumar Swaminathan 		case MBX_NOWAIT:
609282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
609382527734SSukumar Swaminathan 			    "%s: Nowait.",
609482527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
609582527734SSukumar Swaminathan 			break;
6096291a2b48SSukumar Swaminathan 
609782527734SSukumar Swaminathan 		case MBX_SLEEP:
609882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
609982527734SSukumar Swaminathan 			    "%s: mb=%p Sleep.",
610082527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
610182527734SSukumar Swaminathan 			    mb);
610282527734SSukumar Swaminathan 			break;
6103291a2b48SSukumar Swaminathan 
610482527734SSukumar Swaminathan 		case MBX_POLL:
610582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
610682527734SSukumar Swaminathan 			    "%s: mb=%p Polled.",
610782527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
610882527734SSukumar Swaminathan 			    mb);
610982527734SSukumar Swaminathan 			break;
6110291a2b48SSukumar Swaminathan 
611182527734SSukumar Swaminathan 		default:
611282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
611382527734SSukumar Swaminathan 			    "%s: mb=%p (%d).",
611482527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
611582527734SSukumar Swaminathan 			    mb, hba->mbox_queue_flag);
611682527734SSukumar Swaminathan 			break;
611782527734SSukumar Swaminathan 		}
611882527734SSukumar Swaminathan 	} else {
6119291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
6120291a2b48SSukumar Swaminathan 	}
6121291a2b48SSukumar Swaminathan 
6122291a2b48SSukumar Swaminathan 	hba->flag |= FC_MBOX_TIMEOUT;
612382527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
6124291a2b48SSukumar Swaminathan 
6125291a2b48SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
6126291a2b48SSukumar Swaminathan 
6127291a2b48SSukumar Swaminathan 	/* Perform mailbox cleanup */
6128291a2b48SSukumar Swaminathan 	/* This will wake any sleeping or polling threads */
6129291a2b48SSukumar Swaminathan 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
6130291a2b48SSukumar Swaminathan 
6131291a2b48SSukumar Swaminathan 	/* Trigger adapter shutdown */
6132bb63f56eSSukumar Swaminathan 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
6133291a2b48SSukumar Swaminathan 
6134291a2b48SSukumar Swaminathan 	return;
6135291a2b48SSukumar Swaminathan 
613682527734SSukumar Swaminathan } /* emlxs_sli3_timer_check_mbox() */
6137291a2b48SSukumar Swaminathan 
6138291a2b48SSukumar Swaminathan 
6139291a2b48SSukumar Swaminathan /*
6140291a2b48SSukumar Swaminathan  * emlxs_mb_config_port  Issue a CONFIG_PORT mailbox command
6141291a2b48SSukumar Swaminathan  */
614282527734SSukumar Swaminathan static uint32_t
614382527734SSukumar Swaminathan emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t sli_mode,
6144291a2b48SSukumar Swaminathan     uint32_t hbainit)
6145291a2b48SSukumar Swaminathan {
614682527734SSukumar Swaminathan 	MAILBOX		*mb = (MAILBOX *)mbq;
6147291a2b48SSukumar Swaminathan 	emlxs_vpd_t	*vpd = &VPD;
6148291a2b48SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
6149291a2b48SSukumar Swaminathan 	emlxs_config_t	*cfg;
6150291a2b48SSukumar Swaminathan 	RING		*rp;
6151291a2b48SSukumar Swaminathan 	uint64_t	pcb;
6152291a2b48SSukumar Swaminathan 	uint64_t	mbx;
6153291a2b48SSukumar Swaminathan 	uint64_t	hgp;
6154291a2b48SSukumar Swaminathan 	uint64_t	pgp;
6155291a2b48SSukumar Swaminathan 	uint64_t	rgp;
6156291a2b48SSukumar Swaminathan 	MAILBOX		*mbox;
6157291a2b48SSukumar Swaminathan 	SLIM2		*slim;
6158291a2b48SSukumar Swaminathan 	SLI2_RDSC	*rdsc;
6159291a2b48SSukumar Swaminathan 	uint64_t	offset;
6160291a2b48SSukumar Swaminathan 	uint32_t	Laddr;
6161291a2b48SSukumar Swaminathan 	uint32_t	i;
6162291a2b48SSukumar Swaminathan 
6163291a2b48SSukumar Swaminathan 	cfg = &CFG;
6164291a2b48SSukumar Swaminathan 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
6165291a2b48SSukumar Swaminathan 	mbox = NULL;
6166291a2b48SSukumar Swaminathan 	slim = NULL;
6167291a2b48SSukumar Swaminathan 
6168291a2b48SSukumar Swaminathan 	mb->mbxCommand = MBX_CONFIG_PORT;
6169291a2b48SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
617082527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
6171291a2b48SSukumar Swaminathan 
6172291a2b48SSukumar Swaminathan 	mb->un.varCfgPort.pcbLen = sizeof (PCB);
6173291a2b48SSukumar Swaminathan 	mb->un.varCfgPort.hbainit[0] = hbainit;
6174291a2b48SSukumar Swaminathan 
617582527734SSukumar Swaminathan 	pcb = hba->sli.sli3.slim2.phys +
617682527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)&(slim->pcb));
617782527734SSukumar Swaminathan 	mb->un.varCfgPort.pcbLow = PADDR_LO(pcb);
617882527734SSukumar Swaminathan 	mb->un.varCfgPort.pcbHigh = PADDR_HI(pcb);
6179291a2b48SSukumar Swaminathan 
6180291a2b48SSukumar Swaminathan 	/* Set Host pointers in SLIM flag */
6181291a2b48SSukumar Swaminathan 	mb->un.varCfgPort.hps = 1;
6182291a2b48SSukumar Swaminathan 
6183291a2b48SSukumar Swaminathan 	/* Initialize hba structure for assumed default SLI2 mode */
6184291a2b48SSukumar Swaminathan 	/* If config port succeeds, then we will update it then   */
6185291a2b48SSukumar Swaminathan 	hba->sli_mode = sli_mode;
618682527734SSukumar Swaminathan 	hba->vpi_max = 0;
6187291a2b48SSukumar Swaminathan 	hba->flag &= ~FC_NPIV_ENABLED;
6188291a2b48SSukumar Swaminathan 
618982527734SSukumar Swaminathan 	if (sli_mode == EMLXS_HBA_SLI3_MODE) {
6190291a2b48SSukumar Swaminathan 		mb->un.varCfgPort.sli_mode = EMLXS_HBA_SLI3_MODE;
6191291a2b48SSukumar Swaminathan 		mb->un.varCfgPort.cerbm = 1;
6192291a2b48SSukumar Swaminathan 		mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ;
6193291a2b48SSukumar Swaminathan 
6194291a2b48SSukumar Swaminathan 		if (cfg[CFG_NPIV_ENABLE].current) {
6195291a2b48SSukumar Swaminathan 			if (vpd->feaLevelHigh >= 0x09) {
6196291a2b48SSukumar Swaminathan 				if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
6197291a2b48SSukumar Swaminathan 					mb->un.varCfgPort.vpi_max =
6198291a2b48SSukumar Swaminathan 					    MAX_VPORTS - 1;
6199291a2b48SSukumar Swaminathan 				} else {
6200291a2b48SSukumar Swaminathan 					mb->un.varCfgPort.vpi_max =
6201291a2b48SSukumar Swaminathan 					    MAX_VPORTS_LIMITED - 1;
6202291a2b48SSukumar Swaminathan 				}
6203291a2b48SSukumar Swaminathan 
6204291a2b48SSukumar Swaminathan 				mb->un.varCfgPort.cmv = 1;
6205291a2b48SSukumar Swaminathan 			} else {
6206291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
6207291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
6208291a2b48SSukumar Swaminathan 				    "CFGPORT: Firmware does not support NPIV. "
6209291a2b48SSukumar Swaminathan 				    "level=%d", vpd->feaLevelHigh);
6210291a2b48SSukumar Swaminathan 			}
6211291a2b48SSukumar Swaminathan 
6212291a2b48SSukumar Swaminathan 		}
6213291a2b48SSukumar Swaminathan 	}
6214291a2b48SSukumar Swaminathan 
6215291a2b48SSukumar Swaminathan 	/*
6216291a2b48SSukumar Swaminathan 	 * Now setup pcb
6217291a2b48SSukumar Swaminathan 	 */
621882527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.type = TYPE_NATIVE_SLI2;
621982527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2;
622082527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.maxRing =
622182527734SSukumar Swaminathan 	    (hba->sli.sli3.ring_count - 1);
622282527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mailBoxSize =
6223291a2b48SSukumar Swaminathan 	    sizeof (MAILBOX) + MBOX_EXTENSION_SIZE;
6224291a2b48SSukumar Swaminathan 
622582527734SSukumar Swaminathan 	mbx = hba->sli.sli3.slim2.phys +
622682527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)&(slim->mbx));
622782527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrHigh = PADDR_HI(mbx);
622882527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrLow = PADDR_LO(mbx);
6229291a2b48SSukumar Swaminathan 
6230291a2b48SSukumar Swaminathan 
6231291a2b48SSukumar Swaminathan 	/*
6232291a2b48SSukumar Swaminathan 	 * Set up HGP - Port Memory
6233291a2b48SSukumar Swaminathan 	 *
6234291a2b48SSukumar Swaminathan 	 * CR0Put   - SLI2(no HBQs) =	0xc0, With HBQs =	0x80
6235291a2b48SSukumar Swaminathan 	 * RR0Get			0xc4			0x84
6236291a2b48SSukumar Swaminathan 	 * CR1Put			0xc8			0x88
6237291a2b48SSukumar Swaminathan 	 * RR1Get			0xcc			0x8c
6238291a2b48SSukumar Swaminathan 	 * CR2Put			0xd0			0x90
6239291a2b48SSukumar Swaminathan 	 * RR2Get			0xd4			0x94
6240291a2b48SSukumar Swaminathan 	 * CR3Put			0xd8			0x98
6241291a2b48SSukumar Swaminathan 	 * RR3Get			0xdc			0x9c
6242291a2b48SSukumar Swaminathan 	 *
6243291a2b48SSukumar Swaminathan 	 * Reserved			0xa0-0xbf
6244291a2b48SSukumar Swaminathan 	 *
6245291a2b48SSukumar Swaminathan 	 * If HBQs configured:
6246291a2b48SSukumar Swaminathan 	 * HBQ 0 Put ptr  0xc0
6247291a2b48SSukumar Swaminathan 	 * HBQ 1 Put ptr  0xc4
6248291a2b48SSukumar Swaminathan 	 * HBQ 2 Put ptr  0xc8
6249291a2b48SSukumar Swaminathan 	 * ...
6250291a2b48SSukumar Swaminathan 	 * HBQ(M-1)Put Pointer 0xc0+(M-1)*4
6251291a2b48SSukumar Swaminathan 	 */
6252291a2b48SSukumar Swaminathan 
6253291a2b48SSukumar Swaminathan 	if (sli_mode >= EMLXS_HBA_SLI3_MODE) {
6254291a2b48SSukumar Swaminathan 		/* ERBM is enabled */
625582527734SSukumar Swaminathan 		hba->sli.sli3.hgp_ring_offset = 0x80;
625682527734SSukumar Swaminathan 		hba->sli.sli3.hgp_hbq_offset = 0xC0;
6257291a2b48SSukumar Swaminathan 
625882527734SSukumar Swaminathan 		hba->sli.sli3.iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
625982527734SSukumar Swaminathan 		hba->sli.sli3.iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
6260291a2b48SSukumar Swaminathan 
626182527734SSukumar Swaminathan 	} else { /* SLI2 */
6262291a2b48SSukumar Swaminathan 		/* ERBM is disabled */
626382527734SSukumar Swaminathan 		hba->sli.sli3.hgp_ring_offset = 0xC0;
626482527734SSukumar Swaminathan 		hba->sli.sli3.hgp_hbq_offset = 0;
6265291a2b48SSukumar Swaminathan 
626682527734SSukumar Swaminathan 		hba->sli.sli3.iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
626782527734SSukumar Swaminathan 		hba->sli.sli3.iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
6268291a2b48SSukumar Swaminathan 	}
6269291a2b48SSukumar Swaminathan 
6270291a2b48SSukumar Swaminathan 	/* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */
6271291a2b48SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
627282527734SSukumar Swaminathan 		hgp = hba->sli.sli3.slim2.phys +
6273291a2b48SSukumar Swaminathan 		    (uint64_t)((unsigned long)&(mbox->us.s2.host));
627482527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh =
627582527734SSukumar Swaminathan 		    PADDR_HI(hgp);
627682527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow =
627782527734SSukumar Swaminathan 		    PADDR_LO(hgp);
6278291a2b48SSukumar Swaminathan 	} else {
627982527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh =
6280291a2b48SSukumar Swaminathan 		    (uint32_t)ddi_get32(hba->pci_acc_handle,
6281291a2b48SSukumar Swaminathan 		    (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER));
6282291a2b48SSukumar Swaminathan 
6283291a2b48SSukumar Swaminathan 		Laddr =
6284291a2b48SSukumar Swaminathan 		    ddi_get32(hba->pci_acc_handle,
6285291a2b48SSukumar Swaminathan 		    (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER));
6286291a2b48SSukumar Swaminathan 		Laddr &= ~0x4;
628782527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow =
628882527734SSukumar Swaminathan 		    (uint32_t)(Laddr + hba->sli.sli3.hgp_ring_offset);
6289291a2b48SSukumar Swaminathan 
62904baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
62914baa2c25SSukumar Swaminathan 		/* Access handle validation */
629282527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
62934baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
629482527734SSukumar Swaminathan 
6295291a2b48SSukumar Swaminathan 	}
6296291a2b48SSukumar Swaminathan 
629782527734SSukumar Swaminathan 	pgp = hba->sli.sli3.slim2.phys +
629882527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)&(mbox->us.s2.port));
629982527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrHigh =
630082527734SSukumar Swaminathan 	    PADDR_HI(pgp);
630182527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrLow =
630282527734SSukumar Swaminathan 	    PADDR_LO(pgp);
6303291a2b48SSukumar Swaminathan 
6304291a2b48SSukumar Swaminathan 	offset = 0;
6305291a2b48SSukumar Swaminathan 	for (i = 0; i < 4; i++) {
630682527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[i];
630782527734SSukumar Swaminathan 		rdsc = &((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.rdsc[i];
6308291a2b48SSukumar Swaminathan 
6309291a2b48SSukumar Swaminathan 		/* Setup command ring */
631082527734SSukumar Swaminathan 		rgp = hba->sli.sli3.slim2.phys +
6311291a2b48SSukumar Swaminathan 		    (uint64_t)((unsigned long)&(slim->IOCBs[offset]));
631282527734SSukumar Swaminathan 		rdsc->cmdAddrHigh = PADDR_HI(rgp);
631382527734SSukumar Swaminathan 		rdsc->cmdAddrLow = PADDR_LO(rgp);
6314291a2b48SSukumar Swaminathan 		rdsc->cmdEntries = rp->fc_numCiocb;
6315291a2b48SSukumar Swaminathan 
6316291a2b48SSukumar Swaminathan 		rp->fc_cmdringaddr =
631782527734SSukumar Swaminathan 		    (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset];
631882527734SSukumar Swaminathan 		offset += rdsc->cmdEntries * hba->sli.sli3.iocb_cmd_size;
6319291a2b48SSukumar Swaminathan 
6320291a2b48SSukumar Swaminathan 		/* Setup response ring */
632182527734SSukumar Swaminathan 		rgp = hba->sli.sli3.slim2.phys +
6322291a2b48SSukumar Swaminathan 		    (uint64_t)((unsigned long)&(slim->IOCBs[offset]));
632382527734SSukumar Swaminathan 		rdsc->rspAddrHigh = PADDR_HI(rgp);
632482527734SSukumar Swaminathan 		rdsc->rspAddrLow = PADDR_LO(rgp);
6325291a2b48SSukumar Swaminathan 		rdsc->rspEntries = rp->fc_numRiocb;
6326291a2b48SSukumar Swaminathan 
6327291a2b48SSukumar Swaminathan 		rp->fc_rspringaddr =
632882527734SSukumar Swaminathan 		    (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset];
632982527734SSukumar Swaminathan 		offset += rdsc->rspEntries * hba->sli.sli3.iocb_rsp_size;
6330291a2b48SSukumar Swaminathan 	}
6331291a2b48SSukumar Swaminathan 
633282527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)
633382527734SSukumar Swaminathan 	    (&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb),
633482527734SSukumar Swaminathan 	    (uint8_t *)(&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb),
633582527734SSukumar Swaminathan 	    sizeof (PCB));
6336291a2b48SSukumar Swaminathan 
633782527734SSukumar Swaminathan 	offset = ((uint64_t)((unsigned long)
633882527734SSukumar Swaminathan 	    &(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb)) -
633982527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
634082527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, (off_t)offset,
634182527734SSukumar Swaminathan 	    sizeof (PCB), DDI_DMA_SYNC_FORDEV);
6342291a2b48SSukumar Swaminathan 
6343291a2b48SSukumar Swaminathan 	return (0);
6344291a2b48SSukumar Swaminathan 
6345291a2b48SSukumar Swaminathan } /* emlxs_mb_config_port() */
6346291a2b48SSukumar Swaminathan 
6347291a2b48SSukumar Swaminathan 
634882527734SSukumar Swaminathan static uint32_t
6349291a2b48SSukumar Swaminathan emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id)
6350291a2b48SSukumar Swaminathan {
6351291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6352291a2b48SSukumar Swaminathan 	HBQ_INIT_t *hbq;
6353291a2b48SSukumar Swaminathan 	MATCHMAP *mp;
6354291a2b48SSukumar Swaminathan 	HBQE_t *hbqE;
6355291a2b48SSukumar Swaminathan 	MAILBOX *mb;
635682527734SSukumar Swaminathan 	MAILBOXQ *mbq;
6357291a2b48SSukumar Swaminathan 	void *ioa2;
6358291a2b48SSukumar Swaminathan 	uint32_t j;
6359291a2b48SSukumar Swaminathan 	uint32_t count;
6360291a2b48SSukumar Swaminathan 	uint32_t size;
6361291a2b48SSukumar Swaminathan 	uint32_t ringno;
6362291a2b48SSukumar Swaminathan 	uint32_t seg;
6363291a2b48SSukumar Swaminathan 
6364291a2b48SSukumar Swaminathan 	switch (hbq_id) {
6365291a2b48SSukumar Swaminathan 	case EMLXS_ELS_HBQ_ID:
6366291a2b48SSukumar Swaminathan 		count = MEM_ELSBUF_COUNT;
6367291a2b48SSukumar Swaminathan 		size = MEM_ELSBUF_SIZE;
6368291a2b48SSukumar Swaminathan 		ringno = FC_ELS_RING;
6369291a2b48SSukumar Swaminathan 		seg = MEM_ELSBUF;
6370291a2b48SSukumar Swaminathan 		HBASTATS.ElsUbPosted = count;
6371291a2b48SSukumar Swaminathan 		break;
6372291a2b48SSukumar Swaminathan 
6373291a2b48SSukumar Swaminathan 	case EMLXS_IP_HBQ_ID:
6374291a2b48SSukumar Swaminathan 		count = MEM_IPBUF_COUNT;
6375291a2b48SSukumar Swaminathan 		size = MEM_IPBUF_SIZE;
6376291a2b48SSukumar Swaminathan 		ringno = FC_IP_RING;
6377291a2b48SSukumar Swaminathan 		seg = MEM_IPBUF;
6378291a2b48SSukumar Swaminathan 		HBASTATS.IpUbPosted = count;
6379291a2b48SSukumar Swaminathan 		break;
6380291a2b48SSukumar Swaminathan 
6381291a2b48SSukumar Swaminathan 	case EMLXS_CT_HBQ_ID:
6382291a2b48SSukumar Swaminathan 		count = MEM_CTBUF_COUNT;
6383291a2b48SSukumar Swaminathan 		size = MEM_CTBUF_SIZE;
6384291a2b48SSukumar Swaminathan 		ringno = FC_CT_RING;
6385291a2b48SSukumar Swaminathan 		seg = MEM_CTBUF;
6386291a2b48SSukumar Swaminathan 		HBASTATS.CtUbPosted = count;
6387291a2b48SSukumar Swaminathan 		break;
6388291a2b48SSukumar Swaminathan 
6389291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
6390291a2b48SSukumar Swaminathan 	case EMLXS_FCT_HBQ_ID:
6391291a2b48SSukumar Swaminathan 		count = MEM_FCTBUF_COUNT;
6392291a2b48SSukumar Swaminathan 		size = MEM_FCTBUF_SIZE;
6393291a2b48SSukumar Swaminathan 		ringno = FC_FCT_RING;
6394291a2b48SSukumar Swaminathan 		seg = MEM_FCTBUF;
6395291a2b48SSukumar Swaminathan 		HBASTATS.FctUbPosted = count;
6396291a2b48SSukumar Swaminathan 		break;
6397291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
6398291a2b48SSukumar Swaminathan 
6399291a2b48SSukumar Swaminathan 	default:
6400291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6401*8f23e9faSHans Rosenfeld 		    "hbq_setup: Invalid HBQ id. (%x)", hbq_id);
6402291a2b48SSukumar Swaminathan 		return (1);
6403291a2b48SSukumar Swaminathan 	}
6404291a2b48SSukumar Swaminathan 
6405291a2b48SSukumar Swaminathan 	/* Configure HBQ */
640682527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
6407291a2b48SSukumar Swaminathan 	hbq->HBQ_numEntries = count;
6408291a2b48SSukumar Swaminathan 
6409291a2b48SSukumar Swaminathan 	/* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */
6410*8f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) {
6411291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6412*8f23e9faSHans Rosenfeld 		    "hbq_setup: Unable to get mailbox.");
6413291a2b48SSukumar Swaminathan 		return (1);
6414291a2b48SSukumar Swaminathan 	}
641582527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
6416291a2b48SSukumar Swaminathan 
6417291a2b48SSukumar Swaminathan 	/* Allocate HBQ Host buffer and Initialize the HBQEs */
6418291a2b48SSukumar Swaminathan 	if (emlxs_hbq_alloc(hba, hbq_id)) {
6419291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6420*8f23e9faSHans Rosenfeld 		    "hbq_setup: Unable to allocate HBQ.");
6421a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6422291a2b48SSukumar Swaminathan 		return (1);
6423291a2b48SSukumar Swaminathan 	}
6424291a2b48SSukumar Swaminathan 
6425291a2b48SSukumar Swaminathan 	hbq->HBQ_recvNotify = 1;
6426291a2b48SSukumar Swaminathan 	hbq->HBQ_num_mask = 0;			/* Bind to ring */
6427291a2b48SSukumar Swaminathan 	hbq->HBQ_profile = 0;			/* Selection profile */
6428291a2b48SSukumar Swaminathan 						/* 0=all, 7=logentry */
6429291a2b48SSukumar Swaminathan 	hbq->HBQ_ringMask = 1 << ringno;	/* b0100 * ringno - Binds */
6430291a2b48SSukumar Swaminathan 						/* HBQ to a ring */
6431291a2b48SSukumar Swaminathan 						/* Ring0=b0001, Ring1=b0010, */
6432291a2b48SSukumar Swaminathan 						/* Ring2=b0100 */
6433291a2b48SSukumar Swaminathan 	hbq->HBQ_headerLen = 0;			/* 0 if not profile 4 or 5 */
6434291a2b48SSukumar Swaminathan 	hbq->HBQ_logEntry = 0;			/* Set to 1 if this HBQ will */
6435291a2b48SSukumar Swaminathan 						/* be used for */
6436291a2b48SSukumar Swaminathan 	hbq->HBQ_id = hbq_id;
6437291a2b48SSukumar Swaminathan 	hbq->HBQ_PutIdx_next = 0;
6438291a2b48SSukumar Swaminathan 	hbq->HBQ_PutIdx = hbq->HBQ_numEntries - 1;
6439291a2b48SSukumar Swaminathan 	hbq->HBQ_GetIdx = 0;
6440291a2b48SSukumar Swaminathan 	hbq->HBQ_PostBufCnt = hbq->HBQ_numEntries;
6441291a2b48SSukumar Swaminathan 	bzero(hbq->HBQ_PostBufs, sizeof (hbq->HBQ_PostBufs));
6442291a2b48SSukumar Swaminathan 
6443291a2b48SSukumar Swaminathan 	/* Fill in POST BUFFERs in HBQE */
6444291a2b48SSukumar Swaminathan 	hbqE = (HBQE_t *)hbq->HBQ_host_buf.virt;
6445291a2b48SSukumar Swaminathan 	for (j = 0; j < hbq->HBQ_numEntries; j++, hbqE++) {
6446291a2b48SSukumar Swaminathan 		/* Allocate buffer to post */
6447291a2b48SSukumar Swaminathan 		if ((mp = (MATCHMAP *)emlxs_mem_get(hba,
6448*8f23e9faSHans Rosenfeld 		    seg)) == 0) {
6449291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6450*8f23e9faSHans Rosenfeld 			    "hbq_setup: Unable to allocate HBQ buffer. "
6451291a2b48SSukumar Swaminathan 			    "cnt=%d", j);
6452291a2b48SSukumar Swaminathan 			emlxs_hbq_free_all(hba, hbq_id);
6453291a2b48SSukumar Swaminathan 			return (1);
6454291a2b48SSukumar Swaminathan 		}
6455291a2b48SSukumar Swaminathan 
6456291a2b48SSukumar Swaminathan 		hbq->HBQ_PostBufs[j] = mp;
6457291a2b48SSukumar Swaminathan 
6458291a2b48SSukumar Swaminathan 		hbqE->unt.ext.HBQ_tag = hbq_id;
6459291a2b48SSukumar Swaminathan 		hbqE->unt.ext.HBQE_tag = j;
6460291a2b48SSukumar Swaminathan 		hbqE->bde.tus.f.bdeSize = size;
6461291a2b48SSukumar Swaminathan 		hbqE->bde.tus.f.bdeFlags = 0;
646282527734SSukumar Swaminathan 		hbqE->unt.w = BE_SWAP32(hbqE->unt.w);
646382527734SSukumar Swaminathan 		hbqE->bde.tus.w = BE_SWAP32(hbqE->bde.tus.w);
6464291a2b48SSukumar Swaminathan 		hbqE->bde.addrLow =
646582527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_LO(mp->phys));
6466291a2b48SSukumar Swaminathan 		hbqE->bde.addrHigh =
646782527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_HI(mp->phys));
6468291a2b48SSukumar Swaminathan 	}
6469291a2b48SSukumar Swaminathan 
6470291a2b48SSukumar Swaminathan 	/* Issue CONFIG_HBQ */
647182527734SSukumar Swaminathan 	emlxs_mb_config_hbq(hba, mbq, hbq_id);
647282527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
6473291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
6474*8f23e9faSHans Rosenfeld 		    "hbq_setup: Unable to config HBQ. cmd=%x status=%x",
6475291a2b48SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
6476291a2b48SSukumar Swaminathan 
6477a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6478291a2b48SSukumar Swaminathan 		emlxs_hbq_free_all(hba, hbq_id);
6479291a2b48SSukumar Swaminathan 		return (1);
6480291a2b48SSukumar Swaminathan 	}
6481291a2b48SSukumar Swaminathan 
6482291a2b48SSukumar Swaminathan 	/* Setup HBQ Get/Put indexes */
648382527734SSukumar Swaminathan 	ioa2 = (void *)((char *)hba->sli.sli3.slim_addr +
648482527734SSukumar Swaminathan 	    (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t))));
6485291a2b48SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, hbq->HBQ_PutIdx);
6486291a2b48SSukumar Swaminathan 
648782527734SSukumar Swaminathan 	hba->sli.sli3.hbq_count++;
6488291a2b48SSukumar Swaminathan 
6489a9800bebSGarrett D'Amore 	emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6490291a2b48SSukumar Swaminathan 
64914baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64924baa2c25SSukumar Swaminathan 	/* Access handle validation */
649382527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
64944baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
64954baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
64964baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
64974baa2c25SSukumar Swaminathan 		emlxs_hbq_free_all(hba, hbq_id);
64984baa2c25SSukumar Swaminathan 		return (1);
64994baa2c25SSukumar Swaminathan 	}
65004baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
65014baa2c25SSukumar Swaminathan 
6502291a2b48SSukumar Swaminathan 	return (0);
6503291a2b48SSukumar Swaminathan 
650482527734SSukumar Swaminathan } /* emlxs_hbq_setup() */
6505291a2b48SSukumar Swaminathan 
6506291a2b48SSukumar Swaminathan 
650782527734SSukumar Swaminathan extern void
6508291a2b48SSukumar Swaminathan emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id)
6509291a2b48SSukumar Swaminathan {
6510291a2b48SSukumar Swaminathan 	HBQ_INIT_t *hbq;
6511291a2b48SSukumar Swaminathan 	MBUF_INFO *buf_info;
6512291a2b48SSukumar Swaminathan 	MBUF_INFO bufinfo;
6513291a2b48SSukumar Swaminathan 	uint32_t seg;
6514291a2b48SSukumar Swaminathan 	uint32_t j;
6515291a2b48SSukumar Swaminathan 
6516291a2b48SSukumar Swaminathan 	switch (hbq_id) {
6517291a2b48SSukumar Swaminathan 	case EMLXS_ELS_HBQ_ID:
6518291a2b48SSukumar Swaminathan 		seg = MEM_ELSBUF;
6519291a2b48SSukumar Swaminathan 		HBASTATS.ElsUbPosted = 0;
6520291a2b48SSukumar Swaminathan 		break;
6521291a2b48SSukumar Swaminathan 
6522291a2b48SSukumar Swaminathan 	case EMLXS_IP_HBQ_ID:
6523291a2b48SSukumar Swaminathan 		seg = MEM_IPBUF;
6524291a2b48SSukumar Swaminathan 		HBASTATS.IpUbPosted = 0;
6525291a2b48SSukumar Swaminathan 		break;
6526291a2b48SSukumar Swaminathan 
6527291a2b48SSukumar Swaminathan 	case EMLXS_CT_HBQ_ID:
6528291a2b48SSukumar Swaminathan 		seg = MEM_CTBUF;
6529291a2b48SSukumar Swaminathan 		HBASTATS.CtUbPosted = 0;
6530291a2b48SSukumar Swaminathan 		break;
6531291a2b48SSukumar Swaminathan 
6532291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
6533291a2b48SSukumar Swaminathan 	case EMLXS_FCT_HBQ_ID:
6534291a2b48SSukumar Swaminathan 		seg = MEM_FCTBUF;
6535291a2b48SSukumar Swaminathan 		HBASTATS.FctUbPosted = 0;
6536291a2b48SSukumar Swaminathan 		break;
6537291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
6538291a2b48SSukumar Swaminathan 
6539291a2b48SSukumar Swaminathan 	default:
6540291a2b48SSukumar Swaminathan 		return;
6541291a2b48SSukumar Swaminathan 	}
6542291a2b48SSukumar Swaminathan 
6543291a2b48SSukumar Swaminathan 
654482527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
6545291a2b48SSukumar Swaminathan 
6546291a2b48SSukumar Swaminathan 	if (hbq->HBQ_host_buf.virt != 0) {
6547291a2b48SSukumar Swaminathan 		for (j = 0; j < hbq->HBQ_PostBufCnt; j++) {
6548a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, seg,
6549a9800bebSGarrett D'Amore 			    (void *)hbq->HBQ_PostBufs[j]);
6550291a2b48SSukumar Swaminathan 			hbq->HBQ_PostBufs[j] = NULL;
6551291a2b48SSukumar Swaminathan 		}
6552291a2b48SSukumar Swaminathan 		hbq->HBQ_PostBufCnt = 0;
6553291a2b48SSukumar Swaminathan 
6554291a2b48SSukumar Swaminathan 		buf_info = &bufinfo;
6555291a2b48SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
6556291a2b48SSukumar Swaminathan 
6557291a2b48SSukumar Swaminathan 		buf_info->size = hbq->HBQ_host_buf.size;
6558291a2b48SSukumar Swaminathan 		buf_info->virt = hbq->HBQ_host_buf.virt;
6559291a2b48SSukumar Swaminathan 		buf_info->phys = hbq->HBQ_host_buf.phys;
6560291a2b48SSukumar Swaminathan 		buf_info->dma_handle = hbq->HBQ_host_buf.dma_handle;
6561291a2b48SSukumar Swaminathan 		buf_info->data_handle = hbq->HBQ_host_buf.data_handle;
6562291a2b48SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA;
6563291a2b48SSukumar Swaminathan 
6564291a2b48SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
6565291a2b48SSukumar Swaminathan 
6566291a2b48SSukumar Swaminathan 		hbq->HBQ_host_buf.virt = NULL;
6567291a2b48SSukumar Swaminathan 	}
6568291a2b48SSukumar Swaminathan 
6569291a2b48SSukumar Swaminathan 	return;
6570291a2b48SSukumar Swaminathan 
657182527734SSukumar Swaminathan } /* emlxs_hbq_free_all() */
6572291a2b48SSukumar Swaminathan 
6573291a2b48SSukumar Swaminathan 
657482527734SSukumar Swaminathan extern void
6575291a2b48SSukumar Swaminathan emlxs_update_HBQ_index(emlxs_hba_t *hba, uint32_t hbq_id)
6576291a2b48SSukumar Swaminathan {
65774baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
65784baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
65794baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6580291a2b48SSukumar Swaminathan 	void *ioa2;
6581291a2b48SSukumar Swaminathan 	uint32_t status;
6582291a2b48SSukumar Swaminathan 	uint32_t HBQ_PortGetIdx;
6583291a2b48SSukumar Swaminathan 	HBQ_INIT_t *hbq;
6584291a2b48SSukumar Swaminathan 
6585291a2b48SSukumar Swaminathan 	switch (hbq_id) {
6586291a2b48SSukumar Swaminathan 	case EMLXS_ELS_HBQ_ID:
6587291a2b48SSukumar Swaminathan 		HBASTATS.ElsUbPosted++;
6588291a2b48SSukumar Swaminathan 		break;
6589291a2b48SSukumar Swaminathan 
6590291a2b48SSukumar Swaminathan 	case EMLXS_IP_HBQ_ID:
6591291a2b48SSukumar Swaminathan 		HBASTATS.IpUbPosted++;
6592291a2b48SSukumar Swaminathan 		break;
6593291a2b48SSukumar Swaminathan 
6594291a2b48SSukumar Swaminathan 	case EMLXS_CT_HBQ_ID:
6595291a2b48SSukumar Swaminathan 		HBASTATS.CtUbPosted++;
6596291a2b48SSukumar Swaminathan 		break;
6597291a2b48SSukumar Swaminathan 
6598291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
6599291a2b48SSukumar Swaminathan 	case EMLXS_FCT_HBQ_ID:
6600291a2b48SSukumar Swaminathan 		HBASTATS.FctUbPosted++;
6601291a2b48SSukumar Swaminathan 		break;
6602291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
6603291a2b48SSukumar Swaminathan 
6604291a2b48SSukumar Swaminathan 	default:
6605291a2b48SSukumar Swaminathan 		return;
6606291a2b48SSukumar Swaminathan 	}
6607291a2b48SSukumar Swaminathan 
660882527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
6609291a2b48SSukumar Swaminathan 
6610291a2b48SSukumar Swaminathan 	hbq->HBQ_PutIdx =
6611291a2b48SSukumar Swaminathan 	    (hbq->HBQ_PutIdx + 1 >=
6612291a2b48SSukumar Swaminathan 	    hbq->HBQ_numEntries) ? 0 : hbq->HBQ_PutIdx + 1;
6613291a2b48SSukumar Swaminathan 
6614291a2b48SSukumar Swaminathan 	if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) {
6615291a2b48SSukumar Swaminathan 		HBQ_PortGetIdx =
661682527734SSukumar Swaminathan 		    BE_SWAP32(((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.
6617291a2b48SSukumar Swaminathan 		    HBQ_PortGetIdx[hbq_id]);
6618291a2b48SSukumar Swaminathan 
6619291a2b48SSukumar Swaminathan 		hbq->HBQ_GetIdx = HBQ_PortGetIdx;
6620291a2b48SSukumar Swaminathan 
6621291a2b48SSukumar Swaminathan 		if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) {
6622291a2b48SSukumar Swaminathan 			return;
6623291a2b48SSukumar Swaminathan 		}
6624291a2b48SSukumar Swaminathan 	}
6625291a2b48SSukumar Swaminathan 
662682527734SSukumar Swaminathan 	ioa2 = (void *)((char *)hba->sli.sli3.slim_addr +
662782527734SSukumar Swaminathan 	    (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t))));
6628291a2b48SSukumar Swaminathan 	status = hbq->HBQ_PutIdx;
6629291a2b48SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, status);
6630291a2b48SSukumar Swaminathan 
66314baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
66324baa2c25SSukumar Swaminathan 	/* Access handle validation */
663382527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
66344baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
66354baa2c25SSukumar Swaminathan 
6636291a2b48SSukumar Swaminathan 	return;
6637291a2b48SSukumar Swaminathan 
663882527734SSukumar Swaminathan } /* emlxs_update_HBQ_index() */
6639291a2b48SSukumar Swaminathan 
6640291a2b48SSukumar Swaminathan 
664182527734SSukumar Swaminathan static void
664282527734SSukumar Swaminathan emlxs_sli3_enable_intr(emlxs_hba_t *hba)
6643291a2b48SSukumar Swaminathan {
66444baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
66454baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
66464baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6647291a2b48SSukumar Swaminathan 	uint32_t status;
6648291a2b48SSukumar Swaminathan 
6649291a2b48SSukumar Swaminathan 	/* Enable mailbox, error attention interrupts */
665082527734SSukumar Swaminathan 	status = (uint32_t)(HC_MBINT_ENA);
6651291a2b48SSukumar Swaminathan 
6652291a2b48SSukumar Swaminathan 	/* Enable ring interrupts */
665382527734SSukumar Swaminathan 	if (hba->sli.sli3.ring_count >= 4) {
6654291a2b48SSukumar Swaminathan 		status |=
6655291a2b48SSukumar Swaminathan 		    (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA |
6656291a2b48SSukumar Swaminathan 		    HC_R0INT_ENA);
665782527734SSukumar Swaminathan 	} else if (hba->sli.sli3.ring_count == 3) {
6658291a2b48SSukumar Swaminathan 		status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA);
665982527734SSukumar Swaminathan 	} else if (hba->sli.sli3.ring_count == 2) {
6660291a2b48SSukumar Swaminathan 		status |= (HC_R1INT_ENA | HC_R0INT_ENA);
666182527734SSukumar Swaminathan 	} else if (hba->sli.sli3.ring_count == 1) {
6662291a2b48SSukumar Swaminathan 		status |= (HC_R0INT_ENA);
6663291a2b48SSukumar Swaminathan 	}
6664291a2b48SSukumar Swaminathan 
666582527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = status;
666682527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
66674baa2c25SSukumar Swaminathan 
66684baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
66694baa2c25SSukumar Swaminathan 	/* Access handle validation */
667082527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
66714baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6672291a2b48SSukumar Swaminathan 
667382527734SSukumar Swaminathan } /* emlxs_sli3_enable_intr() */
667482527734SSukumar Swaminathan 
667582527734SSukumar Swaminathan 
667682527734SSukumar Swaminathan static void
6677291a2b48SSukumar Swaminathan emlxs_enable_latt(emlxs_hba_t *hba)
6678291a2b48SSukumar Swaminathan {
66794baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
66804baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
66814baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
66824baa2c25SSukumar Swaminathan 
6683291a2b48SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
668482527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
668582527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
66864baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
66874baa2c25SSukumar Swaminathan 	/* Access handle validation */
668882527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
66894baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6690291a2b48SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
6691291a2b48SSukumar Swaminathan 
669282527734SSukumar Swaminathan } /* emlxs_enable_latt() */
669382527734SSukumar Swaminathan 
669482527734SSukumar Swaminathan 
669582527734SSukumar Swaminathan static void
669682527734SSukumar Swaminathan emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att)
6697291a2b48SSukumar Swaminathan {
66984baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
66994baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
67004baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
67014baa2c25SSukumar Swaminathan 
6702291a2b48SSukumar Swaminathan 	/* Disable all adapter interrupts */
670382527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = att;
670482527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
67054baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
67064baa2c25SSukumar Swaminathan 	/* Access handle validation */
670782527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
67084baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6709291a2b48SSukumar Swaminathan 
671082527734SSukumar Swaminathan } /* emlxs_sli3_disable_intr() */
671182527734SSukumar Swaminathan 
671282527734SSukumar Swaminathan 
671382527734SSukumar Swaminathan static uint32_t
6714291a2b48SSukumar Swaminathan emlxs_check_attention(emlxs_hba_t *hba)
6715291a2b48SSukumar Swaminathan {
67164baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
67174baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
67184baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6719291a2b48SSukumar Swaminathan 	uint32_t ha_copy;
6720291a2b48SSukumar Swaminathan 
672182527734SSukumar Swaminathan 	ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
67224baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
67234baa2c25SSukumar Swaminathan 	/* Access handle validation */
672482527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
67254baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6726291a2b48SSukumar Swaminathan 	return (ha_copy);
672782527734SSukumar Swaminathan 
672882527734SSukumar Swaminathan } /* emlxs_check_attention() */
672982527734SSukumar Swaminathan 
6730*8f23e9faSHans Rosenfeld 
6731*8f23e9faSHans Rosenfeld static void
673282527734SSukumar Swaminathan emlxs_sli3_poll_erratt(emlxs_hba_t *hba)
673382527734SSukumar Swaminathan {
673482527734SSukumar Swaminathan 	uint32_t ha_copy;
673582527734SSukumar Swaminathan 
673682527734SSukumar Swaminathan 	ha_copy = emlxs_check_attention(hba);
673782527734SSukumar Swaminathan 
673882527734SSukumar Swaminathan 	/* Adapter error */
673982527734SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
674082527734SSukumar Swaminathan 		HBASTATS.IntrEvent[6]++;
674182527734SSukumar Swaminathan 		emlxs_handle_ff_error(hba);
674282527734SSukumar Swaminathan 	}
6743*8f23e9faSHans Rosenfeld 
6744*8f23e9faSHans Rosenfeld } /* emlxs_sli3_poll_erratt() */
6745*8f23e9faSHans Rosenfeld 
6746*8f23e9faSHans Rosenfeld 
6747*8f23e9faSHans Rosenfeld static uint32_t
6748*8f23e9faSHans Rosenfeld emlxs_sli3_reg_did_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
6749*8f23e9faSHans Rosenfeld {
6750*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
6751*8f23e9faSHans Rosenfeld 	MAILBOXQ *mboxq;
6752*8f23e9faSHans Rosenfeld 	MAILBOX *mb;
6753*8f23e9faSHans Rosenfeld 	MATCHMAP *mp;
6754*8f23e9faSHans Rosenfeld 	NODELIST *ndlp;
6755*8f23e9faSHans Rosenfeld 	emlxs_port_t *vport;
6756*8f23e9faSHans Rosenfeld 	SERV_PARM *sp;
6757*8f23e9faSHans Rosenfeld 	int32_t i;
6758*8f23e9faSHans Rosenfeld 	uint32_t  control;
6759*8f23e9faSHans Rosenfeld 	uint32_t ldata;
6760*8f23e9faSHans Rosenfeld 	uint32_t ldid;
6761*8f23e9faSHans Rosenfeld 	uint16_t lrpi;
6762*8f23e9faSHans Rosenfeld 	uint16_t lvpi;
6763*8f23e9faSHans Rosenfeld 	uint32_t rval;
6764*8f23e9faSHans Rosenfeld 
6765*8f23e9faSHans Rosenfeld 	mb = (MAILBOX *)mbq;
6766*8f23e9faSHans Rosenfeld 
6767*8f23e9faSHans Rosenfeld 	if (mb->mbxStatus) {
6768*8f23e9faSHans Rosenfeld 		if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
6769*8f23e9faSHans Rosenfeld 			control = mb->un.varRegLogin.un.sp.bdeSize;
6770*8f23e9faSHans Rosenfeld 			if (control == 0) {
6771*8f23e9faSHans Rosenfeld 				/* Special handle for vport PLOGI */
6772*8f23e9faSHans Rosenfeld 				if (mbq->iocbq == (uint8_t *)1) {
6773*8f23e9faSHans Rosenfeld 					mbq->iocbq = NULL;
6774*8f23e9faSHans Rosenfeld 				}
6775*8f23e9faSHans Rosenfeld 				return (0);
6776*8f23e9faSHans Rosenfeld 			}
6777*8f23e9faSHans Rosenfeld 			emlxs_mb_retry(hba, mbq);
6778*8f23e9faSHans Rosenfeld 			return (1);
6779*8f23e9faSHans Rosenfeld 		}
6780*8f23e9faSHans Rosenfeld 		if (mb->mbxStatus == MBXERR_RPI_FULL) {
6781*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
6782*8f23e9faSHans Rosenfeld 			    &emlxs_node_create_failed_msg,
6783*8f23e9faSHans Rosenfeld 			    "Limit reached. count=%d", port->node_count);
6784*8f23e9faSHans Rosenfeld 		}
6785*8f23e9faSHans Rosenfeld 
6786*8f23e9faSHans Rosenfeld 		/* Special handle for vport PLOGI */
6787*8f23e9faSHans Rosenfeld 		if (mbq->iocbq == (uint8_t *)1) {
6788*8f23e9faSHans Rosenfeld 			mbq->iocbq = NULL;
6789*8f23e9faSHans Rosenfeld 		}
6790*8f23e9faSHans Rosenfeld 
6791*8f23e9faSHans Rosenfeld 		return (0);
6792*8f23e9faSHans Rosenfeld 	}
6793*8f23e9faSHans Rosenfeld 
6794*8f23e9faSHans Rosenfeld 	mp = (MATCHMAP *)mbq->bp;
6795*8f23e9faSHans Rosenfeld 	if (!mp) {
6796*8f23e9faSHans Rosenfeld 		return (0);
6797*8f23e9faSHans Rosenfeld 	}
6798*8f23e9faSHans Rosenfeld 
6799*8f23e9faSHans Rosenfeld 	ldata = mb->un.varWords[5];
6800*8f23e9faSHans Rosenfeld 	lvpi = (ldata & 0xffff);
6801*8f23e9faSHans Rosenfeld 	port = &VPORT(lvpi);
6802*8f23e9faSHans Rosenfeld 
6803*8f23e9faSHans Rosenfeld 	/* First copy command data */
6804*8f23e9faSHans Rosenfeld 	ldata = mb->un.varWords[0];	/* get rpi */
6805*8f23e9faSHans Rosenfeld 	lrpi = ldata & 0xffff;
6806*8f23e9faSHans Rosenfeld 
6807*8f23e9faSHans Rosenfeld 	ldata = mb->un.varWords[1];	/* get did */
6808*8f23e9faSHans Rosenfeld 	ldid = ldata & MASK_DID;
6809*8f23e9faSHans Rosenfeld 
6810*8f23e9faSHans Rosenfeld 	sp = (SERV_PARM *)mp->virt;
6811*8f23e9faSHans Rosenfeld 
6812*8f23e9faSHans Rosenfeld 	/* Create or update the node */
6813*8f23e9faSHans Rosenfeld 	ndlp = emlxs_node_create(port, ldid, lrpi, sp);
6814*8f23e9faSHans Rosenfeld 
6815*8f23e9faSHans Rosenfeld 	if (ndlp == NULL) {
6816*8f23e9faSHans Rosenfeld 		emlxs_ub_priv_t *ub_priv;
6817*8f23e9faSHans Rosenfeld 
6818*8f23e9faSHans Rosenfeld 		/*
6819*8f23e9faSHans Rosenfeld 		 * Fake a mailbox error, so the mbox_fini
6820*8f23e9faSHans Rosenfeld 		 * can take appropriate action
6821*8f23e9faSHans Rosenfeld 		 */
6822*8f23e9faSHans Rosenfeld 		mb->mbxStatus = MBXERR_RPI_FULL;
6823*8f23e9faSHans Rosenfeld 		if (mbq->ubp) {
6824*8f23e9faSHans Rosenfeld 			ub_priv = ((fc_unsol_buf_t *)mbq->ubp)->ub_fca_private;
6825*8f23e9faSHans Rosenfeld 			ub_priv->flags |= EMLXS_UB_REPLY;
6826*8f23e9faSHans Rosenfeld 		}
6827*8f23e9faSHans Rosenfeld 
6828*8f23e9faSHans Rosenfeld 		/* This must be (0xFFFFFE) which was registered by vport */
6829*8f23e9faSHans Rosenfeld 		if (lrpi == 0) {
6830*8f23e9faSHans Rosenfeld 			return (0);
6831*8f23e9faSHans Rosenfeld 		}
6832*8f23e9faSHans Rosenfeld 
6833*8f23e9faSHans Rosenfeld 		if (!(mboxq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
6834*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6835*8f23e9faSHans Rosenfeld 			    "reg_did_mbcmpl:failed. Unable to allocate mbox");
6836*8f23e9faSHans Rosenfeld 			return (0);
6837*8f23e9faSHans Rosenfeld 		}
6838*8f23e9faSHans Rosenfeld 
6839*8f23e9faSHans Rosenfeld 		mb = (MAILBOX *)mboxq->mbox;
6840*8f23e9faSHans Rosenfeld 		mb->un.varUnregLogin.rpi = lrpi;
6841*8f23e9faSHans Rosenfeld 		mb->un.varUnregLogin.vpi = lvpi;
6842*8f23e9faSHans Rosenfeld 
6843*8f23e9faSHans Rosenfeld 		mb->mbxCommand = MBX_UNREG_LOGIN;
6844*8f23e9faSHans Rosenfeld 		mb->mbxOwner = OWN_HOST;
6845*8f23e9faSHans Rosenfeld 		mboxq->sbp = NULL;
6846*8f23e9faSHans Rosenfeld 		mboxq->ubp = NULL;
6847*8f23e9faSHans Rosenfeld 		mboxq->iocbq = NULL;
6848*8f23e9faSHans Rosenfeld 		mboxq->mbox_cmpl = NULL;
6849*8f23e9faSHans Rosenfeld 		mboxq->context = NULL;
6850*8f23e9faSHans Rosenfeld 		mboxq->port = (void *)port;
6851*8f23e9faSHans Rosenfeld 
6852*8f23e9faSHans Rosenfeld 		rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mboxq, MBX_NOWAIT, 0);
6853*8f23e9faSHans Rosenfeld 		if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
6854*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6855*8f23e9faSHans Rosenfeld 			    "reg_did_mbcmpl:failed. Unable to send request.");
6856*8f23e9faSHans Rosenfeld 
6857*8f23e9faSHans Rosenfeld 			emlxs_mem_put(hba, MEM_MBOX, (void *)mboxq);
6858*8f23e9faSHans Rosenfeld 			return (0);
6859*8f23e9faSHans Rosenfeld 		}
6860*8f23e9faSHans Rosenfeld 
6861*8f23e9faSHans Rosenfeld 		return (0);
6862*8f23e9faSHans Rosenfeld 	}
6863*8f23e9faSHans Rosenfeld 
6864*8f23e9faSHans Rosenfeld 	if (ndlp->nlp_DID == FABRIC_DID) {
6865*8f23e9faSHans Rosenfeld 		/* FLOGI/FDISC successfully completed on this port */
6866*8f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
6867*8f23e9faSHans Rosenfeld 		port->flag |= EMLXS_PORT_FLOGI_CMPL;
6868*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
6869*8f23e9faSHans Rosenfeld 
6870*8f23e9faSHans Rosenfeld 		/* If CLEAR_LA has been sent, then attempt to */
6871*8f23e9faSHans Rosenfeld 		/* register the vpi now */
6872*8f23e9faSHans Rosenfeld 		if (hba->state == FC_READY) {
6873*8f23e9faSHans Rosenfeld 			(void) emlxs_mb_reg_vpi(port, NULL);
6874*8f23e9faSHans Rosenfeld 		}
6875*8f23e9faSHans Rosenfeld 
6876*8f23e9faSHans Rosenfeld 		/*
6877*8f23e9faSHans Rosenfeld 		 * If NPIV Fabric support has just been established on
6878*8f23e9faSHans Rosenfeld 		 * the physical port, then notify the vports of the
6879*8f23e9faSHans Rosenfeld 		 * link up
6880*8f23e9faSHans Rosenfeld 		 */
6881*8f23e9faSHans Rosenfeld 		if ((lvpi == 0) &&
6882*8f23e9faSHans Rosenfeld 		    (hba->flag & FC_NPIV_ENABLED) &&
6883*8f23e9faSHans Rosenfeld 		    (hba->flag & FC_NPIV_SUPPORTED)) {
6884*8f23e9faSHans Rosenfeld 			/* Skip the physical port */
6885*8f23e9faSHans Rosenfeld 			for (i = 1; i < MAX_VPORTS; i++) {
6886*8f23e9faSHans Rosenfeld 				vport = &VPORT(i);
6887*8f23e9faSHans Rosenfeld 
6888*8f23e9faSHans Rosenfeld 				if (!(vport->flag & EMLXS_PORT_BOUND) ||
6889*8f23e9faSHans Rosenfeld 				    !(vport->flag &
6890*8f23e9faSHans Rosenfeld 				    EMLXS_PORT_ENABLED)) {
6891*8f23e9faSHans Rosenfeld 					continue;
6892*8f23e9faSHans Rosenfeld 				}
6893*8f23e9faSHans Rosenfeld 
6894*8f23e9faSHans Rosenfeld 				emlxs_port_online(vport);
6895*8f23e9faSHans Rosenfeld 			}
6896*8f23e9faSHans Rosenfeld 		}
6897*8f23e9faSHans Rosenfeld 	}
6898*8f23e9faSHans Rosenfeld 
6899*8f23e9faSHans Rosenfeld 	/* Check for special restricted login flag */
6900*8f23e9faSHans Rosenfeld 	if (mbq->iocbq == (uint8_t *)1) {
6901*8f23e9faSHans Rosenfeld 		mbq->iocbq = NULL;
6902*8f23e9faSHans Rosenfeld 		(void) EMLXS_SLI_UNREG_NODE(port, ndlp, NULL, NULL, NULL);
6903*8f23e9faSHans Rosenfeld 		return (0);
6904*8f23e9faSHans Rosenfeld 	}
6905*8f23e9faSHans Rosenfeld 
6906*8f23e9faSHans Rosenfeld 	/* Needed for FCT trigger in emlxs_mb_deferred_cmpl */
6907*8f23e9faSHans Rosenfeld 	if (mbq->sbp) {
6908*8f23e9faSHans Rosenfeld 		((emlxs_buf_t *)mbq->sbp)->node = ndlp;
6909*8f23e9faSHans Rosenfeld 	}
6910*8f23e9faSHans Rosenfeld 
6911*8f23e9faSHans Rosenfeld #ifdef DHCHAP_SUPPORT
6912*8f23e9faSHans Rosenfeld 	if (mbq->sbp || mbq->ubp) {
6913*8f23e9faSHans Rosenfeld 		if (emlxs_dhc_auth_start(port, ndlp, mbq->sbp,
6914*8f23e9faSHans Rosenfeld 		    mbq->ubp) == 0) {
6915*8f23e9faSHans Rosenfeld 			/* Auth started - auth completion will */
6916*8f23e9faSHans Rosenfeld 			/* handle sbp and ubp now */
6917*8f23e9faSHans Rosenfeld 			mbq->sbp = NULL;
6918*8f23e9faSHans Rosenfeld 			mbq->ubp = NULL;
6919*8f23e9faSHans Rosenfeld 		}
6920*8f23e9faSHans Rosenfeld 	}
6921*8f23e9faSHans Rosenfeld #endif	/* DHCHAP_SUPPORT */
6922*8f23e9faSHans Rosenfeld 
6923*8f23e9faSHans Rosenfeld 	return (0);
6924*8f23e9faSHans Rosenfeld 
6925*8f23e9faSHans Rosenfeld } /* emlxs_sli3_reg_did_mbcmpl() */
6926*8f23e9faSHans Rosenfeld 
6927*8f23e9faSHans Rosenfeld 
6928*8f23e9faSHans Rosenfeld static uint32_t
6929*8f23e9faSHans Rosenfeld emlxs_sli3_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
6930*8f23e9faSHans Rosenfeld     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
6931*8f23e9faSHans Rosenfeld {
6932*8f23e9faSHans Rosenfeld 	emlxs_hba_t	*hba = HBA;
6933*8f23e9faSHans Rosenfeld 	MATCHMAP	*mp;
6934*8f23e9faSHans Rosenfeld 	MAILBOXQ	*mbq;
6935*8f23e9faSHans Rosenfeld 	MAILBOX		*mb;
6936*8f23e9faSHans Rosenfeld 	uint32_t	rval;
6937*8f23e9faSHans Rosenfeld 
6938*8f23e9faSHans Rosenfeld 	/* Check for invalid node ids to register */
6939*8f23e9faSHans Rosenfeld 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
6940*8f23e9faSHans Rosenfeld 		return (1);
6941*8f23e9faSHans Rosenfeld 	}
6942*8f23e9faSHans Rosenfeld 
6943*8f23e9faSHans Rosenfeld 	if (did & 0xff000000) {
6944*8f23e9faSHans Rosenfeld 		return (1);
6945*8f23e9faSHans Rosenfeld 	}
6946*8f23e9faSHans Rosenfeld 
6947*8f23e9faSHans Rosenfeld 	if ((rval = emlxs_mb_check_sparm(hba, param))) {
6948*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6949*8f23e9faSHans Rosenfeld 		    "Invalid service parameters. did=%06x rval=%d", did,
6950*8f23e9faSHans Rosenfeld 		    rval);
6951*8f23e9faSHans Rosenfeld 
6952*8f23e9faSHans Rosenfeld 		return (1);
6953*8f23e9faSHans Rosenfeld 	}
6954*8f23e9faSHans Rosenfeld 
6955*8f23e9faSHans Rosenfeld 	/* Check if the node limit has been reached */
6956*8f23e9faSHans Rosenfeld 	if (port->node_count >= hba->max_nodes) {
6957*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6958*8f23e9faSHans Rosenfeld 		    "Limit reached. did=%06x count=%d", did,
6959*8f23e9faSHans Rosenfeld 		    port->node_count);
6960*8f23e9faSHans Rosenfeld 
6961*8f23e9faSHans Rosenfeld 		return (1);
6962*8f23e9faSHans Rosenfeld 	}
6963*8f23e9faSHans Rosenfeld 
6964*8f23e9faSHans Rosenfeld 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
6965*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6966*8f23e9faSHans Rosenfeld 		    "Unable to allocate mailbox. did=%x", did);
6967*8f23e9faSHans Rosenfeld 
6968*8f23e9faSHans Rosenfeld 		return (1);
6969*8f23e9faSHans Rosenfeld 	}
6970*8f23e9faSHans Rosenfeld 	mb = (MAILBOX *)mbq->mbox;
6971*8f23e9faSHans Rosenfeld 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
6972*8f23e9faSHans Rosenfeld 
6973*8f23e9faSHans Rosenfeld 	/* Build login request */
6974*8f23e9faSHans Rosenfeld 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
6975*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6976*8f23e9faSHans Rosenfeld 
6977*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6978*8f23e9faSHans Rosenfeld 		    "Unable to allocate buffer. did=%x", did);
6979*8f23e9faSHans Rosenfeld 		return (1);
6980*8f23e9faSHans Rosenfeld 	}
6981*8f23e9faSHans Rosenfeld 	bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM));
6982*8f23e9faSHans Rosenfeld 
6983*8f23e9faSHans Rosenfeld 	mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
6984*8f23e9faSHans Rosenfeld 	mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys);
6985*8f23e9faSHans Rosenfeld 	mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys);
6986*8f23e9faSHans Rosenfeld 	mb->un.varRegLogin.did = did;
6987*8f23e9faSHans Rosenfeld 	mb->un.varWords[30] = 0;	/* flags */
6988*8f23e9faSHans Rosenfeld 	mb->mbxCommand = MBX_REG_LOGIN64;
6989*8f23e9faSHans Rosenfeld 	mb->mbxOwner = OWN_HOST;
6990*8f23e9faSHans Rosenfeld 	mb->un.varRegLogin.vpi = port->vpi;
6991*8f23e9faSHans Rosenfeld 	mb->un.varRegLogin.rpi = 0;
6992*8f23e9faSHans Rosenfeld 
6993*8f23e9faSHans Rosenfeld 	mbq->sbp = (void *)sbp;
6994*8f23e9faSHans Rosenfeld 	mbq->ubp = (void *)ubp;
6995*8f23e9faSHans Rosenfeld 	mbq->iocbq = (void *)iocbq;
6996*8f23e9faSHans Rosenfeld 	mbq->bp = (void *)mp;
6997*8f23e9faSHans Rosenfeld 	mbq->mbox_cmpl = emlxs_sli3_reg_did_mbcmpl;
6998*8f23e9faSHans Rosenfeld 	mbq->context = NULL;
6999*8f23e9faSHans Rosenfeld 	mbq->port = (void *)port;
7000*8f23e9faSHans Rosenfeld 
7001*8f23e9faSHans Rosenfeld 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7002*8f23e9faSHans Rosenfeld 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7003*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
7004*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7005*8f23e9faSHans Rosenfeld 
7006*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
7007*8f23e9faSHans Rosenfeld 		    "Unable to send mbox. did=%x", did);
7008*8f23e9faSHans Rosenfeld 		return (1);
7009*8f23e9faSHans Rosenfeld 	}
7010*8f23e9faSHans Rosenfeld 
7011*8f23e9faSHans Rosenfeld 	return (0);
7012*8f23e9faSHans Rosenfeld 
7013*8f23e9faSHans Rosenfeld } /* emlxs_sli3_reg_did() */
7014*8f23e9faSHans Rosenfeld 
7015*8f23e9faSHans Rosenfeld 
7016*8f23e9faSHans Rosenfeld /*ARGSUSED*/
7017*8f23e9faSHans Rosenfeld static uint32_t
7018*8f23e9faSHans Rosenfeld emlxs_sli3_unreg_node_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
7019*8f23e9faSHans Rosenfeld {
7020*8f23e9faSHans Rosenfeld 	emlxs_port_t	*port = (emlxs_port_t *)mbq->port;
7021*8f23e9faSHans Rosenfeld 	MAILBOX		*mb;
7022*8f23e9faSHans Rosenfeld 	NODELIST	*node;
7023*8f23e9faSHans Rosenfeld 	uint16_t	rpi;
7024*8f23e9faSHans Rosenfeld 
7025*8f23e9faSHans Rosenfeld 	node = (NODELIST *)mbq->context;
7026*8f23e9faSHans Rosenfeld 	mb = (MAILBOX *)mbq;
7027*8f23e9faSHans Rosenfeld 	rpi = (node)? node->nlp_Rpi:0xffff;
7028*8f23e9faSHans Rosenfeld 
7029*8f23e9faSHans Rosenfeld 	if (mb->mbxStatus) {
7030*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7031*8f23e9faSHans Rosenfeld 		    "unreg_node_mbcmpl:failed. node=%p rpi=%d status=%x",
7032*8f23e9faSHans Rosenfeld 		    node, rpi, mb->mbxStatus);
7033*8f23e9faSHans Rosenfeld 
7034*8f23e9faSHans Rosenfeld 		return (0);
7035*8f23e9faSHans Rosenfeld 	}
7036*8f23e9faSHans Rosenfeld 
7037*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7038*8f23e9faSHans Rosenfeld 	    "unreg_node_mbcmpl: node=%p rpi=%d",
7039*8f23e9faSHans Rosenfeld 	    node, rpi);
7040*8f23e9faSHans Rosenfeld 
7041*8f23e9faSHans Rosenfeld 	if (node) {
7042*8f23e9faSHans Rosenfeld 		emlxs_node_rm(port, node);
7043*8f23e9faSHans Rosenfeld 
7044*8f23e9faSHans Rosenfeld 	} else {  /* All nodes */
7045*8f23e9faSHans Rosenfeld 		emlxs_node_destroy_all(port);
7046*8f23e9faSHans Rosenfeld 	}
7047*8f23e9faSHans Rosenfeld 
7048*8f23e9faSHans Rosenfeld 	return (0);
7049*8f23e9faSHans Rosenfeld 
7050*8f23e9faSHans Rosenfeld } /* emlxs_sli3_unreg_node_mbcmpl */
7051*8f23e9faSHans Rosenfeld 
7052*8f23e9faSHans Rosenfeld 
7053*8f23e9faSHans Rosenfeld static uint32_t
7054*8f23e9faSHans Rosenfeld emlxs_sli3_unreg_node(emlxs_port_t *port, NODELIST *node, emlxs_buf_t *sbp,
7055*8f23e9faSHans Rosenfeld     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
7056*8f23e9faSHans Rosenfeld {
7057*8f23e9faSHans Rosenfeld 	emlxs_hba_t	*hba = HBA;
7058*8f23e9faSHans Rosenfeld 	MAILBOXQ	*mbq;
7059*8f23e9faSHans Rosenfeld 	MAILBOX		*mb;
7060*8f23e9faSHans Rosenfeld 	uint16_t	rpi;
7061*8f23e9faSHans Rosenfeld 	uint32_t	rval;
7062*8f23e9faSHans Rosenfeld 
7063*8f23e9faSHans Rosenfeld 	if (node) {
7064*8f23e9faSHans Rosenfeld 		/* Check for base node */
7065*8f23e9faSHans Rosenfeld 		if (node == &port->node_base) {
7066*8f23e9faSHans Rosenfeld 			/* just flush base node */
7067*8f23e9faSHans Rosenfeld 			(void) emlxs_tx_node_flush(port, &port->node_base,
7068*8f23e9faSHans Rosenfeld 			    0, 0, 0);
7069*8f23e9faSHans Rosenfeld 			(void) emlxs_chipq_node_flush(port, 0,
7070*8f23e9faSHans Rosenfeld 			    &port->node_base, 0);
7071*8f23e9faSHans Rosenfeld 
7072*8f23e9faSHans Rosenfeld 			port->did = 0;
7073*8f23e9faSHans Rosenfeld 
7074*8f23e9faSHans Rosenfeld 			/* Return now */
7075*8f23e9faSHans Rosenfeld 			return (1);
7076*8f23e9faSHans Rosenfeld 		}
7077*8f23e9faSHans Rosenfeld 
7078*8f23e9faSHans Rosenfeld 		rpi = (uint16_t)node->nlp_Rpi;
7079*8f23e9faSHans Rosenfeld 
7080*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7081*8f23e9faSHans Rosenfeld 		    "unreg_node:%p  rpi=%d", node, rpi);
7082*8f23e9faSHans Rosenfeld 
7083*8f23e9faSHans Rosenfeld 		/* This node must be (0xFFFFFE) which registered by vport */
7084*8f23e9faSHans Rosenfeld 		if (rpi == 0) {
7085*8f23e9faSHans Rosenfeld 			emlxs_node_rm(port, node);
7086*8f23e9faSHans Rosenfeld 			return (0);
7087*8f23e9faSHans Rosenfeld 		}
7088*8f23e9faSHans Rosenfeld 
7089*8f23e9faSHans Rosenfeld 	} else {	/* Unreg all nodes */
7090*8f23e9faSHans Rosenfeld 		rpi = 0xffff;
7091*8f23e9faSHans Rosenfeld 
7092*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7093*8f23e9faSHans Rosenfeld 		    "unreg_node: All");
7094*8f23e9faSHans Rosenfeld 	}
7095*8f23e9faSHans Rosenfeld 
7096*8f23e9faSHans Rosenfeld 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
7097*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7098*8f23e9faSHans Rosenfeld 		    "unreg_node:failed. Unable to allocate mbox");
7099*8f23e9faSHans Rosenfeld 		return (1);
7100*8f23e9faSHans Rosenfeld 	}
7101*8f23e9faSHans Rosenfeld 
7102*8f23e9faSHans Rosenfeld 	mb = (MAILBOX *)mbq->mbox;
7103*8f23e9faSHans Rosenfeld 	mb->un.varUnregLogin.rpi = rpi;
7104*8f23e9faSHans Rosenfeld 	mb->un.varUnregLogin.vpi = port->vpip->VPI;
7105*8f23e9faSHans Rosenfeld 
7106*8f23e9faSHans Rosenfeld 	mb->mbxCommand = MBX_UNREG_LOGIN;
7107*8f23e9faSHans Rosenfeld 	mb->mbxOwner = OWN_HOST;
7108*8f23e9faSHans Rosenfeld 	mbq->sbp = (void *)sbp;
7109*8f23e9faSHans Rosenfeld 	mbq->ubp = (void *)ubp;
7110*8f23e9faSHans Rosenfeld 	mbq->iocbq = (void *)iocbq;
7111*8f23e9faSHans Rosenfeld 	mbq->mbox_cmpl = emlxs_sli3_unreg_node_mbcmpl;
7112*8f23e9faSHans Rosenfeld 	mbq->context = (void *)node;
7113*8f23e9faSHans Rosenfeld 	mbq->port = (void *)port;
7114*8f23e9faSHans Rosenfeld 
7115*8f23e9faSHans Rosenfeld 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7116*8f23e9faSHans Rosenfeld 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7117*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7118*8f23e9faSHans Rosenfeld 		    "unreg_node:failed. Unable to send request.");
7119*8f23e9faSHans Rosenfeld 
7120*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7121*8f23e9faSHans Rosenfeld 		return (1);
7122*8f23e9faSHans Rosenfeld 	}
7123*8f23e9faSHans Rosenfeld 
7124*8f23e9faSHans Rosenfeld 	return (0);
7125*8f23e9faSHans Rosenfeld 
7126*8f23e9faSHans Rosenfeld } /* emlxs_sli3_unreg_node() */
7127