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  *
88f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
98f23e9faSHans 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 /*
238f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25*a3170057SPaul Winder  * Copyright 2020 RackTop Systems, Inc.
26291a2b48SSukumar Swaminathan  */
27291a2b48SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29291a2b48SSukumar Swaminathan 
30291a2b48SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
3182527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI3_C);
32291a2b48SSukumar Swaminathan 
3382527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq);
3482527734SSukumar Swaminathan static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba);
3582527734SSukumar Swaminathan static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
36291a2b48SSukumar Swaminathan 	uint32_t ha_copy);
37291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
38291a2b48SSukumar Swaminathan static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
39291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4082527734SSukumar Swaminathan 
41291a2b48SSukumar Swaminathan static uint32_t	emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
42291a2b48SSukumar Swaminathan 
4382527734SSukumar Swaminathan static uint32_t emlxs_disable_traffic_cop = 1;
44291a2b48SSukumar Swaminathan 
4582527734SSukumar Swaminathan static int			emlxs_sli3_map_hdw(emlxs_hba_t *hba);
46291a2b48SSukumar Swaminathan 
4782527734SSukumar Swaminathan static void			emlxs_sli3_unmap_hdw(emlxs_hba_t *hba);
48291a2b48SSukumar Swaminathan 
4982527734SSukumar Swaminathan static int32_t			emlxs_sli3_online(emlxs_hba_t *hba);
50291a2b48SSukumar Swaminathan 
518f23e9faSHans Rosenfeld static void			emlxs_sli3_offline(emlxs_hba_t *hba,
528f23e9faSHans Rosenfeld 					uint32_t reset_requested);
53291a2b48SSukumar Swaminathan 
5482527734SSukumar Swaminathan static uint32_t			emlxs_sli3_hba_reset(emlxs_hba_t *hba,
5582527734SSukumar Swaminathan 					uint32_t restart, uint32_t skip_post,
5682527734SSukumar Swaminathan 					uint32_t quiesce);
57291a2b48SSukumar Swaminathan 
5882527734SSukumar Swaminathan static void			emlxs_sli3_hba_kill(emlxs_hba_t *hba);
5982527734SSukumar Swaminathan static void			emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba);
6082527734SSukumar Swaminathan static uint32_t			emlxs_sli3_hba_init(emlxs_hba_t *hba);
61291a2b48SSukumar Swaminathan 
6282527734SSukumar Swaminathan static uint32_t			emlxs_sli2_bde_setup(emlxs_port_t *port,
6382527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
6482527734SSukumar Swaminathan static uint32_t			emlxs_sli3_bde_setup(emlxs_port_t *port,
6582527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
6682527734SSukumar Swaminathan static uint32_t			emlxs_sli2_fct_bde_setup(emlxs_port_t *port,
6782527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
6882527734SSukumar Swaminathan static uint32_t			emlxs_sli3_fct_bde_setup(emlxs_port_t *port,
6982527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
70291a2b48SSukumar Swaminathan 
71291a2b48SSukumar Swaminathan 
7282527734SSukumar Swaminathan static void			emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba,
7382527734SSukumar Swaminathan 					CHANNEL *rp, IOCBQ *iocb_cmd);
74291a2b48SSukumar Swaminathan 
75291a2b48SSukumar Swaminathan 
7682527734SSukumar Swaminathan static uint32_t			emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba,
7782527734SSukumar Swaminathan 					MAILBOXQ *mbq, int32_t flg,
7882527734SSukumar Swaminathan 					uint32_t tmo);
79291a2b48SSukumar Swaminathan 
80291a2b48SSukumar Swaminathan 
8182527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
8282527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_fct_iocb(emlxs_port_t *port,
8382527734SSukumar Swaminathan 					emlxs_buf_t *cmd_sbp, int channel);
84291a2b48SSukumar Swaminathan 
8582527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
86291a2b48SSukumar Swaminathan 
8782527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port,
8882527734SSukumar Swaminathan 					emlxs_buf_t *sbp, int ring);
89291a2b48SSukumar Swaminathan 
9082527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_ip_iocb(emlxs_port_t *port,
9182527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
92291a2b48SSukumar Swaminathan 
9382527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_els_iocb(emlxs_port_t *port,
9482527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
95291a2b48SSukumar Swaminathan 
96291a2b48SSukumar Swaminathan 
9782527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_ct_iocb(emlxs_port_t *port,
9882527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
99291a2b48SSukumar Swaminathan 
100291a2b48SSukumar Swaminathan 
1018f23e9faSHans Rosenfeld static void			emlxs_sli3_poll_intr(emlxs_hba_t *hba);
102291a2b48SSukumar Swaminathan 
10382527734SSukumar Swaminathan static int32_t			emlxs_sli3_intx_intr(char *arg);
10482527734SSukumar Swaminathan #ifdef MSI_SUPPORT
10582527734SSukumar Swaminathan static uint32_t			emlxs_sli3_msi_intr(char *arg1, char *arg2);
10682527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
107291a2b48SSukumar Swaminathan 
10882527734SSukumar Swaminathan static void			emlxs_sli3_enable_intr(emlxs_hba_t *hba);
10982527734SSukumar Swaminathan 
11082527734SSukumar Swaminathan static void			emlxs_sli3_disable_intr(emlxs_hba_t *hba,
11182527734SSukumar Swaminathan 					uint32_t att);
11282527734SSukumar Swaminathan 
113a9800bebSGarrett D'Amore 
11482527734SSukumar Swaminathan static void			emlxs_handle_ff_error(emlxs_hba_t *hba);
11582527734SSukumar Swaminathan 
11682527734SSukumar Swaminathan static uint32_t			emlxs_handle_mb_event(emlxs_hba_t *hba);
11782527734SSukumar Swaminathan 
11882527734SSukumar Swaminathan static void			emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba);
11982527734SSukumar Swaminathan 
12082527734SSukumar Swaminathan static uint32_t			emlxs_mb_config_port(emlxs_hba_t *hba,
12182527734SSukumar Swaminathan 					MAILBOXQ *mbq, uint32_t sli_mode,
12282527734SSukumar Swaminathan 					uint32_t hbainit);
12382527734SSukumar Swaminathan static void			emlxs_enable_latt(emlxs_hba_t *hba);
12482527734SSukumar Swaminathan 
12582527734SSukumar Swaminathan static uint32_t			emlxs_check_attention(emlxs_hba_t *hba);
12682527734SSukumar Swaminathan 
12782527734SSukumar Swaminathan static uint32_t			emlxs_get_attention(emlxs_hba_t *hba,
128a9800bebSGarrett D'Amore 					int32_t msgid);
12982527734SSukumar Swaminathan static void			emlxs_proc_attention(emlxs_hba_t *hba,
13082527734SSukumar Swaminathan 					uint32_t ha_copy);
13182527734SSukumar Swaminathan /* static int			emlxs_handle_rcv_seq(emlxs_hba_t *hba, */
13282527734SSukumar Swaminathan 					/* CHANNEL *cp, IOCBQ *iocbq); */
13382527734SSukumar Swaminathan /* static void			emlxs_update_HBQ_index(emlxs_hba_t *hba, */
13482527734SSukumar Swaminathan 					/* uint32_t hbq_id); */
13582527734SSukumar Swaminathan /* static void			emlxs_hbq_free_all(emlxs_hba_t *hba, */
13682527734SSukumar Swaminathan 					/* uint32_t hbq_id); */
13782527734SSukumar Swaminathan static uint32_t			emlxs_hbq_setup(emlxs_hba_t *hba,
13882527734SSukumar Swaminathan 					uint32_t hbq_id);
1398f23e9faSHans Rosenfeld static void			emlxs_sli3_timer(emlxs_hba_t *hba);
1408f23e9faSHans Rosenfeld 
1418f23e9faSHans Rosenfeld static void			emlxs_sli3_poll_erratt(emlxs_hba_t *hba);
14282527734SSukumar Swaminathan 
1438f23e9faSHans Rosenfeld static uint32_t			emlxs_sli3_reg_did(emlxs_port_t *port,
1448f23e9faSHans Rosenfeld 					uint32_t did, SERV_PARM *param,
1458f23e9faSHans Rosenfeld 					emlxs_buf_t *sbp, fc_unsol_buf_t *ubp,
1468f23e9faSHans Rosenfeld 					IOCBQ *iocbq);
1478f23e9faSHans Rosenfeld 
1488f23e9faSHans Rosenfeld static uint32_t			emlxs_sli3_unreg_node(emlxs_port_t *port,
1498f23e9faSHans Rosenfeld 					NODELIST *node, emlxs_buf_t *sbp,
1508f23e9faSHans Rosenfeld 					fc_unsol_buf_t *ubp, IOCBQ *iocbq);
15182527734SSukumar Swaminathan 
15282527734SSukumar Swaminathan 
15382527734SSukumar Swaminathan /* Define SLI3 API functions */
15482527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli3_api = {
15582527734SSukumar Swaminathan 	emlxs_sli3_map_hdw,
15682527734SSukumar Swaminathan 	emlxs_sli3_unmap_hdw,
15782527734SSukumar Swaminathan 	emlxs_sli3_online,
15882527734SSukumar Swaminathan 	emlxs_sli3_offline,
15982527734SSukumar Swaminathan 	emlxs_sli3_hba_reset,
16082527734SSukumar Swaminathan 	emlxs_sli3_hba_kill,
16182527734SSukumar Swaminathan 	emlxs_sli3_issue_iocb_cmd,
16282527734SSukumar Swaminathan 	emlxs_sli3_issue_mbox_cmd,
16382527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
16482527734SSukumar Swaminathan 	emlxs_sli3_prep_fct_iocb,
16582527734SSukumar Swaminathan #else
16682527734SSukumar Swaminathan 	NULL,
16782527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
16882527734SSukumar Swaminathan 	emlxs_sli3_prep_fcp_iocb,
16982527734SSukumar Swaminathan 	emlxs_sli3_prep_ip_iocb,
17082527734SSukumar Swaminathan 	emlxs_sli3_prep_els_iocb,
17182527734SSukumar Swaminathan 	emlxs_sli3_prep_ct_iocb,
17282527734SSukumar Swaminathan 	emlxs_sli3_poll_intr,
17382527734SSukumar Swaminathan 	emlxs_sli3_intx_intr,
17482527734SSukumar Swaminathan 	emlxs_sli3_msi_intr,
17582527734SSukumar Swaminathan 	emlxs_sli3_disable_intr,
17682527734SSukumar Swaminathan 	emlxs_sli3_timer,
1778f23e9faSHans Rosenfeld 	emlxs_sli3_poll_erratt,
1788f23e9faSHans Rosenfeld 	emlxs_sli3_reg_did,
1798f23e9faSHans Rosenfeld 	emlxs_sli3_unreg_node
18082527734SSukumar Swaminathan };
181291a2b48SSukumar Swaminathan 
182291a2b48SSukumar Swaminathan 
18382527734SSukumar Swaminathan /*
18482527734SSukumar Swaminathan  * emlxs_sli3_online()
18582527734SSukumar Swaminathan  *
18682527734SSukumar Swaminathan  * This routine will start initialization of the SLI2/3 HBA.
18782527734SSukumar Swaminathan  */
18882527734SSukumar Swaminathan static int32_t
emlxs_sli3_online(emlxs_hba_t * hba)18982527734SSukumar Swaminathan emlxs_sli3_online(emlxs_hba_t *hba)
19082527734SSukumar Swaminathan {
19182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
19282527734SSukumar Swaminathan 	emlxs_config_t *cfg;
19382527734SSukumar Swaminathan 	emlxs_vpd_t *vpd;
19482527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
19582527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
19682527734SSukumar Swaminathan 	RING *rp;
19782527734SSukumar Swaminathan 	CHANNEL *cp;
19882527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
19982527734SSukumar Swaminathan 	MATCHMAP *mp1 = NULL;
20082527734SSukumar Swaminathan 	uint8_t *inptr;
20182527734SSukumar Swaminathan 	uint8_t *outptr;
20282527734SSukumar Swaminathan 	uint32_t status;
203a9800bebSGarrett D'Amore 	uint16_t i;
20482527734SSukumar Swaminathan 	uint32_t j;
20582527734SSukumar Swaminathan 	uint32_t read_rev_reset;
20682527734SSukumar Swaminathan 	uint32_t key = 0;
20782527734SSukumar Swaminathan 	uint32_t fw_check;
2086a573d82SSukumar Swaminathan 	uint32_t kern_update = 0;
20982527734SSukumar Swaminathan 	uint32_t rval = 0;
21082527734SSukumar Swaminathan 	uint32_t offset;
21182527734SSukumar Swaminathan 	uint8_t vpd_data[DMP_VPD_SIZE];
21282527734SSukumar Swaminathan 	uint32_t MaxRbusSize;
21382527734SSukumar Swaminathan 	uint32_t MaxIbusSize;
21482527734SSukumar Swaminathan 	uint32_t sli_mode;
21582527734SSukumar Swaminathan 	uint32_t sli_mode_mask;
216291a2b48SSukumar Swaminathan 
21782527734SSukumar Swaminathan 	cfg = &CFG;
21882527734SSukumar Swaminathan 	vpd = &VPD;
21982527734SSukumar Swaminathan 	MaxRbusSize = 0;
22082527734SSukumar Swaminathan 	MaxIbusSize = 0;
22182527734SSukumar Swaminathan 	read_rev_reset = 0;
22282527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
223291a2b48SSukumar Swaminathan 
22482527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
22582527734SSukumar Swaminathan 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
22682527734SSukumar Swaminathan 	}
227291a2b48SSukumar Swaminathan 
228a9800bebSGarrett D'Amore 	/* Set the fw_check flag */
229a9800bebSGarrett D'Amore 	fw_check = cfg[CFG_FW_CHECK].current;
2306a573d82SSukumar Swaminathan 
231a9800bebSGarrett D'Amore 	if ((fw_check & 0x04) ||
232a9800bebSGarrett D'Amore 	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
233a9800bebSGarrett D'Amore 		kern_update = 1;
234a9800bebSGarrett D'Amore 	}
2356a573d82SSukumar Swaminathan 
2366a573d82SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
2376a573d82SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
2386a573d82SSukumar Swaminathan 	hba->fc_edtov = FF_DEF_EDTOV;
2396a573d82SSukumar Swaminathan 	hba->fc_ratov = FF_DEF_RATOV;
2406a573d82SSukumar Swaminathan 	hba->fc_altov = FF_DEF_ALTOV;
2416a573d82SSukumar Swaminathan 	hba->fc_arbtov = FF_DEF_ARBTOV;
2426a573d82SSukumar Swaminathan 
243a9800bebSGarrett D'Amore 	/*
244a9800bebSGarrett D'Amore 	 * Get a buffer which will be used repeatedly for mailbox commands
245a9800bebSGarrett D'Amore 	 */
246a9800bebSGarrett D'Amore 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
2476a573d82SSukumar Swaminathan 
248a9800bebSGarrett D'Amore 	mb = (MAILBOX *)mbq;
2496a573d82SSukumar Swaminathan 
25082527734SSukumar Swaminathan 	/* Initialize sli mode based on configuration parameter */
25182527734SSukumar Swaminathan 	switch (cfg[CFG_SLI_MODE].current) {
25282527734SSukumar Swaminathan 	case 2:	/* SLI2 mode */
25382527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
25482527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
25582527734SSukumar Swaminathan 		break;
256291a2b48SSukumar Swaminathan 
25782527734SSukumar Swaminathan 	case 3:	/* SLI3 mode */
25882527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI3_MODE;
25982527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI3_MASK;
26082527734SSukumar Swaminathan 		break;
261291a2b48SSukumar Swaminathan 
26282527734SSukumar Swaminathan 	case 0:	/* Best available */
26382527734SSukumar Swaminathan 	case 1:	/* Best available */
26482527734SSukumar Swaminathan 	default:
26582527734SSukumar Swaminathan 		if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) {
26682527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
26782527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
26882527734SSukumar Swaminathan 		} else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) {
26982527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
27082527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
2718f23e9faSHans Rosenfeld 		} else {
2728f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2738f23e9faSHans Rosenfeld 			    "No SLI mode available.");
2748f23e9faSHans Rosenfeld 			rval = EIO;
2758f23e9faSHans Rosenfeld 			goto failed;
27682527734SSukumar Swaminathan 		}
2778f23e9faSHans Rosenfeld 		break;
27882527734SSukumar Swaminathan 	}
27982527734SSukumar Swaminathan 	/* SBUS adapters only available in SLI2 */
28082527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
28182527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
28282527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
283291a2b48SSukumar Swaminathan 	}
284291a2b48SSukumar Swaminathan 
2858f23e9faSHans Rosenfeld reset:
28682527734SSukumar Swaminathan 	/* Reset & Initialize the adapter */
28782527734SSukumar Swaminathan 	if (emlxs_sli3_hba_init(hba)) {
28882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
28982527734SSukumar Swaminathan 		    "Unable to init hba.");
290291a2b48SSukumar Swaminathan 
29182527734SSukumar Swaminathan 		rval = EIO;
29282527734SSukumar Swaminathan 		goto failed;
29382527734SSukumar Swaminathan 	}
294291a2b48SSukumar Swaminathan 
29582527734SSukumar Swaminathan #ifdef FMA_SUPPORT
29682527734SSukumar Swaminathan 	/* Access handle validation */
29782527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
29882527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
29982527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
30082527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
30182527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
30282527734SSukumar Swaminathan 	    != DDI_FM_OK)) {
30382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
30482527734SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
30582527734SSukumar Swaminathan 
30682527734SSukumar Swaminathan 		rval = EIO;
30782527734SSukumar Swaminathan 		goto failed;
308291a2b48SSukumar Swaminathan 	}
30982527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
310291a2b48SSukumar Swaminathan 
3118f23e9faSHans Rosenfeld 	/* Check for PEGASUS (This is a special case) */
31282527734SSukumar Swaminathan 	/* We need to check for dual channel adapter */
313*a3170057SPaul Winder 	if (hba->model_info.vendor_id == PCI_VENDOR_ID_EMULEX &&
314*a3170057SPaul Winder 	    hba->model_info.device_id == PCI_DEVICE_ID_PEGASUS) {
31582527734SSukumar Swaminathan 		/* Try to determine if this is a DC adapter */
31682527734SSukumar Swaminathan 		if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) {
31782527734SSukumar Swaminathan 			if (MaxRbusSize == REDUCED_SRAM_CFG) {
31882527734SSukumar Swaminathan 				/* LP9802DC */
31982527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
32082527734SSukumar Swaminathan 					if (emlxs_pci_model[i].id == LP9802DC) {
32182527734SSukumar Swaminathan 						bcopy(&emlxs_pci_model[i],
32282527734SSukumar Swaminathan 						    &hba->model_info,
32382527734SSukumar Swaminathan 						    sizeof (emlxs_model_t));
32482527734SSukumar Swaminathan 						break;
32582527734SSukumar Swaminathan 					}
32682527734SSukumar Swaminathan 				}
32782527734SSukumar Swaminathan 			} else if (hba->model_info.id != LP9802) {
32882527734SSukumar Swaminathan 				/* LP9802 */
32982527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
33082527734SSukumar Swaminathan 					if (emlxs_pci_model[i].id == LP9802) {
33182527734SSukumar Swaminathan 						bcopy(&emlxs_pci_model[i],
33282527734SSukumar Swaminathan 						    &hba->model_info,
33382527734SSukumar Swaminathan 						    sizeof (emlxs_model_t));
33482527734SSukumar Swaminathan 						break;
33582527734SSukumar Swaminathan 					}
33682527734SSukumar Swaminathan 				}
33782527734SSukumar Swaminathan 			}
33882527734SSukumar Swaminathan 		}
33982527734SSukumar Swaminathan 	}
340291a2b48SSukumar Swaminathan 
341291a2b48SSukumar Swaminathan 	/*
34282527734SSukumar Swaminathan 	 * Setup and issue mailbox READ REV command
343291a2b48SSukumar Swaminathan 	 */
34482527734SSukumar Swaminathan 	vpd->opFwRev = 0;
34582527734SSukumar Swaminathan 	vpd->postKernRev = 0;
34682527734SSukumar Swaminathan 	vpd->sli1FwRev = 0;
34782527734SSukumar Swaminathan 	vpd->sli2FwRev = 0;
34882527734SSukumar Swaminathan 	vpd->sli3FwRev = 0;
34982527734SSukumar Swaminathan 	vpd->sli4FwRev = 0;
35082527734SSukumar Swaminathan 
35182527734SSukumar Swaminathan 	vpd->postKernName[0] = 0;
35282527734SSukumar Swaminathan 	vpd->opFwName[0] = 0;
35382527734SSukumar Swaminathan 	vpd->sli1FwName[0] = 0;
35482527734SSukumar Swaminathan 	vpd->sli2FwName[0] = 0;
35582527734SSukumar Swaminathan 	vpd->sli3FwName[0] = 0;
35682527734SSukumar Swaminathan 	vpd->sli4FwName[0] = 0;
35782527734SSukumar Swaminathan 
35882527734SSukumar Swaminathan 	vpd->opFwLabel[0] = 0;
35982527734SSukumar Swaminathan 	vpd->sli1FwLabel[0] = 0;
36082527734SSukumar Swaminathan 	vpd->sli2FwLabel[0] = 0;
36182527734SSukumar Swaminathan 	vpd->sli3FwLabel[0] = 0;
36282527734SSukumar Swaminathan 	vpd->sli4FwLabel[0] = 0;
36382527734SSukumar Swaminathan 
36482527734SSukumar Swaminathan 	/* Sanity check */
36582527734SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
36682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
36782527734SSukumar Swaminathan 		    "Adapter / SLI mode mismatch mask:x%x",
36882527734SSukumar Swaminathan 		    hba->model_info.sli_mask);
36982527734SSukumar Swaminathan 
37082527734SSukumar Swaminathan 		rval = EIO;
37182527734SSukumar Swaminathan 		goto failed;
372291a2b48SSukumar Swaminathan 	}
373291a2b48SSukumar Swaminathan 
37482527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
37582527734SSukumar Swaminathan 	emlxs_mb_read_rev(hba, mbq, 0);
37682527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
37782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
37882527734SSukumar Swaminathan 		    "Unable to read rev. Mailbox cmd=%x status=%x",
37982527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
380291a2b48SSukumar Swaminathan 
38182527734SSukumar Swaminathan 		rval = EIO;
38282527734SSukumar Swaminathan 		goto failed;
383291a2b48SSukumar Swaminathan 	}
384291a2b48SSukumar Swaminathan 
38582527734SSukumar Swaminathan 	if (mb->un.varRdRev.rr == 0) {
38682527734SSukumar Swaminathan 		/* Old firmware */
38782527734SSukumar Swaminathan 		if (read_rev_reset == 0) {
38882527734SSukumar Swaminathan 			read_rev_reset = 1;
389291a2b48SSukumar Swaminathan 
39082527734SSukumar Swaminathan 			goto reset;
39182527734SSukumar Swaminathan 		} else {
39282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
39382527734SSukumar Swaminathan 			    "Outdated firmware detected.");
39482527734SSukumar Swaminathan 		}
395291a2b48SSukumar Swaminathan 
39682527734SSukumar Swaminathan 		vpd->rBit = 0;
39782527734SSukumar Swaminathan 	} else {
39882527734SSukumar Swaminathan 		if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) {
39982527734SSukumar Swaminathan 			if (read_rev_reset == 0) {
40082527734SSukumar Swaminathan 				read_rev_reset = 1;
401291a2b48SSukumar Swaminathan 
40282527734SSukumar Swaminathan 				goto reset;
40382527734SSukumar Swaminathan 			} else {
40482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
40582527734SSukumar Swaminathan 				    "Non-operational firmware detected. "
40682527734SSukumar Swaminathan 				    "type=%x",
40782527734SSukumar Swaminathan 				    mb->un.varRdRev.un.b.ProgType);
40882527734SSukumar Swaminathan 			}
40982527734SSukumar Swaminathan 		}
410291a2b48SSukumar Swaminathan 
41182527734SSukumar Swaminathan 		vpd->rBit = 1;
41282527734SSukumar Swaminathan 		vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1;
41382527734SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel,
41482527734SSukumar Swaminathan 		    16);
41582527734SSukumar Swaminathan 		vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2;
41682527734SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel,
41782527734SSukumar Swaminathan 		    16);
418291a2b48SSukumar Swaminathan 
41982527734SSukumar Swaminathan 		/*
42082527734SSukumar Swaminathan 		 * Lets try to read the SLI3 version
42182527734SSukumar Swaminathan 		 * Setup and issue mailbox READ REV(v3) command
42282527734SSukumar Swaminathan 		 */
42382527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
424