1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22*4c3888b8SHans Rosenfeld /* Copyright 2015 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25*4c3888b8SHans Rosenfeld  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28fcf3ce44SJohn Forte /*
29fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
30fcf3ce44SJohn Forte  *
31fcf3ce44SJohn Forte  * ***********************************************************************
32fcf3ce44SJohn Forte  * *									**
33fcf3ce44SJohn Forte  * *				NOTICE					**
34*4c3888b8SHans Rosenfeld  * *		COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION		**
35fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
36fcf3ce44SJohn Forte  * *									**
37fcf3ce44SJohn Forte  * ***********************************************************************
38fcf3ce44SJohn Forte  *
39fcf3ce44SJohn Forte  */
40fcf3ce44SJohn Forte 
41fcf3ce44SJohn Forte #include <ql_apps.h>
42fcf3ce44SJohn Forte #include <ql_api.h>
43fcf3ce44SJohn Forte #include <ql_debug.h>
44fcf3ce44SJohn Forte #include <ql_init.h>
45fcf3ce44SJohn Forte #include <ql_iocb.h>
46fcf3ce44SJohn Forte #include <ql_isr.h>
47fcf3ce44SJohn Forte #include <ql_mbx.h>
48eb82ff87SDaniel Beauregard #include <ql_nx.h>
49fcf3ce44SJohn Forte #include <ql_xioctl.h>
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte /*
52fcf3ce44SJohn Forte  * Local data
53fcf3ce44SJohn Forte  */
54fcf3ce44SJohn Forte 
55fcf3ce44SJohn Forte /*
56fcf3ce44SJohn Forte  * Local prototypes
57fcf3ce44SJohn Forte  */
58fcf3ce44SJohn Forte static uint16_t ql_nvram_request(ql_adapter_state_t *, uint32_t);
59fcf3ce44SJohn Forte static int ql_nvram_24xx_config(ql_adapter_state_t *);
60*4c3888b8SHans Rosenfeld static void ql_23_properties(ql_adapter_state_t *, ql_init_cb_t *);
61*4c3888b8SHans Rosenfeld static void ql_24xx_properties(ql_adapter_state_t *, ql_init_24xx_cb_t *);
62fcf3ce44SJohn Forte static int ql_check_isp_firmware(ql_adapter_state_t *);
63fcf3ce44SJohn Forte static int ql_load_flash_fw(ql_adapter_state_t *);
64fcf3ce44SJohn Forte static int ql_configure_loop(ql_adapter_state_t *);
65fcf3ce44SJohn Forte static int ql_configure_hba(ql_adapter_state_t *);
66fcf3ce44SJohn Forte static int ql_configure_fabric(ql_adapter_state_t *);
67fcf3ce44SJohn Forte static int ql_configure_device_d_id(ql_adapter_state_t *);
68*4c3888b8SHans Rosenfeld static void ql_update_dev(ql_adapter_state_t *, uint32_t);
69fcf3ce44SJohn Forte static void ql_set_max_read_req(ql_adapter_state_t *);
705dfd244aSDaniel Beauregard static void ql_configure_n_port_info(ql_adapter_state_t *);
71*4c3888b8SHans Rosenfeld static void ql_reset_24xx_chip(ql_adapter_state_t *);
72f33c1cdbSDaniel Beauregard static void ql_mps_reset(ql_adapter_state_t *);
73a2b3ff35SDaniel Beauregard 
74fcf3ce44SJohn Forte /*
75fcf3ce44SJohn Forte  * ql_initialize_adapter
76fcf3ce44SJohn Forte  *	Initialize board.
77fcf3ce44SJohn Forte  *
78fcf3ce44SJohn Forte  * Input:
79fcf3ce44SJohn Forte  *	ha = adapter state pointer.
80fcf3ce44SJohn Forte  *
81fcf3ce44SJohn Forte  * Returns:
82fcf3ce44SJohn Forte  *	ql local function return status code.
83fcf3ce44SJohn Forte  *
84fcf3ce44SJohn Forte  * Context:
85fcf3ce44SJohn Forte  *	Kernel context.
86fcf3ce44SJohn Forte  */
87fcf3ce44SJohn Forte int
ql_initialize_adapter(ql_adapter_state_t * ha)88fcf3ce44SJohn Forte ql_initialize_adapter(ql_adapter_state_t *ha)
89fcf3ce44SJohn Forte {
90fcf3ce44SJohn Forte 	int			rval;
91fcf3ce44SJohn Forte 	class_svc_param_t	*class3_param;
92fcf3ce44SJohn Forte 	caddr_t			msg;
93fcf3ce44SJohn Forte 	la_els_logi_t		*els = &ha->loginparams;
94fcf3ce44SJohn Forte 	int			retries = 5;
95fcf3ce44SJohn Forte 
96*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started cfg=0x%llx\n", ha->cfg_flags);
97fcf3ce44SJohn Forte 
98fcf3ce44SJohn Forte 	do {
99fcf3ce44SJohn Forte 		/* Clear adapter flags. */
100fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
101fcf3ce44SJohn Forte 		ha->task_daemon_flags &= TASK_DAEMON_STOP_FLG |
102fcf3ce44SJohn Forte 		    TASK_DAEMON_SLEEPING_FLG | TASK_DAEMON_ALIVE_FLG |
103fcf3ce44SJohn Forte 		    TASK_DAEMON_IDLE_CHK_FLG;
104fcf3ce44SJohn Forte 		ha->task_daemon_flags |= LOOP_DOWN;
105fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
106fcf3ce44SJohn Forte 
107fcf3ce44SJohn Forte 		ha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
108fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
10916dd44c2SDaniel Beauregard 		ha->flags |= ABORT_CMDS_LOOP_DOWN_TMO;
110fcf3ce44SJohn Forte 		ha->flags &= ~ONLINE;
111fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 		ha->state = FC_STATE_OFFLINE;
114fcf3ce44SJohn Forte 		msg = "Loop OFFLINE";
115fcf3ce44SJohn Forte 
116fcf3ce44SJohn Forte 		rval = ql_pci_sbus_config(ha);
117fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
118fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
119fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
120fcf3ce44SJohn Forte 				EL(ha, "ql_pci_sbus_cfg, isp_abort_needed\n");
121fcf3ce44SJohn Forte 				ha->task_daemon_flags |= ISP_ABORT_NEEDED;
122fcf3ce44SJohn Forte 			}
123fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
124fcf3ce44SJohn Forte 			continue;
125fcf3ce44SJohn Forte 		}
126fcf3ce44SJohn Forte 
1275dfd244aSDaniel Beauregard 		(void) ql_setup_fcache(ha);
128fcf3ce44SJohn Forte 
129fcf3ce44SJohn Forte 		/* Reset ISP chip. */
130fcf3ce44SJohn Forte 		ql_reset_chip(ha);
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 		/* Get NVRAM configuration if needed. */
133fcf3ce44SJohn Forte 		if (ha->init_ctrl_blk.cb.version == 0) {
134fcf3ce44SJohn Forte 			(void) ql_nvram_config(ha);
135fcf3ce44SJohn Forte 		}
136fcf3ce44SJohn Forte 
137fcf3ce44SJohn Forte 		/* Determine which RISC code to use. */
138eb82ff87SDaniel Beauregard 		if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) {
139*4c3888b8SHans Rosenfeld 			if (ha->dev_state != NX_DEV_READY) {
140*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state not ready, isp_abort_needed_2"
141*4c3888b8SHans Rosenfeld 				    "\n");
142*4c3888b8SHans Rosenfeld 				TASK_DAEMON_LOCK(ha);
143*4c3888b8SHans Rosenfeld 				ha->task_daemon_flags |= ISP_ABORT_NEEDED;
144*4c3888b8SHans Rosenfeld 				TASK_DAEMON_UNLOCK(ha);
145*4c3888b8SHans Rosenfeld 				break;
146*4c3888b8SHans Rosenfeld 			}
147*4c3888b8SHans Rosenfeld 			if ((rval = ql_mbx_wrap_test(ha, NULL)) == QL_SUCCESS) {
148eb82ff87SDaniel Beauregard 				rval = ql_load_isp_firmware(ha);
149eb82ff87SDaniel Beauregard 			}
150fcf3ce44SJohn Forte 		}
151fcf3ce44SJohn Forte 
152fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
1535dfd244aSDaniel Beauregard 		    QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS) {
154fcf3ce44SJohn Forte 
155*4c3888b8SHans Rosenfeld 			ql_enable_intr(ha);
156fcf3ce44SJohn Forte 			(void) ql_fw_ready(ha, ha->fwwait);
157fcf3ce44SJohn Forte 
158*4c3888b8SHans Rosenfeld 			if (!DRIVER_SUSPENDED(ha) &&
159fcf3ce44SJohn Forte 			    ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
160fcf3ce44SJohn Forte 				if (ha->topology & QL_LOOP_CONNECTION) {
161fcf3ce44SJohn Forte 					ha->state = ha->state | FC_STATE_LOOP;
162fcf3ce44SJohn Forte 					msg = "Loop ONLINE";
163*4c3888b8SHans Rosenfeld 					TASK_DAEMON_LOCK(ha);
164fcf3ce44SJohn Forte 					ha->task_daemon_flags |= STATE_ONLINE;
165*4c3888b8SHans Rosenfeld 					TASK_DAEMON_UNLOCK(ha);
166fcf3ce44SJohn Forte 				} else if (ha->topology & QL_P2P_CONNECTION) {
167fcf3ce44SJohn Forte 					ha->state = ha->state |
168fcf3ce44SJohn Forte 					    FC_STATE_ONLINE;
169fcf3ce44SJohn Forte 					msg = "Link ONLINE";
170*4c3888b8SHans Rosenfeld 					TASK_DAEMON_LOCK(ha);
171fcf3ce44SJohn Forte 					ha->task_daemon_flags |= STATE_ONLINE;
172*4c3888b8SHans Rosenfeld 					TASK_DAEMON_UNLOCK(ha);
173fcf3ce44SJohn Forte 				} else {
174fcf3ce44SJohn Forte 					msg = "Unknown Link state";
175fcf3ce44SJohn Forte 				}
176fcf3ce44SJohn Forte 			}
177fcf3ce44SJohn Forte 		} else {
178fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
179fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
180fcf3ce44SJohn Forte 				EL(ha, "failed, isp_abort_needed\n");
181fcf3ce44SJohn Forte 				ha->task_daemon_flags |= ISP_ABORT_NEEDED |
182fcf3ce44SJohn Forte 				    LOOP_DOWN;
183fcf3ce44SJohn Forte 			}
184fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
185fcf3ce44SJohn Forte 		}
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 	} while (retries-- != 0 && ha->task_daemon_flags & ISP_ABORT_NEEDED);
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 	cmn_err(CE_NOTE, "!Qlogic %s(%d): %s", QL_NAME, ha->instance, msg);
190fcf3ce44SJohn Forte 
191*4c3888b8SHans Rosenfeld 	/* Enable ISP interrupts if not already enabled. */
192*4c3888b8SHans Rosenfeld 	if (!(ha->flags & INTERRUPTS_ENABLED)) {
193*4c3888b8SHans Rosenfeld 		ql_enable_intr(ha);
194eb82ff87SDaniel Beauregard 	}
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
197*4c3888b8SHans Rosenfeld 	ha->flags |= ONLINE;
198fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
199fcf3ce44SJohn Forte 
200*4c3888b8SHans Rosenfeld 	/*
201*4c3888b8SHans Rosenfeld 	 * Set flash write-protection.
202*4c3888b8SHans Rosenfeld 	 */
203*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
204*4c3888b8SHans Rosenfeld 	    ha->dev_state == NX_DEV_READY) {
205*4c3888b8SHans Rosenfeld 		ql_24xx_protect_flash(ha);
206*4c3888b8SHans Rosenfeld 	}
207*4c3888b8SHans Rosenfeld 
208*4c3888b8SHans Rosenfeld 	TASK_DAEMON_LOCK(ha);
209*4c3888b8SHans Rosenfeld 	ha->task_daemon_flags &= ~(FC_STATE_CHANGE | MARKER_NEEDED |
210fcf3ce44SJohn Forte 	    COMMAND_WAIT_NEEDED);
211*4c3888b8SHans Rosenfeld 	TASK_DAEMON_UNLOCK(ha);
212fcf3ce44SJohn Forte 
213fcf3ce44SJohn Forte 	/*
214fcf3ce44SJohn Forte 	 * Setup login parameters.
215fcf3ce44SJohn Forte 	 */
216*4c3888b8SHans Rosenfeld 	bcopy(QL_VERSION, ha->adapter_stats->revlvl.qlddv, strlen(QL_VERSION));
217*4c3888b8SHans Rosenfeld 
218fcf3ce44SJohn Forte 	els->common_service.fcph_version = 0x2006;
219fcf3ce44SJohn Forte 	els->common_service.btob_credit = 3;
220*4c3888b8SHans Rosenfeld 	els->common_service.cmn_features =
221*4c3888b8SHans Rosenfeld 	    ha->topology & QL_N_PORT ? 0x8000 : 0x8800;
222fcf3ce44SJohn Forte 	els->common_service.conc_sequences = 0xff;
223fcf3ce44SJohn Forte 	els->common_service.relative_offset = 3;
224fcf3ce44SJohn Forte 	els->common_service.e_d_tov = 0x07d0;
225fcf3ce44SJohn Forte 
226fcf3ce44SJohn Forte 	class3_param = (class_svc_param_t *)&els->class_3;
227fcf3ce44SJohn Forte 	class3_param->class_valid_svc_opt = 0x8800;
228fcf3ce44SJohn Forte 	class3_param->rcv_data_size = els->common_service.rx_bufsize;
229fcf3ce44SJohn Forte 	class3_param->conc_sequences = 0xff;
230*4c3888b8SHans Rosenfeld 	class3_param->open_sequences_per_exch = 1;
231fcf3ce44SJohn Forte 
232fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
233fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
234fcf3ce44SJohn Forte 	} else {
235fcf3ce44SJohn Forte 		/*EMPTY*/
236*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
237fcf3ce44SJohn Forte 	}
238fcf3ce44SJohn Forte 	return (rval);
239fcf3ce44SJohn Forte }
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte /*
242fcf3ce44SJohn Forte  * ql_pci_sbus_config
243fcf3ce44SJohn Forte  *	Setup device PCI/SBUS configuration registers.
244fcf3ce44SJohn Forte  *
245fcf3ce44SJohn Forte  * Input:
246fcf3ce44SJohn Forte  *	ha = adapter state pointer.
247fcf3ce44SJohn Forte  *
248fcf3ce44SJohn Forte  * Returns:
249fcf3ce44SJohn Forte  *	ql local function return status code.
250fcf3ce44SJohn Forte  *
251fcf3ce44SJohn Forte  * Context:
252fcf3ce44SJohn Forte  *	Kernel context.
253fcf3ce44SJohn Forte  */
254fcf3ce44SJohn Forte int
ql_pci_sbus_config(ql_adapter_state_t * ha)255fcf3ce44SJohn Forte ql_pci_sbus_config(ql_adapter_state_t *ha)
256fcf3ce44SJohn Forte {
257fcf3ce44SJohn Forte 	uint32_t	timer;
258fcf3ce44SJohn Forte 	uint16_t	cmd, w16;
259fcf3ce44SJohn Forte 
260*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
263fcf3ce44SJohn Forte 		w16 = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle,
264fcf3ce44SJohn Forte 		    (uint16_t *)(ha->sbus_fpga_iobase + FPGA_REVISION));
265fcf3ce44SJohn Forte 		EL(ha, "FPGA rev is %d.%d", (w16 & 0xf0) >> 4,
266fcf3ce44SJohn Forte 		    w16 & 0xf);
267fcf3ce44SJohn Forte 	} else {
268fcf3ce44SJohn Forte 		/*
269fcf3ce44SJohn Forte 		 * we want to respect framework's setting of PCI
270fcf3ce44SJohn Forte 		 * configuration space command register and also
271fcf3ce44SJohn Forte 		 * want to make sure that all bits of interest to us
272fcf3ce44SJohn Forte 		 * are properly set in command register.
273fcf3ce44SJohn Forte 		 */
274fcf3ce44SJohn Forte 		cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
275fcf3ce44SJohn Forte 		cmd = (uint16_t)(cmd | PCI_COMM_IO | PCI_COMM_MAE |
276*4c3888b8SHans Rosenfeld 		    PCI_COMM_ME | PCI_COMM_PARITY_DETECT |
277*4c3888b8SHans Rosenfeld 		    PCI_COMM_SERR_ENABLE);
278*4c3888b8SHans Rosenfeld 		if (ql_get_cap_ofst(ha, PCI_CAP_ID_PCIX)) {
279*4c3888b8SHans Rosenfeld 			cmd = (uint16_t)(cmd | PCI_COMM_MEMWR_INVAL);
280*4c3888b8SHans Rosenfeld 		}
281fcf3ce44SJohn Forte 
282fcf3ce44SJohn Forte 		/*
283fcf3ce44SJohn Forte 		 * If this is a 2300 card and not 2312, reset the
284fcf3ce44SJohn Forte 		 * MEMWR_INVAL due to a bug in the 2300. Unfortunately, the
285fcf3ce44SJohn Forte 		 * 2310 also reports itself as a 2300 so we need to get the
286fcf3ce44SJohn Forte 		 * fb revision level -- a 6 indicates it really is a 2300 and
287fcf3ce44SJohn Forte 		 * not a 2310.
288fcf3ce44SJohn Forte 		 */
289fcf3ce44SJohn Forte 
290fcf3ce44SJohn Forte 		if (ha->device_id == 0x2300) {
291fcf3ce44SJohn Forte 			/* Pause RISC. */
292fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
293fcf3ce44SJohn Forte 			for (timer = 0; timer < 30000; timer++) {
294fcf3ce44SJohn Forte 				if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) !=
295fcf3ce44SJohn Forte 				    0) {
296fcf3ce44SJohn Forte 					break;
297fcf3ce44SJohn Forte 				} else {
298fcf3ce44SJohn Forte 					drv_usecwait(MILLISEC);
299fcf3ce44SJohn Forte 				}
300fcf3ce44SJohn Forte 			}
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte 			/* Select FPM registers. */
303fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, ctrl_status, 0x20);
304fcf3ce44SJohn Forte 
305fcf3ce44SJohn Forte 			/* Get the fb rev level */
306fcf3ce44SJohn Forte 			if (RD16_IO_REG(ha, fb_cmd) == 6) {
307fcf3ce44SJohn Forte 				cmd = (uint16_t)(cmd & ~PCI_COMM_MEMWR_INVAL);
308fcf3ce44SJohn Forte 			}
309fcf3ce44SJohn Forte 
310fcf3ce44SJohn Forte 			/* Deselect FPM registers. */
311fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, ctrl_status, 0x0);
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte 			/* Release RISC module. */
314fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
315fcf3ce44SJohn Forte 			for (timer = 0; timer < 30000; timer++) {
316fcf3ce44SJohn Forte 				if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) ==
317fcf3ce44SJohn Forte 				    0) {
318fcf3ce44SJohn Forte 					break;
319fcf3ce44SJohn Forte 				} else {
320fcf3ce44SJohn Forte 					drv_usecwait(MILLISEC);
321fcf3ce44SJohn Forte 				}
322fcf3ce44SJohn Forte 			}
323fcf3ce44SJohn Forte 		} else if (ha->device_id == 0x2312) {
324fcf3ce44SJohn Forte 			/*
325fcf3ce44SJohn Forte 			 * cPCI ISP2312 specific code to service function 1
326fcf3ce44SJohn Forte 			 * hot-swap registers.
327fcf3ce44SJohn Forte 			 */
328fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, ctrl_status) & ISP_FUNC_NUM_MASK)
329fcf3ce44SJohn Forte 			    != 0) {
330fcf3ce44SJohn Forte 				ql_pci_config_put8(ha, 0x66, 0xc2);
331fcf3ce44SJohn Forte 			}
332fcf3ce44SJohn Forte 		}
333fcf3ce44SJohn Forte 
334*4c3888b8SHans Rosenfeld 		if (!(CFG_IST(ha, CFG_CTRL_82XX)) &&
335eb82ff87SDaniel Beauregard 		    ha->pci_max_read_req != 0) {
336fcf3ce44SJohn Forte 			ql_set_max_read_req(ha);
337fcf3ce44SJohn Forte 		}
338fcf3ce44SJohn Forte 
339fcf3ce44SJohn Forte 		ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 		/* Set cache line register. */
342fcf3ce44SJohn Forte 		ql_pci_config_put8(ha, PCI_CONF_CACHE_LINESZ, 0x10);
343fcf3ce44SJohn Forte 
344fcf3ce44SJohn Forte 		/* Set latency register. */
345fcf3ce44SJohn Forte 		ql_pci_config_put8(ha, PCI_CONF_LATENCY_TIMER, 0x40);
346fcf3ce44SJohn Forte 
347fcf3ce44SJohn Forte 		/* Reset expansion ROM address decode enable. */
348*4c3888b8SHans Rosenfeld 		if (!CFG_IST(ha, CFG_CTRL_278083)) {
349*4c3888b8SHans Rosenfeld 			w16 = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_ROM);
350*4c3888b8SHans Rosenfeld 			w16 = (uint16_t)(w16 & ~BIT_0);
351*4c3888b8SHans Rosenfeld 			ql_pci_config_put16(ha, PCI_CONF_ROM, w16);
352*4c3888b8SHans Rosenfeld 		}
353fcf3ce44SJohn Forte 	}
354fcf3ce44SJohn Forte 
355*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
356fcf3ce44SJohn Forte 
357fcf3ce44SJohn Forte 	return (QL_SUCCESS);
358fcf3ce44SJohn Forte }
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte /*
361fcf3ce44SJohn Forte  * Set the PCI max read request value.
362fcf3ce44SJohn Forte  *
363fcf3ce44SJohn Forte  * Input:
364fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
365fcf3ce44SJohn Forte  *
366fcf3ce44SJohn Forte  * Output:
367fcf3ce44SJohn Forte  *	none.
368fcf3ce44SJohn Forte  *
369fcf3ce44SJohn Forte  * Returns:
370fcf3ce44SJohn Forte  *
371fcf3ce44SJohn Forte  * Context:
372fcf3ce44SJohn Forte  *	Kernel context.
373fcf3ce44SJohn Forte  */
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte static void
ql_set_max_read_req(ql_adapter_state_t * ha)376fcf3ce44SJohn Forte ql_set_max_read_req(ql_adapter_state_t *ha)
377fcf3ce44SJohn Forte {
378*4c3888b8SHans Rosenfeld 	int		ofst;
379fcf3ce44SJohn Forte 	uint16_t	read_req, w16;
380fcf3ce44SJohn Forte 	uint16_t	tmp = ha->pci_max_read_req;
381fcf3ce44SJohn Forte 
382*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
383*4c3888b8SHans Rosenfeld 
384*4c3888b8SHans Rosenfeld 	if ((ofst = ql_get_cap_ofst(ha, PCI_CAP_ID_PCIX))) {
385*4c3888b8SHans Rosenfeld 		ofst += PCI_PCIX_COMMAND;
386*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "PCI-X Command Reg = %xh\n", ofst);
387fcf3ce44SJohn Forte 		/* check for vaild override value */
388fcf3ce44SJohn Forte 		if (tmp == 512 || tmp == 1024 || tmp == 2048 ||
389fcf3ce44SJohn Forte 		    tmp == 4096) {
390fcf3ce44SJohn Forte 			/* shift away the don't cares */
391fcf3ce44SJohn Forte 			tmp = (uint16_t)(tmp >> 10);
392fcf3ce44SJohn Forte 			/* convert bit pos to request value */
393fcf3ce44SJohn Forte 			for (read_req = 0; tmp != 0; read_req++) {
394fcf3ce44SJohn Forte 				tmp = (uint16_t)(tmp >> 1);
395fcf3ce44SJohn Forte 			}
396*4c3888b8SHans Rosenfeld 			w16 = (uint16_t)ql_pci_config_get16(ha, ofst);
397fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 & ~(BIT_3 & BIT_2));
398fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 | (read_req << 2));
399*4c3888b8SHans Rosenfeld 			ql_pci_config_put16(ha, ofst, w16);
400fcf3ce44SJohn Forte 		} else {
401fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
402fcf3ce44SJohn Forte 			    "'pci-max-read-request': %d; using system "
403fcf3ce44SJohn Forte 			    "default\n", tmp);
404fcf3ce44SJohn Forte 		}
405*4c3888b8SHans Rosenfeld 	} else if ((ofst = ql_get_cap_ofst(ha, PCI_CAP_ID_PCI_E))) {
406*4c3888b8SHans Rosenfeld 		ofst += PCI_PCIE_DEVICE_CONTROL;
407*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "PCI-E Device Control Reg = %xh\n", ofst);
408fcf3ce44SJohn Forte 		if (tmp == 128 || tmp == 256 || tmp == 512 ||
409fcf3ce44SJohn Forte 		    tmp == 1024 || tmp == 2048 || tmp == 4096) {
410fcf3ce44SJohn Forte 			/* shift away the don't cares */
411fcf3ce44SJohn Forte 			tmp = (uint16_t)(tmp >> 8);
412fcf3ce44SJohn Forte 			/* convert bit pos to request value */
413fcf3ce44SJohn Forte 			for (read_req = 0; tmp != 0; read_req++) {
414fcf3ce44SJohn Forte 				tmp = (uint16_t)(tmp >> 1);
415fcf3ce44SJohn Forte 			}
416*4c3888b8SHans Rosenfeld 			w16 = (uint16_t)ql_pci_config_get16(ha, ofst);
417fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 & ~(BIT_14 | BIT_13 |
418fcf3ce44SJohn Forte 			    BIT_12));
419fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 | (read_req << 12));
420*4c3888b8SHans Rosenfeld 			ql_pci_config_put16(ha, ofst, w16);
421fcf3ce44SJohn Forte 		} else {
422fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
423fcf3ce44SJohn Forte 			    "'pci-max-read-request': %d; using system "
424fcf3ce44SJohn Forte 			    "default\n", tmp);
425fcf3ce44SJohn Forte 		}
426fcf3ce44SJohn Forte 	}
427*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
428fcf3ce44SJohn Forte }
429fcf3ce44SJohn Forte 
430fcf3ce44SJohn Forte /*
431fcf3ce44SJohn Forte  * NVRAM configuration.
432fcf3ce44SJohn Forte  *
433fcf3ce44SJohn Forte  * Input:
434fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
435*4c3888b8SHans Rosenfeld  *	ha->req_q[0]:	request ring
436fcf3ce44SJohn Forte  *
437fcf3ce44SJohn Forte  * Output:
438fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
439fcf3ce44SJohn Forte  *	host adapters parameters in host adapter block
440fcf3ce44SJohn Forte  *
441fcf3ce44SJohn Forte  * Returns:
442fcf3ce44SJohn Forte  *	ql local function return status code.
443fcf3ce44SJohn Forte  *
444fcf3ce44SJohn Forte  * Context:
445fcf3ce44SJohn Forte  *	Kernel context.
446fcf3ce44SJohn Forte  */
447fcf3ce44SJohn Forte int
ql_nvram_config(ql_adapter_state_t * ha)448fcf3ce44SJohn Forte ql_nvram_config(ql_adapter_state_t *ha)
449fcf3ce44SJohn Forte {
450fcf3ce44SJohn Forte 	uint32_t	cnt;
451fcf3ce44SJohn Forte 	caddr_t		dptr1, dptr2;
452fcf3ce44SJohn Forte 	ql_init_cb_t	*icb = &ha->init_ctrl_blk.cb;
453fcf3ce44SJohn Forte 	ql_ip_init_cb_t	*ip_icb = &ha->ip_init_ctrl_blk.cb;
454*4c3888b8SHans Rosenfeld 	nvram_t		*nv = (nvram_t *)ha->req_q[0]->req_ring.bp;
455*4c3888b8SHans Rosenfeld 	uint16_t	*wptr = (uint16_t *)ha->req_q[0]->req_ring.bp;
456fcf3ce44SJohn Forte 	uint8_t		chksum = 0;
457fcf3ce44SJohn Forte 	int		rval;
458fcf3ce44SJohn Forte 	int		idpromlen;
459fcf3ce44SJohn Forte 	char		idprombuf[32];
460fcf3ce44SJohn Forte 	uint32_t	start_addr;
461*4c3888b8SHans Rosenfeld 	la_els_logi_t	*els = &ha->loginparams;
462fcf3ce44SJohn Forte 
463*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
464fcf3ce44SJohn Forte 
465*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
466fcf3ce44SJohn Forte 		return (ql_nvram_24xx_config(ha));
467fcf3ce44SJohn Forte 	}
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 	start_addr = 0;
470fcf3ce44SJohn Forte 	if ((rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) ==
471fcf3ce44SJohn Forte 	    QL_SUCCESS) {
472fcf3ce44SJohn Forte 		/* Verify valid NVRAM checksum. */
473*4c3888b8SHans Rosenfeld 		for (cnt = 0; cnt < sizeof (nvram_t) / 2; cnt++) {
474fcf3ce44SJohn Forte 			*wptr = (uint16_t)ql_get_nvram_word(ha,
475fcf3ce44SJohn Forte 			    (uint32_t)(cnt + start_addr));
476fcf3ce44SJohn Forte 			chksum = (uint8_t)(chksum + (uint8_t)*wptr);
477fcf3ce44SJohn Forte 			chksum = (uint8_t)(chksum + (uint8_t)(*wptr >> 8));
478fcf3ce44SJohn Forte 			wptr++;
479fcf3ce44SJohn Forte 		}
480fcf3ce44SJohn Forte 		ql_release_nvram(ha);
481fcf3ce44SJohn Forte 	}
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 	/* Bad NVRAM data, set defaults parameters. */
484fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
485fcf3ce44SJohn Forte 	    nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
486fcf3ce44SJohn Forte 	    nv->nvram_version < 1) {
487fcf3ce44SJohn Forte 
488fcf3ce44SJohn Forte 		EL(ha, "failed, rval=%xh, checksum=%xh, "
489fcf3ce44SJohn Forte 		    "id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, "
490fcf3ce44SJohn Forte 		    "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
491fcf3ce44SJohn Forte 		    nv->id[2], nv->id[3], ha->xioctl->fdesc.flash_size,
492fcf3ce44SJohn Forte 		    ha->subven_id, nv->nvram_version);
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 		/* Don't print nvram message if it's an on-board 2200 */
495*4c3888b8SHans Rosenfeld 		if (!((CFG_IST(ha, CFG_CTRL_22XX)) &&
496fcf3ce44SJohn Forte 		    (ha->xioctl->fdesc.flash_size == 0))) {
497fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed,"
498fcf3ce44SJohn Forte 			    " using driver defaults.", QL_NAME, ha->instance);
499fcf3ce44SJohn Forte 		}
500fcf3ce44SJohn Forte 
501fcf3ce44SJohn Forte 		/* Reset NVRAM data. */
502fcf3ce44SJohn Forte 		bzero((void *)nv, sizeof (nvram_t));
503fcf3ce44SJohn Forte 
504fcf3ce44SJohn Forte 		/*
505fcf3ce44SJohn Forte 		 * Set default initialization control block.
506fcf3ce44SJohn Forte 		 */
507fcf3ce44SJohn Forte 		nv->parameter_block_version = ICB_VERSION;
508fcf3ce44SJohn Forte 		nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
509fcf3ce44SJohn Forte 		nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
510fcf3ce44SJohn Forte 
511fcf3ce44SJohn Forte 		nv->max_frame_length[1] = 4;
512fcf3ce44SJohn Forte 
513fcf3ce44SJohn Forte 		/*
514fcf3ce44SJohn Forte 		 * Allow 2048 byte frames for 2300
515fcf3ce44SJohn Forte 		 */
516*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_2363)) {
517fcf3ce44SJohn Forte 			nv->max_frame_length[1] = 8;
518fcf3ce44SJohn Forte 		}
519fcf3ce44SJohn Forte 		nv->max_iocb_allocation[1] = 1;
520fcf3ce44SJohn Forte 		nv->execution_throttle[0] = 16;
521fcf3ce44SJohn Forte 		nv->login_retry_count = 8;
522fcf3ce44SJohn Forte 
523fcf3ce44SJohn Forte 		idpromlen = 32;
524fcf3ce44SJohn Forte 
525fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
526fcf3ce44SJohn Forte 		if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
527fcf3ce44SJohn Forte 		    DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
528fcf3ce44SJohn Forte 		    &idpromlen) != DDI_PROP_SUCCESS) {
529fcf3ce44SJohn Forte 
530*4c3888b8SHans Rosenfeld 			QL_PRINT_10(ha, "Unable to read idprom "
531*4c3888b8SHans Rosenfeld 			    "property\n");
532fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
533fcf3ce44SJohn Forte 			    "property", QL_NAME, ha->instance);
534fcf3ce44SJohn Forte 
535fcf3ce44SJohn Forte 			nv->port_name[2] = 33;
536fcf3ce44SJohn Forte 			nv->port_name[3] = 224;
537fcf3ce44SJohn Forte 			nv->port_name[4] = 139;
538fcf3ce44SJohn Forte 			nv->port_name[7] = (uint8_t)
539fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
540fcf3ce44SJohn Forte 		} else {
541fcf3ce44SJohn Forte 
542fcf3ce44SJohn Forte 			nv->port_name[2] = idprombuf[2];
543fcf3ce44SJohn Forte 			nv->port_name[3] = idprombuf[3];
544fcf3ce44SJohn Forte 			nv->port_name[4] = idprombuf[4];
545fcf3ce44SJohn Forte 			nv->port_name[5] = idprombuf[5];
546fcf3ce44SJohn Forte 			nv->port_name[6] = idprombuf[6];
547fcf3ce44SJohn Forte 			nv->port_name[7] = idprombuf[7];
548fcf3ce44SJohn Forte 			nv->port_name[0] = (uint8_t)
549fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
550fcf3ce44SJohn Forte 		}
551fcf3ce44SJohn Forte 
552fcf3ce44SJohn Forte 		/* Don't print nvram message if it's an on-board 2200 */
553*4c3888b8SHans Rosenfeld 		if (!(CFG_IST(ha, CFG_CTRL_22XX)) &&
554fcf3ce44SJohn Forte 		    (ha->xioctl->fdesc.flash_size == 0)) {
555fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using"
556fcf3ce44SJohn Forte 			    " default HBA parameters and temporary WWPN:"
557fcf3ce44SJohn Forte 			    " %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
558fcf3ce44SJohn Forte 			    ha->instance, nv->port_name[0], nv->port_name[1],
559fcf3ce44SJohn Forte 			    nv->port_name[2], nv->port_name[3],
560fcf3ce44SJohn Forte 			    nv->port_name[4], nv->port_name[5],
561fcf3ce44SJohn Forte 			    nv->port_name[6], nv->port_name[7]);
562fcf3ce44SJohn Forte 		}
563fcf3ce44SJohn Forte 
564fcf3ce44SJohn Forte 		nv->login_timeout = 4;
565fcf3ce44SJohn Forte 
566fcf3ce44SJohn Forte 		/* Set default connection options for the 23xx to 2 */
567*4c3888b8SHans Rosenfeld 		if (!(CFG_IST(ha, CFG_CTRL_22XX))) {
568fcf3ce44SJohn Forte 			nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
569fcf3ce44SJohn Forte 			    BIT_5);
570fcf3ce44SJohn Forte 		}
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte 		/*
573fcf3ce44SJohn Forte 		 * Set default host adapter parameters
574fcf3ce44SJohn Forte 		 */
575fcf3ce44SJohn Forte 		nv->host_p[0] = BIT_1;
576fcf3ce44SJohn Forte 		nv->host_p[1] = BIT_2;
577fcf3ce44SJohn Forte 		nv->reset_delay = 5;
578fcf3ce44SJohn Forte 		nv->port_down_retry_count = 8;
579fcf3ce44SJohn Forte 		nv->maximum_luns_per_target[0] = 8;
580fcf3ce44SJohn Forte 
581fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
582fcf3ce44SJohn Forte 	}
583fcf3ce44SJohn Forte 
584fcf3ce44SJohn Forte 	/* Reset initialization control blocks. */
585fcf3ce44SJohn Forte 	bzero((void *)icb, sizeof (ql_init_cb_t));
586*4c3888b8SHans Rosenfeld 	bzero((void *)ip_icb, sizeof (ql_ip_init_cb_t));
587fcf3ce44SJohn Forte 
588fcf3ce44SJohn Forte 	/*
589fcf3ce44SJohn Forte 	 * Copy over NVRAM RISC parameter block
590fcf3ce44SJohn Forte 	 * to initialization control block.
591fcf3ce44SJohn Forte 	 */
592fcf3ce44SJohn Forte 	dptr1 = (caddr_t)icb;
593fcf3ce44SJohn Forte 	dptr2 = (caddr_t)&nv->parameter_block_version;
594fcf3ce44SJohn Forte 	cnt = (uint32_t)((uintptr_t)&icb->request_q_outpointer[0] -
595fcf3ce44SJohn Forte 	    (uintptr_t)&icb->version);
596fcf3ce44SJohn Forte 	while (cnt-- != 0) {
597fcf3ce44SJohn Forte 		*dptr1++ = *dptr2++;
598fcf3ce44SJohn Forte 	}
599fcf3ce44SJohn Forte 
600fcf3ce44SJohn Forte 	/* Copy 2nd half. */
601fcf3ce44SJohn Forte 	dptr1 = (caddr_t)&icb->add_fw_opt[0];
602fcf3ce44SJohn Forte 	cnt = (uint32_t)((uintptr_t)&icb->reserved_3[0] -
603fcf3ce44SJohn Forte 	    (uintptr_t)&icb->add_fw_opt[0]);
604fcf3ce44SJohn Forte 	while (cnt-- != 0) {
605fcf3ce44SJohn Forte 		*dptr1++ = *dptr2++;
606fcf3ce44SJohn Forte 	}
607fcf3ce44SJohn Forte 
608*4c3888b8SHans Rosenfeld 	ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
609*4c3888b8SHans Rosenfeld 	    nv->execution_throttle[1]);
610*4c3888b8SHans Rosenfeld 	ha->loop_reset_delay = nv->reset_delay;
611*4c3888b8SHans Rosenfeld 	ha->port_down_retry_count = nv->port_down_retry_count;
612*4c3888b8SHans Rosenfeld 	ha->maximum_luns_per_target = CHAR_TO_SHORT(
613*4c3888b8SHans Rosenfeld 	    nv->maximum_luns_per_target[0], nv->maximum_luns_per_target[1]);
614*4c3888b8SHans Rosenfeld 	if (ha->maximum_luns_per_target == 0) {
615*4c3888b8SHans Rosenfeld 		ha->maximum_luns_per_target++;
616*4c3888b8SHans Rosenfeld 	}
617*4c3888b8SHans Rosenfeld 	ha->adapter_features = CHAR_TO_SHORT(nv->adapter_features[0],
618*4c3888b8SHans Rosenfeld 	    nv->adapter_features[1]);
619*4c3888b8SHans Rosenfeld 
620*4c3888b8SHans Rosenfeld 	/* Check for adapter node name (big endian). */
621*4c3888b8SHans Rosenfeld 	for (cnt = 0; cnt < 8; cnt++) {
622*4c3888b8SHans Rosenfeld 		if (icb->node_name[cnt] != 0) {
623*4c3888b8SHans Rosenfeld 			break;
624*4c3888b8SHans Rosenfeld 		}
625*4c3888b8SHans Rosenfeld 	}
626*4c3888b8SHans Rosenfeld 
627*4c3888b8SHans Rosenfeld 	/* Copy port name if no node name (big endian). */
628*4c3888b8SHans Rosenfeld 	if (cnt == 8) {
629*4c3888b8SHans Rosenfeld 		for (cnt = 0; cnt < 8; cnt++) {
630*4c3888b8SHans Rosenfeld 			icb->node_name[cnt] = icb->port_name[cnt];
631*4c3888b8SHans Rosenfeld 		}
632*4c3888b8SHans Rosenfeld 		icb->node_name[0] = (uint8_t)(icb->node_name[0] & ~BIT_0);
633*4c3888b8SHans Rosenfeld 		icb->port_name[0] = (uint8_t)(icb->node_name[0] | BIT_0);
634*4c3888b8SHans Rosenfeld 	}
635*4c3888b8SHans Rosenfeld 
636*4c3888b8SHans Rosenfeld 	ADAPTER_STATE_LOCK(ha);
637*4c3888b8SHans Rosenfeld 	ha->cfg_flags &= ~(CFG_ENABLE_FULL_LIP_LOGIN | CFG_ENABLE_TARGET_RESET |
638*4c3888b8SHans Rosenfeld 	    CFG_ENABLE_LIP_RESET | CFG_LOAD_FLASH_FW | CFG_FAST_TIMEOUT |
639*4c3888b8SHans Rosenfeld 	    CFG_DISABLE_RISC_CODE_LOAD | CFG_ENABLE_FWEXTTRACE |
640*4c3888b8SHans Rosenfeld 	    CFG_ENABLE_FWFCETRACE | CFG_SET_CACHE_LINE_SIZE_1 | CFG_LR_SUPPORT);
641*4c3888b8SHans Rosenfeld 	if (nv->host_p[0] & BIT_4) {
642*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_DISABLE_RISC_CODE_LOAD;
643*4c3888b8SHans Rosenfeld 	}
644*4c3888b8SHans Rosenfeld 	if (nv->host_p[0] & BIT_5) {
645*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_SET_CACHE_LINE_SIZE_1;
646*4c3888b8SHans Rosenfeld 	}
647*4c3888b8SHans Rosenfeld 	if (nv->host_p[1] & BIT_2) {
648*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN;
649*4c3888b8SHans Rosenfeld 	}
650*4c3888b8SHans Rosenfeld 	if (nv->host_p[1] & BIT_3) {
651*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_TARGET_RESET;
652*4c3888b8SHans Rosenfeld 	}
653*4c3888b8SHans Rosenfeld 	nv->adapter_features[0] & BIT_3 ?
654*4c3888b8SHans Rosenfeld 	    (ha->flags |= MULTI_CHIP_ADAPTER) :
655*4c3888b8SHans Rosenfeld 	    (ha->flags &= ~MULTI_CHIP_ADAPTER);
656*4c3888b8SHans Rosenfeld 	ADAPTER_STATE_UNLOCK(ha);
657*4c3888b8SHans Rosenfeld 
658*4c3888b8SHans Rosenfeld 	/* Get driver properties. */
659*4c3888b8SHans Rosenfeld 	ql_23_properties(ha, icb);
660*4c3888b8SHans Rosenfeld 
661fcf3ce44SJohn Forte 	/*
662fcf3ce44SJohn Forte 	 * Setup driver firmware options.
663fcf3ce44SJohn Forte 	 */
664fcf3ce44SJohn Forte 	icb->firmware_options[0] = (uint8_t)
665fcf3ce44SJohn Forte 	    (icb->firmware_options[0] | BIT_6 | BIT_1);
666fcf3ce44SJohn Forte 
667fcf3ce44SJohn Forte 	/*
668fcf3ce44SJohn Forte 	 * There is no use enabling fast post for SBUS or 2300
6695dfd244aSDaniel Beauregard 	 * Always enable 64bit addressing, except SBUS cards.
670fcf3ce44SJohn Forte 	 */
6715dfd244aSDaniel Beauregard 	ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
672*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_SBUS_CARD | CFG_CTRL_2363)) {
673fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
674fcf3ce44SJohn Forte 		    (icb->firmware_options[0] & ~BIT_3);
675fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
676fcf3ce44SJohn Forte 			icb->special_options[0] = (uint8_t)
677fcf3ce44SJohn Forte 			    (icb->special_options[0] | BIT_5);
6785dfd244aSDaniel Beauregard 			ha->cfg_flags &= ~CFG_ENABLE_64BIT_ADDRESSING;
679fcf3ce44SJohn Forte 		}
680fcf3ce44SJohn Forte 	} else {
681fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
682fcf3ce44SJohn Forte 		    (icb->firmware_options[0] | BIT_3);
683fcf3ce44SJohn Forte 	}
684fcf3ce44SJohn Forte 	/* RIO and ZIO not supported. */
685fcf3ce44SJohn Forte 	icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] &
686fcf3ce44SJohn Forte 	    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte 	icb->firmware_options[1] = (uint8_t)(icb->firmware_options[1] |
689fcf3ce44SJohn Forte 	    BIT_7 | BIT_6 | BIT_5 | BIT_2 | BIT_0);
690fcf3ce44SJohn Forte 	icb->firmware_options[0] = (uint8_t)
691fcf3ce44SJohn Forte 	    (icb->firmware_options[0] & ~(BIT_5 | BIT_4));
692fcf3ce44SJohn Forte 	icb->firmware_options[1] = (uint8_t)
693fcf3ce44SJohn Forte 	    (icb->firmware_options[1] & ~BIT_4);
694*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
695*4c3888b8SHans Rosenfeld 		icb->firmware_options[1] = (uint8_t)
696*4c3888b8SHans Rosenfeld 		    (icb->firmware_options[1] | BIT_7 | BIT_6);
697*4c3888b8SHans Rosenfeld 		icb->add_fw_opt[1] = (uint8_t)
698*4c3888b8SHans Rosenfeld 		    (icb->add_fw_opt[1] | BIT_5 | BIT_4);
699*4c3888b8SHans Rosenfeld 	}
700fcf3ce44SJohn Forte 	icb->add_fw_opt[1] = (uint8_t)(icb->add_fw_opt[1] & ~(BIT_5 | BIT_4));
701fcf3ce44SJohn Forte 	icb->special_options[0] = (uint8_t)(icb->special_options[0] | BIT_1);
702fcf3ce44SJohn Forte 
703*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_2363)) {
704fcf3ce44SJohn Forte 		if ((icb->special_options[1] & 0x20) == 0) {
705fcf3ce44SJohn Forte 			EL(ha, "50 ohm is not set\n");
706fcf3ce44SJohn Forte 		}
707fcf3ce44SJohn Forte 	}
708fcf3ce44SJohn Forte 
709fcf3ce44SJohn Forte 	/*
710fcf3ce44SJohn Forte 	 * Set host adapter parameters
711fcf3ce44SJohn Forte 	 */
712*4c3888b8SHans Rosenfeld 	/* Get adapter id string for Sun branded 23xx only */
713*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_23XX) && nv->adapInfo[0] != 0) {
714*4c3888b8SHans Rosenfeld 		(void) snprintf((int8_t *)ha->adapInfo, 16, "%s",
715*4c3888b8SHans Rosenfeld 		    nv->adapInfo);
716*4c3888b8SHans Rosenfeld 	}
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	ha->r_a_tov = (uint16_t)(icb->login_timeout < R_A_TOV_DEFAULT ?
719fcf3ce44SJohn Forte 	    R_A_TOV_DEFAULT : icb->login_timeout);
720fcf3ce44SJohn Forte 
721*4c3888b8SHans Rosenfeld 	els->common_service.rx_bufsize = CHAR_TO_SHORT(
722*4c3888b8SHans Rosenfeld 	    icb->max_frame_length[0], icb->max_frame_length[1]);
723*4c3888b8SHans Rosenfeld 	bcopy((void *)icb->port_name, (void *)els->nport_ww_name.raw_wwn, 8);
724*4c3888b8SHans Rosenfeld 	bcopy((void *)icb->node_name, (void *)els->node_ww_name.raw_wwn, 8);
725*4c3888b8SHans Rosenfeld 
726*4c3888b8SHans Rosenfeld 	cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
727*4c3888b8SHans Rosenfeld 	    "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
728*4c3888b8SHans Rosenfeld 	    QL_NAME, ha->instance,
729*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[0], els->nport_ww_name.raw_wwn[1],
730*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[2], els->nport_ww_name.raw_wwn[3],
731*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[4], els->nport_ww_name.raw_wwn[5],
732*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[6], els->nport_ww_name.raw_wwn[7],
733*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[0], els->node_ww_name.raw_wwn[1],
734*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[2], els->node_ww_name.raw_wwn[3],
735*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[4], els->node_ww_name.raw_wwn[5],
736*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[6], els->node_ww_name.raw_wwn[7]);
737fcf3ce44SJohn Forte 	/*
738fcf3ce44SJohn Forte 	 * Setup ring parameters in initialization control block
739fcf3ce44SJohn Forte 	 */
740*4c3888b8SHans Rosenfeld 	cnt = ha->req_q[0]->req_entry_cnt;
741fcf3ce44SJohn Forte 	icb->request_q_length[0] = LSB(cnt);
742fcf3ce44SJohn Forte 	icb->request_q_length[1] = MSB(cnt);
743*4c3888b8SHans Rosenfeld 	cnt = ha->rsp_queues[0]->rsp_entry_cnt;
744fcf3ce44SJohn Forte 	icb->response_q_length[0] = LSB(cnt);
745fcf3ce44SJohn Forte 	icb->response_q_length[1] = MSB(cnt);
746fcf3ce44SJohn Forte 
747*4c3888b8SHans Rosenfeld 	start_addr = ha->req_q[0]->req_ring.cookie.dmac_address;
748*4c3888b8SHans Rosenfeld 	icb->request_q_address[0] = LSB(LSW(start_addr));
749*4c3888b8SHans Rosenfeld 	icb->request_q_address[1] = MSB(LSW(start_addr));
750*4c3888b8SHans Rosenfeld 	icb->request_q_address[2] = LSB(MSW(start_addr));
751*4c3888b8SHans Rosenfeld 	icb->request_q_address[3] = MSB(MSW(start_addr));
752*4c3888b8SHans Rosenfeld 
753*4c3888b8SHans Rosenfeld 	start_addr = ha->req_q[0]->req_ring.cookie.dmac_notused;
754*4c3888b8SHans Rosenfeld 	icb->request_q_address[4] = LSB(LSW(start_addr));
755*4c3888b8SHans Rosenfeld 	icb->request_q_address[5] = MSB(LSW(start_addr));
756*4c3888b8SHans Rosenfeld 	icb->request_q_address[6] = LSB(MSW(start_addr));
757*4c3888b8SHans Rosenfeld 	icb->request_q_address[7] = MSB(MSW(start_addr));
758*4c3888b8SHans Rosenfeld 
759*4c3888b8SHans Rosenfeld 	start_addr = ha->rsp_queues[0]->rsp_ring.cookie.dmac_address;
760*4c3888b8SHans Rosenfeld 	icb->response_q_address[0] = LSB(LSW(start_addr));
761*4c3888b8SHans Rosenfeld 	icb->response_q_address[1] = MSB(LSW(start_addr));
762*4c3888b8SHans Rosenfeld 	icb->response_q_address[2] = LSB(MSW(start_addr));
763*4c3888b8SHans Rosenfeld 	icb->response_q_address[3] = MSB(MSW(start_addr));
764*4c3888b8SHans Rosenfeld 
765*4c3888b8SHans Rosenfeld 	start_addr = ha->rsp_queues[0]->rsp_ring.cookie.dmac_notused;
766*4c3888b8SHans Rosenfeld 	icb->response_q_address[4] = LSB(LSW(start_addr));
767*4c3888b8SHans Rosenfeld 	icb->response_q_address[5] = MSB(LSW(start_addr));
768*4c3888b8SHans Rosenfeld 	icb->response_q_address[6] = LSB(MSW(start_addr));
769*4c3888b8SHans Rosenfeld 	icb->response_q_address[7] = MSB(MSW(start_addr));
770fcf3ce44SJohn Forte 
771fcf3ce44SJohn Forte 	/*
772fcf3ce44SJohn Forte 	 * Setup IP initialization control block
773fcf3ce44SJohn Forte 	 */
774fcf3ce44SJohn Forte 	ip_icb->version = IP_ICB_VERSION;
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
777fcf3ce44SJohn Forte 		ip_icb->ip_firmware_options[0] = (uint8_t)
778fcf3ce44SJohn Forte 		    (ip_icb->ip_firmware_options[0] | BIT_2 | BIT_0);
779fcf3ce44SJohn Forte 	} else {
780fcf3ce44SJohn Forte 		ip_icb->ip_firmware_options[0] = (uint8_t)
781fcf3ce44SJohn Forte 		    (ip_icb->ip_firmware_options[0] | BIT_2);
782fcf3ce44SJohn Forte 	}
783fcf3ce44SJohn Forte 
784fcf3ce44SJohn Forte 	cnt = RCVBUF_CONTAINER_CNT;
785fcf3ce44SJohn Forte 	ip_icb->queue_size[0] = LSB(cnt);
786fcf3ce44SJohn Forte 	ip_icb->queue_size[1] = MSB(cnt);
787fcf3ce44SJohn Forte 
788*4c3888b8SHans Rosenfeld 	start_addr = ha->rcv_ring.cookie.dmac_address;
789*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[0] = LSB(LSW(start_addr));
790*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[1] = MSB(LSW(start_addr));
791*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[2] = LSB(MSW(start_addr));
792*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[3] = MSB(MSW(start_addr));
793*4c3888b8SHans Rosenfeld 
794*4c3888b8SHans Rosenfeld 	start_addr = ha->rcv_ring.cookie.dmac_notused;
795*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[4] = LSB(LSW(start_addr));
796*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[5] = MSB(LSW(start_addr));
797*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[6] = LSB(MSW(start_addr));
798*4c3888b8SHans Rosenfeld 	ip_icb->queue_address[7] = MSB(MSW(start_addr));
799fcf3ce44SJohn Forte 
800fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
801fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
802fcf3ce44SJohn Forte 	} else {
803fcf3ce44SJohn Forte 		/*EMPTY*/
804*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
805fcf3ce44SJohn Forte 	}
806fcf3ce44SJohn Forte 	return (rval);
807fcf3ce44SJohn Forte }
808fcf3ce44SJohn Forte 
809fcf3ce44SJohn Forte /*
810fcf3ce44SJohn Forte  * Get NVRAM data word
811fcf3ce44SJohn Forte  *	Calculates word position in NVRAM and calls request routine to
812fcf3ce44SJohn Forte  *	get the word from NVRAM.
813fcf3ce44SJohn Forte  *
814fcf3ce44SJohn Forte  * Input:
815fcf3ce44SJohn Forte  *	ha = adapter state pointer.
816fcf3ce44SJohn Forte  *	address = NVRAM word address.
817fcf3ce44SJohn Forte  *
818fcf3ce44SJohn Forte  * Returns:
819fcf3ce44SJohn Forte  *	data word.
820fcf3ce44SJohn Forte  *
821fcf3ce44SJohn Forte  * Context:
822fcf3ce44SJohn Forte  *	Kernel context.
823fcf3ce44SJohn Forte  */
824fcf3ce44SJohn Forte uint16_t
ql_get_nvram_word(ql_adapter_state_t * ha,uint32_t address)825fcf3ce44SJohn Forte ql_get_nvram_word(ql_adapter_state_t *ha, uint32_t address)
826fcf3ce44SJohn Forte {
827fcf3ce44SJohn Forte 	uint32_t	nv_cmd;
828fcf3ce44SJohn Forte 	uint16_t	rval;
829fcf3ce44SJohn Forte 
830*4c3888b8SHans Rosenfeld 	QL_PRINT_4(ha, "started\n");
831fcf3ce44SJohn Forte 
832fcf3ce44SJohn Forte 	nv_cmd = address << 16;
833fcf3ce44SJohn Forte 	nv_cmd = nv_cmd | NV_READ_OP;
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 	rval = (uint16_t)ql_nvram_request(ha, nv_cmd);
836fcf3ce44SJohn Forte 
837*4c3888b8SHans Rosenfeld 	QL_PRINT_4(ha, "NVRAM data = %xh\n", rval);
838fcf3ce44SJohn Forte 
839fcf3ce44SJohn Forte 	return (rval);
840fcf3ce44SJohn Forte }
841fcf3ce44SJohn Forte 
842fcf3ce44SJohn Forte /*
843fcf3ce44SJohn Forte  * NVRAM request
844fcf3ce44SJohn Forte  *	Sends read command to NVRAM and gets data from NVRAM.
845fcf3ce44SJohn Forte  *
846fcf3ce44SJohn Forte  * Input:
847fcf3ce44SJohn Forte  *	ha = adapter state pointer.
848fcf3ce44SJohn Forte  *	nv_cmd = Bit 26= start bit
849fcf3ce44SJohn Forte  *	Bit 25, 24 = opcode
850fcf3ce44SJohn Forte  *	Bit 23-16 = address
851fcf3ce44SJohn Forte  *	Bit 15-0 = write data
852fcf3ce44SJohn Forte  *
853fcf3ce44SJohn Forte  * Returns:
854fcf3ce44SJohn Forte  *	data word.
855fcf3ce44SJohn Forte  *
856fcf3ce44SJohn Forte  * Context:
857fcf3ce44SJohn Forte  *	Kernel context.
858fcf3ce44SJohn Forte  */
859fcf3ce44SJohn Forte static uint16_t
ql_nvram_request(ql_adapter_state_t * ha,uint32_t nv_cmd)860fcf3ce44SJohn Forte ql_nvram_request(ql_adapter_state_t *ha, uint32_t nv_cmd)
861fcf3ce44SJohn Forte {
862fcf3ce44SJohn Forte 	uint8_t		cnt;
863fcf3ce44SJohn Forte 	uint16_t	reg_data;
864fcf3ce44SJohn Forte 	uint16_t	data = 0;
865fcf3ce44SJohn Forte 
866fcf3ce44SJohn Forte 	/* Send command to NVRAM. */
867fcf3ce44SJohn Forte 
868fcf3ce44SJohn Forte 	nv_cmd <<= 5;
869fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 11; cnt++) {
870fcf3ce44SJohn Forte 		if (nv_cmd & BIT_31) {
871fcf3ce44SJohn Forte 			ql_nv_write(ha, NV_DATA_OUT);
872fcf3ce44SJohn Forte 		} else {
873fcf3ce44SJohn Forte 			ql_nv_write(ha, 0);
874fcf3ce44SJohn Forte 		}
875fcf3ce44SJohn Forte 		nv_cmd <<= 1;
876fcf3ce44SJohn Forte 	}
877fcf3ce44SJohn Forte 
878fcf3ce44SJohn Forte 	/* Read data from NVRAM. */
879fcf3ce44SJohn Forte 
880fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 16; cnt++) {
881*4c3888b8SHans Rosenfeld 		WRT16_IO_REG(ha, nvram, NV_SELECT + NV_CLOCK);
882fcf3ce44SJohn Forte 		ql_nv_delay();
883fcf3ce44SJohn Forte 		data <<= 1;
884fcf3ce44SJohn Forte 		reg_data = RD16_IO_REG(ha, nvram);
885fcf3ce44SJohn Forte 		if (reg_data & NV_DATA_IN) {
886fcf3ce44SJohn Forte 			data = (uint16_t)(data | BIT_0);
887fcf3ce44SJohn Forte 		}
888fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, nvram, NV_SELECT);
889fcf3ce44SJohn Forte 		ql_nv_delay();
890fcf3ce44SJohn Forte 	}
891fcf3ce44SJohn Forte 
892fcf3ce44SJohn Forte 	/* Deselect chip. */
893fcf3ce44SJohn Forte 
894fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, NV_DESELECT);
895fcf3ce44SJohn Forte 	ql_nv_delay();
896fcf3ce44SJohn Forte 
897fcf3ce44SJohn Forte 	return (data);
898fcf3ce44SJohn Forte }
899fcf3ce44SJohn Forte 
900fcf3ce44SJohn Forte void
ql_nv_write(ql_adapter_state_t * ha,uint16_t data)901fcf3ce44SJohn Forte ql_nv_write(ql_adapter_state_t *ha, uint16_t data)
902fcf3ce44SJohn Forte {
903fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
904fcf3ce44SJohn Forte 	ql_nv_delay();
905fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT | NV_CLOCK));
906fcf3ce44SJohn Forte 	ql_nv_delay();
907fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
908fcf3ce44SJohn Forte 	ql_nv_delay();
909fcf3ce44SJohn Forte }
910fcf3ce44SJohn Forte 
911fcf3ce44SJohn Forte void
ql_nv_delay(void)9125dfd244aSDaniel Beauregard ql_nv_delay(void)
9135dfd244aSDaniel Beauregard {
914fcf3ce44SJohn Forte 	drv_usecwait(NV_DELAY_COUNT);
915fcf3ce44SJohn Forte }
916fcf3ce44SJohn Forte 
917fcf3ce44SJohn Forte /*
918fcf3ce44SJohn Forte  * ql_nvram_24xx_config
919fcf3ce44SJohn Forte  *	ISP2400 nvram.
920fcf3ce44SJohn Forte  *
921fcf3ce44SJohn Forte  * Input:
922fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
923*4c3888b8SHans Rosenfeld  *	ha->req_q[0]:	request ring
924fcf3ce44SJohn Forte  *
925fcf3ce44SJohn Forte  * Output:
926fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
927fcf3ce44SJohn Forte  *	host adapters parameters in host adapter block
928fcf3ce44SJohn Forte  *
929fcf3ce44SJohn Forte  * Returns:
930fcf3ce44SJohn Forte  *	ql local function return status code.
931fcf3ce44SJohn Forte  *
932fcf3ce44SJohn Forte  * Context:
933fcf3ce44SJohn Forte  *	Kernel context.
934fcf3ce44SJohn Forte  */
935fcf3ce44SJohn Forte int
ql_nvram_24xx_config(ql_adapter_state_t * ha)936fcf3ce44SJohn Forte ql_nvram_24xx_config(ql_adapter_state_t *ha)
937fcf3ce44SJohn Forte {
938*4c3888b8SHans Rosenfeld 	uint32_t		index, addr;
939*4c3888b8SHans Rosenfeld 	uint32_t		chksum = 0, saved_chksum = 0;
940fcf3ce44SJohn Forte 	uint32_t		*longptr;
941fcf3ce44SJohn Forte 	nvram_24xx_t		nvram;
942fcf3ce44SJohn Forte 	int			idpromlen;
943fcf3ce44SJohn Forte 	char			idprombuf[32];
944fcf3ce44SJohn Forte 	caddr_t			src, dst;
945fcf3ce44SJohn Forte 	uint16_t		w1;
946fcf3ce44SJohn Forte 	int			rval;
947fcf3ce44SJohn Forte 	nvram_24xx_t		*nv = (nvram_24xx_t *)&nvram;
948fcf3ce44SJohn Forte 	ql_init_24xx_cb_t	*icb =
949fcf3ce44SJohn Forte 	    (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24;
950fcf3ce44SJohn Forte 	ql_ip_init_24xx_cb_t	*ip_icb = &ha->ip_init_ctrl_blk.cb24;
951*4c3888b8SHans Rosenfeld 	la_els_logi_t		*els = &ha->loginparams;
952fcf3ce44SJohn Forte 
953*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
954fcf3ce44SJohn Forte 
955fcf3ce44SJohn Forte 	if ((rval = ql_lock_nvram(ha, &addr, LNF_NVRAM_DATA)) == QL_SUCCESS) {
956fcf3ce44SJohn Forte 
957fcf3ce44SJohn Forte 		/* Get NVRAM data and calculate checksum. */
958fcf3ce44SJohn Forte 		longptr = (uint32_t *)nv;
959fcf3ce44SJohn Forte 		chksum = saved_chksum = 0;
960fcf3ce44SJohn Forte 		for (index = 0; index < sizeof (nvram_24xx_t) / 4; index++) {
961fcf3ce44SJohn Forte 			rval = ql_24xx_read_flash(ha, addr++, longptr);
962fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
963fcf3ce44SJohn Forte 				EL(ha, "24xx_read_flash failed=%xh\n", rval);
964fcf3ce44SJohn Forte 				break;
965fcf3ce44SJohn Forte 			}
966fcf3ce44SJohn Forte 			saved_chksum = chksum;
967fcf3ce44SJohn Forte 			chksum += *longptr;
968fcf3ce44SJohn Forte 			LITTLE_ENDIAN_32(longptr);
969fcf3ce44SJohn Forte 			longptr++;
970fcf3ce44SJohn Forte 		}
971fcf3ce44SJohn Forte 
972fcf3ce44SJohn Forte 		ql_release_nvram(ha);
973fcf3ce44SJohn Forte 	}
974fcf3ce44SJohn Forte 
975fcf3ce44SJohn Forte 	/* Bad NVRAM data, set defaults parameters. */
976fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
977fcf3ce44SJohn Forte 	    nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
978fcf3ce44SJohn Forte 	    (nv->nvram_version[0] | nv->nvram_version[1]) == 0) {
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed, using "
981fcf3ce44SJohn Forte 		    "driver defaults.", QL_NAME, ha->instance);
982fcf3ce44SJohn Forte 		EL(ha, "failed, rval=%xh, checksum=%xh, id=%c%c%c%c, "
983fcf3ce44SJohn Forte 		    "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
984fcf3ce44SJohn Forte 		    nv->id[2], nv->id[3], CHAR_TO_SHORT(nv->nvram_version[0],
985fcf3ce44SJohn Forte 		    nv->nvram_version[1]));
986fcf3ce44SJohn Forte 
987fcf3ce44SJohn Forte 		saved_chksum = ~saved_chksum + 1;
988fcf3ce44SJohn Forte 
989fcf3ce44SJohn Forte 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_NVRAM_CHKSUM_ERR, 0,
990fcf3ce44SJohn Forte 		    MSW(saved_chksum), LSW(saved_chksum));
991fcf3ce44SJohn Forte 
992fcf3ce44SJohn Forte 		/* Reset NVRAM data. */
993fcf3ce44SJohn Forte 		bzero((void *)nv, sizeof (nvram_24xx_t));
994fcf3ce44SJohn Forte 
995fcf3ce44SJohn Forte 		/*
996fcf3ce44SJohn Forte 		 * Set default initialization control block.
997fcf3ce44SJohn Forte 		 */
998fcf3ce44SJohn Forte 		nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
999fcf3ce44SJohn Forte 		nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
1000fcf3ce44SJohn Forte 
1001fcf3ce44SJohn Forte 		nv->version[0] = 1;
1002fcf3ce44SJohn Forte 		nv->max_frame_length[1] = 8;
1003fcf3ce44SJohn Forte 		nv->execution_throttle[0] = 16;
1004eb82ff87SDaniel Beauregard 		nv->exchange_count[0] = 128;
1005fcf3ce44SJohn Forte 		nv->max_luns_per_target[0] = 8;
1006fcf3ce44SJohn Forte 
1007fcf3ce44SJohn Forte 		idpromlen = 32;
1008fcf3ce44SJohn Forte 
1009fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
101016dd44c2SDaniel Beauregard 		if (rval = ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
1011fcf3ce44SJohn Forte 		    DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
1012fcf3ce44SJohn Forte 		    &idpromlen) != DDI_PROP_SUCCESS) {
1013fcf3ce44SJohn Forte 
1014fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
101516dd44c2SDaniel Beauregard 			    "property, rval=%x", QL_NAME, ha->instance, rval);
1016fcf3ce44SJohn Forte 
1017fcf3ce44SJohn Forte 			nv->port_name[0] = 33;
1018fcf3ce44SJohn Forte 			nv->port_name[3] = 224;
1019fcf3ce44SJohn Forte 			nv->port_name[4] = 139;
1020fcf3ce44SJohn Forte 			nv->port_name[7] = (uint8_t)
1021fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
1022fcf3ce44SJohn Forte 		} else {
1023fcf3ce44SJohn Forte 			nv->port_name[2] = idprombuf[2];
1024fcf3ce44SJohn Forte 			nv->port_name[3] = idprombuf[3];
1025fcf3ce44SJohn Forte 			nv->port_name[4] = idprombuf[4];
1026fcf3ce44SJohn Forte 			nv->port_name[5] = idprombuf[5];
1027fcf3ce44SJohn Forte 			nv->port_name[6] = idprombuf[6];
1028fcf3ce44SJohn Forte 			nv->port_name[7] = idprombuf[7];
1029fcf3ce44SJohn Forte 			nv->port_name[0] = (uint8_t)
1030fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
1031fcf3ce44SJohn Forte 		}
1032fcf3ce44SJohn Forte 
1033fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using default "
1034fcf3ce44SJohn Forte 		    "HBA parameters and temporary "
1035fcf3ce44SJohn Forte 		    "WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
1036fcf3ce44SJohn Forte 		    ha->instance, nv->port_name[0], nv->port_name[1],
1037fcf3ce44SJohn Forte 		    nv->port_name[2], nv->port_name[3], nv->port_name[4],
1038fcf3ce44SJohn Forte 		    nv->port_name[5], nv->port_name[6], nv->port_name[7]);
1039fcf3ce44SJohn Forte 
1040fcf3ce44SJohn Forte 		nv->login_retry_count[0] = 8;
1041fcf3ce44SJohn Forte 
1042fcf3ce44SJohn Forte 		nv->firmware_options_1[0] = BIT_2 | BIT_1;
1043fcf3ce44SJohn Forte 		nv->firmware_options_1[1] = BIT_5;
1044fcf3ce44SJohn Forte 		nv->firmware_options_2[0] = BIT_5;
1045fcf3ce44SJohn Forte 		nv->firmware_options_2[1] = BIT_4;
1046fcf3ce44SJohn Forte 		nv->firmware_options_3[1] = BIT_6;
1047fcf3ce44SJohn Forte 
1048fcf3ce44SJohn Forte 		/*
1049fcf3ce44SJohn Forte 		 * Set default host adapter parameters
1050fcf3ce44SJohn Forte 		 */
1051fcf3ce44SJohn Forte 		nv->host_p[0] = BIT_4 | BIT_1;
1052fcf3ce44SJohn Forte 		nv->host_p[1] = BIT_3 | BIT_2;
1053fcf3ce44SJohn Forte 		nv->reset_delay = 5;
1054fcf3ce44SJohn Forte 		nv->max_luns_per_target[0] = 128;
1055fcf3ce44SJohn Forte 		nv->port_down_retry_count[0] = 30;
1056fcf3ce44SJohn Forte 		nv->link_down_timeout[0] = 30;
1057fcf3ce44SJohn Forte 
1058*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
10595dfd244aSDaniel Beauregard 			nv->firmware_options_3[2] = BIT_4;
10605dfd244aSDaniel Beauregard 			nv->feature_mask_l[0] = 9;
10615dfd244aSDaniel Beauregard 			nv->ext_blk.version[0] = 1;
10625dfd244aSDaniel Beauregard 			nv->ext_blk.fcf_vlan_match = 1;
10635dfd244aSDaniel Beauregard 			nv->ext_blk.fcf_vlan_id[0] = LSB(1002);
10645dfd244aSDaniel Beauregard 			nv->ext_blk.fcf_vlan_id[1] = MSB(1002);
1065eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[1] = 2;
1066eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[2] = 3;
1067eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[3] = 4;
1068eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[4] = MSB(ha->instance);
1069eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[5] = LSB(ha->instance);
10705dfd244aSDaniel Beauregard 		}
10715dfd244aSDaniel Beauregard 
1072fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
1073fcf3ce44SJohn Forte 	}
1074fcf3ce44SJohn Forte 
1075fcf3ce44SJohn Forte 	/* Reset initialization control blocks. */
1076fcf3ce44SJohn Forte 	bzero((void *)icb, sizeof (ql_init_24xx_cb_t));
1077fcf3ce44SJohn Forte 
1078fcf3ce44SJohn Forte 	/*
1079fcf3ce44SJohn Forte 	 * Copy over NVRAM Firmware Initialization Control Block.
1080fcf3ce44SJohn Forte 	 */
1081fcf3ce44SJohn Forte 	dst = (caddr_t)icb;
1082fcf3ce44SJohn Forte 	src = (caddr_t)&nv->version;
1083fcf3ce44SJohn Forte 	index = (uint32_t)((uintptr_t)&icb->response_q_inpointer[0] -
1084fcf3ce44SJohn Forte 	    (uintptr_t)icb);
1085fcf3ce44SJohn Forte 	while (index--) {
1086fcf3ce44SJohn Forte 		*dst++ = *src++;
1087fcf3ce44SJohn Forte 	}
1088fcf3ce44SJohn Forte 	icb->login_retry_count[0] = nv->login_retry_count[0];
1089fcf3ce44SJohn Forte 	icb->login_retry_count[1] = nv->login_retry_count[1];
1090fcf3ce44SJohn Forte 	icb->link_down_on_nos[0] = nv->link_down_on_nos[0];
1091fcf3ce44SJohn Forte 	icb->link_down_on_nos[1] = nv->link_down_on_nos[1];
1092fcf3ce44SJohn Forte 
1093*4c3888b8SHans Rosenfeld 	/* Copy 2nd half. */
1094fcf3ce44SJohn Forte 	dst = (caddr_t)&icb->interrupt_delay_timer;
1095fcf3ce44SJohn Forte 	src = (caddr_t)&nv->interrupt_delay_timer;
10965dfd244aSDaniel Beauregard 	index = (uint32_t)((uintptr_t)&icb->qos -
1097fcf3ce44SJohn Forte 	    (uintptr_t)&icb->interrupt_delay_timer);
1098fcf3ce44SJohn Forte 	while (index--) {
1099fcf3ce44SJohn Forte 		*dst++ = *src++;
1100fcf3ce44SJohn Forte 	}
1101fcf3ce44SJohn Forte 
1102*4c3888b8SHans Rosenfeld 	ha->execution_throttle = 16;
1103*4c3888b8SHans Rosenfeld 	ha->loop_reset_delay = nv->reset_delay;
1104*4c3888b8SHans Rosenfeld 	ha->port_down_retry_count = CHAR_TO_SHORT(nv->port_down_retry_count[0],
1105*4c3888b8SHans Rosenfeld 	    nv->port_down_retry_count[1]);
1106*4c3888b8SHans Rosenfeld 	ha->maximum_luns_per_target = CHAR_TO_SHORT(
1107*4c3888b8SHans Rosenfeld 	    nv->max_luns_per_target[0], nv->max_luns_per_target[1]);
1108*4c3888b8SHans Rosenfeld 	if (ha->maximum_luns_per_target == 0) {
1109*4c3888b8SHans Rosenfeld 		ha->maximum_luns_per_target++;
1110*4c3888b8SHans Rosenfeld 	}
1111*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
11125dfd244aSDaniel Beauregard 		dst = (caddr_t)icb->enode_mac_addr;
1113a2b3ff35SDaniel Beauregard 		src = (caddr_t)nv->fw.isp8001.e_node_mac_addr;
1114a2b3ff35SDaniel Beauregard 		index = sizeof (nv->fw.isp8001.e_node_mac_addr);
11155dfd244aSDaniel Beauregard 		while (index--) {
11165dfd244aSDaniel Beauregard 			*dst++ = *src++;
11175dfd244aSDaniel Beauregard 		}
11185dfd244aSDaniel Beauregard 		dst = (caddr_t)&icb->ext_blk;
11195dfd244aSDaniel Beauregard 		src = (caddr_t)&nv->ext_blk;
11205dfd244aSDaniel Beauregard 		index = sizeof (ql_ext_icb_8100_t);
11215dfd244aSDaniel Beauregard 		while (index--) {
11225dfd244aSDaniel Beauregard 			*dst++ = *src++;
11235dfd244aSDaniel Beauregard 		}
1124a2b3ff35SDaniel Beauregard 		EL(ha, "e_node_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x\n",
1125a2b3ff35SDaniel Beauregard 		    icb->enode_mac_addr[0], icb->enode_mac_addr[1],
1126a2b3ff35SDaniel Beauregard 		    icb->enode_mac_addr[2], icb->enode_mac_addr[3],
1127a2b3ff35SDaniel Beauregard 		    icb->enode_mac_addr[4], icb->enode_mac_addr[5]);
1128*4c3888b8SHans Rosenfeld 	}
1129*4c3888b8SHans Rosenfeld 
1130*4c3888b8SHans Rosenfeld 	/* Check for adapter node name (big endian). */
1131*4c3888b8SHans Rosenfeld 	for (index = 0; index < 8; index++) {
1132*4c3888b8SHans Rosenfeld 		if (icb->node_name[index] != 0) {
1133*4c3888b8SHans Rosenfeld 			break;
1134*4c3888b8SHans Rosenfeld 		}
1135*4c3888b8SHans Rosenfeld 	}
1136*4c3888b8SHans Rosenfeld 
1137*4c3888b8SHans Rosenfeld 	/* Copy port name if no node name (big endian). */
1138*4c3888b8SHans Rosenfeld 	if (index == 8) {
1139*4c3888b8SHans Rosenfeld 		for (index = 0; index < 8; index++) {
1140*4c3888b8SHans Rosenfeld 			icb->node_name[index] = icb->port_name[index];
1141*4c3888b8SHans Rosenfeld 		}
1142*4c3888b8SHans Rosenfeld 		icb->node_name[0] = (uint8_t)(icb->node_name[0] & ~BIT_0);
1143*4c3888b8SHans Rosenfeld 		icb->port_name[0] = (uint8_t)(icb->node_name[0] | BIT_0);
1144*4c3888b8SHans Rosenfeld 	}
1145*4c3888b8SHans Rosenfeld 
1146*4c3888b8SHans Rosenfeld 	ADAPTER_STATE_LOCK(ha);
1147*4c3888b8SHans Rosenfeld 	ha->cfg_flags &= ~(CFG_ENABLE_FULL_LIP_LOGIN | CFG_ENABLE_TARGET_RESET |
1148*4c3888b8SHans Rosenfeld 	    CFG_ENABLE_LIP_RESET | CFG_LOAD_FLASH_FW | CFG_FAST_TIMEOUT |
1149*4c3888b8SHans Rosenfeld 	    CFG_DISABLE_RISC_CODE_LOAD | CFG_ENABLE_FWEXTTRACE |
1150*4c3888b8SHans Rosenfeld 	    CFG_ENABLE_FWFCETRACE | CFG_SET_CACHE_LINE_SIZE_1 | CFG_LR_SUPPORT);
1151*4c3888b8SHans Rosenfeld 	if (nv->host_p[1] & BIT_2) {
1152*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN;
1153*4c3888b8SHans Rosenfeld 	}
1154*4c3888b8SHans Rosenfeld 	if (nv->host_p[1] & BIT_3) {
1155*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_TARGET_RESET;
1156*4c3888b8SHans Rosenfeld 	}
1157*4c3888b8SHans Rosenfeld 	ha->flags &= ~MULTI_CHIP_ADAPTER;
1158*4c3888b8SHans Rosenfeld 	ADAPTER_STATE_UNLOCK(ha);
1159*4c3888b8SHans Rosenfeld 
1160*4c3888b8SHans Rosenfeld 	/* Get driver properties. */
1161*4c3888b8SHans Rosenfeld 	ql_24xx_properties(ha, icb);
1162*4c3888b8SHans Rosenfeld 
1163*4c3888b8SHans Rosenfeld 	/*
1164*4c3888b8SHans Rosenfeld 	 * Setup driver firmware options.
1165*4c3888b8SHans Rosenfeld 	 */
1166*4c3888b8SHans Rosenfeld 	if (!CFG_IST(ha, CFG_FCOE_SUPPORT)) {
1167fcf3ce44SJohn Forte 		icb->firmware_options_1[0] = (uint8_t)
1168fcf3ce44SJohn Forte 		    (icb->firmware_options_1[0] | BIT_1);
11695dfd244aSDaniel Beauregard 		icb->firmware_options_1[1] = (uint8_t)
11705dfd244aSDaniel Beauregard 		    (icb->firmware_options_1[1] | BIT_5 | BIT_2);
11715dfd244aSDaniel Beauregard 		icb->firmware_options_3[0] = (uint8_t)
11725dfd244aSDaniel Beauregard 		    (icb->firmware_options_3[0] | BIT_1);
1173fcf3ce44SJohn Forte 	}
11745dfd244aSDaniel Beauregard 	icb->firmware_options_1[0] = (uint8_t)(icb->firmware_options_1[0] &
11755dfd244aSDaniel Beauregard 	    ~(BIT_5 | BIT_4));
11765dfd244aSDaniel Beauregard 	icb->firmware_options_1[1] = (uint8_t)(icb->firmware_options_1[1] |
11775dfd244aSDaniel Beauregard 	    BIT_6);
11785dfd244aSDaniel Beauregard 	icb->firmware_options_2[0] = (uint8_t)(icb->firmware_options_2[0] &
11795dfd244aSDaniel Beauregard 	    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
1180fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
1181fcf3ce44SJohn Forte 		icb->firmware_options_2[1] = (uint8_t)
1182fcf3ce44SJohn Forte 		    (icb->firmware_options_2[1] | BIT_4);
1183fcf3ce44SJohn Forte 	} else {
1184fcf3ce44SJohn Forte 		icb->firmware_options_2[1] = (uint8_t)
1185fcf3ce44SJohn Forte 		    (icb->firmware_options_2[1] & ~BIT_4);
1186fcf3ce44SJohn Forte 	}
1187fcf3ce44SJohn Forte 	icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] &
1188fcf3ce44SJohn Forte 	    ~BIT_7);
1189fcf3ce44SJohn Forte 
1190fcf3ce44SJohn Forte 	/*
1191fcf3ce44SJohn Forte 	 * Set host adapter parameters
1192fcf3ce44SJohn Forte 	 */
1193*4c3888b8SHans Rosenfeld 	w1 = CHAR_TO_SHORT(icb->login_timeout[0], icb->login_timeout[1]);
1194*4c3888b8SHans Rosenfeld 	ha->r_a_tov = (uint16_t)(w1 < R_A_TOV_DEFAULT ? R_A_TOV_DEFAULT : w1);
1195*4c3888b8SHans Rosenfeld 
1196fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1197fcf3ce44SJohn Forte 	ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
1198eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_81XX) && nv->enhanced_features[0] & BIT_0) {
1199eb82ff87SDaniel Beauregard 		ha->cfg_flags |= CFG_LR_SUPPORT;
1200eb82ff87SDaniel Beauregard 	}
1201fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1202fcf3ce44SJohn Forte 
1203*4c3888b8SHans Rosenfeld 	/* Queue shadowing */
1204*4c3888b8SHans Rosenfeld 	if (ha->flags & QUEUE_SHADOW_PTRS) {
1205*4c3888b8SHans Rosenfeld 		icb->firmware_options_2[3] = (uint8_t)
1206*4c3888b8SHans Rosenfeld 		    (icb->firmware_options_2[3] | BIT_6 | BIT_5);
1207*4c3888b8SHans Rosenfeld 	} else {
1208*4c3888b8SHans Rosenfeld 		icb->firmware_options_2[3] = (uint8_t)
1209*4c3888b8SHans Rosenfeld 		    (icb->firmware_options_2[3] | ~(BIT_6 | BIT_5));
1210fcf3ce44SJohn Forte 	}
1211fcf3ce44SJohn Forte 
1212fcf3ce44SJohn Forte 	/* ISP2422 Serial Link Control */
1213*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_24XX)) {
12145dfd244aSDaniel Beauregard 		ha->serdes_param[0] = CHAR_TO_SHORT(nv->fw.isp2400.swing_opt[0],
12155dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_opt[1]);
12165dfd244aSDaniel Beauregard 		ha->serdes_param[1] = CHAR_TO_SHORT(nv->fw.isp2400.swing_1g[0],
12175dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_1g[1]);
12185dfd244aSDaniel Beauregard 		ha->serdes_param[2] = CHAR_TO_SHORT(nv->fw.isp2400.swing_2g[0],
12195dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_2g[1]);
12205dfd244aSDaniel Beauregard 		ha->serdes_param[3] = CHAR_TO_SHORT(nv->fw.isp2400.swing_4g[0],
12215dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_4g[1]);
12225dfd244aSDaniel Beauregard 	}
1223fcf3ce44SJohn Forte 
1224*4c3888b8SHans Rosenfeld 	els->common_service.rx_bufsize = CHAR_TO_SHORT(
1225*4c3888b8SHans Rosenfeld 	    icb->max_frame_length[0], icb->max_frame_length[1]);
1226*4c3888b8SHans Rosenfeld 	bcopy((void *)icb->port_name, (void *)els->nport_ww_name.raw_wwn, 8);
1227*4c3888b8SHans Rosenfeld 	bcopy((void *)icb->node_name, (void *)els->node_ww_name.raw_wwn, 8);
1228*4c3888b8SHans Rosenfeld 
1229*4c3888b8SHans Rosenfeld 	cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
1230*4c3888b8SHans Rosenfeld 	    "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
1231*4c3888b8SHans Rosenfeld 	    QL_NAME, ha->instance,
1232*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[0], els->nport_ww_name.raw_wwn[1],
1233*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[2], els->nport_ww_name.raw_wwn[3],
1234*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[4], els->nport_ww_name.raw_wwn[5],
1235*4c3888b8SHans Rosenfeld 	    els->nport_ww_name.raw_wwn[6], els->nport_ww_name.raw_wwn[7],
1236*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[0], els->node_ww_name.raw_wwn[1],
1237*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[2], els->node_ww_name.raw_wwn[3],
1238*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[4], els->node_ww_name.raw_wwn[5],
1239*4c3888b8SHans Rosenfeld 	    els->node_ww_name.raw_wwn[6], els->node_ww_name.raw_wwn[7]);
1240fcf3ce44SJohn Forte 	/*
1241fcf3ce44SJohn Forte 	 * Setup ring parameters in initialization control block
1242fcf3ce44SJohn Forte 	 */
1243*4c3888b8SHans Rosenfeld 	w1 = ha->req_q[0]->req_entry_cnt;
1244fcf3ce44SJohn Forte 	icb->request_q_length[0] = LSB(w1);
1245fcf3ce44SJohn Forte 	icb->request_q_length[1] = MSB(w1);
1246*4c3888b8SHans Rosenfeld 	w1 = ha->rsp_queues[0]->rsp_entry_cnt;
1247fcf3ce44SJohn Forte 	icb->response_q_length[0] = LSB(w1);
1248fcf3ce44SJohn Forte 	icb->response_q_length[1] = MSB(w1);
1249fcf3ce44SJohn Forte 
1250*4c3888b8SHans Rosenfeld 	addr = ha->req_q[0]->req_ring.cookie.dmac_address;
1251*4c3888b8SHans Rosenfeld 	icb->request_q_address[0] = LSB(LSW(addr));
1252*4c3888b8SHans Rosenfeld 	icb->request_q_address[1] = MSB(LSW(addr));
1253*4c3888b8SHans Rosenfeld 	icb->request_q_address[2] = LSB(MSW(addr));
1254*4c3888b8SHans Rosenfeld 	icb->request_q_address[3] = MSB(MSW(addr));
1255*4c3888b8SHans Rosenfeld 
1256*4c3888b8SHans Rosenfeld 	addr = ha->req_q[0]->req_ring.cookie.dmac_notused;
1257*4c3888b8SHans Rosenfeld 	icb->request_q_address[4] = LSB(LSW(addr));
1258*4c3888b8SHans Rosenfeld 	icb->request_q_address[5] = MSB(LSW(addr));
1259*4c3888b8SHans Rosenfeld 	icb->request_q_address[6] = LSB(MSW(addr));
1260*4c3888b8SHans Rosenfeld 	icb->request_q_address[7] = MSB(MSW(addr));
1261*4c3888b8SHans Rosenfeld 
1262*4c3888b8SHans Rosenfeld 	addr = ha->rsp_queues[0]->rsp_ring.cookie.dmac_address;
1263*4c3888b8SHans Rosenfeld 	icb->response_q_address[0] = LSB(LSW(addr));
1264*4c3888b8SHans Rosenfeld 	icb->response_q_address[1] = MSB(LSW(addr));
1265*4c3888b8SHans Rosenfeld 	icb->response_q_address[2] = LSB(MSW(addr));
1266*4c3888b8SHans Rosenfeld 	icb->response_q_address[3] = MSB(MSW(addr));
1267*4c3888b8SHans Rosenfeld 
1268*4c3888b8SHans Rosenfeld 	addr = ha->rsp_queues[0]->rsp_ring.cookie.dmac_notused;
1269*4c3888b8SHans Rosenfeld 	icb->response_q_address[4] = LSB(LSW(addr));
1270*4c3888b8SHans Rosenfeld 	icb->response_q_address[5] = MSB(LSW(addr));
1271*4c3888b8SHans Rosenfeld 	icb->response_q_address[6] = LSB(MSW(addr));
1272*4c3888b8SHans Rosenfeld 	icb->response_q_address[7] = MSB(MSW(addr));
1273fcf3ce44SJohn Forte 
1274fcf3ce44SJohn Forte 	/*
1275fcf3ce44SJohn Forte 	 * Setup IP initialization control block
1276fcf3ce44SJohn Forte 	 */
1277fcf3ce44SJohn Forte 	ip_icb->version = IP_ICB_24XX_VERSION;
1278fcf3ce44SJohn Forte 
1279fcf3ce44SJohn Forte 	ip_icb->ip_firmware_options[0] = (uint8_t)
1280fcf3ce44SJohn Forte 	    (ip_icb->ip_firmware_options[0] | BIT_2);
1281fcf3ce44SJohn Forte 
1282fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
1283fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
1284fcf3ce44SJohn Forte 	} else {
1285fcf3ce44SJohn Forte 		/*EMPTY*/
1286*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
1287fcf3ce44SJohn Forte 	}
1288fcf3ce44SJohn Forte 	return (rval);
1289fcf3ce44SJohn Forte }
1290fcf3ce44SJohn Forte 
1291fcf3ce44SJohn Forte /*
1292fcf3ce44SJohn Forte  * ql_lock_nvram
1293fcf3ce44SJohn Forte  *	Locks NVRAM access and returns starting address of NVRAM.
1294fcf3ce44SJohn Forte  *
1295fcf3ce44SJohn Forte  * Input:
1296fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1297fcf3ce44SJohn Forte  *	addr:	pointer for start address.
1298fcf3ce44SJohn Forte  *	flags:	Are mutually exclusive:
1299fcf3ce44SJohn Forte  *		LNF_NVRAM_DATA --> get nvram
1300fcf3ce44SJohn Forte  *		LNF_VPD_DATA --> get vpd data (24/25xx only).
1301fcf3ce44SJohn Forte  *
1302fcf3ce44SJohn Forte  * Returns:
1303fcf3ce44SJohn Forte  *	ql local function return status code.
1304fcf3ce44SJohn Forte  *
1305fcf3ce44SJohn Forte  * Context:
1306fcf3ce44SJohn Forte  *	Kernel context.
1307fcf3ce44SJohn Forte  */
1308fcf3ce44SJohn Forte int
ql_lock_nvram(ql_adapter_state_t * ha,uint32_t * addr,uint32_t flags)1309fcf3ce44SJohn Forte ql_lock_nvram(ql_adapter_state_t *ha, uint32_t *addr, uint32_t flags)
1310fcf3ce44SJohn Forte {
1311fcf3ce44SJohn Forte 	int	i;
1312fcf3ce44SJohn Forte 
1313*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1314*4c3888b8SHans Rosenfeld 
1315fcf3ce44SJohn Forte 	if ((flags & LNF_NVRAM_DATA) && (flags & LNF_VPD_DATA)) {
1316fcf3ce44SJohn Forte 		EL(ha, "invalid options for function");
1317fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
1318fcf3ce44SJohn Forte 	}
1319fcf3ce44SJohn Forte 
1320fcf3ce44SJohn Forte 	if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
1321fcf3ce44SJohn Forte 		if ((flags & LNF_NVRAM_DATA) == 0) {
1322fcf3ce44SJohn Forte 			EL(ha, "invalid 2312/2322 option for HBA");
1323fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1324fcf3ce44SJohn Forte 		}
1325fcf3ce44SJohn Forte 
1326fcf3ce44SJohn Forte 		/* if function number is non-zero, then adjust offset */
13275dfd244aSDaniel Beauregard 		*addr = ha->flash_nvram_addr;
1328fcf3ce44SJohn Forte 
1329fcf3ce44SJohn Forte 		/* Try to get resource lock. Wait for 10 seconds max */
1330fcf3ce44SJohn Forte 		for (i = 0; i < 10000; i++) {
1331fcf3ce44SJohn Forte 			/* if nvram busy bit is reset, acquire sema */
1332fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, nvram) & 0x8000) == 0) {
1333fcf3ce44SJohn Forte 				WRT16_IO_REG(ha, host_to_host_sema, 1);
1334fcf3ce44SJohn Forte 				drv_usecwait(MILLISEC);
1335fcf3ce44SJohn Forte 				if (RD16_IO_REG(ha, host_to_host_sema) & 1) {
1336fcf3ce44SJohn Forte 					break;
1337fcf3ce44SJohn Forte 				}
1338fcf3ce44SJohn Forte 			}
1339fcf3ce44SJohn Forte 			drv_usecwait(MILLISEC);
1340fcf3ce44SJohn Forte 		}
1341fcf3ce44SJohn Forte 		if ((RD16_IO_REG(ha, host_to_host_sema) & 1) == 0) {
1342fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): unable to get NVRAM lock",
1343fcf3ce44SJohn Forte 			    QL_NAME, ha->instance);
1344fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1345fcf3ce44SJohn Forte 		}
1346*4c3888b8SHans Rosenfeld 	} else if (CFG_IST(ha, CFG_CTRL_24XX)) {
1347fcf3ce44SJohn Forte 		if (flags & LNF_VPD_DATA) {
13485dfd244aSDaniel Beauregard 			*addr = NVRAM_DATA_ADDR | ha->flash_vpd_addr;
1349fcf3ce44SJohn Forte 		} else if (flags & LNF_NVRAM_DATA) {
13505dfd244aSDaniel Beauregard 			*addr = NVRAM_DATA_ADDR | ha->flash_nvram_addr;
1351fcf3ce44SJohn Forte 		} else {
13525dfd244aSDaniel Beauregard 			EL(ha, "invalid 2422 option for HBA");
1353fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1354fcf3ce44SJohn Forte 		}
1355fcf3ce44SJohn Forte 
1356fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1357*4c3888b8SHans Rosenfeld 	} else if (CFG_IST(ha, CFG_CTRL_252780818283)) {
1358fcf3ce44SJohn Forte 		if (flags & LNF_VPD_DATA) {
13595dfd244aSDaniel Beauregard 			*addr = ha->flash_data_addr | ha->flash_vpd_addr;
1360fcf3ce44SJohn Forte 		} else if (flags & LNF_NVRAM_DATA) {
13615dfd244aSDaniel Beauregard 			*addr = ha->flash_data_addr | ha->flash_nvram_addr;
1362fcf3ce44SJohn Forte 		} else {
13635dfd244aSDaniel Beauregard 			EL(ha, "invalid 2581 option for HBA");
1364fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1365fcf3ce44SJohn Forte 		}
1366fcf3ce44SJohn Forte 
1367fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1368fcf3ce44SJohn Forte 	} else {
1369fcf3ce44SJohn Forte 		if ((flags & LNF_NVRAM_DATA) == 0) {
1370fcf3ce44SJohn Forte 			EL(ha, "invalid option for HBA");
1371fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1372fcf3ce44SJohn Forte 		}
1373fcf3ce44SJohn Forte 		*addr = 0;
1374fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1375fcf3ce44SJohn Forte 	}
1376fcf3ce44SJohn Forte 
1377*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1378*4c3888b8SHans Rosenfeld 
1379fcf3ce44SJohn Forte 	return (QL_SUCCESS);
1380fcf3ce44SJohn Forte }
1381fcf3ce44SJohn Forte 
1382fcf3ce44SJohn Forte /*
1383fcf3ce44SJohn Forte  * ql_release_nvram
1384fcf3ce44SJohn Forte  *	Releases NVRAM access.
1385fcf3ce44SJohn Forte  *
1386fcf3ce44SJohn Forte  * Input:
1387fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1388fcf3ce44SJohn Forte  *
1389fcf3ce44SJohn Forte  * Context:
1390fcf3ce44SJohn Forte  *	Kernel context.
1391fcf3ce44SJohn Forte  */
1392fcf3ce44SJohn Forte void
ql_release_nvram(ql_adapter_state_t * ha)1393fcf3ce44SJohn Forte ql_release_nvram(ql_adapter_state_t *ha)
1394fcf3ce44SJohn Forte {
1395*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1396*4c3888b8SHans Rosenfeld 
1397fcf3ce44SJohn Forte 	if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
1398fcf3ce44SJohn Forte 		/* Release resource lock */
1399fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, host_to_host_sema, 0);
1400fcf3ce44SJohn Forte 	} else {
1401fcf3ce44SJohn Forte 		GLOBAL_HW_UNLOCK();
1402fcf3ce44SJohn Forte 	}
1403*4c3888b8SHans Rosenfeld 
1404*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1405fcf3ce44SJohn Forte }
1406fcf3ce44SJohn Forte 
1407fcf3ce44SJohn Forte /*
1408fcf3ce44SJohn Forte  * ql_23_properties
1409fcf3ce44SJohn Forte  *	Copies driver properties to NVRAM or adapter structure.
1410fcf3ce44SJohn Forte  *
1411fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1412fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1413fcf3ce44SJohn Forte  *	override the default values using driver.conf
1414fcf3ce44SJohn Forte  *
1415fcf3ce44SJohn Forte  * Input:
1416fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1417*4c3888b8SHans Rosenfeld  *	icb:	Init control block structure pointer.
1418fcf3ce44SJohn Forte  *
1419fcf3ce44SJohn Forte  * Context:
1420fcf3ce44SJohn Forte  *	Kernel context.
1421fcf3ce44SJohn Forte  */
1422fcf3ce44SJohn Forte static void
ql_23_properties(ql_adapter_state_t * ha,ql_init_cb_t * icb)1423*4c3888b8SHans Rosenfeld ql_23_properties(ql_adapter_state_t *ha, ql_init_cb_t *icb)
1424fcf3ce44SJohn Forte {
1425fcf3ce44SJohn Forte 	uint32_t	data, cnt;
1426fcf3ce44SJohn Forte 
1427*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1428fcf3ce44SJohn Forte 
1429fcf3ce44SJohn Forte 	/* Get frame payload size. */
1430fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
1431fcf3ce44SJohn Forte 		data = 2048;
1432fcf3ce44SJohn Forte 	}
1433fcf3ce44SJohn Forte 	if (data == 512 || data == 1024 || data == 2048) {
1434*4c3888b8SHans Rosenfeld 		icb->max_frame_length[0] = LSB(data);
1435*4c3888b8SHans Rosenfeld 		icb->max_frame_length[1] = MSB(data);
1436fcf3ce44SJohn Forte 	} else {
1437fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'max-frame-length': "
1438fcf3ce44SJohn Forte 		    "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1439*4c3888b8SHans Rosenfeld 		    icb->max_frame_length[0], icb->max_frame_length[1]));
1440fcf3ce44SJohn Forte 	}
1441fcf3ce44SJohn Forte 
1442fcf3ce44SJohn Forte 	/* Get max IOCB allocation. */
1443*4c3888b8SHans Rosenfeld 	icb->max_iocb_allocation[0] = 0;
1444*4c3888b8SHans Rosenfeld 	icb->max_iocb_allocation[1] = 1;
1445fcf3ce44SJohn Forte 
1446fcf3ce44SJohn Forte 	/* Get execution throttle. */
1447fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
1448fcf3ce44SJohn Forte 		data = 32;
1449fcf3ce44SJohn Forte 	}
1450fcf3ce44SJohn Forte 	if (data != 0 && data < 65536) {
1451*4c3888b8SHans Rosenfeld 		icb->execution_throttle[0] = LSB(data);
1452*4c3888b8SHans Rosenfeld 		icb->execution_throttle[1] = MSB(data);
1453fcf3ce44SJohn Forte 	} else {
1454fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'execution-throttle': "
1455fcf3ce44SJohn Forte 		    "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1456*4c3888b8SHans Rosenfeld 		    icb->execution_throttle[0], icb->execution_throttle[1]));
1457fcf3ce44SJohn Forte 	}
1458fcf3ce44SJohn Forte 
1459fcf3ce44SJohn Forte 	/* Get Login timeout. */
1460fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
1461fcf3ce44SJohn Forte 		data = 3;
1462fcf3ce44SJohn Forte 	}
1463fcf3ce44SJohn Forte 	if (data < 256) {
1464*4c3888b8SHans Rosenfeld 		icb->login_timeout = (uint8_t)data;
1465fcf3ce44SJohn Forte 	} else {
1466fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-timeout': "
1467*4c3888b8SHans Rosenfeld 		    "%d; using nvram value of %d\n", data, icb->login_timeout);
1468fcf3ce44SJohn Forte 	}
1469fcf3ce44SJohn Forte 
1470fcf3ce44SJohn Forte 	/* Get retry count. */
1471fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
1472fcf3ce44SJohn Forte 		data = 4;
1473fcf3ce44SJohn Forte 	}
1474fcf3ce44SJohn Forte 	if (data < 256) {
1475*4c3888b8SHans Rosenfeld 		icb->login_retry_count = (uint8_t)data;
1476fcf3ce44SJohn Forte 	} else {
1477fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-retry-count': "
1478fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data,
1479*4c3888b8SHans Rosenfeld 		    icb->login_retry_count);
1480fcf3ce44SJohn Forte 	}
1481fcf3ce44SJohn Forte 
1482fcf3ce44SJohn Forte 	/* Get adapter hard loop ID enable. */
1483*4c3888b8SHans Rosenfeld 	data = ql_get_prop(ha, "enable-adapter-hard-loop-ID");
1484fcf3ce44SJohn Forte 	if (data == 0) {
1485*4c3888b8SHans Rosenfeld 		icb->firmware_options[0] =
1486*4c3888b8SHans Rosenfeld 		    (uint8_t)(icb->firmware_options[0] & ~BIT_0);
1487fcf3ce44SJohn Forte 	} else if (data == 1) {
1488*4c3888b8SHans Rosenfeld 		icb->firmware_options[0] =
1489*4c3888b8SHans Rosenfeld 		    (uint8_t)(icb->firmware_options[0] | BIT_0);
1490fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1491fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1492fcf3ce44SJohn Forte 		    "'enable-adapter-hard-loop-ID': %d; using nvram value "
1493*4c3888b8SHans Rosenfeld 		    "of %d\n", data, icb->firmware_options[0] & BIT_0 ? 1 : 0);
1494fcf3ce44SJohn Forte 	}
1495fcf3ce44SJohn Forte 
1496fcf3ce44SJohn Forte 	/* Get adapter hard loop ID. */
1497*4c3888b8SHans Rosenfeld 	data = ql_get_prop(ha, "adapter-hard-loop-ID");
1498fcf3ce44SJohn Forte 	if (data < 126) {
1499*4c3888b8SHans Rosenfeld 		icb->hard_address[0] = (uint8_t)data;
1500fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1501fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'adapter-hard-loop-ID': "
150216dd44c2SDaniel Beauregard 		    "%d; using nvram value of %d\n",
1503*4c3888b8SHans Rosenfeld 		    data, icb->hard_address[0]);
1504fcf3ce44SJohn Forte 	}
1505fcf3ce44SJohn Forte 
1506fcf3ce44SJohn Forte 	/* Get LIP reset. */
1507fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
1508fcf3ce44SJohn Forte 	    0xffffffff) {
1509fcf3ce44SJohn Forte 		data = 0;
1510fcf3ce44SJohn Forte 	}
1511fcf3ce44SJohn Forte 	if (data == 0) {
1512*4c3888b8SHans Rosenfeld 		ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET;
1513fcf3ce44SJohn Forte 	} else if (data == 1) {
1514*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_LIP_RESET;
1515fcf3ce44SJohn Forte 	} else {
1516fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1517fcf3ce44SJohn Forte 		    "'enable-LIP-reset-on-bus-reset': %d; using nvram value "
1518*4c3888b8SHans Rosenfeld 		    "of %d\n", data,
1519*4c3888b8SHans Rosenfeld 		    CFG_IST(ha, CFG_ENABLE_LIP_RESET) ? 1 : 0);
1520fcf3ce44SJohn Forte 	}
1521fcf3ce44SJohn Forte 
1522fcf3ce44SJohn Forte 	/* Get LIP full login. */
1523fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
1524fcf3ce44SJohn Forte 	    0xffffffff) {
1525fcf3ce44SJohn Forte 		data = 1;
1526fcf3ce44SJohn Forte 	}
1527fcf3ce44SJohn Forte 	if (data == 0) {
1528*4c3888b8SHans Rosenfeld 		ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN;
1529fcf3ce44SJohn Forte 	} else if (data == 1) {
1530*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN;
1531fcf3ce44SJohn Forte 	} else {
1532fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1533fcf3ce44SJohn Forte 		    "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
1534*4c3888b8SHans Rosenfeld 		    "value of %d\n", data,
1535*4c3888b8SHans Rosenfeld 		    CFG_IST(ha, CFG_ENABLE_FULL_LIP_LOGIN) ? 1 : 0);
1536fcf3ce44SJohn Forte 	}
1537fcf3ce44SJohn Forte 
1538fcf3ce44SJohn Forte 	/* Get target reset. */
1539fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
1540fcf3ce44SJohn Forte 	    0xffffffff) {
1541fcf3ce44SJohn Forte 		data = 0;
1542fcf3ce44SJohn Forte 	}
1543fcf3ce44SJohn Forte 	if (data == 0) {
1544*4c3888b8SHans Rosenfeld 		ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET;
1545fcf3ce44SJohn Forte 	} else if (data == 1) {
1546*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_TARGET_RESET;
1547fcf3ce44SJohn Forte 	} else {
1548fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1549fcf3ce44SJohn Forte 		    "'enable-target-reset-on-bus-reset': %d; using nvram "
1550*4c3888b8SHans Rosenfeld 		    "value of %d", data,
1551*4c3888b8SHans Rosenfeld 		    CFG_IST(ha, CFG_ENABLE_TARGET_RESET) ? 1 : 0);
1552fcf3ce44SJohn Forte 	}
1553fcf3ce44SJohn Forte 
1554fcf3ce44SJohn Forte 	/* Get reset delay. */
1555fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
1556fcf3ce44SJohn Forte 		data = 5;
1557fcf3ce44SJohn Forte 	}
1558fcf3ce44SJohn Forte 	if (data != 0 && data < 256) {
1559*4c3888b8SHans Rosenfeld 		ha->loop_reset_delay = (uint8_t)data;
1560fcf3ce44SJohn Forte 	} else {
1561fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'reset-delay': %d; "
1562*4c3888b8SHans Rosenfeld 		    "using nvram value of %d", data, ha->loop_reset_delay);
1563fcf3ce44SJohn Forte 	}
1564fcf3ce44SJohn Forte 
1565fcf3ce44SJohn Forte 	/* Get port down retry count. */
1566fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
1567fcf3ce44SJohn Forte 		data = 8;
1568fcf3ce44SJohn Forte 	}
1569fcf3ce44SJohn Forte 	if (data < 256) {
1570*4c3888b8SHans Rosenfeld 		ha->port_down_retry_count = (uint8_t)data;
1571fcf3ce44SJohn Forte 	} else {
1572fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-count':"
1573fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data,
1574*4c3888b8SHans Rosenfeld 		    ha->port_down_retry_count);
1575fcf3ce44SJohn Forte 	}
1576fcf3ce44SJohn Forte 
1577fcf3ce44SJohn Forte 	/* Get connection mode setting. */
1578fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) {
1579fcf3ce44SJohn Forte 		data = 2;
1580fcf3ce44SJohn Forte 	}
1581*4c3888b8SHans Rosenfeld 	cnt = CFG_IST(ha, CFG_CTRL_22XX) ? 3 : 2;
1582fcf3ce44SJohn Forte 	if (data <= cnt) {
1583*4c3888b8SHans Rosenfeld 		icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] &
1584fcf3ce44SJohn Forte 		    ~(BIT_6 | BIT_5 | BIT_4));
1585*4c3888b8SHans Rosenfeld 		icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] |
1586fcf3ce44SJohn Forte 		    (uint8_t)(data << 4));
1587fcf3ce44SJohn Forte 	} else {
1588fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'connection-options': "
1589fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data,
1590*4c3888b8SHans Rosenfeld 		    (icb->add_fw_opt[0] >> 4) & 0x3);
1591fcf3ce44SJohn Forte 	}
1592fcf3ce44SJohn Forte 
1593fcf3ce44SJohn Forte 	/* Get data rate setting. */
1594*4c3888b8SHans Rosenfeld 	if ((CFG_IST(ha, CFG_CTRL_22XX)) == 0) {
1595fcf3ce44SJohn Forte 		if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
1596fcf3ce44SJohn Forte 			data = 2;
1597fcf3ce44SJohn Forte 		}
1598fcf3ce44SJohn Forte 		if (data < 3) {
1599*4c3888b8SHans Rosenfeld 			icb->special_options[1] = (uint8_t)
1600*4c3888b8SHans Rosenfeld 			    (icb->special_options[1] & 0x3f);
1601*4c3888b8SHans Rosenfeld 			icb->special_options[1] = (uint8_t)
1602*4c3888b8SHans Rosenfeld 			    (icb->special_options[1] | (uint8_t)(data << 6));
1603fcf3ce44SJohn Forte 		} else {
1604fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for 'fc-data-rate': "
1605fcf3ce44SJohn Forte 			    "%d; using nvram value of %d\n", data,
1606*4c3888b8SHans Rosenfeld 			    (icb->special_options[1] >> 6) & 0x3);
1607fcf3ce44SJohn Forte 		}
1608fcf3ce44SJohn Forte 	}
1609fcf3ce44SJohn Forte 
1610fcf3ce44SJohn Forte 	/* Get IP FW container count. */
1611fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.cc[0] = LSB(ql_ip_buffer_count);
1612fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.cc[1] = MSB(ql_ip_buffer_count);
1613fcf3ce44SJohn Forte 
1614fcf3ce44SJohn Forte 	/* Get IP low water mark. */
1615fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.low_water_mark[0] = LSB(ql_ip_low_water);
1616fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.low_water_mark[1] = MSB(ql_ip_low_water);
1617fcf3ce44SJohn Forte 
1618fcf3ce44SJohn Forte 	/* Get IP fast register post count. */
1619fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.fast_post_reg_count[0] =
1620fcf3ce44SJohn Forte 	    ql_ip_fast_post_count;
1621fcf3ce44SJohn Forte 
1622fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1623fcf3ce44SJohn Forte 
1624fcf3ce44SJohn Forte 	ql_common_properties(ha);
1625fcf3ce44SJohn Forte 
1626fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1627fcf3ce44SJohn Forte 
1628*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1629fcf3ce44SJohn Forte }
1630fcf3ce44SJohn Forte 
1631fcf3ce44SJohn Forte /*
1632fcf3ce44SJohn Forte  * ql_common_properties
1633fcf3ce44SJohn Forte  *	Driver properties adapter structure.
1634fcf3ce44SJohn Forte  *
1635fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1636fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1637fcf3ce44SJohn Forte  *	override the default values using driver.conf
1638fcf3ce44SJohn Forte  *
1639fcf3ce44SJohn Forte  * Input:
1640fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1641fcf3ce44SJohn Forte  *
1642fcf3ce44SJohn Forte  * Context:
1643fcf3ce44SJohn Forte  *	Kernel context.
1644fcf3ce44SJohn Forte  */
1645fcf3ce44SJohn Forte void
ql_common_properties(ql_adapter_state_t * ha)1646fcf3ce44SJohn Forte ql_common_properties(ql_adapter_state_t *ha)
1647fcf3ce44SJohn Forte {
1648fcf3ce44SJohn Forte 	uint32_t	data;
1649fcf3ce44SJohn Forte 
1650*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
165116dd44c2SDaniel Beauregard 
165216dd44c2SDaniel Beauregard 	/* Get extended logging enable. */
165316dd44c2SDaniel Beauregard 	if ((data = ql_get_prop(ha, "extended-logging")) == 0xffffffff ||
165416dd44c2SDaniel Beauregard 	    data == 0) {
165516dd44c2SDaniel Beauregard 		ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
165616dd44c2SDaniel Beauregard 	} else if (data == 1) {
165716dd44c2SDaniel Beauregard 		ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
165816dd44c2SDaniel Beauregard 	} else {
165916dd44c2SDaniel Beauregard 		EL(ha, "invalid parameter value for 'extended-logging': %d;"
166016dd44c2SDaniel Beauregard 		    " using default value of 0\n", data);
166116dd44c2SDaniel Beauregard 		ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
166216dd44c2SDaniel Beauregard 	}
166316dd44c2SDaniel Beauregard 
1664fcf3ce44SJohn Forte 	/* Get FCP 2 Error Recovery. */
1665fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-FCP-2-error-recovery")) ==
1666fcf3ce44SJohn Forte 	    0xffffffff || data == 1) {
1667fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
1668fcf3ce44SJohn Forte 	} else if (data == 0) {
1669fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_FCP_2_SUPPORT;
1670fcf3ce44SJohn Forte 	} else {
1671fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1672fcf3ce44SJohn Forte 		    "'enable-FCP-2-error-recovery': %d; using nvram value of "
1673fcf3ce44SJohn Forte 		    "1\n", data);
1674fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
1675fcf3ce44SJohn Forte 	}
1676fcf3ce44SJohn Forte 
1677fcf3ce44SJohn Forte #ifdef QL_DEBUG_LEVEL_2
1678fcf3ce44SJohn Forte 	ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
1679fcf3ce44SJohn Forte #endif
1680fcf3ce44SJohn Forte 
1681fcf3ce44SJohn Forte 	/* Get port down retry delay. */
1682fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-delay")) == 0xffffffff) {
1683fcf3ce44SJohn Forte 		ha->port_down_retry_delay = PORT_RETRY_TIME;
1684fcf3ce44SJohn Forte 	} else if (data < 256) {
1685fcf3ce44SJohn Forte 		ha->port_down_retry_delay = (uint8_t)data;
1686fcf3ce44SJohn Forte 	} else {
1687fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-delay':"
1688fcf3ce44SJohn Forte 		    " %d; using default value of %d", data, PORT_RETRY_TIME);
1689fcf3ce44SJohn Forte 		ha->port_down_retry_delay = PORT_RETRY_TIME;
1690fcf3ce44SJohn Forte 	}
1691fcf3ce44SJohn Forte 
1692fcf3ce44SJohn Forte 	/* Get queue full retry count. */
1693fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "queue-full-retry-count")) == 0xffffffff) {
1694fcf3ce44SJohn Forte 		ha->qfull_retry_count = 16;
1695fcf3ce44SJohn Forte 	} else if (data < 256) {
1696fcf3ce44SJohn Forte 		ha->qfull_retry_count = (uint8_t)data;
1697fcf3ce44SJohn Forte 	} else {
1698fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'queue-full-retry-count':"
1699fcf3ce44SJohn Forte 		    " %d; using default value of 16", data);
1700fcf3ce44SJohn Forte 		ha->qfull_retry_count = 16;
1701fcf3ce44SJohn Forte 	}
1702fcf3ce44SJohn Forte 
1703fcf3ce44SJohn Forte 	/* Get queue full retry delay. */
1704fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "queue-full-retry-delay")) == 0xffffffff) {
1705fcf3ce44SJohn Forte 		ha->qfull_retry_delay = PORT_RETRY_TIME;
1706fcf3ce44SJohn Forte 	} else if (data < 256) {
1707fcf3ce44SJohn Forte 		ha->qfull_retry_delay = (uint8_t)data;
1708fcf3ce44SJohn Forte 	} else {
1709fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'queue-full-retry-delay':"
1710fcf3ce44SJohn Forte 		    " %d; using default value of %d", data, PORT_RETRY_TIME);
1711fcf3ce44SJohn Forte 		ha->qfull_retry_delay = PORT_RETRY_TIME;
1712fcf3ce44SJohn Forte 	}
1713fcf3ce44SJohn Forte 
1714fcf3ce44SJohn Forte 	/* Get loop down timeout. */
1715fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "link-down-timeout")) == 0xffffffff) {
1716fcf3ce44SJohn Forte 		data = 0;
1717fcf3ce44SJohn Forte 	} else if (data > 255) {
1718fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'link-down-timeout': %d;"
1719fcf3ce44SJohn Forte 		    " using nvram value of 0\n", data);
1720fcf3ce44SJohn Forte 		data = 0;
1721fcf3ce44SJohn Forte 	}
1722fcf3ce44SJohn Forte 	ha->loop_down_abort_time = (uint8_t)(LOOP_DOWN_TIMER_START - data);
1723fcf3ce44SJohn Forte 	if (ha->loop_down_abort_time == LOOP_DOWN_TIMER_START) {
1724fcf3ce44SJohn Forte 		ha->loop_down_abort_time--;
1725fcf3ce44SJohn Forte 	} else if (ha->loop_down_abort_time <= LOOP_DOWN_TIMER_END) {
1726fcf3ce44SJohn Forte 		ha->loop_down_abort_time = LOOP_DOWN_TIMER_END + 1;
1727fcf3ce44SJohn Forte 	}
1728fcf3ce44SJohn Forte 
1729fcf3ce44SJohn Forte 	/* Get link down error enable. */
1730fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-link-down-error")) == 0xffffffff ||
1731fcf3ce44SJohn Forte 	    data == 1) {
1732fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_LINK_DOWN_REPORTING;
1733fcf3ce44SJohn Forte 	} else if (data == 0) {
1734fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_LINK_DOWN_REPORTING;
1735fcf3ce44SJohn Forte 	} else {
1736fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'link-down-error': %d;"
1737fcf3ce44SJohn Forte 		    " using default value of 1\n", data);
1738fcf3ce44SJohn Forte 	}
1739fcf3ce44SJohn Forte 
1740fcf3ce44SJohn Forte 	/*
1741fcf3ce44SJohn Forte 	 * Get firmware dump flags.
1742fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT		BIT_0
1743fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR	BIT_1
1744fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT	BIT_2
1745fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT	BIT_3
1746fcf3ce44SJohn Forte 	 */
1747fcf3ce44SJohn Forte 	ha->cfg_flags &= ~(CFG_DUMP_MAILBOX_TIMEOUT |
1748fcf3ce44SJohn Forte 	    CFG_DUMP_ISP_SYSTEM_ERROR | CFG_DUMP_DRIVER_COMMAND_TIMEOUT |
1749fcf3ce44SJohn Forte 	    CFG_DUMP_LOOP_OFFLINE_TIMEOUT);
1750fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "firmware-dump-flags")) != 0xffffffff) {
1751fcf3ce44SJohn Forte 		if (data & BIT_0) {
1752fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_MAILBOX_TIMEOUT;
1753fcf3ce44SJohn Forte 		}
1754fcf3ce44SJohn Forte 		if (data & BIT_1) {
1755fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_ISP_SYSTEM_ERROR;
1756fcf3ce44SJohn Forte 		}
1757fcf3ce44SJohn Forte 		if (data & BIT_2) {
1758fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_DRIVER_COMMAND_TIMEOUT;
1759fcf3ce44SJohn Forte 		}
1760fcf3ce44SJohn Forte 		if (data & BIT_3) {
1761fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_LOOP_OFFLINE_TIMEOUT;
1762fcf3ce44SJohn Forte 		}
1763fcf3ce44SJohn Forte 	}
1764fcf3ce44SJohn Forte 
1765fcf3ce44SJohn Forte 	/* Get the PCI max read request size override. */
1766fcf3ce44SJohn Forte 	ha->pci_max_read_req = 0;
1767fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "pci-max-read-request")) != 0xffffffff &&
1768fcf3ce44SJohn Forte 	    data != 0) {
1769fcf3ce44SJohn Forte 		ha->pci_max_read_req = (uint16_t)(data);
1770fcf3ce44SJohn Forte 	}
1771fcf3ce44SJohn Forte 
1772*4c3888b8SHans Rosenfeld 	/* Get the plogi retry params overrides. */
1773*4c3888b8SHans Rosenfeld 	if ((data = ql_get_prop(ha, "plogi_params_retry_count")) !=
1774*4c3888b8SHans Rosenfeld 	    0xffffffff && data != 0) {
1775*4c3888b8SHans Rosenfeld 		ha->plogi_params->retry_cnt = (uint32_t)(data);
1776*4c3888b8SHans Rosenfeld 	}
1777*4c3888b8SHans Rosenfeld 	if ((data = ql_get_prop(ha, "plogi_params_retry_delay")) !=
1778*4c3888b8SHans Rosenfeld 	    0xffffffff && data != 0) {
1779*4c3888b8SHans Rosenfeld 		ha->plogi_params->retry_dly_usec = (uint32_t)(data);
1780*4c3888b8SHans Rosenfeld 	}
1781*4c3888b8SHans Rosenfeld 
1782a2b3ff35SDaniel Beauregard 	/*
1783a2b3ff35SDaniel Beauregard 	 * Set default fw wait, adjusted for slow FCF's.
1784a2b3ff35SDaniel Beauregard 	 * Revisit when FCF's as fast as FC switches.
1785a2b3ff35SDaniel Beauregard 	 */
1786*4c3888b8SHans Rosenfeld 	ha->fwwait = (uint8_t)(CFG_IST(ha, CFG_FCOE_SUPPORT) ? 45 : 10);
1787fcf3ce44SJohn Forte 	/* Get the attach fw_ready override value. */
1788fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "init-loop-sync-wait")) != 0xffffffff) {
1789fcf3ce44SJohn Forte 		if (data > 0 && data <= 240) {
1790fcf3ce44SJohn Forte 			ha->fwwait = (uint8_t)data;
1791fcf3ce44SJohn Forte 		} else {
1792fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
1793fcf3ce44SJohn Forte 			    "'init-loop-sync-wait': %d; using default "
1794fcf3ce44SJohn Forte 			    "value of %d\n", data, ha->fwwait);
1795fcf3ce44SJohn Forte 		}
1796fcf3ce44SJohn Forte 	}
1797fcf3ce44SJohn Forte 
1798*4c3888b8SHans Rosenfeld 	/* Get fm-capable property */
1799*4c3888b8SHans Rosenfeld 	ha->fm_capabilities = DDI_FM_NOT_CAPABLE;
1800*4c3888b8SHans Rosenfeld 	if ((data = ql_get_prop(ha, "fm-capable")) != 0xffffffff) {
1801*4c3888b8SHans Rosenfeld 		if (data == 0) {
1802*4c3888b8SHans Rosenfeld 			ha->fm_capabilities = DDI_FM_NOT_CAPABLE;
1803*4c3888b8SHans Rosenfeld 		} else if (data > 0xf) {
1804*4c3888b8SHans Rosenfeld 			ha->fm_capabilities = 0xf;
1805*4c3888b8SHans Rosenfeld 
1806*4c3888b8SHans Rosenfeld 		} else {
1807*4c3888b8SHans Rosenfeld 			ha->fm_capabilities = (int)(data);
1808*4c3888b8SHans Rosenfeld 		}
1809*4c3888b8SHans Rosenfeld 	} else {
1810*4c3888b8SHans Rosenfeld 		ha->fm_capabilities = (int)(DDI_FM_EREPORT_CAPABLE
1811*4c3888b8SHans Rosenfeld 		    | DDI_FM_ERRCB_CAPABLE);
1812*4c3888b8SHans Rosenfeld 	}
1813*4c3888b8SHans Rosenfeld 
1814*4c3888b8SHans Rosenfeld 	if ((data = ql_get_prop(ha, "msix-vectors")) == 0xffffffff) {
1815*4c3888b8SHans Rosenfeld 		ha->mq_msix_vectors = 0;
1816*4c3888b8SHans Rosenfeld 	} else if (data < 256) {
1817*4c3888b8SHans Rosenfeld 		ha->mq_msix_vectors = (uint8_t)data;
1818*4c3888b8SHans Rosenfeld 	} else {
1819*4c3888b8SHans Rosenfeld 		EL(ha, "invalid parameter value for 'msix-vectors': "
1820*4c3888b8SHans Rosenfeld 		    "%d; using value of %d\n", data, 0);
1821*4c3888b8SHans Rosenfeld 		ha->mq_msix_vectors = 0;
1822*4c3888b8SHans Rosenfeld 	}
1823*4c3888b8SHans Rosenfeld 
1824*4c3888b8SHans Rosenfeld 	/* Get number of completion threads. */
1825*4c3888b8SHans Rosenfeld 	if ((data = ql_get_prop(ha, "completion-threads")) == 0xffffffff) {
1826*4c3888b8SHans Rosenfeld 		ha->completion_thds = 4;
1827*4c3888b8SHans Rosenfeld 	} else if (data < 256 && data >= 1) {
1828*4c3888b8SHans Rosenfeld 		ha->completion_thds = (uint8_t)data;
1829*4c3888b8SHans Rosenfeld 	} else {
1830*4c3888b8SHans Rosenfeld 		EL(ha, "invalid parameter value for 'completion-threads':"
1831*4c3888b8SHans Rosenfeld 		    " %d; using default value of %d", data, 4);
1832*4c3888b8SHans Rosenfeld 		ha->completion_thds = 4;
1833*4c3888b8SHans Rosenfeld 	}
1834*4c3888b8SHans Rosenfeld 
1835*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1836fcf3ce44SJohn Forte }
1837fcf3ce44SJohn Forte 
1838fcf3ce44SJohn Forte /*
1839fcf3ce44SJohn Forte  * ql_24xx_properties
1840fcf3ce44SJohn Forte  *	Copies driver properties to NVRAM or adapter structure.
1841fcf3ce44SJohn Forte  *
1842fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1843fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1844fcf3ce44SJohn Forte  *	override the default values using /etc/system.
1845fcf3ce44SJohn Forte  *
1846fcf3ce44SJohn Forte  * Input:
1847fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1848*4c3888b8SHans Rosenfeld  *	icb:	Init control block structure pointer.
1849fcf3ce44SJohn Forte  *
1850fcf3ce44SJohn Forte  * Context:
1851fcf3ce44SJohn Forte  *	Kernel context.
1852fcf3ce44SJohn Forte  */
1853fcf3ce44SJohn Forte static void
ql_24xx_properties(ql_adapter_state_t * ha,ql_init_24xx_cb_t * icb)1854*4c3888b8SHans Rosenfeld ql_24xx_properties(ql_adapter_state_t *ha, ql_init_24xx_cb_t *icb)
1855fcf3ce44SJohn Forte {
1856fcf3ce44SJohn Forte 	uint32_t	data;
1857fcf3ce44SJohn Forte 
1858*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
1859fcf3ce44SJohn Forte 
1860fcf3ce44SJohn Forte 	/* Get frame size */
1861fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
1862fcf3ce44SJohn Forte 		data = 2048;
1863fcf3ce44SJohn Forte 	}
1864eb82ff87SDaniel Beauregard 	if (data == 512 || data == 1024 || data == 2048 || data == 2112) {
1865*4c3888b8SHans Rosenfeld 		icb->max_frame_length[0] = LSB(data);
1866*4c3888b8SHans Rosenfeld 		icb->max_frame_length[1] = MSB(data);
1867fcf3ce44SJohn Forte 	} else {
1868fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'max-frame-length': %d;"
1869fcf3ce44SJohn Forte 		    " using nvram default of %d\n", data, CHAR_TO_SHORT(
1870*4c3888b8SHans Rosenfeld 		    icb->max_frame_length[0], icb->max_frame_length[1]));
1871fcf3ce44SJohn Forte 	}
1872fcf3ce44SJohn Forte 
1873fcf3ce44SJohn Forte 	/* Get execution throttle. */
1874fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
1875fcf3ce44SJohn Forte 		data = 32;
1876fcf3ce44SJohn Forte 	}
1877fcf3ce44SJohn Forte 	if (data != 0 && data < 65536) {
1878*4c3888b8SHans Rosenfeld 		icb->execution_throttle[0] = LSB(data);
1879*4c3888b8SHans Rosenfeld 		icb->execution_throttle[1] = MSB(data);
1880fcf3ce44SJohn Forte 	} else {
1881fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'execution-throttle':"
1882fcf3ce44SJohn Forte 		    " %d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1883*4c3888b8SHans Rosenfeld 		    icb->execution_throttle[0], icb->execution_throttle[1]));
1884fcf3ce44SJohn Forte 	}
1885fcf3ce44SJohn Forte 
1886fcf3ce44SJohn Forte 	/* Get Login timeout. */
1887fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
1888fcf3ce44SJohn Forte 		data = 3;
1889fcf3ce44SJohn Forte 	}
1890fcf3ce44SJohn Forte 	if (data < 65536) {
1891*4c3888b8SHans Rosenfeld 		icb->login_timeout[0] = LSB(data);
1892*4c3888b8SHans Rosenfeld 		icb->login_timeout[1] = MSB(data);
1893fcf3ce44SJohn Forte 	} else {
1894fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-timeout': %d; "
1895fcf3ce44SJohn Forte 		    "using nvram value of %d\n", data, CHAR_TO_SHORT(
1896*4c3888b8SHans Rosenfeld 		    icb->login_timeout[0], icb->login_timeout[1]));
1897fcf3ce44SJohn Forte 	}
1898fcf3ce44SJohn Forte 
1899fcf3ce44SJohn Forte 	/* Get retry count. */
1900fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
1901fcf3ce44SJohn Forte 		data = 4;
1902fcf3ce44SJohn Forte 	}
1903fcf3ce44SJohn Forte 	if (data < 65536) {
1904*4c3888b8SHans Rosenfeld 		icb->login_retry_count[0] = LSB(data);
1905*4c3888b8SHans Rosenfeld 		icb->login_retry_count[1] = MSB(data);
1906fcf3ce44SJohn Forte 	} else {
1907fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-retry-count': "
1908fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1909*4c3888b8SHans Rosenfeld 		    icb->login_retry_count[0], icb->login_retry_count[1]));
1910fcf3ce44SJohn Forte 	}
1911fcf3ce44SJohn Forte 
1912fcf3ce44SJohn Forte 	/* Get adapter hard loop ID enable. */
1913*4c3888b8SHans Rosenfeld 	data = ql_get_prop(ha, "enable-adapter-hard-loop-ID");
1914fcf3ce44SJohn Forte 	if (data == 0) {
1915*4c3888b8SHans Rosenfeld 		icb->firmware_options_1[0] =
1916*4c3888b8SHans Rosenfeld 		    (uint8_t)(icb->firmware_options_1[0] & ~BIT_0);
1917fcf3ce44SJohn Forte 	} else if (data == 1) {
1918*4c3888b8SHans Rosenfeld 		icb->firmware_options_1[0] =
1919*4c3888b8SHans Rosenfeld 		    (uint8_t)(icb->firmware_options_1[0] | BIT_0);
1920fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1921fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1922fcf3ce44SJohn Forte 		    "'enable-adapter-hard-loop-ID': %d; using nvram value "
1923fcf3ce44SJohn Forte 		    "of %d\n", data,
1924*4c3888b8SHans Rosenfeld 		    icb->firmware_options_1[0] & BIT_0 ? 1 : 0);
1925fcf3ce44SJohn Forte 	}
1926fcf3ce44SJohn Forte 
1927fcf3ce44SJohn Forte 	/* Get adapter hard loop ID. */
1928*4c3888b8SHans Rosenfeld 	data = ql_get_prop(ha, "adapter-hard-loop-ID");
1929fcf3ce44SJohn Forte 	if (data < 126) {
1930*4c3888b8SHans Rosenfeld 		icb->hard_address[0] = LSB(data);
1931*4c3888b8SHans Rosenfeld 		icb->hard_address[1] = MSB(data);
1932fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1933fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'adapter-hard-loop-ID':"
1934fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1935*4c3888b8SHans Rosenfeld 		    icb->hard_address[0], icb->hard_address[1]));
1936fcf3ce44SJohn Forte 	}
1937fcf3ce44SJohn Forte 
1938fcf3ce44SJohn Forte 	/* Get LIP reset. */
1939fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
1940fcf3ce44SJohn Forte 	    0xffffffff) {
1941fcf3ce44SJohn Forte 		data = 0;
1942fcf3ce44SJohn Forte 	}
1943fcf3ce44SJohn Forte 	if (data == 0) {
1944fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET;
1945fcf3ce44SJohn Forte 	} else if (data == 1) {
1946fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_LIP_RESET;
1947fcf3ce44SJohn Forte 	} else {
1948fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1949fcf3ce44SJohn Forte 		    "'enable-LIP-reset-on-bus-reset': %d; using value of 0\n",
1950fcf3ce44SJohn Forte 		    data);
1951fcf3ce44SJohn Forte 	}
1952fcf3ce44SJohn Forte 
1953fcf3ce44SJohn Forte 	/* Get LIP full login. */
1954fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
1955fcf3ce44SJohn Forte 	    0xffffffff) {
1956fcf3ce44SJohn Forte 		data = 1;
1957fcf3ce44SJohn Forte 	}
1958fcf3ce44SJohn Forte 	if (data == 0) {
1959*4c3888b8SHans Rosenfeld 		ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN;
1960fcf3ce44SJohn Forte 	} else if (data == 1) {
1961*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN;
1962fcf3ce44SJohn Forte 	} else {
1963fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1964fcf3ce44SJohn Forte 		    "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
1965*4c3888b8SHans Rosenfeld 		    "value of %d\n", data,
1966*4c3888b8SHans Rosenfeld 		    ha->cfg_flags & CFG_ENABLE_FULL_LIP_LOGIN ? 1 : 0);
1967fcf3ce44SJohn Forte 	}
1968fcf3ce44SJohn Forte 
1969fcf3ce44SJohn Forte 	/* Get target reset. */
1970fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
1971fcf3ce44SJohn Forte 	    0xffffffff) {
1972fcf3ce44SJohn Forte 		data = 0;
1973fcf3ce44SJohn Forte 	}
1974fcf3ce44SJohn Forte 	if (data == 0) {
1975*4c3888b8SHans Rosenfeld 		ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET;
1976fcf3ce44SJohn Forte 	} else if (data == 1) {
1977*4c3888b8SHans Rosenfeld 		ha->cfg_flags |= CFG_ENABLE_TARGET_RESET;
1978fcf3ce44SJohn Forte 	} else {
1979fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1980fcf3ce44SJohn Forte 		    "'enable-target-reset-on-bus-reset': %d; using nvram "
1981*4c3888b8SHans Rosenfeld 		    "value of %d", data,
1982*4c3888b8SHans Rosenfeld 		    ha->cfg_flags & CFG_ENABLE_TARGET_RESET ? 1 : 0);
1983fcf3ce44SJohn Forte 	}
1984fcf3ce44SJohn Forte 
1985fcf3ce44SJohn Forte 	/* Get reset delay. */
1986fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
1987fcf3ce44SJohn Forte 		data = 5;
1988fcf3ce44SJohn Forte 	}
1989fcf3ce44SJohn Forte 	if (data != 0 && data < 256) {
1990*4c3888b8SHans Rosenfeld 		ha->loop_reset_delay = (uint8_t)data;
1991fcf3ce44SJohn Forte 	} else {
1992fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'reset-delay': %d; "
1993*4c3888b8SHans Rosenfeld 		    "using nvram value of %d", data, ha->loop_reset_delay);
1994fcf3ce44SJohn Forte 	}
1995fcf3ce44SJohn Forte 
1996fcf3ce44SJohn Forte 	/* Get port down retry count. */
1997fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
1998fcf3ce44SJohn Forte 		data = 8;
1999fcf3ce44SJohn Forte 	}
2000fcf3ce44SJohn Forte 	if (data < 256) {
2001*4c3888b8SHans Rosenfeld 		ha->port_down_retry_count = (uint16_t)data;
2002fcf3ce44SJohn Forte 	} else {
2003fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-count':"
2004*4c3888b8SHans Rosenfeld 		    " %d; using nvram value of %d\n", data,
2005*4c3888b8SHans Rosenfeld 		    ha->port_down_retry_count);
2006fcf3ce44SJohn Forte 	}
2007fcf3ce44SJohn Forte 
2008*4c3888b8SHans Rosenfeld 	if (!(CFG_IST(ha, CFG_FCOE_SUPPORT))) {
2009*4c3888b8SHans Rosenfeld 		uint32_t	conn;
2010*4c3888b8SHans Rosenfeld 
2011eb82ff87SDaniel Beauregard 		/* Get connection mode setting. */
2012*4c3888b8SHans Rosenfeld 		if ((conn = ql_get_prop(ha, "connection-options")) ==
2013eb82ff87SDaniel Beauregard 		    0xffffffff) {
2014*4c3888b8SHans Rosenfeld 			conn = 2;
2015eb82ff87SDaniel Beauregard 		}
2016*4c3888b8SHans Rosenfeld 		if (conn <= 2) {
2017*4c3888b8SHans Rosenfeld 			icb->firmware_options_2[0] = (uint8_t)
2018*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[0] &
2019eb82ff87SDaniel Beauregard 			    ~(BIT_6 | BIT_5 | BIT_4));
2020*4c3888b8SHans Rosenfeld 			icb->firmware_options_2[0] = (uint8_t)
2021*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[0] | (uint8_t)(conn << 4));
2022eb82ff87SDaniel Beauregard 		} else {
2023eb82ff87SDaniel Beauregard 			EL(ha, "invalid parameter value for 'connection-"
2024*4c3888b8SHans Rosenfeld 			    "options': %d; using nvram value of %d\n", conn,
2025*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[0] >> 4) & 0x3);
2026*4c3888b8SHans Rosenfeld 		}
2027*4c3888b8SHans Rosenfeld 		conn = icb->firmware_options_2[0] >> 4 & 0x3;
2028*4c3888b8SHans Rosenfeld 		if (conn == 0 && ha->max_vports > 125) {
2029*4c3888b8SHans Rosenfeld 			ha->max_vports = 125;
2030eb82ff87SDaniel Beauregard 		}
2031fcf3ce44SJohn Forte 
2032eb82ff87SDaniel Beauregard 		/* Get data rate setting. */
2033eb82ff87SDaniel Beauregard 		if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
2034eb82ff87SDaniel Beauregard 			data = 2;
2035eb82ff87SDaniel Beauregard 		}
2036*4c3888b8SHans Rosenfeld 		if ((CFG_IST(ha, CFG_CTRL_24XX) && data < 4) ||
2037*4c3888b8SHans Rosenfeld 		    (CFG_IST(ha, CFG_CTRL_25XX) && data < 5) ||
2038*4c3888b8SHans Rosenfeld 		    (CFG_IST(ha, CFG_CTRL_2783) && data < 6)) {
2039*4c3888b8SHans Rosenfeld 			if (CFG_IST(ha, CFG_CTRL_2783) && data == 5 &&
2040*4c3888b8SHans Rosenfeld 			    conn == 0) {
2041*4c3888b8SHans Rosenfeld 				EL(ha, "invalid parameter value for 'fc-data-"
2042*4c3888b8SHans Rosenfeld 				    "rate': %d; using nvram value of %d\n",
2043*4c3888b8SHans Rosenfeld 				    data, 2);
2044*4c3888b8SHans Rosenfeld 				data = 2;
2045*4c3888b8SHans Rosenfeld 			}
2046*4c3888b8SHans Rosenfeld 			icb->firmware_options_3[1] = (uint8_t)
2047*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_3[1] & 0x1f);
2048*4c3888b8SHans Rosenfeld 			icb->firmware_options_3[1] = (uint8_t)
2049*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_3[1] | (uint8_t)(data << 5));
2050eb82ff87SDaniel Beauregard 		} else {
2051eb82ff87SDaniel Beauregard 			EL(ha, "invalid parameter value for 'fc-data-rate': "
2052eb82ff87SDaniel Beauregard 			    "%d; using nvram value of %d\n", data,
2053*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_3[1] >> 5) & 0x7);
2054eb82ff87SDaniel Beauregard 		}
2055fcf3ce44SJohn Forte 	}
2056fcf3ce44SJohn Forte 
2057fcf3ce44SJohn Forte 	/* Get IP FW container count. */
2058fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.cc[0] = LSB(ql_ip_buffer_count);
2059fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.cc[1] = MSB(ql_ip_buffer_count);
2060fcf3ce44SJohn Forte 
2061fcf3ce44SJohn Forte 	/* Get IP low water mark. */
2062fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.low_water_mark[0] = LSB(ql_ip_low_water);
2063fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.low_water_mark[1] = MSB(ql_ip_low_water);
2064fcf3ce44SJohn Forte 
2065fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
2066fcf3ce44SJohn Forte 
2067fcf3ce44SJohn Forte 	/* Get enable flash load. */
2068fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-flash-load")) == 0xffffffff ||
2069fcf3ce44SJohn Forte 	    data == 0) {
2070fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_LOAD_FLASH_FW;
2071fcf3ce44SJohn Forte 	} else if (data == 1) {
2072fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_LOAD_FLASH_FW;
2073fcf3ce44SJohn Forte 	} else {
2074fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'enable-flash-load': "
2075fcf3ce44SJohn Forte 		    "%d; using default value of 0\n", data);
2076fcf3ce44SJohn Forte 	}
2077fcf3ce44SJohn Forte 
2078fcf3ce44SJohn Forte 	/* Enable firmware extended tracing */
2079fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-fwexttrace")) != 0xffffffff) {
2080fcf3ce44SJohn Forte 		if (data != 0) {
2081fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_ENABLE_FWEXTTRACE;
2082fcf3ce44SJohn Forte 		}
2083fcf3ce44SJohn Forte 	}
2084fcf3ce44SJohn Forte 
2085fcf3ce44SJohn Forte 	/* Enable firmware fc tracing */
2086fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-fwfcetrace")) != 0xffffffff) {
2087fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FWFCETRACE;
2088fcf3ce44SJohn Forte 		ha->fwfcetraceopt = data;
2089fcf3ce44SJohn Forte 	}
2090fcf3ce44SJohn Forte 
2091c1fad183SDaniel Beauregard 	/* Enable fast timeout */
2092c1fad183SDaniel Beauregard 	if ((data = ql_get_prop(ha, "enable-fasttimeout")) != 0xffffffff) {
2093c1fad183SDaniel Beauregard 		if (data != 0) {
2094c1fad183SDaniel Beauregard 			ha->cfg_flags |= CFG_FAST_TIMEOUT;
2095c1fad183SDaniel Beauregard 		}
2096c1fad183SDaniel Beauregard 	}
2097c1fad183SDaniel Beauregard 
2098fcf3ce44SJohn Forte 	ql_common_properties(ha);
2099fcf3ce44SJohn Forte 
2100fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
2101fcf3ce44SJohn Forte 
2102*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
2103fcf3ce44SJohn Forte }
2104fcf3ce44SJohn Forte 
2105fcf3ce44SJohn Forte /*
2106fcf3ce44SJohn Forte  * ql_get_prop
2107fcf3ce44SJohn Forte  *	Get property value from configuration file.
2108fcf3ce44SJohn Forte  *
2109fcf3ce44SJohn Forte  * Input:
2110fcf3ce44SJohn Forte  *	ha= adapter state pointer.
2111fcf3ce44SJohn Forte  *	string = property string pointer.
2112fcf3ce44SJohn Forte  *
2113fcf3ce44SJohn Forte  * Returns:
2114fcf3ce44SJohn Forte  *	0xFFFFFFFF = no property else property value.
2115fcf3ce44SJohn Forte  *
2116fcf3ce44SJohn Forte  * Context:
2117fcf3ce44SJohn Forte  *	Kernel context.
2118fcf3ce44SJohn Forte  */
2119fcf3ce44SJohn Forte uint32_t
ql_get_prop(ql_adapter_state_t * ha,char * string)2120fcf3ce44SJohn Forte ql_get_prop(ql_adapter_state_t *ha, char *string)
2121fcf3ce44SJohn Forte {
2122fcf3ce44SJohn Forte 	char		buf[256];
212316dd44c2SDaniel Beauregard 	uint32_t	data = 0xffffffff;
212416dd44c2SDaniel Beauregard 
212516dd44c2SDaniel Beauregard 	/*
212616dd44c2SDaniel Beauregard 	 * Look for a adapter instance NPIV (virtual port) specific parameter
212716dd44c2SDaniel Beauregard 	 */
2128*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
212916dd44c2SDaniel Beauregard 		(void) sprintf(buf, "hba%d-vp%d-%s", ha->instance,
213016dd44c2SDaniel Beauregard 		    ha->vp_index, string);
213116dd44c2SDaniel Beauregard 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
213216dd44c2SDaniel Beauregard 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
213316dd44c2SDaniel Beauregard 		    buf, (int)0xffffffff);
213416dd44c2SDaniel Beauregard 	}
2135fcf3ce44SJohn Forte 
213616dd44c2SDaniel Beauregard 	/*
213716dd44c2SDaniel Beauregard 	 * Get adapter instance parameter if a vp specific one isn't found.
213816dd44c2SDaniel Beauregard 	 */
213916dd44c2SDaniel Beauregard 	if (data == 0xffffffff) {
214016dd44c2SDaniel Beauregard 		(void) sprintf(buf, "hba%d-%s", ha->instance, string);
214116dd44c2SDaniel Beauregard 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
214216dd44c2SDaniel Beauregard 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip,
214316dd44c2SDaniel Beauregard 		    0, buf, (int)0xffffffff);
214416dd44c2SDaniel Beauregard 	}
2145fcf3ce44SJohn Forte 
2146fcf3ce44SJohn Forte 	/* Adapter instance parameter found? */
2147fcf3ce44SJohn Forte 	if (data == 0xffffffff) {
2148fcf3ce44SJohn Forte 		/* No, get default parameter. */
2149fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
2150fcf3ce44SJohn Forte 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
2151fcf3ce44SJohn Forte 		    string, (int)0xffffffff);
2152fcf3ce44SJohn Forte 	}
2153fcf3ce44SJohn Forte 
2154fcf3ce44SJohn Forte 	return (data);
2155fcf3ce44SJohn Forte }
2156fcf3ce44SJohn Forte 
2157fcf3ce44SJohn Forte /*
2158fcf3ce44SJohn Forte  * ql_check_isp_firmware
2159fcf3ce44SJohn Forte  *	Checks if using already loaded RISC code or drivers copy.
2160fcf3ce44SJohn Forte  *	If using already loaded code, save a copy of it.
2161fcf3ce44SJohn Forte  *
2162fcf3ce44SJohn Forte  * Input:
2163fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2164fcf3ce44SJohn Forte  *
2165fcf3ce44SJohn Forte  * Returns:
2166fcf3ce44SJohn Forte  *	ql local function return status code.
2167fcf3ce44SJohn Forte  *
2168fcf3ce44SJohn Forte  * Context:
2169fcf3ce44SJohn Forte  *	Kernel context.
2170fcf3ce44SJohn Forte  */
2171fcf3ce44SJohn Forte static int
ql_check_isp_firmware(ql_adapter_state_t * ha)2172fcf3ce44SJohn Forte ql_check_isp_firmware(ql_adapter_state_t *ha)
2173fcf3ce44SJohn Forte {
2174fcf3ce44SJohn Forte 	int		rval;
2175fcf3ce44SJohn Forte 	uint16_t	word_count;
2176fcf3ce44SJohn Forte 	uint32_t	byte_count;
2177fcf3ce44SJohn Forte 	uint32_t	fw_size, *lptr;
2178fcf3ce44SJohn Forte 	caddr_t		bufp;
2179fcf3ce44SJohn Forte 	uint16_t	risc_address = (uint16_t)ha->risc_fw[0].addr;
2180fcf3ce44SJohn Forte 
2181*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
2182fcf3ce44SJohn Forte 
2183eb82ff87SDaniel Beauregard 	/* Test for firmware running. */
2184*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_82XX)) {
2185*4c3888b8SHans Rosenfeld 		if ((rval = ql_8021_fw_chk(ha)) == QL_SUCCESS) {
2186*4c3888b8SHans Rosenfeld 			rval = ql_start_firmware(ha);
2187*4c3888b8SHans Rosenfeld 		}
2188*4c3888b8SHans Rosenfeld 	} else if (CFG_IST(ha, CFG_CTRL_278083)) {
2189*4c3888b8SHans Rosenfeld 		ha->dev_state = NX_DEV_READY;
2190*4c3888b8SHans Rosenfeld 		if (ha->rom_status == MBS_ROM_FW_RUNNING) {
2191*4c3888b8SHans Rosenfeld 			EL(ha, "ISP ROM Status = MBS_ROM_FW_RUNNING\n");
2192*4c3888b8SHans Rosenfeld 			rval = QL_SUCCESS;
2193*4c3888b8SHans Rosenfeld 		} else if (ha->rom_status == MBS_ROM_IDLE) {
2194*4c3888b8SHans Rosenfeld 			EL(ha, "ISP ROM Status = MBS_ROM_IDLE\n");
2195eb82ff87SDaniel Beauregard 			rval = QL_FUNCTION_FAILED;
2196eb82ff87SDaniel Beauregard 		} else {
2197*4c3888b8SHans Rosenfeld 			EL(ha, "ISP ROM Status, mbx0=%xh\n", ha->rom_status);
2198*4c3888b8SHans Rosenfeld 			rval = QL_FUNCTION_FAILED;
2199eb82ff87SDaniel Beauregard 		}
2200eb82ff87SDaniel Beauregard 	} else if (CFG_IST(ha, CFG_DISABLE_RISC_CODE_LOAD)) {
2201*4c3888b8SHans Rosenfeld 		ha->dev_state = NX_DEV_READY;
2202fcf3ce44SJohn Forte 		if (ha->risc_code != NULL) {
2203fcf3ce44SJohn Forte 			kmem_free(ha->risc_code, ha->risc_code_size);
2204fcf3ce44SJohn Forte 			ha->risc_code = NULL;
2205fcf3ce44SJohn Forte 			ha->risc_code_size = 0;
2206fcf3ce44SJohn Forte 		}
2207fcf3ce44SJohn Forte 
2208fcf3ce44SJohn Forte 		/* Get RISC code length. */
2209*4c3888b8SHans Rosenfeld 		rval = ql_rd_risc_ram(ha, risc_address + 3,
2210*4c3888b8SHans Rosenfeld 		    ha->req_q[0]->req_ring.cookie.dmac_laddress, 1);
2211fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2212*4c3888b8SHans Rosenfeld 			lptr = (uint32_t *)ha->req_q[0]->req_ring.bp;
2213fcf3ce44SJohn Forte 			fw_size = *lptr << 1;
2214fcf3ce44SJohn Forte 
2215fcf3ce44SJohn Forte 			if ((bufp = kmem_alloc(fw_size, KM_SLEEP)) != NULL) {
2216fcf3ce44SJohn Forte 				ha->risc_code_size = fw_size;
2217fcf3ce44SJohn Forte 				ha->risc_code = bufp;
2218fcf3ce44SJohn Forte 				ha->fw_transfer_size = 128;
2219fcf3ce44SJohn Forte 
2220fcf3ce44SJohn Forte 				/* Dump RISC code. */
2221fcf3ce44SJohn Forte 				do {
2222fcf3ce44SJohn Forte 					if (fw_size > ha->fw_transfer_size) {
2223fcf3ce44SJohn Forte 						byte_count =
2224fcf3ce44SJohn Forte 						    ha->fw_transfer_size;
2225fcf3ce44SJohn Forte 					} else {
2226fcf3ce44SJohn Forte 						byte_count = fw_size;
2227fcf3ce44SJohn Forte 					}
2228fcf3ce44SJohn Forte 
2229fcf3ce44SJohn Forte 					word_count =
2230fcf3ce44SJohn Forte 					    (uint16_t)(byte_count >> 1);
2231fcf3ce44SJohn Forte 
2232fcf3ce44SJohn Forte 					rval = ql_rd_risc_ram(ha, risc_address,
2233*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.cookie.
2234*4c3888b8SHans Rosenfeld 					    dmac_laddress, word_count);
2235fcf3ce44SJohn Forte 					if (rval != QL_SUCCESS) {
2236fcf3ce44SJohn Forte 						kmem_free(ha->risc_code,
2237fcf3ce44SJohn Forte 						    ha->risc_code_size);
2238fcf3ce44SJohn Forte 						ha->risc_code = NULL;
2239fcf3ce44SJohn Forte 						ha->risc_code_size = 0;
2240fcf3ce44SJohn Forte 						break;
2241fcf3ce44SJohn Forte 					}
2242fcf3ce44SJohn Forte 
2243fcf3ce44SJohn Forte 					(void) ddi_dma_sync(
2244*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.dma_handle,
2245*4c3888b8SHans Rosenfeld 					    0, byte_count,
2246fcf3ce44SJohn Forte 					    DDI_DMA_SYNC_FORKERNEL);
2247*4c3888b8SHans Rosenfeld 					ddi_rep_get16(
2248*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.acc_handle,
2249*4c3888b8SHans Rosenfeld 					    (uint16_t *)bufp, (uint16_t *)
2250*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.bp,
2251fcf3ce44SJohn Forte 					    word_count, DDI_DEV_AUTOINCR);
2252fcf3ce44SJohn Forte 
2253fcf3ce44SJohn Forte 					risc_address += word_count;
2254fcf3ce44SJohn Forte 					fw_size -= byte_count;
2255fcf3ce44SJohn Forte 					bufp	+= byte_count;
2256fcf3ce44SJohn Forte 				} while (fw_size != 0);
2257fcf3ce44SJohn Forte 			}
2258eb82ff87SDaniel Beauregard 			rval = QL_FUNCTION_FAILED;
2259fcf3ce44SJohn Forte 		}
2260fcf3ce44SJohn Forte 	} else {
2261*4c3888b8SHans Rosenfeld 		ha->dev_state = NX_DEV_READY;
2262fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
2263fcf3ce44SJohn Forte 	}
2264fcf3ce44SJohn Forte 
2265fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2266fcf3ce44SJohn Forte 		EL(ha, "Load RISC code\n");
2267fcf3ce44SJohn Forte 	} else {
2268fcf3ce44SJohn Forte 		/*EMPTY*/
2269*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
2270fcf3ce44SJohn Forte 	}
2271fcf3ce44SJohn Forte 	return (rval);
2272fcf3ce44SJohn Forte }
2273fcf3ce44SJohn Forte 
2274fcf3ce44SJohn Forte /*
2275*4c3888b8SHans Rosenfeld  * ql_load_isp_firmware
2276*4c3888b8SHans Rosenfeld  *	Load and start RISC firmware.
2277*4c3888b8SHans Rosenfeld  *	Uses request ring for DMA buffer.
2278fcf3ce44SJohn Forte  *
2279fcf3ce44SJohn Forte  * Input:
2280fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2281fcf3ce44SJohn Forte  *
2282fcf3ce44SJohn Forte  * Returns:
2283fcf3ce44SJohn Forte  *	ql local function return status code.
2284fcf3ce44SJohn Forte  *
2285fcf3ce44SJohn Forte  * Context:
2286fcf3ce44SJohn Forte  *	Kernel context.
2287fcf3ce44SJohn Forte  */
2288*4c3888b8SHans Rosenfeld int
ql_load_isp_firmware(ql_adapter_state_t * vha)2289*4c3888b8SHans Rosenfeld ql_load_isp_firmware(ql_adapter_state_t *vha)
2290fcf3ce44SJohn Forte {
2291*4c3888b8SHans Rosenfeld 	caddr_t			risc_code_address;
2292*4c3888b8SHans Rosenfeld 	uint32_t		risc_address, risc_code_size;
2293*4c3888b8SHans Rosenfeld 	int			rval = QL_FUNCTION_FAILED;
2294*4c3888b8SHans Rosenfeld 	uint32_t		word_count, cnt;
2295*4c3888b8SHans Rosenfeld 	size_t			byte_count;
2296*4c3888b8SHans Rosenfeld 	ql_adapter_state_t	*ha = vha->pha;
2297fcf3ce44SJohn Forte 
2298*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
2299fcf3ce44SJohn Forte 
2300*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_82XX)) {
2301*4c3888b8SHans Rosenfeld 		rval = ql_8021_reset_fw(ha) == NX_DEV_READY ?
2302*4c3888b8SHans Rosenfeld 		    QL_SUCCESS : QL_FUNCTION_FAILED;
2303eb82ff87SDaniel Beauregard 	} else {
2304eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_81XX)) {
2305eb82ff87SDaniel Beauregard 			ql_mps_reset(ha);
2306eb82ff87SDaniel Beauregard 		}
2307f33c1cdbSDaniel Beauregard 
2308eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) {
2309*4c3888b8SHans Rosenfeld 			QL_PRINT_10(ha, "CFG_LOAD_FLASH_FW exit\n");
2310eb82ff87SDaniel Beauregard 			return (ql_load_flash_fw(ha));
2311eb82ff87SDaniel Beauregard 		}
2312fcf3ce44SJohn Forte 
2313*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_27XX)) {
2314*4c3888b8SHans Rosenfeld 			(void) ql_2700_get_module_dmp_template(ha);
2315*4c3888b8SHans Rosenfeld 		}
2316fcf3ce44SJohn Forte 
2317eb82ff87SDaniel Beauregard 		/* Load firmware segments */
2318eb82ff87SDaniel Beauregard 		for (cnt = 0; cnt < MAX_RISC_CODE_SEGMENTS &&
2319eb82ff87SDaniel Beauregard 		    ha->risc_fw[cnt].code != NULL; cnt++) {
2320fcf3ce44SJohn Forte 
2321eb82ff87SDaniel Beauregard 			risc_code_address = ha->risc_fw[cnt].code;
2322eb82ff87SDaniel Beauregard 			risc_address = ha->risc_fw[cnt].addr;
2323*4c3888b8SHans Rosenfeld 			if ((risc_address = ha->risc_fw[cnt].addr) == 0) {
2324*4c3888b8SHans Rosenfeld 				continue;
2325*4c3888b8SHans Rosenfeld 			}
2326eb82ff87SDaniel Beauregard 			risc_code_size = ha->risc_fw[cnt].length;
2327fcf3ce44SJohn Forte 
2328eb82ff87SDaniel Beauregard 			while (risc_code_size) {
2329*4c3888b8SHans Rosenfeld 				if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
2330eb82ff87SDaniel Beauregard 					word_count = ha->fw_transfer_size >> 2;
2331eb82ff87SDaniel Beauregard 					if (word_count > risc_code_size) {
2332eb82ff87SDaniel Beauregard 						word_count = risc_code_size;
2333eb82ff87SDaniel Beauregard 					}
2334eb82ff87SDaniel Beauregard 					byte_count = word_count << 2;
2335fcf3ce44SJohn Forte 
2336*4c3888b8SHans Rosenfeld 					ddi_rep_put32(
2337*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.acc_handle,
2338eb82ff87SDaniel Beauregard 					    (uint32_t *)risc_code_address,
2339*4c3888b8SHans Rosenfeld 					    (uint32_t *)
2340*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.bp,
2341eb82ff87SDaniel Beauregard 					    word_count, DDI_DEV_AUTOINCR);
2342eb82ff87SDaniel Beauregard 				} else {
2343eb82ff87SDaniel Beauregard 					word_count = ha->fw_transfer_size >> 1;
2344eb82ff87SDaniel Beauregard 					if (word_count > risc_code_size) {
2345eb82ff87SDaniel Beauregard 						word_count = risc_code_size;
2346eb82ff87SDaniel Beauregard 					}
2347eb82ff87SDaniel Beauregard 					byte_count = word_count << 1;
2348eb82ff87SDaniel Beauregard 
2349*4c3888b8SHans Rosenfeld 					ddi_rep_put16(
2350*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.acc_handle,
2351eb82ff87SDaniel Beauregard 					    (uint16_t *)risc_code_address,
2352*4c3888b8SHans Rosenfeld 					    (uint16_t *)
2353*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.bp,
2354eb82ff87SDaniel Beauregard 					    word_count, DDI_DEV_AUTOINCR);
2355fcf3ce44SJohn Forte 				}
2356fcf3ce44SJohn Forte 
2357*4c3888b8SHans Rosenfeld 				(void) ddi_dma_sync(
2358*4c3888b8SHans Rosenfeld 				    ha->req_q[0]->req_ring.dma_handle,
2359*4c3888b8SHans Rosenfeld 				    0, byte_count, DDI_DMA_SYNC_FORDEV);
2360fcf3ce44SJohn Forte 
2361eb82ff87SDaniel Beauregard 				rval = ql_wrt_risc_ram(ha, risc_address,
2362*4c3888b8SHans Rosenfeld 				    ha->req_q[0]->req_ring.cookie.dmac_laddress,
2363*4c3888b8SHans Rosenfeld 				    word_count);
2364eb82ff87SDaniel Beauregard 				if (rval != QL_SUCCESS) {
2365eb82ff87SDaniel Beauregard 					EL(ha, "failed, load=%xh\n", rval);
2366eb82ff87SDaniel Beauregard 					cnt = MAX_RISC_CODE_SEGMENTS;
2367eb82ff87SDaniel Beauregard 					break;
2368eb82ff87SDaniel Beauregard 				}
2369fcf3ce44SJohn Forte 
2370eb82ff87SDaniel Beauregard 				risc_address += word_count;
2371eb82ff87SDaniel Beauregard 				risc_code_size -= word_count;
2372eb82ff87SDaniel Beauregard 				risc_code_address += byte_count;
2373fcf3ce44SJohn Forte 			}
2374fcf3ce44SJohn Forte 		}
2375fcf3ce44SJohn Forte 	}
2376*4c3888b8SHans Rosenfeld 	bzero(ha->req_q[0]->req_ring.bp, ha->fw_transfer_size);
2377fcf3ce44SJohn Forte 
2378fcf3ce44SJohn Forte 	/* Start firmware. */
2379fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2380fcf3ce44SJohn Forte 		rval = ql_start_firmware(ha);
2381fcf3ce44SJohn Forte 	}
2382fcf3ce44SJohn Forte 
2383fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2384fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2385fcf3ce44SJohn Forte 	} else {
2386fcf3ce44SJohn Forte 		/*EMPTY*/
2387*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
2388fcf3ce44SJohn Forte 	}
2389fcf3ce44SJohn Forte 
2390fcf3ce44SJohn Forte 	return (rval);
2391fcf3ce44SJohn Forte }
2392fcf3ce44SJohn Forte 
2393fcf3ce44SJohn Forte /*
2394fcf3ce44SJohn Forte  * ql_load_flash_fw
2395fcf3ce44SJohn Forte  *	Gets ISP24xx firmware from flash and loads ISP.
2396fcf3ce44SJohn Forte  *
2397fcf3ce44SJohn Forte  * Input:
2398fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
2399fcf3ce44SJohn Forte  *
2400fcf3ce44SJohn Forte  * Returns:
24015dfd244aSDaniel Beauregard  *	ql local function return status code.
2402fcf3ce44SJohn Forte  */
2403fcf3ce44SJohn Forte static int
ql_load_flash_fw(ql_adapter_state_t * ha)2404fcf3ce44SJohn Forte ql_load_flash_fw(ql_adapter_state_t *ha)
2405fcf3ce44SJohn Forte {
2406fcf3ce44SJohn Forte 	int		rval;
2407fcf3ce44SJohn Forte 	uint8_t		seg_cnt;
2408fcf3ce44SJohn Forte 	uint32_t	risc_address, xfer_size, count,	*bp, faddr;
2409fcf3ce44SJohn Forte 	uint32_t	risc_code_size = 0;
2410fcf3ce44SJohn Forte 
2411*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
2412fcf3ce44SJohn Forte 
2413*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_278083)) {
2414*4c3888b8SHans Rosenfeld 		if ((rval = ql_load_flash_image(ha)) != QL_SUCCESS) {
2415*4c3888b8SHans Rosenfeld 			EL(ha, "load_flash_image status=%xh\n", rval);
2416*4c3888b8SHans Rosenfeld 		} else if (CFG_IST(ha, CFG_CTRL_27XX) &&
2417*4c3888b8SHans Rosenfeld 		    (rval = ql_2700_get_flash_dmp_template(ha)) !=
2418*4c3888b8SHans Rosenfeld 		    QL_SUCCESS) {
2419*4c3888b8SHans Rosenfeld 			EL(ha, "get_flash_dmp_template status=%xh\n", rval);
2420*4c3888b8SHans Rosenfeld 		}
2421*4c3888b8SHans Rosenfeld 	} else {
2422*4c3888b8SHans Rosenfeld 		faddr = ha->flash_data_addr | ha->flash_fw_addr;
2423*4c3888b8SHans Rosenfeld 
2424*4c3888b8SHans Rosenfeld 		for (seg_cnt = 0; seg_cnt < 2; seg_cnt++) {
2425*4c3888b8SHans Rosenfeld 			xfer_size = ha->fw_transfer_size >> 2;
2426*4c3888b8SHans Rosenfeld 			do {
2427*4c3888b8SHans Rosenfeld 				GLOBAL_HW_LOCK();
2428*4c3888b8SHans Rosenfeld 
2429*4c3888b8SHans Rosenfeld 				/* Read data from flash. */
2430*4c3888b8SHans Rosenfeld 				bp = (uint32_t *)ha->req_q[0]->req_ring.bp;
2431*4c3888b8SHans Rosenfeld 				for (count = 0; count < xfer_size; count++) {
2432*4c3888b8SHans Rosenfeld 					rval = ql_24xx_read_flash(ha, faddr++,
2433*4c3888b8SHans Rosenfeld 					    bp);
2434*4c3888b8SHans Rosenfeld 					if (rval != QL_SUCCESS) {
2435*4c3888b8SHans Rosenfeld 						break;
2436*4c3888b8SHans Rosenfeld 					}
2437*4c3888b8SHans Rosenfeld 					ql_chg_endian((uint8_t *)bp++, 4);
2438*4c3888b8SHans Rosenfeld 				}
2439fcf3ce44SJohn Forte 
2440*4c3888b8SHans Rosenfeld 				GLOBAL_HW_UNLOCK();
2441fcf3ce44SJohn Forte 
2442fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS) {
2443*4c3888b8SHans Rosenfeld 					EL(ha, "24xx_read_flash failed=%xh\n",
2444*4c3888b8SHans Rosenfeld 					    rval);
2445fcf3ce44SJohn Forte 					break;
2446fcf3ce44SJohn Forte 				}
2447fcf3ce44SJohn Forte 
2448*4c3888b8SHans Rosenfeld 				if (risc_code_size == 0) {
2449*4c3888b8SHans Rosenfeld 					bp = (uint32_t *)
2450*4c3888b8SHans Rosenfeld 					    ha->req_q[0]->req_ring.bp;
2451*4c3888b8SHans Rosenfeld 					risc_address = bp[2];
2452*4c3888b8SHans Rosenfeld 					risc_code_size = bp[3];
2453*4c3888b8SHans Rosenfeld 					ha->risc_fw[seg_cnt].addr =
2454*4c3888b8SHans Rosenfeld 					    risc_address;
2455*4c3888b8SHans Rosenfeld 				}
2456fcf3ce44SJohn Forte 
2457*4c3888b8SHans Rosenfeld 				if (risc_code_size < xfer_size) {
2458*4c3888b8SHans Rosenfeld 					faddr -= xfer_size - risc_code_size;
2459*4c3888b8SHans Rosenfeld 					xfer_size = risc_code_size;
2460*4c3888b8SHans Rosenfeld 				}
2461fcf3ce44SJohn Forte 
2462*4c3888b8SHans Rosenfeld 				(void) ddi_dma_sync(
2463*4c3888b8SHans Rosenfeld 				    ha->req_q[0]->req_ring.dma_handle,
2464*4c3888b8SHans Rosenfeld 				    0, xfer_size << 2, DDI_DMA_SYNC_FORDEV);
2465fcf3ce44SJohn Forte 
2466*4c3888b8SHans Rosenfeld 				rval = ql_wrt_risc_ram(ha, risc_address,
2467*4c3888b8SHans Rosenfeld 				    ha->req_q[0]->req_ring.cookie.dmac_laddress,
2468*4c3888b8SHans Rosenfeld 				    xfer_size);
2469*4c3888b8SHans Rosenfeld 				if (rval != QL_SUCCESS) {
2470*4c3888b8SHans Rosenfeld 					EL(ha, "ql_wrt_risc_ram failed=%xh\n",
2471*4c3888b8SHans Rosenfeld 					    rval);
2472*4c3888b8SHans Rosenfeld 					break;
2473*4c3888b8SHans Rosenfeld 				}
2474fcf3ce44SJohn Forte 
2475*4c3888b8SHans Rosenfeld 				risc_address += xfer_size;
2476*4c3888b8SHans Rosenfeld 				risc_code_size -= xfer_size;
2477*4c3888b8SHans Rosenfeld 			} while (risc_code_size);
2478fcf3ce44SJohn Forte 
2479fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2480fcf3ce44SJohn Forte 				break;
2481fcf3ce44SJohn Forte 			}
2482fcf3ce44SJohn Forte 		}
2483fcf3ce44SJohn Forte 	}
2484fcf3ce44SJohn Forte 
2485fcf3ce44SJohn Forte 	/* Start firmware. */
2486fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2487fcf3ce44SJohn Forte 		rval = ql_start_firmware(ha);
2488fcf3ce44SJohn Forte 	}
2489fcf3ce44SJohn Forte 
2490fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2491fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2492fcf3ce44SJohn Forte 	} else {
2493fcf3ce44SJohn Forte 		/*EMPTY*/
2494*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
2495fcf3ce44SJohn Forte 	}
2496fcf3ce44SJohn Forte 	return (rval);
2497fcf3ce44SJohn Forte }
2498fcf3ce44SJohn Forte 
2499fcf3ce44SJohn Forte /*
2500fcf3ce44SJohn Forte  * ql_start_firmware
2501fcf3ce44SJohn Forte  *	Starts RISC code.
2502fcf3ce44SJohn Forte  *
2503fcf3ce44SJohn Forte  * Input:
2504fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2505fcf3ce44SJohn Forte  *
2506fcf3ce44SJohn Forte  * Returns:
2507fcf3ce44SJohn Forte  *	ql local function return status code.
2508fcf3ce44SJohn Forte  *
2509fcf3ce44SJohn Forte  * Context:
2510fcf3ce44SJohn Forte  *	Kernel context.
2511fcf3ce44SJohn Forte  */
2512fcf3ce44SJohn Forte int
ql_start_firmware(ql_adapter_state_t * vha)2513fcf3ce44SJohn Forte ql_start_firmware(ql_adapter_state_t *vha)
2514fcf3ce44SJohn Forte {
25155dfd244aSDaniel Beauregard 	int			rval, rval2;
25165dfd244aSDaniel Beauregard 	uint32_t		data;
2517*4c3888b8SHans Rosenfeld 	ql_mbx_data_t		mr = {0};
2518fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
2519*4c3888b8SHans Rosenfeld 	ql_init_24xx_cb_t	*icb =
2520*4c3888b8SHans Rosenfeld 	    (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24;
2521fcf3ce44SJohn Forte 
2522*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
2523fcf3ce44SJohn Forte 
2524*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_82XX)) {
2525eb82ff87SDaniel Beauregard 		/* Save firmware version. */
2526eb82ff87SDaniel Beauregard 		rval = ql_get_fw_version(ha, &mr, MAILBOX_TOV);
2527eb82ff87SDaniel Beauregard 		ha->fw_major_version = mr.mb[1];
2528eb82ff87SDaniel Beauregard 		ha->fw_minor_version = mr.mb[2];
2529eb82ff87SDaniel Beauregard 		ha->fw_subminor_version = mr.mb[3];
2530f885d00fSDaniel Beauregard 		ha->fw_attributes = mr.mb[6];
2531eb82ff87SDaniel Beauregard 	} else if ((rval = ql_verify_checksum(ha)) == QL_SUCCESS) {
2532eb82ff87SDaniel Beauregard 		/* Verify checksum of loaded RISC code. */
2533fcf3ce44SJohn Forte 		/* Start firmware execution. */
2534fcf3ce44SJohn Forte 		(void) ql_execute_fw(ha);
2535fcf3ce44SJohn Forte 
2536fcf3ce44SJohn Forte 		/* Save firmware version. */
2537eb82ff87SDaniel Beauregard 		(void) ql_get_fw_version(ha, &mr, MAILBOX_TOV);
2538fcf3ce44SJohn Forte 		ha->fw_major_version = mr.mb[1];
2539fcf3ce44SJohn Forte 		ha->fw_minor_version = mr.mb[2];
2540fcf3ce44SJohn Forte 		ha->fw_subminor_version = mr.mb[3];
2541*4c3888b8SHans Rosenfeld 		ha->fw_ext_memory_end = SHORT_TO_LONG(mr.mb[4], mr.mb[5]);
2542*4c3888b8SHans Rosenfeld 		ha->fw_ext_memory_size = ((ha->fw_ext_memory_end -
2543fcf3ce44SJohn Forte 		    0x100000) + 1) * 4;
2544*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_278083)) {
2545*4c3888b8SHans Rosenfeld 			ha->fw_attributes = SHORT_TO_LONG(mr.mb[6], mr.mb[15]);
2546*4c3888b8SHans Rosenfeld 			ha->phy_fw_major_version = LSB(mr.mb[13]);
2547*4c3888b8SHans Rosenfeld 			ha->phy_fw_minor_version = MSB(mr.mb[14]);
2548*4c3888b8SHans Rosenfeld 			ha->phy_fw_subminor_version = LSB(mr.mb[14]);
2549*4c3888b8SHans Rosenfeld 			ha->fw_ext_attributes = SHORT_TO_LONG(mr.mb[16],
2550*4c3888b8SHans Rosenfeld 			    mr.mb[17]);
2551*4c3888b8SHans Rosenfeld 		} else {
2552*4c3888b8SHans Rosenfeld 			ha->fw_attributes = mr.mb[6];
25535dfd244aSDaniel Beauregard 			ha->phy_fw_major_version = LSB(mr.mb[8]);
25545dfd244aSDaniel Beauregard 			ha->phy_fw_minor_version = MSB(mr.mb[9]);
25555dfd244aSDaniel Beauregard 			ha->phy_fw_subminor_version = LSB(mr.mb[9]);
2556*4c3888b8SHans Rosenfeld 			ha->mpi_capability_list =
2557*4c3888b8SHans Rosenfeld 			    SHORT_TO_LONG(mr.mb[13], mr.mb[12]);
2558*4c3888b8SHans Rosenfeld 		}
2559*4c3888b8SHans Rosenfeld 		ha->mpi_fw_major_version = LSB(mr.mb[10]);
2560*4c3888b8SHans Rosenfeld 		ha->mpi_fw_minor_version = MSB(mr.mb[11]);
2561*4c3888b8SHans Rosenfeld 		ha->mpi_fw_subminor_version = LSB(mr.mb[11]);
2562*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_27XX)) {
2563*4c3888b8SHans Rosenfeld 			ha->fw_shared_ram_start =
2564*4c3888b8SHans Rosenfeld 			    SHORT_TO_LONG(mr.mb[18], mr.mb[19]);
2565*4c3888b8SHans Rosenfeld 			ha->fw_shared_ram_end =
2566*4c3888b8SHans Rosenfeld 			    SHORT_TO_LONG(mr.mb[20], mr.mb[21]);
2567*4c3888b8SHans Rosenfeld 			ha->fw_ddr_ram_start =
2568*4c3888b8SHans Rosenfeld 			    SHORT_TO_LONG(mr.mb[22], mr.mb[23]);
2569*4c3888b8SHans Rosenfeld 			ha->fw_ddr_ram_end =
2570*4c3888b8SHans Rosenfeld 			    SHORT_TO_LONG(mr.mb[24], mr.mb[25]);
2571*4c3888b8SHans Rosenfeld 		}
2572*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_FLASH_ACC_SUPPORT)) {
25735dfd244aSDaniel Beauregard 			if ((rval2 = ql_flash_access(ha, FAC_GET_SECTOR_SIZE,
25745dfd244aSDaniel Beauregard 			    0, 0, &data)) == QL_SUCCESS) {
25755dfd244aSDaniel Beauregard 				ha->xioctl->fdesc.block_size = data << 2;
2576*4c3888b8SHans Rosenfeld 				QL_PRINT_10(ha, "fdesc.block_size="
2577*4c3888b8SHans Rosenfeld 				    "%xh\n",
25785dfd244aSDaniel Beauregard 				    ha->xioctl->fdesc.block_size);
25795dfd244aSDaniel Beauregard 			} else {
25805dfd244aSDaniel Beauregard 				EL(ha, "flash_access status=%xh\n", rval2);
25815dfd244aSDaniel Beauregard 			}
25825dfd244aSDaniel Beauregard 		}
25835dfd244aSDaniel Beauregard 
2584fcf3ce44SJohn Forte 		/* Set Serdes Transmit Parameters. */
2585*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_24XX) && ha->serdes_param[0] & BIT_0) {
2586fcf3ce44SJohn Forte 			mr.mb[1] = ha->serdes_param[0];
2587fcf3ce44SJohn Forte 			mr.mb[2] = ha->serdes_param[1];
2588fcf3ce44SJohn Forte 			mr.mb[3] = ha->serdes_param[2];
2589fcf3ce44SJohn Forte 			mr.mb[4] = ha->serdes_param[3];
2590fcf3ce44SJohn Forte 			(void) ql_serdes_param(ha, &mr);
2591fcf3ce44SJohn Forte 		}
2592fcf3ce44SJohn Forte 	}
2593f885d00fSDaniel Beauregard 	/* ETS workaround */
2594f885d00fSDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_81XX) && ql_enable_ets) {
2595f885d00fSDaniel Beauregard 		if (ql_get_firmware_option(ha, &mr) == QL_SUCCESS) {
2596f885d00fSDaniel Beauregard 			mr.mb[2] = (uint16_t)
2597f885d00fSDaniel Beauregard 			    (mr.mb[2] | FO2_FCOE_512_MAX_MEM_WR_BURST);
2598f885d00fSDaniel Beauregard 			(void) ql_set_firmware_option(ha, &mr);
2599f885d00fSDaniel Beauregard 		}
2600f885d00fSDaniel Beauregard 	}
2601*4c3888b8SHans Rosenfeld 
2602*4c3888b8SHans Rosenfeld 	if (ha->flags & MULTI_QUEUE) {
2603*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "MULTI_QUEUE\n");
2604*4c3888b8SHans Rosenfeld 		icb->msi_x_vector[0] = LSB(ha->rsp_queues[0]->msi_x_vector);
2605*4c3888b8SHans Rosenfeld 		icb->msi_x_vector[1] = MSB(ha->rsp_queues[0]->msi_x_vector);
2606*4c3888b8SHans Rosenfeld 		if (ha->iflags & IFLG_INTR_MSIX &&
2607*4c3888b8SHans Rosenfeld 		    CFG_IST(ha, CFG_NO_INTR_HSHAKE_SUP)) {
2608*4c3888b8SHans Rosenfeld 			QL_PRINT_10(ha, "NO_INTR_HANDSHAKE\n");
2609*4c3888b8SHans Rosenfeld 			ADAPTER_STATE_LOCK(ha);
2610*4c3888b8SHans Rosenfeld 			ha->flags |= NO_INTR_HANDSHAKE;
2611*4c3888b8SHans Rosenfeld 			ADAPTER_STATE_UNLOCK(ha);
2612*4c3888b8SHans Rosenfeld 			icb->firmware_options_2[2] = (uint8_t)
2613*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[2] & ~(BIT_6 | BIT_5));
2614*4c3888b8SHans Rosenfeld 			icb->firmware_options_2[2] = (uint8_t)
2615*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[2] | BIT_7);
2616*4c3888b8SHans Rosenfeld 		} else {
2617*4c3888b8SHans Rosenfeld 			icb->firmware_options_2[2] = (uint8_t)
2618*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[2] & ~BIT_5);
2619*4c3888b8SHans Rosenfeld 			icb->firmware_options_2[2] = (uint8_t)
2620*4c3888b8SHans Rosenfeld 			    (icb->firmware_options_2[2] | BIT_7 | BIT_6);
2621*4c3888b8SHans Rosenfeld 		}
2622*4c3888b8SHans Rosenfeld 	} else {
2623*4c3888b8SHans Rosenfeld 		icb->firmware_options_2[2] = (uint8_t)
2624*4c3888b8SHans Rosenfeld 		    (icb->firmware_options_2[2] & ~(BIT_7 | BIT_5));
2625*4c3888b8SHans Rosenfeld 		icb->firmware_options_2[2] = (uint8_t)
2626*4c3888b8SHans Rosenfeld 		    (icb->firmware_options_2[2] | BIT_6);
2627*4c3888b8SHans Rosenfeld 	}
2628*4c3888b8SHans Rosenfeld 	icb->firmware_options_2[3] = (uint8_t)
2629*4c3888b8SHans Rosenfeld 	    (icb->firmware_options_2[3] & ~(BIT_1 | BIT_0));
2630*4c3888b8SHans Rosenfeld 
2631*4c3888b8SHans Rosenfeld 	/* Set fw execution throttle. */
2632*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_22XX) ||
2633*4c3888b8SHans Rosenfeld 	    ql_get_resource_cnts(ha, &mr) != QL_SUCCESS) {
2634*4c3888b8SHans Rosenfeld 		icb->execution_throttle[0] = 0xff;
2635*4c3888b8SHans Rosenfeld 		icb->execution_throttle[1] = 0xff;
2636*4c3888b8SHans Rosenfeld 	} else {
2637*4c3888b8SHans Rosenfeld 		icb->execution_throttle[0] = LSB(mr.mb[6]);
2638*4c3888b8SHans Rosenfeld 		icb->execution_throttle[1] = MSB(mr.mb[6]);
2639*4c3888b8SHans Rosenfeld 	}
2640*4c3888b8SHans Rosenfeld 	EL(ha, "icb->execution_throttle %d\n",
2641*4c3888b8SHans Rosenfeld 	    CHAR_TO_SHORT(icb->execution_throttle[0],
2642*4c3888b8SHans Rosenfeld 	    icb->execution_throttle[1]));
2643*4c3888b8SHans Rosenfeld 
2644fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2645fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~FIRMWARE_LOADED;
2646fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2647fcf3ce44SJohn Forte 	} else {
2648fcf3ce44SJohn Forte 		ha->task_daemon_flags |= FIRMWARE_LOADED;
2649*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
2650fcf3ce44SJohn Forte 	}
2651fcf3ce44SJohn Forte 	return (rval);
2652fcf3ce44SJohn Forte }
2653fcf3ce44SJohn Forte 
2654fcf3ce44SJohn Forte /*
2655fcf3ce44SJohn Forte  * ql_set_cache_line
2656fcf3ce44SJohn Forte  *	Sets PCI cache line parameter.
2657fcf3ce44SJohn Forte  *
2658fcf3ce44SJohn Forte  * Input:
2659fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2660fcf3ce44SJohn Forte  *
2661fcf3ce44SJohn Forte  * Returns:
2662fcf3ce44SJohn Forte  *	ql local function return status code.
2663fcf3ce44SJohn Forte  *
2664fcf3ce44SJohn Forte  * Context:
2665fcf3ce44SJohn Forte  *	Kernel context.
2666fcf3ce44SJohn Forte  */
2667fcf3ce44SJohn Forte int
ql_set_cache_line(ql_adapter_state_t * ha)2668fcf3ce44SJohn Forte ql_set_cache_line(ql_adapter_state_t *ha)
2669fcf3ce44SJohn Forte {
2670*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
2671fcf3ce44SJohn Forte 
2672fcf3ce44SJohn Forte 	/* Set the cache line. */
2673fcf3ce44SJohn Forte 	if (CFG_IST(ha->pha, CFG_SET_CACHE_LINE_SIZE_1)) {
2674fcf3ce44SJohn Forte 		/* Set cache line register. */
2675fcf3ce44SJohn Forte 		ql_pci_config_put8(ha->pha, PCI_CONF_CACHE_LINESZ, 1);
2676fcf3ce44SJohn Forte 	}
2677fcf3ce44SJohn Forte 
2678*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
2679fcf3ce44SJohn Forte 
2680fcf3ce44SJohn Forte 	return (QL_SUCCESS);
2681fcf3ce44SJohn Forte }
2682fcf3ce44SJohn Forte 
2683fcf3ce44SJohn Forte /*
2684fcf3ce44SJohn Forte  * ql_init_rings
2685fcf3ce44SJohn Forte  *	Initializes firmware and ring pointers.
2686fcf3ce44SJohn Forte  *
2687fcf3ce44SJohn Forte  *	Beginning of response ring has initialization control block
2688fcf3ce44SJohn Forte  *	already built by nvram config routine.
2689fcf3ce44SJohn Forte  *
2690fcf3ce44SJohn Forte  * Input:
2691*4c3888b8SHans Rosenfeld  *	ha =			adapter state pointer.
2692*4c3888b8SHans Rosenfeld  *	ha->req_q =		request rings
2693*4c3888b8SHans Rosenfeld  *	ha->rsp_queues =	response rings
2694*4c3888b8SHans Rosenfeld  *	ha->init_ctrl_blk =	initialization control block
2695fcf3ce44SJohn Forte  *
2696fcf3ce44SJohn Forte  * Returns:
2697fcf3ce44SJohn Forte  *	ql local function return status code.
2698fcf3ce44SJohn Forte  *
2699fcf3ce44SJohn Forte  * Context:
2700fcf3ce44SJohn Forte  *	Kernel context.
2701fcf3ce44SJohn Forte  */
2702fcf3ce44SJohn Forte int
ql_init_rings(ql_adapter_state_t * vha2)2703fcf3ce44SJohn Forte ql_init_rings(ql_adapter_state_t *vha2)
2704fcf3ce44SJohn Forte {
2705fcf3ce44SJohn Forte 	int			rval, rval2;
2706fcf3ce44SJohn Forte 	uint16_t		index;
2707fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
2708fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha2->pha;
2709fcf3ce44SJohn Forte 
2710*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
2711fcf3ce44SJohn Forte 
2712fcf3ce44SJohn Forte 	/* Clear outstanding commands array. */
2713*4c3888b8SHans Rosenfeld 	for (index = 0; index < ha->osc_max_cnt; index++) {
2714fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
2715fcf3ce44SJohn Forte 	}
2716fcf3ce44SJohn Forte 	ha->osc_index = 1;
2717fcf3ce44SJohn Forte 
2718fcf3ce44SJohn Forte 	ha->pending_cmds.first = NULL;
2719fcf3ce44SJohn Forte 	ha->pending_cmds.last = NULL;
2720fcf3ce44SJohn Forte 
2721fcf3ce44SJohn Forte 	/* Initialize firmware. */
2722*4c3888b8SHans Rosenfeld 	ha->req_q[0]->req_ring_ptr = ha->req_q[0]->req_ring.bp;
2723*4c3888b8SHans Rosenfeld 	ha->req_q[0]->req_ring_index = 0;
2724*4c3888b8SHans Rosenfeld 	ha->req_q[0]->req_q_cnt = REQUEST_ENTRY_CNT - 1;
2725*4c3888b8SHans Rosenfeld 	ha->rsp_queues[0]->rsp_ring_ptr = ha->rsp_queues[0]->rsp_ring.bp;
2726*4c3888b8SHans Rosenfeld 	ha->rsp_queues[0]->rsp_ring_index = 0;
2727fcf3ce44SJohn Forte 
2728fcf3ce44SJohn Forte 	if (ha->flags & VP_ENABLED) {
2729fcf3ce44SJohn Forte 		ql_adapter_state_t	*vha;
2730fcf3ce44SJohn Forte 		ql_init_24xx_cb_t	*icb = &ha->init_ctrl_blk.cb24;
2731fcf3ce44SJohn Forte 
2732fcf3ce44SJohn Forte 		bzero(icb->vp_count,
2733fcf3ce44SJohn Forte 		    ((uintptr_t)icb + sizeof (ql_init_24xx_cb_t)) -
2734fcf3ce44SJohn Forte 		    (uintptr_t)icb->vp_count);
2735*4c3888b8SHans Rosenfeld 		icb->vp_count[0] = ha->max_vports - 1;
2736fcf3ce44SJohn Forte 
2737fcf3ce44SJohn Forte 		/* Allow connection option 2. */
2738fcf3ce44SJohn Forte 		icb->global_vp_option[0] = BIT_1;
2739fcf3ce44SJohn Forte 
2740*4c3888b8SHans Rosenfeld 		/* Setup default options for all ports. */
2741*4c3888b8SHans Rosenfeld 		for (index = 0; index < ha->max_vports; index++) {
2742*4c3888b8SHans Rosenfeld 			icb->vpc[index].options = VPO_TARGET_MODE_DISABLED |
2743*4c3888b8SHans Rosenfeld 			    VPO_INITIATOR_MODE_ENABLED;
2744*4c3888b8SHans Rosenfeld 		}
2745*4c3888b8SHans Rosenfeld 		/* Setup enabled ports. */
2746*4c3888b8SHans Rosenfeld 		for (vha = ha->vp_next; vha != NULL; vha = vha->vp_next) {
2747*4c3888b8SHans Rosenfeld 			if (vha->vp_index == 0 ||
2748*4c3888b8SHans Rosenfeld 			    vha->vp_index >= ha->max_vports) {
2749*4c3888b8SHans Rosenfeld 				continue;
2750*4c3888b8SHans Rosenfeld 			}
2751fcf3ce44SJohn Forte 
2752fcf3ce44SJohn Forte 			index = (uint8_t)(vha->vp_index - 1);
2753fcf3ce44SJohn Forte 			bcopy(vha->loginparams.node_ww_name.raw_wwn,
2754fcf3ce44SJohn Forte 			    icb->vpc[index].node_name, 8);
2755fcf3ce44SJohn Forte 			bcopy(vha->loginparams.nport_ww_name.raw_wwn,
2756fcf3ce44SJohn Forte 			    icb->vpc[index].port_name, 8);
2757fcf3ce44SJohn Forte 
2758fcf3ce44SJohn Forte 			if (vha->flags & VP_ENABLED) {
2759fcf3ce44SJohn Forte 				icb->vpc[index].options = (uint8_t)
2760fcf3ce44SJohn Forte 				    (icb->vpc[index].options | VPO_ENABLED);
2761fcf3ce44SJohn Forte 			}
2762fcf3ce44SJohn Forte 		}
2763fcf3ce44SJohn Forte 	}
2764fcf3ce44SJohn Forte 
2765eb82ff87SDaniel Beauregard 	for (index = 0; index < 2; index++) {
2766eb82ff87SDaniel Beauregard 		rval = ql_init_firmware(ha);
2767eb82ff87SDaniel Beauregard 		if (rval == QL_COMMAND_ERROR) {
2768eb82ff87SDaniel Beauregard 			EL(ha, "stopping firmware\n");
2769eb82ff87SDaniel Beauregard 			(void) ql_stop_firmware(ha);
2770eb82ff87SDaniel Beauregard 		} else {
2771eb82ff87SDaniel Beauregard 			break;
2772eb82ff87SDaniel Beauregard 		}
2773eb82ff87SDaniel Beauregard 	}
2774fcf3ce44SJohn Forte 
2775*4c3888b8SHans Rosenfeld 	if (rval == QL_SUCCESS && CFG_IST(ha, CFG_ISP_FW_TYPE_1)) {
2776fcf3ce44SJohn Forte 		/* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */
2777fcf3ce44SJohn Forte 		rval = ql_get_firmware_option(ha, &mr);
2778fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2779fcf3ce44SJohn Forte 			mr.mb[1] = (uint16_t)(mr.mb[1] | BIT_9);
2780fcf3ce44SJohn Forte 			mr.mb[2] = 0;
2781fcf3ce44SJohn Forte 			mr.mb[3] = BIT_10;
2782fcf3ce44SJohn Forte 			rval = ql_set_firmware_option(ha, &mr);
2783fcf3ce44SJohn Forte 		}
2784fcf3ce44SJohn Forte 	}
2785fcf3ce44SJohn Forte 
2786fcf3ce44SJohn Forte 	if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWFCETRACE))) {
278716dd44c2SDaniel Beauregard 		/* Firmware Fibre Channel Event Trace Buffer */
278816dd44c2SDaniel Beauregard 		if ((rval2 = ql_get_dma_mem(ha, &ha->fwfcetracebuf, FWFCESIZE,
278916dd44c2SDaniel Beauregard 		    LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
2790fcf3ce44SJohn Forte 			EL(ha, "fcetrace buffer alloc failed: %xh\n", rval2);
2791fcf3ce44SJohn Forte 		} else {
2792fcf3ce44SJohn Forte 			if ((rval2 = ql_fw_etrace(ha, &ha->fwfcetracebuf,
2793*4c3888b8SHans Rosenfeld 			    FTO_FCE_TRACE_ENABLE, NULL)) != QL_SUCCESS) {
2794fcf3ce44SJohn Forte 				EL(ha, "fcetrace enable failed: %xh\n", rval2);
2795fcf3ce44SJohn Forte 				ql_free_phys(ha, &ha->fwfcetracebuf);
2796fcf3ce44SJohn Forte 			}
2797fcf3ce44SJohn Forte 		}
2798fcf3ce44SJohn Forte 	}
2799fcf3ce44SJohn Forte 
2800fcf3ce44SJohn Forte 	if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE))) {
280116dd44c2SDaniel Beauregard 		/* Firmware Extended Trace Buffer */
280216dd44c2SDaniel Beauregard 		if ((rval2 = ql_get_dma_mem(ha, &ha->fwexttracebuf, FWEXTSIZE,
280316dd44c2SDaniel Beauregard 		    LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
2804fcf3ce44SJohn Forte 			EL(ha, "exttrace buffer alloc failed: %xh\n", rval2);
2805fcf3ce44SJohn Forte 		} else {
2806fcf3ce44SJohn Forte 			if ((rval2 = ql_fw_etrace(ha, &ha->fwexttracebuf,
2807*4c3888b8SHans Rosenfeld 			    FTO_EXT_TRACE_ENABLE, NULL)) != QL_SUCCESS) {
2808fcf3ce44SJohn Forte 				EL(ha, "exttrace enable failed: %xh\n", rval2);
2809fcf3ce44SJohn Forte 				ql_free_phys(ha, &ha->fwexttracebuf);
2810fcf3ce44SJohn Forte 			}
2811fcf3ce44SJohn Forte 		}
2812fcf3ce44SJohn Forte 	}
2813fcf3ce44SJohn Forte 
2814fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && CFG_IST(ha, CFG_CTRL_MENLO)) {
2815fcf3ce44SJohn Forte 		ql_mbx_iocb_t	*pkt;
2816fcf3ce44SJohn Forte 		clock_t		timer;
2817fcf3ce44SJohn Forte 
2818fcf3ce44SJohn Forte 		/* Wait for firmware login of menlo. */
2819fcf3ce44SJohn Forte 		for (timer = 3000; timer; timer--) {
2820fcf3ce44SJohn Forte 			if (ha->flags & MENLO_LOGIN_OPERATIONAL) {
2821fcf3ce44SJohn Forte 				break;
2822fcf3ce44SJohn Forte 			}
2823fcf3ce44SJohn Forte 
2824fcf3ce44SJohn Forte 			if (!(ha->flags & INTERRUPTS_ENABLED) ||
2825fcf3ce44SJohn Forte 			    ddi_in_panic()) {
2826eb82ff87SDaniel Beauregard 				if (INTERRUPT_PENDING(ha)) {
2827fcf3ce44SJohn Forte 					(void) ql_isr((caddr_t)ha);
2828fcf3ce44SJohn Forte 					INTR_LOCK(ha);
2829fcf3ce44SJohn Forte 					ha->intr_claimed = B_TRUE;
2830fcf3ce44SJohn Forte 					INTR_UNLOCK(ha);
2831fcf3ce44SJohn Forte 				}
2832fcf3ce44SJohn Forte 			}
2833fcf3ce44SJohn Forte 
2834fcf3ce44SJohn Forte 			/* Delay for 1 tick (10 milliseconds). */
2835fcf3ce44SJohn Forte 			ql_delay(ha, 10000);
2836fcf3ce44SJohn Forte 		}
2837fcf3ce44SJohn Forte 
2838fcf3ce44SJohn Forte 		if (timer == 0) {
2839fcf3ce44SJohn Forte 			rval = QL_FUNCTION_TIMEOUT;
2840fcf3ce44SJohn Forte 		} else {
2841fcf3ce44SJohn Forte 			pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
2842fcf3ce44SJohn Forte 			if (pkt == NULL) {
2843fcf3ce44SJohn Forte 				EL(ha, "failed, kmem_zalloc\n");
2844fcf3ce44SJohn Forte 				rval = QL_MEMORY_ALLOC_FAILED;
2845fcf3ce44SJohn Forte 			} else {
2846fcf3ce44SJohn Forte 				pkt->mvfy.entry_type = VERIFY_MENLO_TYPE;
2847fcf3ce44SJohn Forte 				pkt->mvfy.entry_count = 1;
2848fcf3ce44SJohn Forte 				pkt->mvfy.options_status =
2849fcf3ce44SJohn Forte 				    LE_16(VMF_DO_NOT_UPDATE_FW);
2850fcf3ce44SJohn Forte 
2851fcf3ce44SJohn Forte 				rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
2852fcf3ce44SJohn Forte 				    sizeof (ql_mbx_iocb_t));
2853fcf3ce44SJohn Forte 				LITTLE_ENDIAN_16(&pkt->mvfy.options_status);
2854fcf3ce44SJohn Forte 				LITTLE_ENDIAN_16(&pkt->mvfy.failure_code);
2855fcf3ce44SJohn Forte 
2856fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS ||
2857fcf3ce44SJohn Forte 				    (pkt->mvfy.entry_status & 0x3c) != 0 ||
2858fcf3ce44SJohn Forte 				    pkt->mvfy.options_status != CS_COMPLETE) {
2859fcf3ce44SJohn Forte 					EL(ha, "failed, status=%xh, es=%xh, "
2860fcf3ce44SJohn Forte 					    "cs=%xh, fc=%xh\n", rval,
2861fcf3ce44SJohn Forte 					    pkt->mvfy.entry_status & 0x3c,
2862fcf3ce44SJohn Forte 					    pkt->mvfy.options_status,
2863fcf3ce44SJohn Forte 					    pkt->mvfy.failure_code);
2864fcf3ce44SJohn Forte 					if (rval == QL_SUCCESS) {
2865fcf3ce44SJohn Forte 						rval = QL_FUNCTION_FAILED;
2866fcf3ce44SJohn Forte 					}
2867fcf3ce44SJohn Forte 				}
2868fcf3ce44SJohn Forte 
2869fcf3ce44SJohn Forte 				kmem_free(pkt, sizeof (ql_mbx_iocb_t));
2870fcf3ce44SJohn Forte 			}
2871fcf3ce44SJohn Forte 		}
2872fcf3ce44SJohn Forte 	}
2873fcf3ce44SJohn Forte 
2874fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2875fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2876fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~FIRMWARE_UP;
2877fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2878fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2879fcf3ce44SJohn Forte 	} else {
2880fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2881fcf3ce44SJohn Forte 		ha->task_daemon_flags |= FIRMWARE_UP;
2882fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2883*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "done\n");
2884fcf3ce44SJohn Forte 	}
2885fcf3ce44SJohn Forte 	return (rval);
2886fcf3ce44SJohn Forte }
2887fcf3ce44SJohn Forte 
2888fcf3ce44SJohn Forte /*
2889fcf3ce44SJohn Forte  * ql_fw_ready
2890fcf3ce44SJohn Forte  *	Waits for firmware ready. If firmware becomes ready
2891fcf3ce44SJohn Forte  *	device queues and RISC code are synchronized.
2892fcf3ce44SJohn Forte  *
2893fcf3ce44SJohn Forte  * Input:
2894fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2895fcf3ce44SJohn Forte  *	secs = max wait time, in seconds (0-255).
2896fcf3ce44SJohn Forte  *
2897fcf3ce44SJohn Forte  * Returns:
2898fcf3ce44SJohn Forte  *	ql local function return status code.
2899fcf3ce44SJohn Forte  *
2900fcf3ce44SJohn Forte  * Context:
2901fcf3ce44SJohn Forte  *	Kernel context.
2902fcf3ce44SJohn Forte  */
2903fcf3ce44SJohn Forte int
ql_fw_ready(ql_adapter_state_t * ha,uint8_t secs)2904fcf3ce44SJohn Forte ql_fw_ready(ql_adapter_state_t *ha, uint8_t secs)
2905fcf3ce44SJohn Forte {
2906fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
2907*4c3888b8SHans Rosenfeld 	clock_t		timer, login_wait, wait;
2908fcf3ce44SJohn Forte 	clock_t		dly = 250000;
2909fcf3ce44SJohn Forte 	clock_t		sec_delay = MICROSEC / dly;
2910fcf3ce44SJohn Forte 	int		rval = QL_FUNCTION_FAILED;
2911*4c3888b8SHans Rosenfeld 	uint16_t	state[6] = {0};
2912fcf3ce44SJohn Forte 
2913*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
2914fcf3ce44SJohn Forte 
2915*4c3888b8SHans Rosenfeld 	login_wait = ha->r_a_tov * 2 * sec_delay;
2916*4c3888b8SHans Rosenfeld 	timer = wait = secs * sec_delay;
2917*4c3888b8SHans Rosenfeld 	state[0] = 0xffff;
2918fcf3ce44SJohn Forte 
2919fcf3ce44SJohn Forte 	/* Wait for ISP to finish LIP */
2920*4c3888b8SHans Rosenfeld 	while (login_wait != 0 && wait != 0 &&
2921*4c3888b8SHans Rosenfeld 	    !(ha->task_daemon_flags & ISP_ABORT_NEEDED) &&
2922*4c3888b8SHans Rosenfeld 	    !(ha->flags & MPI_RESET_NEEDED)) {
2923fcf3ce44SJohn Forte 
2924fcf3ce44SJohn Forte 		rval = ql_get_firmware_state(ha, &mr);
2925fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2926*4c3888b8SHans Rosenfeld 			if (mr.mb[1] != FSTATE_READY) {
2927*4c3888b8SHans Rosenfeld 				if (mr.mb[1] == FSTATE_LOSS_SYNC &&
2928*4c3888b8SHans Rosenfeld 				    mr.mb[4] == FSTATE_MPI_NIC_ERROR &&
2929*4c3888b8SHans Rosenfeld 				    CFG_IST(ha, CFG_FCOE_SUPPORT)) {
2930*4c3888b8SHans Rosenfeld 					EL(ha, "mpi_nic_error, "
2931*4c3888b8SHans Rosenfeld 					    "isp_abort_needed\n");
2932*4c3888b8SHans Rosenfeld 					ADAPTER_STATE_LOCK(ha);
2933*4c3888b8SHans Rosenfeld 					ha->flags |= MPI_RESET_NEEDED;
2934*4c3888b8SHans Rosenfeld 					ADAPTER_STATE_UNLOCK(ha);
2935*4c3888b8SHans Rosenfeld 					if (!(ha->task_daemon_flags &
2936*4c3888b8SHans Rosenfeld 					    ABORT_ISP_ACTIVE)) {
2937*4c3888b8SHans Rosenfeld 						TASK_DAEMON_LOCK(ha);
2938*4c3888b8SHans Rosenfeld 						ha->task_daemon_flags |=
2939*4c3888b8SHans Rosenfeld 						    ISP_ABORT_NEEDED;
2940*4c3888b8SHans Rosenfeld 						TASK_DAEMON_UNLOCK(ha);
2941*4c3888b8SHans Rosenfeld 					}
2942*4c3888b8SHans Rosenfeld 				}
2943fcf3ce44SJohn Forte 				if (mr.mb[1] != FSTATE_WAIT_LOGIN) {
2944*4c3888b8SHans Rosenfeld 					timer = --wait;
2945*4c3888b8SHans Rosenfeld 				} else {
2946*4c3888b8SHans Rosenfeld 					timer = --login_wait;
2947fcf3ce44SJohn Forte 				}
2948fcf3ce44SJohn Forte 				rval = QL_FUNCTION_FAILED;
2949fcf3ce44SJohn Forte 			} else {
2950fcf3ce44SJohn Forte 				/* Firmware is ready. Get 2 * R_A_TOV. */
2951fcf3ce44SJohn Forte 				rval = ql_get_timeout_parameters(ha,
2952fcf3ce44SJohn Forte 				    &ha->r_a_tov);
2953fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS) {
2954fcf3ce44SJohn Forte 					EL(ha, "failed, get_timeout_param"
2955fcf3ce44SJohn Forte 					    "=%xh\n", rval);
2956fcf3ce44SJohn Forte 				}
2957fcf3ce44SJohn Forte 
2958fcf3ce44SJohn Forte 				/* Configure loop. */
2959fcf3ce44SJohn Forte 				rval = ql_configure_loop(ha);
2960fcf3ce44SJohn Forte 				(void) ql_marker(ha, 0, 0, MK_SYNC_ALL);
2961fcf3ce44SJohn Forte 
2962fcf3ce44SJohn Forte 				if (ha->task_daemon_flags &
2963fcf3ce44SJohn Forte 				    LOOP_RESYNC_NEEDED) {
2964fcf3ce44SJohn Forte 					wait--;
2965fcf3ce44SJohn Forte 					EL(ha, "loop trans; tdf=%xh\n",
2966fcf3ce44SJohn Forte 					    ha->task_daemon_flags);
2967fcf3ce44SJohn Forte 				} else {
2968fcf3ce44SJohn Forte 					break;
2969fcf3ce44SJohn Forte 				}
2970fcf3ce44SJohn Forte 			}
2971fcf3ce44SJohn Forte 		} else {
2972*4c3888b8SHans Rosenfeld 			break;
2973fcf3ce44SJohn Forte 		}
2974fcf3ce44SJohn Forte 
2975*4c3888b8SHans Rosenfeld 		if (state[0] != mr.mb[1] || state[1] != mr.mb[2] ||
2976*4c3888b8SHans Rosenfeld 		    state[2] != mr.mb[3] || state[3] != mr.mb[4] ||
2977*4c3888b8SHans Rosenfeld 		    state[4] != mr.mb[5] || state[5] != mr.mb[6]) {
2978*4c3888b8SHans Rosenfeld 			EL(ha, "mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, "
2979*4c3888b8SHans Rosenfeld 			    "mbx5=%xh, mbx6=%xh\n", mr.mb[1], mr.mb[2],
2980*4c3888b8SHans Rosenfeld 			    mr.mb[3], mr.mb[4], mr.mb[5], mr.mb[6]);
2981*4c3888b8SHans Rosenfeld 			state[0] = mr.mb[1];
2982*4c3888b8SHans Rosenfeld 			state[1] = mr.mb[2];
2983*4c3888b8SHans Rosenfeld 			state[2] = mr.mb[3];
2984*4c3888b8SHans Rosenfeld 			state[3] = mr.mb[4];
2985*4c3888b8SHans Rosenfeld 			state[4] = mr.mb[5];
2986*4c3888b8SHans Rosenfeld 			state[5] = mr.mb[6];
2987fcf3ce44SJohn Forte 		}
2988fcf3ce44SJohn Forte 
2989fcf3ce44SJohn Forte 		/* Delay for a tick if waiting. */
2990*4c3888b8SHans Rosenfeld 		if (timer != 0) {
2991fcf3ce44SJohn Forte 			if (timer % 4 == 0) {
2992fcf3ce44SJohn Forte 				delay(drv_usectohz(dly));
2993fcf3ce44SJohn Forte 			} else {
2994fcf3ce44SJohn Forte 				drv_usecwait(dly);
2995fcf3ce44SJohn Forte 			}
2996fcf3ce44SJohn Forte 		} else {
2997fcf3ce44SJohn Forte 			rval = QL_FUNCTION_TIMEOUT;
2998fcf3ce44SJohn Forte 		}
2999fcf3ce44SJohn Forte 	}
3000fcf3ce44SJohn Forte 
3001fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3002*4c3888b8SHans Rosenfeld 		if ((ha->task_daemon_flags & ISP_ABORT_NEEDED ||
3003*4c3888b8SHans Rosenfeld 		    ha->flags & MPI_RESET_NEEDED) &&
3004*4c3888b8SHans Rosenfeld 		    ha->task_daemon_flags & LOOP_RESYNC_NEEDED) {
3005*4c3888b8SHans Rosenfeld 			TASK_DAEMON_LOCK(ha);
3006*4c3888b8SHans Rosenfeld 			ha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED;
3007*4c3888b8SHans Rosenfeld 			TASK_DAEMON_UNLOCK(ha);
3008*4c3888b8SHans Rosenfeld 		}
3009fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3010fcf3ce44SJohn Forte 	} else {
3011fcf3ce44SJohn Forte 		/*EMPTY*/
3012*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "done\n");
3013fcf3ce44SJohn Forte 	}
3014fcf3ce44SJohn Forte 	return (rval);
3015fcf3ce44SJohn Forte }
3016fcf3ce44SJohn Forte 
3017fcf3ce44SJohn Forte /*
3018fcf3ce44SJohn Forte  * ql_configure_loop
3019fcf3ce44SJohn Forte  *	Setup configurations based on loop.
3020fcf3ce44SJohn Forte  *
3021fcf3ce44SJohn Forte  * Input:
3022fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3023fcf3ce44SJohn Forte  *
3024fcf3ce44SJohn Forte  * Returns:
3025fcf3ce44SJohn Forte  *	ql local function return status code.
3026fcf3ce44SJohn Forte  *
3027fcf3ce44SJohn Forte  * Context:
3028fcf3ce44SJohn Forte  *	Kernel context.
3029fcf3ce44SJohn Forte  */
3030fcf3ce44SJohn Forte static int
ql_configure_loop(ql_adapter_state_t * ha)3031fcf3ce44SJohn Forte ql_configure_loop(ql_adapter_state_t *ha)
3032fcf3ce44SJohn Forte {
3033*4c3888b8SHans Rosenfeld 	int			rval = QL_SUCCESS;
3034fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
3035fcf3ce44SJohn Forte 
3036*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
3037fcf3ce44SJohn Forte 
3038fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
3039fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
3040fcf3ce44SJohn Forte 		if (!(vha->task_daemon_flags & LOOP_RESYNC_NEEDED) &&
3041*4c3888b8SHans Rosenfeld 		    vha->vp_index != 0 &&
3042*4c3888b8SHans Rosenfeld 		    (!(vha->flags & VP_ENABLED) ||
3043*4c3888b8SHans Rosenfeld 		    vha->flags & VP_ID_NOT_ACQUIRED)) {
3044fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
3045fcf3ce44SJohn Forte 			continue;
3046fcf3ce44SJohn Forte 		}
3047fcf3ce44SJohn Forte 		vha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED;
3048fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
3049fcf3ce44SJohn Forte 
3050fcf3ce44SJohn Forte 		rval = ql_configure_hba(vha);
3051fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
3052fcf3ce44SJohn Forte 		    (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
3053fcf3ce44SJohn Forte 			rval = ql_configure_device_d_id(vha);
3054fcf3ce44SJohn Forte 			if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
3055fcf3ce44SJohn Forte 			    (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
3056fcf3ce44SJohn Forte 				(void) ql_configure_fabric(vha);
3057fcf3ce44SJohn Forte 			}
3058fcf3ce44SJohn Forte 		}
3059fcf3ce44SJohn Forte 	}
3060fcf3ce44SJohn Forte 
3061fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3062fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3063fcf3ce44SJohn Forte 	} else {
3064fcf3ce44SJohn Forte 		/*EMPTY*/
3065*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
3066fcf3ce44SJohn Forte 	}
3067fcf3ce44SJohn Forte 	return (rval);
3068fcf3ce44SJohn Forte }
3069fcf3ce44SJohn Forte 
30705dfd244aSDaniel Beauregard /*
30715dfd244aSDaniel Beauregard  * ql_configure_n_port_info
30725dfd244aSDaniel Beauregard  *	Setup configurations based on N port 2 N port topology.
30735dfd244aSDaniel Beauregard  *
30745dfd244aSDaniel Beauregard  * Input:
30755dfd244aSDaniel Beauregard  *	ha = adapter state pointer.
30765dfd244aSDaniel Beauregard  *
30775dfd244aSDaniel Beauregard  * Returns:
30785dfd244aSDaniel Beauregard  *	ql local function return status code.
30795dfd244aSDaniel Beauregard  *
30805dfd244aSDaniel Beauregard  * Context:
30815dfd244aSDaniel Beauregard  *	Kernel context.
3082*4c3888b8SHans Rosenfeld  *	ADAPTER_STATE_LOCK must be already obtained
30835dfd244aSDaniel Beauregard  */
30845dfd244aSDaniel Beauregard static void
ql_configure_n_port_info(ql_adapter_state_t * ha)30855dfd244aSDaniel Beauregard ql_configure_n_port_info(ql_adapter_state_t *ha)
30865dfd244aSDaniel Beauregard {
3087*4c3888b8SHans Rosenfeld 	ql_tgt_t		tmp_tq;
3088*4c3888b8SHans Rosenfeld 	ql_tgt_t		*tq;
3089*4c3888b8SHans Rosenfeld 	uint8_t			*cb_port_name;
3090*4c3888b8SHans Rosenfeld 	ql_link_t		*link;
3091*4c3888b8SHans Rosenfeld 	int			index, rval;
3092*4c3888b8SHans Rosenfeld 	uint16_t		loop_id = 0;
3093*4c3888b8SHans Rosenfeld 	uint32_t		found = 0;
3094*4c3888b8SHans Rosenfeld 	ql_dev_id_list_t	*list;
3095*4c3888b8SHans Rosenfeld 	uint32_t		list_size;
3096*4c3888b8SHans Rosenfeld 	ql_mbx_data_t		mr;
3097*4c3888b8SHans Rosenfeld 	port_id_t		d_id = {0, 0, 0, 0};
30985dfd244aSDaniel Beauregard 
3099*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
31005dfd244aSDaniel Beauregard 
31015dfd244aSDaniel Beauregard 	/* Free existing target queues. */
31025dfd244aSDaniel Beauregard 	for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
31035dfd244aSDaniel Beauregard 		link = ha->dev[index].first;
31045dfd244aSDaniel Beauregard 		while (link != NULL) {
31055dfd244aSDaniel Beauregard 			tq = link->base_address;
31065dfd244aSDaniel Beauregard 			link = link->next;
3107*4c3888b8SHans Rosenfeld 
3108*4c3888b8SHans Rosenfeld 			/* workaround FW issue, do implicit logout */
3109*4c3888b8SHans Rosenfeld 			/* Never logo to the reused loopid!! */
3110*4c3888b8SHans Rosenfeld 			if ((tq->loop_id != 0x7ff) &&
3111*4c3888b8SHans Rosenfeld 			    (tq->loop_id != 0x7fe)) {
3112*4c3888b8SHans Rosenfeld 				if (found == 0) {
3113*4c3888b8SHans Rosenfeld 					rval = ql_get_port_database(ha,
3114*4c3888b8SHans Rosenfeld 					    tq, PDF_NONE);
3115*4c3888b8SHans Rosenfeld 					if ((rval == QL_SUCCESS) &&
3116*4c3888b8SHans Rosenfeld 					    (tq->master_state ==
3117*4c3888b8SHans Rosenfeld 					    PD_STATE_PORT_LOGGED_IN)) {
3118*4c3888b8SHans Rosenfeld 						EL(ha, "nport id (%xh) "
3119*4c3888b8SHans Rosenfeld 						    "loop_id=%xh "
3120*4c3888b8SHans Rosenfeld 						    "reappeared\n",
3121*4c3888b8SHans Rosenfeld 						    tq->d_id.b24,
3122*4c3888b8SHans Rosenfeld 						    tq->loop_id);
3123*4c3888b8SHans Rosenfeld 						bcopy((void *)&tq->port_name[0],
3124*4c3888b8SHans Rosenfeld 						    (void *)&ha->n_port->
3125*4c3888b8SHans Rosenfeld 						    port_name[0],
3126*4c3888b8SHans Rosenfeld 						    8);
3127*4c3888b8SHans Rosenfeld 						bcopy((void *)&tq->node_name[0],
3128*4c3888b8SHans Rosenfeld 						    (void *)&ha->n_port->
3129*4c3888b8SHans Rosenfeld 						    node_name[0],
3130*4c3888b8SHans Rosenfeld 						    8);
3131*4c3888b8SHans Rosenfeld 						ha->n_port->d_id.b24 =
3132*4c3888b8SHans Rosenfeld 						    tq->d_id.b24;
3133*4c3888b8SHans Rosenfeld 						found = 1;
3134*4c3888b8SHans Rosenfeld 						continue;
3135*4c3888b8SHans Rosenfeld 					}
3136*4c3888b8SHans Rosenfeld 				}
3137*4c3888b8SHans Rosenfeld 				(void) ql_logout_fabric_port(ha, tq);
3138*4c3888b8SHans Rosenfeld 			}
3139*4c3888b8SHans Rosenfeld 
3140*4c3888b8SHans Rosenfeld 			tq->loop_id = PORT_NO_LOOP_ID;
31415dfd244aSDaniel Beauregard 		}
31425dfd244aSDaniel Beauregard 	}
31435dfd244aSDaniel Beauregard 
3144*4c3888b8SHans Rosenfeld 	if (found == 1) {
3145*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done found\n");
3146*4c3888b8SHans Rosenfeld 		return;
3147*4c3888b8SHans Rosenfeld 	}
3148*4c3888b8SHans Rosenfeld 
3149*4c3888b8SHans Rosenfeld 	tq = &tmp_tq;
3150*4c3888b8SHans Rosenfeld 
31515dfd244aSDaniel Beauregard 	/*
31525dfd244aSDaniel Beauregard 	 * If the N_Port's WWPN is larger than our's then it has the
31535dfd244aSDaniel Beauregard 	 * N_Port login initiative.  It will have determined that and
31545dfd244aSDaniel Beauregard 	 * logged in with the firmware.  This results in a device
31555dfd244aSDaniel Beauregard 	 * database entry.  In this situation we will later send up a PLOGI
31565dfd244aSDaniel Beauregard 	 * by proxy for the N_Port to get things going.
31575dfd244aSDaniel Beauregard 	 *
31585dfd244aSDaniel Beauregard 	 * If the N_Ports WWPN is smaller then the firmware has the
31595dfd244aSDaniel Beauregard 	 * N_Port login initiative and does a FLOGI in order to obtain the
31605dfd244aSDaniel Beauregard 	 * N_Ports WWNN and WWPN.  These names are required later
31615dfd244aSDaniel Beauregard 	 * during Leadvilles FLOGI.  No PLOGI is done by the firmware in
31625dfd244aSDaniel Beauregard 	 * anticipation of a PLOGI via the driver from the upper layers.
31635dfd244aSDaniel Beauregard 	 * Upon reciept of said PLOGI the driver issues an ELS PLOGI
31645dfd244aSDaniel Beauregard 	 * pass-through command and the firmware assumes the s_id
31655dfd244aSDaniel Beauregard 	 * and the N_Port assumes the d_id and Bob's your uncle.
31665dfd244aSDaniel Beauregard 	 */
31675dfd244aSDaniel Beauregard 
31685dfd244aSDaniel Beauregard 	/*
31695dfd244aSDaniel Beauregard 	 * In N port 2 N port topology the FW provides a port database entry at
31705dfd244aSDaniel Beauregard 	 * loop_id 0x7fe which allows us to acquire the Ports WWPN.
31715dfd244aSDaniel Beauregard 	 */
31725dfd244aSDaniel Beauregard 	tq->d_id.b.al_pa = 0;
31735dfd244aSDaniel Beauregard 	tq->d_id.b.area = 0;
31745dfd244aSDaniel Beauregard 	tq->d_id.b.domain = 0;
31755dfd244aSDaniel Beauregard 	tq->loop_id = 0x7fe;
31765dfd244aSDaniel Beauregard 
31775dfd244aSDaniel Beauregard 	rval = ql_get_port_database(ha, tq, PDF_NONE);
31785dfd244aSDaniel Beauregard 
3179*4c3888b8SHans Rosenfeld 	/*
3180*4c3888b8SHans Rosenfeld 	 * Only collect the P2P remote port information in the case of
3181*4c3888b8SHans Rosenfeld 	 * QL_SUCCESS. FW should have always logged in (flogi) to remote
3182*4c3888b8SHans Rosenfeld 	 * port at this point.
3183*4c3888b8SHans Rosenfeld 	 */
3184*4c3888b8SHans Rosenfeld 	if (rval == QL_SUCCESS) {
3185*4c3888b8SHans Rosenfeld 		cb_port_name = &ha->loginparams.nport_ww_name.raw_wwn[0];
31865dfd244aSDaniel Beauregard 
31875dfd244aSDaniel Beauregard 		if ((ql_wwn_cmp(ha, (la_wwn_t *)&tq->port_name[0],
31885dfd244aSDaniel Beauregard 		    (la_wwn_t *)cb_port_name) == 1)) {
31895dfd244aSDaniel Beauregard 			EL(ha, "target port has N_Port login initiative\n");
31905dfd244aSDaniel Beauregard 		} else {
31915dfd244aSDaniel Beauregard 			EL(ha, "host port has N_Port login initiative\n");
31925dfd244aSDaniel Beauregard 		}
31935dfd244aSDaniel Beauregard 
31945dfd244aSDaniel Beauregard 		/* Capture the N Ports WWPN */
31955dfd244aSDaniel Beauregard 
31965dfd244aSDaniel Beauregard 		bcopy((void *)&tq->port_name[0],
31975dfd244aSDaniel Beauregard 		    (void *)&ha->n_port->port_name[0], 8);
31985dfd244aSDaniel Beauregard 		bcopy((void *)&tq->node_name[0],
31995dfd244aSDaniel Beauregard 		    (void *)&ha->n_port->node_name[0], 8);
32005dfd244aSDaniel Beauregard 
32015dfd244aSDaniel Beauregard 		/* Resolve an n_port_handle */
32025dfd244aSDaniel Beauregard 		ha->n_port->n_port_handle = 0x7fe;
32035dfd244aSDaniel Beauregard 
3204*4c3888b8SHans Rosenfeld 	}
32055dfd244aSDaniel Beauregard 
3206*4c3888b8SHans Rosenfeld 	list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
3207*4c3888b8SHans Rosenfeld 	list = (ql_dev_id_list_t *)kmem_zalloc(list_size, KM_SLEEP);
3208*4c3888b8SHans Rosenfeld 
3209*4c3888b8SHans Rosenfeld 	if (ql_get_id_list(ha, (caddr_t)list, list_size, &mr) ==
3210*4c3888b8SHans Rosenfeld 	    QL_SUCCESS) {
3211*4c3888b8SHans Rosenfeld 			/* For the p2p mr.mb[1] must be 1 */
3212*4c3888b8SHans Rosenfeld 			if (mr.mb[1] == 1) {
3213*4c3888b8SHans Rosenfeld 				index = 0;
3214*4c3888b8SHans Rosenfeld 				ql_dev_list(ha, list, index,
3215*4c3888b8SHans Rosenfeld 				    &d_id, &loop_id);
3216*4c3888b8SHans Rosenfeld 				ha->n_port->n_port_handle = loop_id;
3217*4c3888b8SHans Rosenfeld 
3218*4c3888b8SHans Rosenfeld 				tq->loop_id = loop_id;
3219*4c3888b8SHans Rosenfeld 				tq->d_id.b24 = d_id.b24;
3220*4c3888b8SHans Rosenfeld 				ha->n_port->d_id.b24 = d_id.b24;
32215dfd244aSDaniel Beauregard 			} else {
32225dfd244aSDaniel Beauregard 				for (index = 0; index <= LAST_LOCAL_LOOP_ID;
32235dfd244aSDaniel Beauregard 				    index++) {
32245dfd244aSDaniel Beauregard 					/* resuse tq */
32255dfd244aSDaniel Beauregard 					tq->loop_id = (uint16_t)index;
32265dfd244aSDaniel Beauregard 					rval = ql_get_port_database(ha, tq,
32275dfd244aSDaniel Beauregard 					    PDF_NONE);
32285dfd244aSDaniel Beauregard 					if (rval == QL_NOT_LOGGED_IN) {
32295dfd244aSDaniel Beauregard 						if (tq->master_state ==
32305dfd244aSDaniel Beauregard 						    PD_STATE_PLOGI_PENDING) {
32315dfd244aSDaniel Beauregard 							ha->n_port->
32325dfd244aSDaniel Beauregard 							    n_port_handle =
32335dfd244aSDaniel Beauregard 							    tq->loop_id;
3234*4c3888b8SHans Rosenfeld 							ha->n_port->d_id.b24 =
3235*4c3888b8SHans Rosenfeld 							    tq->hard_addr.b24;
32365dfd244aSDaniel Beauregard 							break;
32375dfd244aSDaniel Beauregard 						}
3238*4c3888b8SHans Rosenfeld 					} else if (rval == QL_SUCCESS) {
32395dfd244aSDaniel Beauregard 						ha->n_port->n_port_handle =
32405dfd244aSDaniel Beauregard 						    tq->loop_id;
3241*4c3888b8SHans Rosenfeld 						ha->n_port->d_id.b24 =
3242*4c3888b8SHans Rosenfeld 						    tq->hard_addr.b24;
3243*4c3888b8SHans Rosenfeld 
32445dfd244aSDaniel Beauregard 						break;
32455dfd244aSDaniel Beauregard 					}
32465dfd244aSDaniel Beauregard 				}
3247*4c3888b8SHans Rosenfeld 				if (index > LAST_LOCAL_LOOP_ID) {
3248*4c3888b8SHans Rosenfeld 					EL(ha, "P2P:exceeded last id, "
3249*4c3888b8SHans Rosenfeld 					    "n_port_handle = %xh\n",
3250*4c3888b8SHans Rosenfeld 					    ha->n_port->n_port_handle);
3251*4c3888b8SHans Rosenfeld 
3252*4c3888b8SHans Rosenfeld 					ha->n_port->n_port_handle = 0;
3253*4c3888b8SHans Rosenfeld 					tq->loop_id = 0;
3254*4c3888b8SHans Rosenfeld 				}
32555dfd244aSDaniel Beauregard 			}
32565dfd244aSDaniel Beauregard 		} else {
32575dfd244aSDaniel Beauregard 			kmem_free(list, list_size);
3258*4c3888b8SHans Rosenfeld 			EL(ha, "ql_get_dev_list unsuccessful\n");
3259*4c3888b8SHans Rosenfeld 			return;
32605dfd244aSDaniel Beauregard 		}
3261*4c3888b8SHans Rosenfeld 
3262*4c3888b8SHans Rosenfeld 		/* with the tq->loop_id to get the port database */
3263*4c3888b8SHans Rosenfeld 
3264*4c3888b8SHans Rosenfeld 		rval = ql_get_port_database(ha, tq, PDF_NONE);
3265*4c3888b8SHans Rosenfeld 
3266*4c3888b8SHans Rosenfeld 		if (rval == QL_NOT_LOGGED_IN) {
3267*4c3888b8SHans Rosenfeld 			if (tq->master_state == PD_STATE_PLOGI_PENDING) {
3268*4c3888b8SHans Rosenfeld 				bcopy((void *)&tq->port_name[0],
3269*4c3888b8SHans Rosenfeld 				    (void *)&ha->n_port->port_name[0], 8);
3270*4c3888b8SHans Rosenfeld 				bcopy((void *)&tq->node_name[0],
3271*4c3888b8SHans Rosenfeld 				    (void *)&ha->n_port->node_name[0], 8);
3272*4c3888b8SHans Rosenfeld 				bcopy((void *)&tq->hard_addr,
3273*4c3888b8SHans Rosenfeld 				    (void *)&ha->n_port->d_id,
3274*4c3888b8SHans Rosenfeld 				    sizeof (port_id_t));
3275*4c3888b8SHans Rosenfeld 				ha->n_port->d_id.b24 = d_id.b24;
3276*4c3888b8SHans Rosenfeld 			}
3277*4c3888b8SHans Rosenfeld 		} else if (rval == QL_SUCCESS) {
3278*4c3888b8SHans Rosenfeld 			bcopy((void *)&tq->port_name[0],
3279*4c3888b8SHans Rosenfeld 			    (void *)&ha->n_port->port_name[0], 8);
3280*4c3888b8SHans Rosenfeld 			bcopy((void *)&tq->node_name[0],
3281*4c3888b8SHans Rosenfeld 			    (void *)&ha->n_port->node_name[0], 8);
3282*4c3888b8SHans Rosenfeld 			bcopy((void *)&tq->hard_addr,
3283*4c3888b8SHans Rosenfeld 			    (void *)&ha->n_port->d_id, sizeof (port_id_t));
3284*4c3888b8SHans Rosenfeld 			ha->n_port->d_id.b24 = d_id.b24;
3285*4c3888b8SHans Rosenfeld 
3286*4c3888b8SHans Rosenfeld 		}
3287*4c3888b8SHans Rosenfeld 
3288*4c3888b8SHans Rosenfeld 		kmem_free(list, list_size);
3289*4c3888b8SHans Rosenfeld 
3290*4c3888b8SHans Rosenfeld 		EL(ha, "d_id = %xh, nport_handle = %xh, tq->loop_id = %xh",
3291*4c3888b8SHans Rosenfeld 		    tq->d_id.b24, ha->n_port->n_port_handle, tq->loop_id);
32925dfd244aSDaniel Beauregard }
32935dfd244aSDaniel Beauregard 
32945dfd244aSDaniel Beauregard 
3295fcf3ce44SJohn Forte /*
3296fcf3ce44SJohn Forte  * ql_configure_hba
3297fcf3ce44SJohn Forte  *	Setup adapter context.
3298fcf3ce44SJohn Forte  *
3299fcf3ce44SJohn Forte  * Input:
3300fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3301fcf3ce44SJohn Forte  *
3302fcf3ce44SJohn Forte  * Returns:
3303fcf3ce44SJohn Forte  *	ql local function return status code.
3304fcf3ce44SJohn Forte  *
3305fcf3ce44SJohn Forte  * Context:
3306fcf3ce44SJohn Forte  *	Kernel context.
3307fcf3ce44SJohn Forte  */
3308fcf3ce44SJohn Forte static int
ql_configure_hba(ql_adapter_state_t * ha)3309fcf3ce44SJohn Forte ql_configure_hba(ql_adapter_state_t *ha)
3310fcf3ce44SJohn Forte {
3311fcf3ce44SJohn Forte 	uint8_t		*bp;
3312fcf3ce44SJohn Forte 	int		rval;
3313fcf3ce44SJohn Forte 	uint32_t	state;
3314fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
3315fcf3ce44SJohn Forte 
3316*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
3317fcf3ce44SJohn Forte 
3318fcf3ce44SJohn Forte 	/* Get host addresses. */
3319fcf3ce44SJohn Forte 	rval = ql_get_adapter_id(ha, &mr);
3320fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
3321fcf3ce44SJohn Forte 		ha->topology = (uint8_t)(ha->topology &
3322fcf3ce44SJohn Forte 		    ~(QL_N_PORT | QL_NL_PORT | QL_F_PORT | QL_FL_PORT));
3323fcf3ce44SJohn Forte 
3324fcf3ce44SJohn Forte 		/* Save Host d_id, alpa, loop ID. */
3325fcf3ce44SJohn Forte 		ha->loop_id = mr.mb[1];
3326fcf3ce44SJohn Forte 		ha->d_id.b.al_pa = LSB(mr.mb[2]);
3327fcf3ce44SJohn Forte 		ha->d_id.b.area = MSB(mr.mb[2]);
3328fcf3ce44SJohn Forte 		ha->d_id.b.domain = LSB(mr.mb[3]);
3329*4c3888b8SHans Rosenfeld 		ha->bbcr_initial = LSB(mr.mb[15]);
3330*4c3888b8SHans Rosenfeld 		ha->bbcr_runtime = MSB(mr.mb[15]);
3331fcf3ce44SJohn Forte 
3332fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3333fcf3ce44SJohn Forte 		ha->flags &= ~FDISC_ENABLED;
3334*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_UNLOCK(ha);
3335fcf3ce44SJohn Forte 
3336fcf3ce44SJohn Forte 		/* Get loop topology. */
3337fcf3ce44SJohn Forte 		switch (mr.mb[6]) {
3338*4c3888b8SHans Rosenfeld 		case GID_TOP_NL_PORT:
3339fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_NL_PORT);
3340*4c3888b8SHans Rosenfeld 			ha->loop_id = mr.mb[1];
3341fcf3ce44SJohn Forte 			break;
3342*4c3888b8SHans Rosenfeld 		case GID_TOP_FL_PORT:
3343fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_FL_PORT);
3344*4c3888b8SHans Rosenfeld 			ha->loop_id = mr.mb[1];
3345fcf3ce44SJohn Forte 			break;
3346*4c3888b8SHans Rosenfeld 		case GID_TOP_N_PORT:
3347*4c3888b8SHans Rosenfeld 		case GID_TOP_N_PORT_NO_TGT:
3348fcf3ce44SJohn Forte 			ha->flags |= POINT_TO_POINT;
3349fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_N_PORT);
3350*4c3888b8SHans Rosenfeld 			ha->loop_id = 0xffff;
3351*4c3888b8SHans Rosenfeld 			if (CFG_IST(ha, CFG_N2N_SUPPORT)) {
33525dfd244aSDaniel Beauregard 				ql_configure_n_port_info(ha);
33535dfd244aSDaniel Beauregard 			}
3354fcf3ce44SJohn Forte 			break;
3355*4c3888b8SHans Rosenfeld 		case GID_TOP_F_PORT:
3356fcf3ce44SJohn Forte 			ha->flags |= POINT_TO_POINT;
3357fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_F_PORT);
3358*4c3888b8SHans Rosenfeld 			ha->loop_id = 0xffff;
3359fcf3ce44SJohn Forte 
3360fcf3ce44SJohn Forte 			/* Get supported option. */
3361*4c3888b8SHans Rosenfeld 			if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
33625dfd244aSDaniel Beauregard 			    mr.mb[7] & GID_FP_NPIV_SUPPORT) {
3363*4c3888b8SHans Rosenfeld 				ADAPTER_STATE_LOCK(ha);
3364fcf3ce44SJohn Forte 				ha->flags |= FDISC_ENABLED;
3365*4c3888b8SHans Rosenfeld 				ADAPTER_STATE_UNLOCK(ha);
3366fcf3ce44SJohn Forte 			}
33677a2b99c0SDaniel Beauregard 			/* Get VLAN ID, mac address */
3368*4c3888b8SHans Rosenfeld 			if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
3369*4c3888b8SHans Rosenfeld 				ha->flags |= FDISC_ENABLED;
33707a2b99c0SDaniel Beauregard 				ha->fabric_params = mr.mb[7];
33717a2b99c0SDaniel Beauregard 				ha->fcoe_vlan_id = (uint16_t)(mr.mb[9] & 0xfff);
33727a2b99c0SDaniel Beauregard 				ha->fcoe_fcf_idx = mr.mb[10];
3373*4c3888b8SHans Rosenfeld 				ha->fcoe_vnport_mac[5] = MSB(mr.mb[11]);
3374*4c3888b8SHans Rosenfeld 				ha->fcoe_vnport_mac[4] = LSB(mr.mb[11]);
3375*4c3888b8SHans Rosenfeld 				ha->fcoe_vnport_mac[3] = MSB(mr.mb[12]);
3376*4c3888b8SHans Rosenfeld 				ha->fcoe_vnport_mac[2] = LSB(mr.mb[12]);
3377*4c3888b8SHans Rosenfeld 				ha->fcoe_vnport_mac[1] = MSB(mr.mb[13]);
3378*4c3888b8SHans Rosenfeld 				ha->fcoe_vnport_mac[0] = LSB(mr.mb[13]);
33797a2b99c0SDaniel Beauregard 			}
3380fcf3ce44SJohn Forte 			break;
3381fcf3ce44SJohn Forte 		default:
3382*4c3888b8SHans Rosenfeld 			QL_PRINT_2(ha, "UNKNOWN topology=%xh, d_id=%xh\n",
3383*4c3888b8SHans Rosenfeld 			    mr.mb[6], ha->d_id.b24);
3384fcf3ce44SJohn Forte 			rval = QL_FUNCTION_FAILED;
3385fcf3ce44SJohn Forte 			break;
3386fcf3ce44SJohn Forte 		}
3387fcf3ce44SJohn Forte 
3388*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_2363 | CFG_ISP_FW_TYPE_2)) {
3389fcf3ce44SJohn Forte 			mr.mb[1] = 0;
3390fcf3ce44SJohn Forte 			mr.mb[2] = 0;
3391fcf3ce44SJohn Forte 			rval = ql_data_rate(ha, &mr);
3392fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
3393fcf3ce44SJohn Forte 				EL(ha, "data_rate status=%xh\n", rval);
3394fcf3ce44SJohn Forte 				state = FC_STATE_FULL_SPEED;
3395fcf3ce44SJohn Forte 			} else {
3396f885d00fSDaniel Beauregard 				ha->iidma_rate = mr.mb[1];
33975dfd244aSDaniel Beauregard 				if (mr.mb[1] == IIDMA_RATE_1GB) {
3398fcf3ce44SJohn Forte 					state = FC_STATE_1GBIT_SPEED;
33995dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_2GB) {
3400fcf3ce44SJohn Forte 					state = FC_STATE_2GBIT_SPEED;
34015dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_4GB) {
3402fcf3ce44SJohn Forte 					state = FC_STATE_4GBIT_SPEED;
34035dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_8GB) {
3404fcf3ce44SJohn Forte 					state = FC_STATE_8GBIT_SPEED;
34055dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_10GB) {
34065dfd244aSDaniel Beauregard 					state = FC_STATE_10GBIT_SPEED;
3407*4c3888b8SHans Rosenfeld 				} else if (mr.mb[1] == IIDMA_RATE_16GB) {
3408*4c3888b8SHans Rosenfeld 					state = FC_STATE_16GBIT_SPEED;
3409*4c3888b8SHans Rosenfeld 				} else if (mr.mb[1] == IIDMA_RATE_32GB) {
3410*4c3888b8SHans Rosenfeld 					state = FC_STATE_32GBIT_SPEED;
3411fcf3ce44SJohn Forte 				} else {
3412fcf3ce44SJohn Forte 					state = 0;
3413fcf3ce44SJohn Forte 				}
3414fcf3ce44SJohn Forte 			}
3415fcf3ce44SJohn Forte 		} else {
3416f885d00fSDaniel Beauregard 			ha->iidma_rate = IIDMA_RATE_1GB;
3417fcf3ce44SJohn Forte 			state = FC_STATE_FULL_SPEED;
3418fcf3ce44SJohn Forte 		}
3419fcf3ce44SJohn Forte 		ha->state = FC_PORT_STATE_MASK(ha->state) | state;
342016dd44c2SDaniel Beauregard 	} else if (rval == MBS_COMMAND_ERROR) {
342116dd44c2SDaniel Beauregard 		EL(ha, "mbox cmd error, rval = %xh, mr.mb[1]=%hx\n",
342216dd44c2SDaniel Beauregard 		    rval, mr.mb[1]);
3423fcf3ce44SJohn Forte 	}
3424fcf3ce44SJohn Forte 
3425fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3426fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3427fcf3ce44SJohn Forte 	} else {
3428fcf3ce44SJohn Forte 		bp = ha->loginparams.nport_ww_name.raw_wwn;
3429*4c3888b8SHans Rosenfeld 		EL(ha, "topology=%xh, hba port id=%xh, "
3430fcf3ce44SJohn Forte 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n",
3431fcf3ce44SJohn Forte 		    ha->topology, ha->d_id.b24, bp[0], bp[1],
3432fcf3ce44SJohn Forte 		    bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]);
3433fcf3ce44SJohn Forte 	}
3434fcf3ce44SJohn Forte 	return (rval);
3435fcf3ce44SJohn Forte }
3436fcf3ce44SJohn Forte 
3437fcf3ce44SJohn Forte /*
3438fcf3ce44SJohn Forte  * ql_configure_device_d_id
3439fcf3ce44SJohn Forte  *	Updates device loop ID.
3440fcf3ce44SJohn Forte  *	Also adds to device queue any new devices found on private loop.
3441fcf3ce44SJohn Forte  *
3442fcf3ce44SJohn Forte  * Input:
3443fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3444fcf3ce44SJohn Forte  *
3445fcf3ce44SJohn Forte  * Returns:
3446fcf3ce44SJohn Forte  *	ql local function return status code.
3447fcf3ce44SJohn Forte  *
3448fcf3ce44SJohn Forte  * Context:
3449fcf3ce44SJohn Forte  *	Kernel context.
3450fcf3ce44SJohn Forte  */
3451fcf3ce44SJohn Forte static int
ql_configure_device_d_id(ql_adapter_state_t * ha)3452fcf3ce44SJohn Forte ql_configure_device_d_id(ql_adapter_state_t *ha)
3453fcf3ce44SJohn Forte {
3454fcf3ce44SJohn Forte 	port_id_t		d_id;
3455fcf3ce44SJohn Forte 	ql_link_t		*link;
3456fcf3ce44SJohn Forte 	int			rval;
3457fcf3ce44SJohn Forte 	int			loop;
3458fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
3459fcf3ce44SJohn Forte 	ql_dev_id_list_t	*list;
3460fcf3ce44SJohn Forte 	uint32_t		list_size;
3461fcf3ce44SJohn Forte 	uint16_t		index, loop_id;
3462fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
3463fcf3ce44SJohn Forte 	uint8_t			retries = MAX_DEVICE_LOST_RETRY;
3464fcf3ce44SJohn Forte 
3465*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
3466fcf3ce44SJohn Forte 
3467fcf3ce44SJohn Forte 	list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
3468fcf3ce44SJohn Forte 	list = kmem_zalloc(list_size, KM_SLEEP);
3469fcf3ce44SJohn Forte 	if (list == NULL) {
3470fcf3ce44SJohn Forte 		rval = QL_MEMORY_ALLOC_FAILED;
3471fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3472fcf3ce44SJohn Forte 		return (rval);
3473fcf3ce44SJohn Forte 	}
3474fcf3ce44SJohn Forte 
3475fcf3ce44SJohn Forte 	do {
3476fcf3ce44SJohn Forte 		/*
3477fcf3ce44SJohn Forte 		 * Get data from RISC code d_id list to init each device queue.
3478fcf3ce44SJohn Forte 		 */
3479fcf3ce44SJohn Forte 		rval = ql_get_id_list(ha, (caddr_t)list, list_size, &mr);
3480fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
3481fcf3ce44SJohn Forte 			kmem_free(list, list_size);
3482fcf3ce44SJohn Forte 			EL(ha, "failed, rval = %xh\n", rval);
3483fcf3ce44SJohn Forte 			return (rval);
3484fcf3ce44SJohn Forte 		}
3485fcf3ce44SJohn Forte 
3486*4c3888b8SHans Rosenfeld 		/*
3487*4c3888b8SHans Rosenfeld 		 * Mark queues as unusable selectively.
3488*4c3888b8SHans Rosenfeld 		 * If the current topology is AL, only fabric tgt queues
3489*4c3888b8SHans Rosenfeld 		 * are marked as unusable and eventually removed.
3490*4c3888b8SHans Rosenfeld 		 * If the current topology is P2P, all fabric tgt queues
3491*4c3888b8SHans Rosenfeld 		 * are processed in ql_configure_n_port_info().
3492*4c3888b8SHans Rosenfeld 		 * If the current topology is Fabric, all previous created
3493*4c3888b8SHans Rosenfeld 		 * non-fabric device should be marked as lost and eventually
3494*4c3888b8SHans Rosenfeld 		 * should be removed.
3495*4c3888b8SHans Rosenfeld 		 */
3496fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3497fcf3ce44SJohn Forte 			for (link = ha->dev[index].first; link != NULL;
3498fcf3ce44SJohn Forte 			    link = link->next) {
3499fcf3ce44SJohn Forte 				tq = link->base_address;
3500*4c3888b8SHans Rosenfeld 
3501*4c3888b8SHans Rosenfeld 				if (VALID_DEVICE_ID(ha, tq->loop_id)) {
3502*4c3888b8SHans Rosenfeld 					DEVICE_QUEUE_LOCK(tq);
3503*4c3888b8SHans Rosenfeld 					if (!(tq->flags & TQF_PLOGI_PROGRS) &&
3504*4c3888b8SHans Rosenfeld 					    !(ha->topology & QL_N_PORT)) {
3505*4c3888b8SHans Rosenfeld 						tq->loop_id = (uint16_t)
3506*4c3888b8SHans Rosenfeld 						    (tq->loop_id |
3507*4c3888b8SHans Rosenfeld 						    PORT_LOST_ID);
3508*4c3888b8SHans Rosenfeld 					}
3509*4c3888b8SHans Rosenfeld 					if ((ha->topology & QL_NL_PORT) &&
3510*4c3888b8SHans Rosenfeld 					    (tq->flags & TQF_FABRIC_DEVICE)) {
3511*4c3888b8SHans Rosenfeld 						tq->loop_id = (uint16_t)
3512*4c3888b8SHans Rosenfeld 						    (tq->loop_id |
3513*4c3888b8SHans Rosenfeld 						    PORT_LOST_ID);
3514*4c3888b8SHans Rosenfeld 					}
3515*4c3888b8SHans Rosenfeld 					DEVICE_QUEUE_UNLOCK(tq);
3516fcf3ce44SJohn Forte 				}
3517fcf3ce44SJohn Forte 			}
3518fcf3ce44SJohn Forte 		}
3519fcf3ce44SJohn Forte 
3520fcf3ce44SJohn Forte 		/* If device not in queues add new queue. */
3521fcf3ce44SJohn Forte 		for (index = 0; index < mr.mb[1]; index++) {
3522fcf3ce44SJohn Forte 			ql_dev_list(ha, list, index, &d_id, &loop_id);
3523fcf3ce44SJohn Forte 
3524fcf3ce44SJohn Forte 			if (VALID_DEVICE_ID(ha, loop_id)) {
3525*4c3888b8SHans Rosenfeld 				ADAPTER_STATE_LOCK(ha);
3526fcf3ce44SJohn Forte 				tq = ql_dev_init(ha, d_id, loop_id);
3527*4c3888b8SHans Rosenfeld 				ADAPTER_STATE_UNLOCK(ha);
3528fcf3ce44SJohn Forte 				if (tq != NULL) {
3529fcf3ce44SJohn Forte 					tq->loop_id = loop_id;
3530fcf3ce44SJohn Forte 
3531fcf3ce44SJohn Forte 					/* Test for fabric device. */
3532*4c3888b8SHans Rosenfeld 					if (ha->topology & QL_F_PORT ||
3533*4c3888b8SHans Rosenfeld 					    d_id.b.domain !=
3534fcf3ce44SJohn Forte 					    ha->d_id.b.domain ||
3535fcf3ce44SJohn Forte 					    d_id.b.area != ha->d_id.b.area) {
3536fcf3ce44SJohn Forte 						tq->flags |= TQF_FABRIC_DEVICE;
3537fcf3ce44SJohn Forte 					}
3538fcf3ce44SJohn Forte 
3539fcf3ce44SJohn Forte 					if (ql_get_port_database(ha, tq,
3540fcf3ce44SJohn Forte 					    PDF_NONE) == QL_SUCCESS) {
3541fcf3ce44SJohn Forte 						tq->loop_id = (uint16_t)
3542fcf3ce44SJohn Forte 						    (tq->loop_id &
3543fcf3ce44SJohn Forte 						    ~PORT_LOST_ID);
3544fcf3ce44SJohn Forte 					}
3545fcf3ce44SJohn Forte 				}
3546fcf3ce44SJohn Forte 			}
3547fcf3ce44SJohn Forte 		}
3548fcf3ce44SJohn Forte 
3549fcf3ce44SJohn Forte 		/* 24xx does not report switch devices in ID list. */
3550*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
3551*4c3888b8SHans Rosenfeld 		    ha->topology & QL_FABRIC_CONNECTION) {
3552*4c3888b8SHans Rosenfeld 			d_id.b24 = FS_FABRIC_F_PORT;
3553*4c3888b8SHans Rosenfeld 			ADAPTER_STATE_LOCK(ha);
3554fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, FL_PORT_24XX_HDL);
3555*4c3888b8SHans Rosenfeld 			ADAPTER_STATE_UNLOCK(ha);
3556fcf3ce44SJohn Forte 			if (tq != NULL) {
355716dd44c2SDaniel Beauregard 				tq->flags |= TQF_FABRIC_DEVICE;
3558fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3559fcf3ce44SJohn Forte 			}
3560*4c3888b8SHans Rosenfeld 
3561*4c3888b8SHans Rosenfeld 			d_id.b24 = FS_NAME_SERVER;
3562*4c3888b8SHans Rosenfeld 			ADAPTER_STATE_LOCK(ha);
3563fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, SNS_24XX_HDL);
3564*4c3888b8SHans Rosenfeld 			ADAPTER_STATE_UNLOCK(ha);
3565fcf3ce44SJohn Forte 			if (tq != NULL) {
356616dd44c2SDaniel Beauregard 				tq->flags |= TQF_FABRIC_DEVICE;
3567fcf3ce44SJohn Forte 				if (ha->vp_index != 0) {
3568fcf3ce44SJohn Forte 					(void) ql_login_fport(ha, tq,
3569fcf3ce44SJohn Forte 					    SNS_24XX_HDL, LFF_NONE, NULL);
3570fcf3ce44SJohn Forte 				}
3571fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3572fcf3ce44SJohn Forte 			}
3573fcf3ce44SJohn Forte 		}
3574fcf3ce44SJohn Forte 
3575fcf3ce44SJohn Forte 		/* Allocate queue for broadcast. */
3576*4c3888b8SHans Rosenfeld 		d_id.b24 = FS_BROADCAST;
3577*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_LOCK(ha);
3578fcf3ce44SJohn Forte 		(void) ql_dev_init(ha, d_id, (uint16_t)
3579*4c3888b8SHans Rosenfeld 		    (CFG_IST(ha, CFG_ISP_FW_TYPE_2) ? BROADCAST_24XX_HDL :
3580fcf3ce44SJohn Forte 		    IP_BROADCAST_LOOP_ID));
3581*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_UNLOCK(ha);
3582fcf3ce44SJohn Forte 
3583*4c3888b8SHans Rosenfeld 		/*
3584*4c3888b8SHans Rosenfeld 		 * Topology change (fabric<->p2p),(fabric<->al)
3585*4c3888b8SHans Rosenfeld 		 * (al<->p2p) have to be taken care of.
3586*4c3888b8SHans Rosenfeld 		 */
3587fcf3ce44SJohn Forte 		loop = FALSE;
3588fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3589*4c3888b8SHans Rosenfeld 			ql_update_dev(ha, index);
3590fcf3ce44SJohn Forte 		}
3591fcf3ce44SJohn Forte 
3592*4c3888b8SHans Rosenfeld 		if ((ha->topology & QL_NL_PORT) && (mr.mb[1] != 0)) {
3593*4c3888b8SHans Rosenfeld 			loop = FALSE;
3594*4c3888b8SHans Rosenfeld 		} else if (mr.mb[1] == 0 && !(ha->topology & QL_F_PORT)) {
3595*4c3888b8SHans Rosenfeld 			loop = TRUE;
3596*4c3888b8SHans Rosenfeld 		}
3597fcf3ce44SJohn Forte 
3598fcf3ce44SJohn Forte 		/* Give devices time to recover. */
3599fcf3ce44SJohn Forte 		if (loop == TRUE) {
3600fcf3ce44SJohn Forte 			drv_usecwait(1000000);
3601fcf3ce44SJohn Forte 		}
3602fcf3ce44SJohn Forte 	} while (retries-- && loop == TRUE &&
3603fcf3ce44SJohn Forte 	    !(ha->pha->task_daemon_flags & LOOP_RESYNC_NEEDED));
3604fcf3ce44SJohn Forte 
3605fcf3ce44SJohn Forte 	kmem_free(list, list_size);
3606fcf3ce44SJohn Forte 
3607fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3608fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
3609fcf3ce44SJohn Forte 	} else {
3610fcf3ce44SJohn Forte 		/*EMPTY*/
3611*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
3612fcf3ce44SJohn Forte 	}
3613fcf3ce44SJohn Forte 
3614fcf3ce44SJohn Forte 	return (rval);
3615fcf3ce44SJohn Forte }
3616fcf3ce44SJohn Forte 
3617fcf3ce44SJohn Forte /*
3618fcf3ce44SJohn Forte  * ql_dev_list
3619fcf3ce44SJohn Forte  *	Gets device d_id and loop ID from firmware device list.
3620fcf3ce44SJohn Forte  *
3621fcf3ce44SJohn Forte  * Input:
3622fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
3623fcf3ce44SJohn Forte  *	list	device list pointer.
3624fcf3ce44SJohn Forte  *	index:	list index of device data.
3625fcf3ce44SJohn Forte  *	d_id:	pointer for d_id data.
3626fcf3ce44SJohn Forte  *	id:	pointer for loop ID.
3627fcf3ce44SJohn Forte  *
3628fcf3ce44SJohn Forte  * Context:
3629fcf3ce44SJohn Forte  *	Kernel context.
3630fcf3ce44SJohn Forte  */
3631fcf3ce44SJohn Forte void
ql_dev_list(ql_adapter_state_t * ha,union ql_dev_id_list * list,uint32_t index,port_id_t * d_id,uint16_t * id)3632fcf3ce44SJohn Forte ql_dev_list(ql_adapter_state_t *ha, union ql_dev_id_list *list,
3633fcf3ce44SJohn Forte     uint32_t index, port_id_t *d_id, uint16_t *id)
3634fcf3ce44SJohn Forte {
3635*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
3636fcf3ce44SJohn Forte 		struct ql_24_dev_id	*list24 = (struct ql_24_dev_id *)list;
3637fcf3ce44SJohn Forte 
3638fcf3ce44SJohn Forte 		d_id->b.al_pa = list24[index].al_pa;
3639fcf3ce44SJohn Forte 		d_id->b.area = list24[index].area;
3640fcf3ce44SJohn Forte 		d_id->b.domain = list24[index].domain;
3641fcf3ce44SJohn Forte 		*id = CHAR_TO_SHORT(list24[index].n_port_hdl_l,
3642fcf3ce44SJohn Forte 		    list24[index].n_port_hdl_h);
3643fcf3ce44SJohn Forte 
3644fcf3ce44SJohn Forte 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
3645fcf3ce44SJohn Forte 		struct ql_ex_dev_id	*list23 = (struct ql_ex_dev_id *)list;
3646fcf3ce44SJohn Forte 
3647fcf3ce44SJohn Forte 		d_id->b.al_pa = list23[index].al_pa;
3648fcf3ce44SJohn Forte 		d_id->b.area = list23[index].area;
3649fcf3ce44SJohn Forte 		d_id->b.domain = list23[index].domain;
3650fcf3ce44SJohn Forte 		*id = CHAR_TO_SHORT(list23[index].loop_id_l,
3651fcf3ce44SJohn Forte 		    list23[index].loop_id_h);
3652fcf3ce44SJohn Forte 
3653fcf3ce44SJohn Forte 	} else {
3654fcf3ce44SJohn Forte 		struct ql_dev_id	*list22 = (struct ql_dev_id *)list;
3655fcf3ce44SJohn Forte 
3656fcf3ce44SJohn Forte 		d_id->b.al_pa = list22[index].al_pa;
3657fcf3ce44SJohn Forte 		d_id->b.area = list22[index].area;
3658fcf3ce44SJohn Forte 		d_id->b.domain = list22[index].domain;
3659fcf3ce44SJohn Forte 		*id = (uint16_t)list22[index].loop_id;
3660fcf3ce44SJohn Forte 	}
3661fcf3ce44SJohn Forte }
3662fcf3ce44SJohn Forte 
3663fcf3ce44SJohn Forte /*
3664fcf3ce44SJohn Forte  * ql_configure_fabric
3665fcf3ce44SJohn Forte  *	Setup fabric context.
3666fcf3ce44SJohn Forte  *
3667fcf3ce44SJohn Forte  * Input:
3668fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3669fcf3ce44SJohn Forte  *
3670fcf3ce44SJohn Forte  * Returns:
3671fcf3ce44SJohn Forte  *	ql local function return status code.
3672fcf3ce44SJohn Forte  *
3673fcf3ce44SJohn Forte  * Context:
3674fcf3ce44SJohn Forte  *	Kernel context.
3675fcf3ce44SJohn Forte  */
3676fcf3ce44SJohn Forte static int
ql_configure_fabric(ql_adapter_state_t * ha)3677fcf3ce44SJohn Forte ql_configure_fabric(ql_adapter_state_t *ha)
3678fcf3ce44SJohn Forte {
3679fcf3ce44SJohn Forte 	port_id_t	d_id;
3680fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3681fcf3ce44SJohn Forte 	int		rval = QL_FUNCTION_FAILED;
3682fcf3ce44SJohn Forte 
3683*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
3684fcf3ce44SJohn Forte 
3685*4c3888b8SHans Rosenfeld 	if (ha->topology & QL_FABRIC_CONNECTION) {
3686*4c3888b8SHans Rosenfeld 		/* Test switch fabric controller present. */
3687*4c3888b8SHans Rosenfeld 		d_id.b24 = FS_FABRIC_F_PORT;
3688fcf3ce44SJohn Forte 		tq = ql_d_id_to_queue(ha, d_id);
3689fcf3ce44SJohn Forte 		if (tq != NULL) {
3690*4c3888b8SHans Rosenfeld 			/* Get port/node names of F_Port. */
3691fcf3ce44SJohn Forte 			(void) ql_get_port_database(ha, tq, PDF_NONE);
3692*4c3888b8SHans Rosenfeld 
3693*4c3888b8SHans Rosenfeld 			d_id.b24 = FS_NAME_SERVER;
3694*4c3888b8SHans Rosenfeld 			tq = ql_d_id_to_queue(ha, d_id);
3695*4c3888b8SHans Rosenfeld 			if (tq != NULL) {
3696*4c3888b8SHans Rosenfeld 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3697*4c3888b8SHans Rosenfeld 				rval = QL_SUCCESS;
3698*4c3888b8SHans Rosenfeld 			}
3699fcf3ce44SJohn Forte 		}
3700fcf3ce44SJohn Forte 	}
3701fcf3ce44SJohn Forte 
3702fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3703fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
3704fcf3ce44SJohn Forte 	} else {
3705fcf3ce44SJohn Forte 		/*EMPTY*/
3706*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
3707fcf3ce44SJohn Forte 	}
3708fcf3ce44SJohn Forte 	return (rval);
3709fcf3ce44SJohn Forte }
3710fcf3ce44SJohn Forte 
3711fcf3ce44SJohn Forte /*
3712fcf3ce44SJohn Forte  * ql_reset_chip
3713fcf3ce44SJohn Forte  *	Reset ISP chip.
3714fcf3ce44SJohn Forte  *
3715fcf3ce44SJohn Forte  * Input:
3716fcf3ce44SJohn Forte  *	ha = adapter block pointer.
3717fcf3ce44SJohn Forte  *	All activity on chip must be already stopped.
3718fcf3ce44SJohn Forte  *	ADAPTER_STATE_LOCK must be released.
3719fcf3ce44SJohn Forte  *
3720fcf3ce44SJohn Forte  * Context:
3721fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3722fcf3ce44SJohn Forte  */
3723fcf3ce44SJohn Forte void
ql_reset_chip(ql_adapter_state_t * vha)3724fcf3ce44SJohn Forte ql_reset_chip(ql_adapter_state_t *vha)
3725fcf3ce44SJohn Forte {
3726fcf3ce44SJohn Forte 	uint32_t		cnt;
3727fcf3ce44SJohn Forte 	uint16_t		cmd;
3728fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
3729fcf3ce44SJohn Forte 
3730*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
3731fcf3ce44SJohn Forte 
3732fcf3ce44SJohn Forte 	/*
3733fcf3ce44SJohn Forte 	 * accessing pci space while not powered can cause panic's
3734fcf3ce44SJohn Forte 	 * on some platforms (i.e. Sunblade 1000's)
3735fcf3ce44SJohn Forte 	 */
3736fcf3ce44SJohn Forte 	if (ha->power_level == PM_LEVEL_D3) {
3737*4c3888b8SHans Rosenfeld 		QL_PRINT_2(ha, "Low Power exit\n");
3738fcf3ce44SJohn Forte 		return;
3739fcf3ce44SJohn Forte 	}
3740fcf3ce44SJohn Forte 
3741*4c3888b8SHans Rosenfeld 	/* Disable ISP interrupts. */
3742*4c3888b8SHans Rosenfeld 	ql_disable_intr(ha);
3743*4c3888b8SHans Rosenfeld 
3744fcf3ce44SJohn Forte 	/* Reset all outbound mailbox registers */
3745fcf3ce44SJohn Forte 	for (cnt = 0; cnt < ha->reg_off->mbox_cnt; cnt++) {
3746eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0);
3747eb82ff87SDaniel Beauregard 	}
3748eb82ff87SDaniel Beauregard 
3749*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_82XX)) {
3750f885d00fSDaniel Beauregard 		ha->timeout_cnt = 0;
3751eb82ff87SDaniel Beauregard 		ql_8021_reset_chip(ha);
3752*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "8021 exit\n");
3753eb82ff87SDaniel Beauregard 		return;
3754fcf3ce44SJohn Forte 	}
3755fcf3ce44SJohn Forte 
3756*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
3757fcf3ce44SJohn Forte 		ql_reset_24xx_chip(ha);
3758*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "24xx exit\n");
3759fcf3ce44SJohn Forte 		return;
3760fcf3ce44SJohn Forte 	}
3761*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "CFG_ISP_FW_TYPE_1 reset\n");
3762fcf3ce44SJohn Forte 
3763fcf3ce44SJohn Forte 	/*
3764fcf3ce44SJohn Forte 	 * We are going to reset the chip in case of 2300. That might cause
3765fcf3ce44SJohn Forte 	 * a PBM ERR if a DMA transaction is in progress. One way of
3766fcf3ce44SJohn Forte 	 * avoiding it is to disable Bus Master operation before we start
3767fcf3ce44SJohn Forte 	 * the reset activity.
3768fcf3ce44SJohn Forte 	 */
3769fcf3ce44SJohn Forte 	cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
3770fcf3ce44SJohn Forte 	cmd = (uint16_t)(cmd & ~PCI_COMM_ME);
3771fcf3ce44SJohn Forte 	ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3772fcf3ce44SJohn Forte 
3773fcf3ce44SJohn Forte 	/* Pause RISC. */
3774fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
3775fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 30000; cnt++) {
3776fcf3ce44SJohn Forte 		if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
3777fcf3ce44SJohn Forte 			break;
3778fcf3ce44SJohn Forte 		}
3779fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3780fcf3ce44SJohn Forte 	}
3781fcf3ce44SJohn Forte 
3782fcf3ce44SJohn Forte 	/*
3783fcf3ce44SJohn Forte 	 * A call to ql_isr() can still happen through
3784fcf3ce44SJohn Forte 	 * ql_mailbox_command(). So Mark that we are/(will-be)
3785fcf3ce44SJohn Forte 	 * running from rom code now.
3786fcf3ce44SJohn Forte 	 */
3787fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
3788fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FIRMWARE_UP | FIRMWARE_LOADED);
3789fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
3790fcf3ce44SJohn Forte 
3791fcf3ce44SJohn Forte 	/* Select FPM registers. */
3792fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0x20);
3793fcf3ce44SJohn Forte 
3794fcf3ce44SJohn Forte 	/* FPM Soft Reset. */
3795fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, fpm_diag_config, 0x100);
3796fcf3ce44SJohn Forte 
3797fcf3ce44SJohn Forte 	/* Toggle FPM reset for 2300 */
3798*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_2363)) {
3799fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fpm_diag_config, 0);
3800fcf3ce44SJohn Forte 	}
3801fcf3ce44SJohn Forte 
3802fcf3ce44SJohn Forte 	/* Select frame buffer registers. */
3803fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0x10);
3804fcf3ce44SJohn Forte 
3805fcf3ce44SJohn Forte 	/* Reset frame buffer FIFOs. */
3806*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_2363)) {
3807fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fb_cmd, 0x00fc);
3808fcf3ce44SJohn Forte 		/* read back fb_cmd until zero or 3 seconds max */
3809fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 300000; cnt++) {
3810fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, fb_cmd) & 0xff) == 0) {
3811fcf3ce44SJohn Forte 				break;
3812fcf3ce44SJohn Forte 			}
3813fcf3ce44SJohn Forte 			drv_usecwait(10);
3814fcf3ce44SJohn Forte 		}
3815*4c3888b8SHans Rosenfeld 	} else {
3816fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fb_cmd, 0xa000);
3817fcf3ce44SJohn Forte 	}
3818fcf3ce44SJohn Forte 
3819fcf3ce44SJohn Forte 	/* Select RISC module registers. */
3820fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0);
3821fcf3ce44SJohn Forte 
3822fcf3ce44SJohn Forte 	/* Reset RISC module. */
3823fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
3824fcf3ce44SJohn Forte 
3825fcf3ce44SJohn Forte 	/* Reset ISP semaphore. */
3826fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, semaphore, 0);
3827fcf3ce44SJohn Forte 
3828fcf3ce44SJohn Forte 	/* Release RISC module. */
3829fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3830fcf3ce44SJohn Forte 
3831fcf3ce44SJohn Forte 	/* Insure mailbox registers are free. */
3832fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
3833fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_CLR_HOST_INT);
3834a2b3ff35SDaniel Beauregard 
3835a2b3ff35SDaniel Beauregard 	/* clear the mailbox command pointer. */
3836*4c3888b8SHans Rosenfeld 	INTR_LOCK(ha);
3837*4c3888b8SHans Rosenfeld 	ha->mcp = NULL;
3838*4c3888b8SHans Rosenfeld 	INTR_UNLOCK(ha);
3839a2b3ff35SDaniel Beauregard 
3840*4c3888b8SHans Rosenfeld 	MBX_REGISTER_LOCK(ha);
3841fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
3842fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
3843*4c3888b8SHans Rosenfeld 	MBX_REGISTER_UNLOCK(ha);
3844fcf3ce44SJohn Forte 
3845fcf3ce44SJohn Forte 	/* Bus Master is disabled so chip reset is safe. */
3846*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_2363)) {
3847fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, ISP_RESET);
3848fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3849fcf3ce44SJohn Forte 
3850fcf3ce44SJohn Forte 		/* Wait for reset to finish. */
3851fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 30000; cnt++) {
3852fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
3853fcf3ce44SJohn Forte 				break;
3854fcf3ce44SJohn Forte 			}
3855fcf3ce44SJohn Forte 			drv_usecwait(MILLISEC);
3856fcf3ce44SJohn Forte 		}
3857fcf3ce44SJohn Forte 	}
3858fcf3ce44SJohn Forte 
3859fcf3ce44SJohn Forte 	/* Wait for RISC to recover from reset. */
3860fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 30000; cnt++) {
3861*4c3888b8SHans Rosenfeld 		if (RD16_IO_REG(ha, mailbox_out[0]) != MBS_ROM_BUSY) {
3862fcf3ce44SJohn Forte 			break;
3863fcf3ce44SJohn Forte 		}
3864fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3865fcf3ce44SJohn Forte 	}
3866fcf3ce44SJohn Forte 
3867fcf3ce44SJohn Forte 	/* restore bus master */
3868fcf3ce44SJohn Forte 	cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
3869fcf3ce44SJohn Forte 	cmd = (uint16_t)(cmd | PCI_COMM_ME);
3870fcf3ce44SJohn Forte 	ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3871fcf3ce44SJohn Forte 
3872fcf3ce44SJohn Forte 	/* Disable RISC pause on FPM parity error. */
3873fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_DISABLE_PARITY_PAUSE);
3874fcf3ce44SJohn Forte 
3875*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_22XX) &&
3876*4c3888b8SHans Rosenfeld 	    RD16_IO_REG(ha, mailbox_out[7]) == 4) {
3877*4c3888b8SHans Rosenfeld 		ha->fw_transfer_size = 128;
3878*4c3888b8SHans Rosenfeld 	}
3879*4c3888b8SHans Rosenfeld 
3880fcf3ce44SJohn Forte 	/* Initialize probe registers */
3881fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
3882fcf3ce44SJohn Forte 		/* Pause RISC. */
3883fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
3884fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 30000; cnt++) {
3885fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
3886fcf3ce44SJohn Forte 				break;
3887fcf3ce44SJohn Forte 			} else {
3888fcf3ce44SJohn Forte 				drv_usecwait(MILLISEC);
3889fcf3ce44SJohn Forte 			}
3890fcf3ce44SJohn Forte 		}
3891fcf3ce44SJohn Forte 
3892fcf3ce44SJohn Forte 		/* Select FPM registers. */
3893fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, 0x30);
3894fcf3ce44SJohn Forte 
3895fcf3ce44SJohn Forte 		/* Set probe register */
3896eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[23], 0x204c);
3897fcf3ce44SJohn Forte 
3898fcf3ce44SJohn Forte 		/* Select RISC module registers. */
3899fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, 0);
3900fcf3ce44SJohn Forte 
3901fcf3ce44SJohn Forte 		/* Release RISC module. */
3902fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3903fcf3ce44SJohn Forte 	}
3904fcf3ce44SJohn Forte 
3905*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
3906fcf3ce44SJohn Forte }
3907fcf3ce44SJohn Forte 
3908fcf3ce44SJohn Forte /*
3909fcf3ce44SJohn Forte  * ql_reset_24xx_chip
3910fcf3ce44SJohn Forte  *	Reset ISP24xx chip.
3911fcf3ce44SJohn Forte  *
3912fcf3ce44SJohn Forte  * Input:
3913fcf3ce44SJohn Forte  *	ha = adapter block pointer.
3914fcf3ce44SJohn Forte  *	All activity on chip must be already stopped.
3915fcf3ce44SJohn Forte  *
3916fcf3ce44SJohn Forte  * Context:
3917fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3918fcf3ce44SJohn Forte  */
3919*4c3888b8SHans Rosenfeld static void
ql_reset_24xx_chip(ql_adapter_state_t * ha)3920fcf3ce44SJohn Forte ql_reset_24xx_chip(ql_adapter_state_t *ha)
3921fcf3ce44SJohn Forte {
3922fcf3ce44SJohn Forte 	uint32_t	timer, stat;
3923fcf3ce44SJohn Forte 
3924*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
3925*4c3888b8SHans Rosenfeld 
3926fcf3ce44SJohn Forte 	/* Shutdown DMA. */
3927*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_MWB_4096_SUPPORT)) {
3928*4c3888b8SHans Rosenfeld 		WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN | MWB_4096_BYTES);
3929*4c3888b8SHans Rosenfeld 	} else {
3930*4c3888b8SHans Rosenfeld 		WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN);
3931*4c3888b8SHans Rosenfeld 	}
3932fcf3ce44SJohn Forte 
3933fcf3ce44SJohn Forte 	/* Wait for DMA to stop. */
3934fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3935fcf3ce44SJohn Forte 		if ((RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE) == 0) {
3936fcf3ce44SJohn Forte 			break;
3937fcf3ce44SJohn Forte 		}
3938fcf3ce44SJohn Forte 		drv_usecwait(100);
3939fcf3ce44SJohn Forte 	}
3940fcf3ce44SJohn Forte 
3941fcf3ce44SJohn Forte 	/* Stop the firmware. */
3942fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3943eb82ff87SDaniel Beauregard 	WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
3944*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[1], 0);
3945*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[2], 0);
3946*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[3], 0);
3947*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[4], 0);
3948*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[5], 0);
3949*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[6], 0);
3950*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[7], 0);
3951*4c3888b8SHans Rosenfeld 	WRT16_IO_REG(ha, mailbox_in[8], 0);
3952fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
3953fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3954eb82ff87SDaniel Beauregard 		stat = RD32_IO_REG(ha, risc2host);
3955fcf3ce44SJohn Forte 		if (stat & BIT_15) {
3956fcf3ce44SJohn Forte 			if ((stat & 0xff) < 0x12) {
3957fcf3ce44SJohn Forte 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3958fcf3ce44SJohn Forte 				break;
3959fcf3ce44SJohn Forte 			}
3960fcf3ce44SJohn Forte 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3961fcf3ce44SJohn Forte 		}
3962fcf3ce44SJohn Forte 		drv_usecwait(100);
3963fcf3ce44SJohn Forte 	}
3964fcf3ce44SJohn Forte 
3965fcf3ce44SJohn Forte 	/* Reset the chip. */
3966*4c3888b8SHans Rosenfeld 	WRT32_IO_REG(ha, ctrl_status, ISP_RESET);
3967fcf3ce44SJohn Forte 	drv_usecwait(100);
3968fcf3ce44SJohn Forte 
3969*4c3888b8SHans Rosenfeld 	/* Wait for RISC to recover from reset. */
3970*4c3888b8SHans Rosenfeld 	for (timer = 30000; timer; timer--) {
3971*4c3888b8SHans Rosenfeld 		ha->rom_status = RD16_IO_REG(ha, mailbox_out[0]);
3972*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_CTRL_278083)) {
3973*4c3888b8SHans Rosenfeld 			/* Wait for RISC to recover from reset. */
3974*4c3888b8SHans Rosenfeld 			if ((ha->rom_status & MBS_ROM_STATUS_MASK) !=
3975*4c3888b8SHans Rosenfeld 			    MBS_ROM_BUSY) {
3976*4c3888b8SHans Rosenfeld 				break;
3977*4c3888b8SHans Rosenfeld 			}
3978*4c3888b8SHans Rosenfeld 		} else {
3979*4c3888b8SHans Rosenfeld 			/* Wait for idle status from ROM firmware. */
3980*4c3888b8SHans Rosenfeld 			if (ha->rom_status == MBS_ROM_IDLE) {
3981*4c3888b8SHans Rosenfeld 				break;
3982*4c3888b8SHans Rosenfeld 			}
3983fcf3ce44SJohn Forte 		}
3984fcf3ce44SJohn Forte 		drv_usecwait(100);
3985fcf3ce44SJohn Forte 	}
3986fcf3ce44SJohn Forte 
3987fcf3ce44SJohn Forte 	/* Wait for reset to finish. */
3988fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3989fcf3ce44SJohn Forte 		if ((RD32_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
3990fcf3ce44SJohn Forte 			break;
3991fcf3ce44SJohn Forte 		}
3992fcf3ce44SJohn Forte 		drv_usecwait(100);
3993fcf3ce44SJohn Forte 	}
3994fcf3ce44SJohn Forte 
3995*4c3888b8SHans Rosenfeld 	ha->adapter_stats->revlvl.isp2200 = RD16_IO_REG(ha, mailbox_out[4]);
3996*4c3888b8SHans Rosenfeld 	ha->adapter_stats->revlvl.risc = RD16_IO_REG(ha, mailbox_out[5]);
3997*4c3888b8SHans Rosenfeld 	ha->adapter_stats->revlvl.frmbfr = RD16_IO_REG(ha, mailbox_out[6]);
3998*4c3888b8SHans Rosenfeld 	ha->adapter_stats->revlvl.riscrom = RD16_IO_REG(ha, mailbox_out[8]);
3999*4c3888b8SHans Rosenfeld 
4000*4c3888b8SHans Rosenfeld 	/* Insure mailbox registers are free. */
4001*4c3888b8SHans Rosenfeld 	WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
4002*4c3888b8SHans Rosenfeld 	WRT32_IO_REG(ha, hccr, HC24_CLR_HOST_INT);
4003*4c3888b8SHans Rosenfeld 
4004a2b3ff35SDaniel Beauregard 	/* clear the mailbox command pointer. */
4005*4c3888b8SHans Rosenfeld 	INTR_LOCK(ha);
4006*4c3888b8SHans Rosenfeld 	ha->mcp = NULL;
4007*4c3888b8SHans Rosenfeld 	INTR_UNLOCK(ha);
4008a2b3ff35SDaniel Beauregard 
4009fcf3ce44SJohn Forte 	/* Insure mailbox registers are free. */
4010*4c3888b8SHans Rosenfeld 	MBX_REGISTER_LOCK(ha);
4011fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
4012fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
4013*4c3888b8SHans Rosenfeld 	MBX_REGISTER_UNLOCK(ha);
4014fcf3ce44SJohn Forte 
40154f8b8adcSDaniel Beauregard 	if (ha->flags & MPI_RESET_NEEDED) {
40164f8b8adcSDaniel Beauregard 		WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
4017eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[0], MBC_RESTART_MPI);
40184f8b8adcSDaniel Beauregard 		WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
40194f8b8adcSDaniel Beauregard 		for (timer = 0; timer < 30000; timer++) {
4020eb82ff87SDaniel Beauregard 			stat = RD32_IO_REG(ha, risc2host);
40214f8b8adcSDaniel Beauregard 			if (stat & BIT_15) {
40224f8b8adcSDaniel Beauregard 				if ((stat & 0xff) < 0x12) {
40234f8b8adcSDaniel Beauregard 					WRT32_IO_REG(ha, hccr,
40244f8b8adcSDaniel Beauregard 					    HC24_CLR_RISC_INT);
40254f8b8adcSDaniel Beauregard 					break;
40264f8b8adcSDaniel Beauregard 				}
40274f8b8adcSDaniel Beauregard 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
40284f8b8adcSDaniel Beauregard 			}
40294f8b8adcSDaniel Beauregard 			drv_usecwait(100);
40304f8b8adcSDaniel Beauregard 		}
40314f8b8adcSDaniel Beauregard 		ADAPTER_STATE_LOCK(ha);
40324f8b8adcSDaniel Beauregard 		ha->flags &= ~MPI_RESET_NEEDED;
40334f8b8adcSDaniel Beauregard 		ADAPTER_STATE_UNLOCK(ha);
40344f8b8adcSDaniel Beauregard 	}
40354f8b8adcSDaniel Beauregard 
4036*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
4037a2b3ff35SDaniel Beauregard }
4038a2b3ff35SDaniel Beauregard 
4039fcf3ce44SJohn Forte /*
4040fcf3ce44SJohn Forte  * ql_abort_isp
4041fcf3ce44SJohn Forte  *	Resets ISP and aborts all outstanding commands.
4042fcf3ce44SJohn Forte  *
4043fcf3ce44SJohn Forte  * Input:
4044fcf3ce44SJohn Forte  *	ha = adapter state pointer.
4045fcf3ce44SJohn Forte  *	DEVICE_QUEUE_LOCK must be released.
4046fcf3ce44SJohn Forte  *
4047fcf3ce44SJohn Forte  * Returns:
4048fcf3ce44SJohn Forte  *	ql local function return status code.
4049fcf3ce44SJohn Forte  *
4050fcf3ce44SJohn Forte  * Context:
4051fcf3ce44SJohn Forte  *	Kernel context.
4052fcf3ce44SJohn Forte  */
4053fcf3ce44SJohn Forte int
ql_abort_isp(ql_adapter_state_t * vha)4054fcf3ce44SJohn Forte ql_abort_isp(ql_adapter_state_t *vha)
4055fcf3ce44SJohn Forte {
4056fcf3ce44SJohn Forte 	ql_link_t		*link, *link2;
4057fcf3ce44SJohn Forte 	uint16_t		index;
4058fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
4059fcf3ce44SJohn Forte 	ql_lun_t		*lq;
4060fcf3ce44SJohn Forte 	int			rval = QL_SUCCESS;
4061fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
4062*4c3888b8SHans Rosenfeld 	boolean_t		abort_loop_down = B_FALSE;
4063fcf3ce44SJohn Forte 
4064*4c3888b8SHans Rosenfeld 	QL_PRINT_2(ha, "started\n");
4065fcf3ce44SJohn Forte 
4066fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
4067fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
4068fcf3ce44SJohn Forte 	if (ha->task_daemon_flags & ABORT_ISP_ACTIVE ||
4069fcf3ce44SJohn Forte 	    (ha->flags & ONLINE) == 0 || ha->flags & ADAPTER_SUSPENDED) {
4070fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
4071*4c3888b8SHans Rosenfeld 		QL_PRINT_2(ha, "already active or suspended tdf=0x%llx, "
4072*4c3888b8SHans Rosenfeld 		    "flgs=0x%llx\n", ha->task_daemon_flags, ha->flags);
4073fcf3ce44SJohn Forte 		return (rval);
4074fcf3ce44SJohn Forte 	}
4075fcf3ce44SJohn Forte 
4076fcf3ce44SJohn Forte 	ha->task_daemon_flags |= ABORT_ISP_ACTIVE;
4077*4c3888b8SHans Rosenfeld 	ha->task_daemon_flags &= ~(MARKER_NEEDED | FIRMWARE_UP |
4078fcf3ce44SJohn Forte 	    FIRMWARE_LOADED);
4079fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
4080fcf3ce44SJohn Forte 		vha->task_daemon_flags &= ~(COMMAND_WAIT_NEEDED |
4081fcf3ce44SJohn Forte 		    LOOP_RESYNC_NEEDED);
4082*4c3888b8SHans Rosenfeld 		vha->task_daemon_flags |= LOOP_DOWN;
4083*4c3888b8SHans Rosenfeld 		if (vha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
4084*4c3888b8SHans Rosenfeld 			abort_loop_down = B_TRUE;
4085*4c3888b8SHans Rosenfeld 			vha->loop_down_timer = LOOP_DOWN_TIMER_START;
4086*4c3888b8SHans Rosenfeld 		}
4087fcf3ce44SJohn Forte 	}
4088fcf3ce44SJohn Forte 
4089fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
4090fcf3ce44SJohn Forte 
4091*4c3888b8SHans Rosenfeld 	ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
4092*4c3888b8SHans Rosenfeld 
4093fcf3ce44SJohn Forte 	if (ha->mailbox_flags & MBX_BUSY_FLG) {
4094fcf3ce44SJohn Forte 		/* Acquire mailbox register lock. */
4095fcf3ce44SJohn Forte 		MBX_REGISTER_LOCK(ha);
4096fcf3ce44SJohn Forte 
4097fcf3ce44SJohn Forte 		/* Wake up mailbox box routine. */
4098fcf3ce44SJohn Forte 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_ABORT);
4099fcf3ce44SJohn Forte 		cv_broadcast(&ha->cv_mbx_intr);
4100fcf3ce44SJohn Forte 
4101fcf3ce44SJohn Forte 		/* Release mailbox register lock. */
4102fcf3ce44SJohn Forte 		MBX_REGISTER_UNLOCK(ha);
4103fcf3ce44SJohn Forte 
4104fcf3ce44SJohn Forte 		/* Wait for mailbox. */
4105fcf3ce44SJohn Forte 		for (index = 100; index &&
4106fcf3ce44SJohn Forte 		    ha->mailbox_flags & MBX_ABORT; index--) {
4107*4c3888b8SHans Rosenfeld 			delay(1);
4108fcf3ce44SJohn Forte 		}
4109fcf3ce44SJohn Forte 	}
4110fcf3ce44SJohn Forte 
4111fcf3ce44SJohn Forte 	/* Wait for commands to end gracefully if not in panic. */
4112fcf3ce44SJohn Forte 	if (ha->flags & PARITY_ERROR) {
4113fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
4114fcf3ce44SJohn Forte 		ha->flags &= ~PARITY_ERROR;
4115fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
4116fcf3ce44SJohn Forte 	} else if (ddi_in_panic() == 0) {
4117fcf3ce44SJohn Forte 		ql_cmd_wait(ha);
4118fcf3ce44SJohn Forte 	}
4119fcf3ce44SJohn Forte 
4120*4c3888b8SHans Rosenfeld 	rval = QL_ABORTED;
4121*4c3888b8SHans Rosenfeld 	if (ha->flags & FW_DUMP_NEEDED) {
4122*4c3888b8SHans Rosenfeld 		rval = ql_binary_fw_dump(ha, TRUE);
4123*4c3888b8SHans Rosenfeld 	}
4124*4c3888b8SHans Rosenfeld 
4125fcf3ce44SJohn Forte 	/* Shutdown IP. */
4126fcf3ce44SJohn Forte 	if (ha->flags & IP_INITIALIZED) {
4127fcf3ce44SJohn Forte 		(void) ql_shutdown_ip(ha);
4128fcf3ce44SJohn Forte 	}
4129fcf3ce44SJohn Forte 
4130*4c3888b8SHans Rosenfeld 	if (ha->task_daemon_flags & ISP_ABORT_NEEDED) {
4131*4c3888b8SHans Rosenfeld 		TASK_DAEMON_LOCK(ha);
4132*4c3888b8SHans Rosenfeld 		ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
4133*4c3888b8SHans Rosenfeld 		TASK_DAEMON_UNLOCK(ha);
4134*4c3888b8SHans Rosenfeld 	}
4135*4c3888b8SHans Rosenfeld 
4136fcf3ce44SJohn Forte 	/* Reset the chip. */
4137*4c3888b8SHans Rosenfeld 	if (rval != QL_SUCCESS) {
4138*4c3888b8SHans Rosenfeld 		rval = QL_SUCCESS;
4139*4c3888b8SHans Rosenfeld 		ql_reset_chip(ha);
4140*4c3888b8SHans Rosenfeld 	}
4141fcf3ce44SJohn Forte 
4142a2b3ff35SDaniel Beauregard 	/*
4143a2b3ff35SDaniel Beauregard 	 * Even though we have waited for outstanding commands to complete,
4144a2b3ff35SDaniel Beauregard 	 * except for ones marked SRB_COMMAND_TIMEOUT, and reset the ISP,
4145a2b3ff35SDaniel Beauregard 	 * there could still be an interrupt thread active.  The interrupt
4146a2b3ff35SDaniel Beauregard 	 * lock will prevent us from getting an sp from the outstanding
4147a2b3ff35SDaniel Beauregard 	 * cmds array that the ISR may be using.
4148a2b3ff35SDaniel Beauregard 	 */
4149a2b3ff35SDaniel Beauregard 
4150fcf3ce44SJohn Forte 	/* Place all commands in outstanding cmd list on device queue. */
4151*4c3888b8SHans Rosenfeld 	ql_requeue_all_cmds(ha);
4152fcf3ce44SJohn Forte 
4153fcf3ce44SJohn Forte 	/*
4154fcf3ce44SJohn Forte 	 * Clear per LUN active count, because there should not be
4155fcf3ce44SJohn Forte 	 * any IO outstanding at this time.
4156fcf3ce44SJohn Forte 	 */
4157fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
4158fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
4159fcf3ce44SJohn Forte 			link = vha->dev[index].first;
4160fcf3ce44SJohn Forte 			while (link != NULL) {
4161fcf3ce44SJohn Forte 				tq = link->base_address;
4162fcf3ce44SJohn Forte 				link = link->next;
4163fcf3ce44SJohn Forte 				DEVICE_QUEUE_LOCK(tq);
4164fcf3ce44SJohn Forte 				tq->outcnt = 0;
4165fcf3ce44SJohn Forte 				tq->flags &= ~TQF_QUEUE_SUSPENDED;
4166fcf3ce44SJohn Forte 				for (link2 = tq->lun_queues.first;
4167fcf3ce44SJohn Forte 				    link2 != NULL; link2 = link2->next) {
4168fcf3ce44SJohn Forte 					lq = link2->base_address;
4169fcf3ce44SJohn Forte 					lq->lun_outcnt = 0;
4170fcf3ce44SJohn Forte 					lq->flags &= ~LQF_UNTAGGED_PENDING;
4171fcf3ce44SJohn Forte 				}
4172fcf3ce44SJohn Forte 				DEVICE_QUEUE_UNLOCK(tq);
4173fcf3ce44SJohn Forte 			}
4174fcf3ce44SJohn Forte 		}
4175fcf3ce44SJohn Forte 	}
4176fcf3ce44SJohn Forte 
4177eb82ff87SDaniel Beauregard 	if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) {
4178*4c3888b8SHans Rosenfeld 		if (ha->dev_state != NX_DEV_READY) {
4179*4c3888b8SHans Rosenfeld 			EL(ha, "dev_state not ready\n");
4180*4c3888b8SHans Rosenfeld 		} else if ((rval = ql_mbx_wrap_test(ha, NULL)) == QL_SUCCESS) {
4181eb82ff87SDaniel Beauregard 			rval = ql_load_isp_firmware(ha);
4182eb82ff87SDaniel Beauregard 		}
4183fcf3ce44SJohn Forte 	}
4184fcf3ce44SJohn Forte 
4185fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
4186fcf3ce44SJohn Forte 	    QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS &&
4187fcf3ce44SJohn Forte 	    (rval = ql_fw_ready(ha, 10)) == QL_SUCCESS) {
4188fcf3ce44SJohn Forte 
4189*4c3888b8SHans Rosenfeld 		/* Enable ISP interrupts. */
4190*4c3888b8SHans Rosenfeld 		if (!(ha->flags & INTERRUPTS_ENABLED)) {
4191*4c3888b8SHans Rosenfeld 			ql_enable_intr(ha);
4192*4c3888b8SHans Rosenfeld 		}
4193*4c3888b8SHans Rosenfeld 
4194fcf3ce44SJohn Forte 		/* If reset abort needed that may have been set. */
4195fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
4196fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED |
4197fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE);
4198fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
4199fcf3ce44SJohn Forte 
4200fcf3ce44SJohn Forte 		/* Set loop online, if it really is. */
4201fcf3ce44SJohn Forte 		ql_loop_online(ha);
4202fcf3ce44SJohn Forte 	} else {
4203fcf3ce44SJohn Forte 		/* Enable ISP interrupts. */
4204*4c3888b8SHans Rosenfeld 		if (!(ha->flags & INTERRUPTS_ENABLED)) {
4205*4c3888b8SHans Rosenfeld 			ql_enable_intr(ha);
4206eb82ff87SDaniel Beauregard 		}
4207fcf3ce44SJohn Forte 
4208fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
4209*4c3888b8SHans Rosenfeld 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
4210*4c3888b8SHans Rosenfeld 			vha->task_daemon_flags |= LOOP_DOWN;
4211*4c3888b8SHans Rosenfeld 		}
4212*4c3888b8SHans Rosenfeld 		ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
4213fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
4214fcf3ce44SJohn Forte 
4215fcf3ce44SJohn Forte 		ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
4216*4c3888b8SHans Rosenfeld 
4217*4c3888b8SHans Rosenfeld 		ql_abort_queues(ha);
4218*4c3888b8SHans Rosenfeld 
4219*4c3888b8SHans Rosenfeld 		TASK_DAEMON_LOCK(ha);
4220*4c3888b8SHans Rosenfeld 		ha->task_daemon_flags &= ~ABORT_ISP_ACTIVE;
4221*4c3888b8SHans Rosenfeld 		TASK_DAEMON_UNLOCK(ha);
4222*4c3888b8SHans Rosenfeld 	}
4223*4c3888b8SHans Rosenfeld 
4224*4c3888b8SHans Rosenfeld 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
4225*4c3888b8SHans Rosenfeld 		if (!(vha->task_daemon_flags & LOOP_DOWN) &&
4226*4c3888b8SHans Rosenfeld 		    abort_loop_down == B_TRUE) {
4227*4c3888b8SHans Rosenfeld 			vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
4228*4c3888b8SHans Rosenfeld 		}
4229fcf3ce44SJohn Forte 	}
4230fcf3ce44SJohn Forte 
4231fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
4232fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
4233fcf3ce44SJohn Forte 	} else {
4234fcf3ce44SJohn Forte 		/*EMPTY*/
4235*4c3888b8SHans Rosenfeld 		QL_PRINT_2(ha, "done\n");
4236fcf3ce44SJohn Forte 	}
4237fcf3ce44SJohn Forte 	return (rval);
4238fcf3ce44SJohn Forte }
4239fcf3ce44SJohn Forte 
4240*4c3888b8SHans Rosenfeld /*
4241*4c3888b8SHans Rosenfeld  * ql_requeue_all_cmds
4242*4c3888b8SHans Rosenfeld  *	Requeue all commands.
4243*4c3888b8SHans Rosenfeld  *
4244*4c3888b8SHans Rosenfeld  * Input:
4245*4c3888b8SHans Rosenfeld  *	ha = virtual adapter state pointer.
4246*4c3888b8SHans Rosenfeld  *
4247*4c3888b8SHans Rosenfeld  * Returns:
4248*4c3888b8SHans Rosenfeld  *	ql local function return status code.
4249*4c3888b8SHans Rosenfeld  *
4250*4c3888b8SHans Rosenfeld  * Context:
4251*4c3888b8SHans Rosenfeld  *	Kernel context.
4252*4c3888b8SHans Rosenfeld  */
4253*4c3888b8SHans Rosenfeld void
ql_requeue_all_cmds(ql_adapter_state_t * ha)4254*4c3888b8SHans Rosenfeld ql_requeue_all_cmds(ql_adapter_state_t *ha)
4255*4c3888b8SHans Rosenfeld {
4256*4c3888b8SHans Rosenfeld 	ql_link_t	*link;
4257*4c3888b8SHans Rosenfeld 	ql_tgt_t	*tq;
4258*4c3888b8SHans Rosenfeld 	ql_lun_t	*lq;
4259*4c3888b8SHans Rosenfeld 	ql_srb_t	*sp;
4260*4c3888b8SHans Rosenfeld 	uint16_t	index;
4261*4c3888b8SHans Rosenfeld 
4262*4c3888b8SHans Rosenfeld 	/* Place all commands in outstanding cmd list on device queue. */
4263*4c3888b8SHans Rosenfeld 	for (index = 1; index < ha->osc_max_cnt; index++) {
4264*4c3888b8SHans Rosenfeld 		INTR_LOCK(ha);
4265*4c3888b8SHans Rosenfeld 		REQUEST_RING_LOCK(ha);
4266*4c3888b8SHans Rosenfeld 		if ((link = ha->pending_cmds.first) != NULL) {
4267*4c3888b8SHans Rosenfeld 			sp = link->base_address;
4268*4c3888b8SHans Rosenfeld 			ql_remove_link(&ha->pending_cmds, &sp->cmd);
4269*4c3888b8SHans Rosenfeld 
4270*4c3888b8SHans Rosenfeld 			REQUEST_RING_UNLOCK(ha);
4271*4c3888b8SHans Rosenfeld 			index = 0;
4272*4c3888b8SHans Rosenfeld 		} else {
4273*4c3888b8SHans Rosenfeld 			REQUEST_RING_UNLOCK(ha);
4274*4c3888b8SHans Rosenfeld 			if ((sp = ha->outstanding_cmds[index]) == NULL ||
4275*4c3888b8SHans Rosenfeld 			    sp == QL_ABORTED_SRB(ha)) {
4276*4c3888b8SHans Rosenfeld 				INTR_UNLOCK(ha);
4277*4c3888b8SHans Rosenfeld 				continue;
4278*4c3888b8SHans Rosenfeld 			}
4279*4c3888b8SHans Rosenfeld 		}
4280*4c3888b8SHans Rosenfeld 
4281*4c3888b8SHans Rosenfeld 		/*
4282*4c3888b8SHans Rosenfeld 		 * It's not obvious but the index for commands pulled from
4283*4c3888b8SHans Rosenfeld 		 * pending will be zero and that entry in the outstanding array
4284*4c3888b8SHans Rosenfeld 		 * is not used so nulling it is "no harm, no foul".
4285*4c3888b8SHans Rosenfeld 		 */
4286*4c3888b8SHans Rosenfeld 
4287*4c3888b8SHans Rosenfeld 		ha->outstanding_cmds[index] = NULL;
4288*4c3888b8SHans Rosenfeld 		sp->handle = 0;
4289*4c3888b8SHans Rosenfeld 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
4290*4c3888b8SHans Rosenfeld 
4291*4c3888b8SHans Rosenfeld 		INTR_UNLOCK(ha);
4292*4c3888b8SHans Rosenfeld 
4293*4c3888b8SHans Rosenfeld 		/* If command timeout. */
4294*4c3888b8SHans Rosenfeld 		if (sp->flags & SRB_COMMAND_TIMEOUT) {
4295*4c3888b8SHans Rosenfeld 			sp->pkt->pkt_reason = CS_TIMEOUT;
4296*4c3888b8SHans Rosenfeld 			sp->flags &= ~SRB_RETRY;
4297*4c3888b8SHans Rosenfeld 			sp->flags |= SRB_ISP_COMPLETED;
4298*4c3888b8SHans Rosenfeld 
4299*4c3888b8SHans Rosenfeld 			/* Call done routine to handle completion. */
4300*4c3888b8SHans Rosenfeld 			ql_done(&sp->cmd, B_FALSE);
4301*4c3888b8SHans Rosenfeld 			continue;
4302*4c3888b8SHans Rosenfeld 		}
4303*4c3888b8SHans Rosenfeld 
4304*4c3888b8SHans Rosenfeld 		/* Acquire target queue lock. */
4305*4c3888b8SHans Rosenfeld 		lq = sp->lun_queue;
4306*4c3888b8SHans Rosenfeld 		tq = lq->target_queue;
4307*4c3888b8SHans Rosenfeld 
4308*4c3888b8SHans Rosenfeld 		/* return any tape IO as exchange dropped due to chip reset */
4309*4c3888b8SHans Rosenfeld 		if (tq->flags & TQF_TAPE_DEVICE) {
4310*4c3888b8SHans Rosenfeld 			sp->pkt->pkt_reason = CS_TRANSPORT;
4311*4c3888b8SHans Rosenfeld 			sp->flags &= ~SRB_RETRY;
4312*4c3888b8SHans Rosenfeld 			sp->flags |= SRB_ISP_COMPLETED;
4313*4c3888b8SHans Rosenfeld 
4314*4c3888b8SHans Rosenfeld 			EL(ha, "rtn seq IO, sp=%ph", sp);
4315*4c3888b8SHans Rosenfeld 
4316*4c3888b8SHans Rosenfeld 			/* Call done routine to handle completion. */
4317*4c3888b8SHans Rosenfeld 			ql_done(&sp->cmd, B_FALSE);
4318*4c3888b8SHans Rosenfeld 			continue;
4319*4c3888b8SHans Rosenfeld 		}
4320*4c3888b8SHans Rosenfeld 
4321*4c3888b8SHans Rosenfeld 		DEVICE_QUEUE_LOCK(tq);
4322*4c3888b8SHans Rosenfeld 
4323*4c3888b8SHans Rosenfeld 		/* Reset watchdog time. */
4324*4c3888b8SHans Rosenfeld 		sp->wdg_q_time = sp->init_wdg_q_time;
4325*4c3888b8SHans Rosenfeld 
4326*4c3888b8SHans Rosenfeld 		/* Place request back on top of device queue. */
4327*4c3888b8SHans Rosenfeld 		sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED |
4328*4c3888b8SHans Rosenfeld 		    SRB_RETRY);
4329*4c3888b8SHans Rosenfeld 
4330*4c3888b8SHans Rosenfeld 		ql_add_link_t(&lq->cmd, &sp->cmd);
4331*4c3888b8SHans Rosenfeld 		sp->flags |= SRB_IN_DEVICE_QUEUE;
4332*4c3888b8SHans Rosenfeld 
4333*4c3888b8SHans Rosenfeld 		/* Release target queue lock. */
4334*4c3888b8SHans Rosenfeld 		DEVICE_QUEUE_UNLOCK(tq);
4335*4c3888b8SHans Rosenfeld 	}
4336*4c3888b8SHans Rosenfeld }
4337*4c3888b8SHans Rosenfeld 
4338fcf3ce44SJohn Forte /*
4339fcf3ce44SJohn Forte  * ql_vport_control
4340fcf3ce44SJohn Forte  *	Issue Virtual Port Control command.
4341fcf3ce44SJohn Forte  *
4342fcf3ce44SJohn Forte  * Input:
4343fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4344fcf3ce44SJohn Forte  *	cmd = control command.
4345fcf3ce44SJohn Forte  *
4346fcf3ce44SJohn Forte  * Returns:
4347fcf3ce44SJohn Forte  *	ql local function return status code.
4348fcf3ce44SJohn Forte  *
4349fcf3ce44SJohn Forte  * Context:
4350fcf3ce44SJohn Forte  *	Kernel context.
4351fcf3ce44SJohn Forte  */
4352fcf3ce44SJohn Forte int
ql_vport_control(ql_adapter_state_t * ha,uint8_t cmd)4353fcf3ce44SJohn Forte ql_vport_control(ql_adapter_state_t *ha, uint8_t cmd)
4354fcf3ce44SJohn Forte {
4355fcf3ce44SJohn Forte 	ql_mbx_iocb_t	*pkt;
4356fcf3ce44SJohn Forte 	uint8_t		bit;
4357fcf3ce44SJohn Forte 	int		rval;
4358fcf3ce44SJohn Forte 	uint32_t	pkt_size;
4359fcf3ce44SJohn Forte 
4360*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
4361fcf3ce44SJohn Forte 
4362fcf3ce44SJohn Forte 	if (ha->vp_index != 0) {
4363fcf3ce44SJohn Forte 		pkt_size = sizeof (ql_mbx_iocb_t);
4364fcf3ce44SJohn Forte 		pkt = kmem_zalloc(pkt_size, KM_SLEEP);
4365fcf3ce44SJohn Forte 		if (pkt == NULL) {
4366fcf3ce44SJohn Forte 			EL(ha, "failed, kmem_zalloc\n");
4367fcf3ce44SJohn Forte 			return (QL_MEMORY_ALLOC_FAILED);
4368fcf3ce44SJohn Forte 		}
4369fcf3ce44SJohn Forte 
4370fcf3ce44SJohn Forte 		pkt->vpc.entry_type = VP_CONTROL_TYPE;
4371fcf3ce44SJohn Forte 		pkt->vpc.entry_count = 1;
4372fcf3ce44SJohn Forte 		pkt->vpc.command = cmd;
4373fcf3ce44SJohn Forte 		pkt->vpc.vp_count = 1;
4374*4c3888b8SHans Rosenfeld 		pkt->vpc.fcf_index = ha->fcoe_fcf_idx;
4375fcf3ce44SJohn Forte 		bit = (uint8_t)(ha->vp_index - 1);
4376fcf3ce44SJohn Forte 		pkt->vpc.vp_index[bit / 8] = (uint8_t)
4377fcf3ce44SJohn Forte 		    (pkt->vpc.vp_index[bit / 8] | BIT_0 << bit % 8);
4378fcf3ce44SJohn Forte 
4379fcf3ce44SJohn Forte 		rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
4380fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && pkt->vpc.status != 0) {
4381fcf3ce44SJohn Forte 			rval = QL_COMMAND_ERROR;
4382fcf3ce44SJohn Forte 		}
4383fcf3ce44SJohn Forte 
4384fcf3ce44SJohn Forte 		kmem_free(pkt, pkt_size);
4385fcf3ce44SJohn Forte 	} else {
4386fcf3ce44SJohn Forte 		rval = QL_SUCCESS;
4387fcf3ce44SJohn Forte 	}
4388fcf3ce44SJohn Forte 
4389fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
4390fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
4391fcf3ce44SJohn Forte 	} else {
4392fcf3ce44SJohn Forte 		/*EMPTY*/
4393*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
4394fcf3ce44SJohn Forte 	}
4395fcf3ce44SJohn Forte 	return (rval);
4396fcf3ce44SJohn Forte }
4397fcf3ce44SJohn Forte 
4398fcf3ce44SJohn Forte /*
4399fcf3ce44SJohn Forte  * ql_vport_modify
4400fcf3ce44SJohn Forte  *	Issue of Modify Virtual Port command.
4401fcf3ce44SJohn Forte  *
4402fcf3ce44SJohn Forte  * Input:
4403fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4404fcf3ce44SJohn Forte  *	cmd = command.
4405fcf3ce44SJohn Forte  *	opt = option.
4406fcf3ce44SJohn Forte  *
4407fcf3ce44SJohn Forte  * Context:
4408fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
4409fcf3ce44SJohn Forte  */
4410fcf3ce44SJohn Forte int
ql_vport_modify(ql_adapter_state_t * ha,uint8_t cmd,uint8_t opt)4411fcf3ce44SJohn Forte ql_vport_modify(ql_adapter_state_t *ha, uint8_t cmd, uint8_t opt)
4412fcf3ce44SJohn Forte {
4413fcf3ce44SJohn Forte 	ql_mbx_iocb_t	*pkt;
4414fcf3ce44SJohn Forte 	int		rval;
4415fcf3ce44SJohn Forte 	uint32_t	pkt_size;
4416fcf3ce44SJohn Forte 
4417*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
4418*4c3888b8SHans Rosenfeld 
4419*4c3888b8SHans Rosenfeld 	if (ha->pha->task_daemon_flags & LOOP_DOWN) {
4420*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "loop_down\n");
4421*4c3888b8SHans Rosenfeld 		return (QL_FUNCTION_FAILED);
4422*4c3888b8SHans Rosenfeld 	}
4423fcf3ce44SJohn Forte 
4424fcf3ce44SJohn Forte 	pkt_size = sizeof (ql_mbx_iocb_t);
4425fcf3ce44SJohn Forte 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
4426fcf3ce44SJohn Forte 	if (pkt == NULL) {
4427fcf3ce44SJohn Forte 		EL(ha, "failed, kmem_zalloc\n");
4428fcf3ce44SJohn Forte 		return (QL_MEMORY_ALLOC_FAILED);
4429fcf3ce44SJohn Forte 	}
4430fcf3ce44SJohn Forte 
4431fcf3ce44SJohn Forte 	pkt->vpm.entry_type = VP_MODIFY_TYPE;
4432fcf3ce44SJohn Forte 	pkt->vpm.entry_count = 1;
4433fcf3ce44SJohn Forte 	pkt->vpm.command = cmd;
4434fcf3ce44SJohn Forte 	pkt->vpm.vp_count = 1;
4435fcf3ce44SJohn Forte 	pkt->vpm.first_vp_index = ha->vp_index;
4436fcf3ce44SJohn Forte 	pkt->vpm.first_options = opt;
4437*4c3888b8SHans Rosenfeld 	pkt->vpm.fcf_index = ha->fcoe_fcf_idx;
4438fcf3ce44SJohn Forte 	bcopy(ha->loginparams.nport_ww_name.raw_wwn, pkt->vpm.first_port_name,
4439fcf3ce44SJohn Forte 	    8);
4440fcf3ce44SJohn Forte 	bcopy(ha->loginparams.node_ww_name.raw_wwn, pkt->vpm.first_node_name,
4441fcf3ce44SJohn Forte 	    8);
4442fcf3ce44SJohn Forte 
4443fcf3ce44SJohn Forte 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
4444fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && pkt->vpm.status != 0) {
4445fcf3ce44SJohn Forte 		EL(ha, "failed, ql_issue_mbx_iocb=%xh, status=%xh\n", rval,
4446fcf3ce44SJohn Forte 		    pkt->vpm.status);
4447fcf3ce44SJohn Forte 		rval = QL_COMMAND_ERROR;
4448fcf3ce44SJohn Forte 	}
4449fcf3ce44SJohn Forte 
4450fcf3ce44SJohn Forte 	kmem_free(pkt, pkt_size);
4451fcf3ce44SJohn Forte 
4452fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
4453fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
4454fcf3ce44SJohn Forte 	} else {
4455fcf3ce44SJohn Forte 		/*EMPTY*/
4456*4c3888b8SHans Rosenfeld 		QL_PRINT_10(ha, "done\n");
4457fcf3ce44SJohn Forte 	}
4458fcf3ce44SJohn Forte 	return (rval);
4459fcf3ce44SJohn Forte }
4460fcf3ce44SJohn Forte 
4461fcf3ce44SJohn Forte /*
4462fcf3ce44SJohn Forte  * ql_vport_enable
4463fcf3ce44SJohn Forte  *	Enable virtual port.
4464fcf3ce44SJohn Forte  *
4465fcf3ce44SJohn Forte  * Input:
4466fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4467fcf3ce44SJohn Forte  *
4468fcf3ce44SJohn Forte  * Context:
4469fcf3ce44SJohn Forte  *	Kernel context.
4470fcf3ce44SJohn Forte  */
4471fcf3ce44SJohn Forte int
ql_vport_enable(ql_adapter_state_t * ha)4472fcf3ce44SJohn Forte ql_vport_enable(ql_adapter_state_t *ha)
4473fcf3ce44SJohn Forte {
4474fcf3ce44SJohn Forte 	int	timer;
4475fcf3ce44SJohn Forte 
4476*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
4477fcf3ce44SJohn Forte 
4478fcf3ce44SJohn Forte 	ha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
4479fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
4480fcf3ce44SJohn Forte 	ha->task_daemon_flags |= LOOP_DOWN;
4481fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FC_STATE_CHANGE | STATE_ONLINE);
4482fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
4483fcf3ce44SJohn Forte 
4484fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
4485fcf3ce44SJohn Forte 	ha->flags |= VP_ENABLED;
4486*4c3888b8SHans Rosenfeld 	ha->flags &= ~VP_ID_NOT_ACQUIRED;
4487fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
4488*4c3888b8SHans Rosenfeld 	ha->fcoe_fcf_idx = 0;
4489fcf3ce44SJohn Forte 
4490fcf3ce44SJohn Forte 	if (ql_vport_modify(ha, VPM_MODIFY_ENABLE, VPO_TARGET_MODE_DISABLED |
4491fcf3ce44SJohn Forte 	    VPO_INITIATOR_MODE_ENABLED | VPO_ENABLED) != QL_SUCCESS) {
4492*4c3888b8SHans Rosenfeld 		QL_PRINT_2(ha, "failed to enable virtual port\n");
4493fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
4494fcf3ce44SJohn Forte 	}
4495fcf3ce44SJohn Forte 	if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) {
4496fcf3ce44SJohn Forte 		/* Wait for loop to come up. */
4497fcf3ce44SJohn Forte 		for (timer = 0; timer < 3000 &&
4498fcf3ce44SJohn Forte 		    !(ha->task_daemon_flags & STATE_ONLINE);
4499fcf3ce44SJohn Forte 		    timer++) {
4500*4c3888b8SHans Rosenfeld 			if (ha->flags & VP_ID_NOT_ACQUIRED) {
4501*4c3888b8SHans Rosenfeld 				break;
4502*4c3888b8SHans Rosenfeld 			}
4503fcf3ce44SJohn Forte 			delay(1);
4504fcf3ce44SJohn Forte 		}
4505fcf3ce44SJohn Forte 	}
4506fcf3ce44SJohn Forte 
4507*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
4508fcf3ce44SJohn Forte 
4509fcf3ce44SJohn Forte 	return (QL_SUCCESS);
4510fcf3ce44SJohn Forte }
4511fcf3ce44SJohn Forte 
4512fcf3ce44SJohn Forte /*
4513fcf3ce44SJohn Forte  * ql_vport_create
4514fcf3ce44SJohn Forte  *	Create virtual port context.
4515fcf3ce44SJohn Forte  *
4516fcf3ce44SJohn Forte  * Input:
4517fcf3ce44SJohn Forte  *	ha:	parent adapter state pointer.
4518fcf3ce44SJohn Forte  *	index:	virtual port index number.
4519fcf3ce44SJohn Forte  *
4520fcf3ce44SJohn Forte  * Context:
4521fcf3ce44SJohn Forte  *	Kernel context.
4522fcf3ce44SJohn Forte  */
4523fcf3ce44SJohn Forte ql_adapter_state_t *
ql_vport_create(ql_adapter_state_t * ha,uint8_t index)4524fcf3ce44SJohn Forte ql_vport_create(ql_adapter_state_t *ha, uint8_t index)
4525fcf3ce44SJohn Forte {
4526fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
4527fcf3ce44SJohn Forte 
4528*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
4529fcf3ce44SJohn Forte 
4530fcf3ce44SJohn Forte 	/* Inherit the parents data. */
4531fcf3ce44SJohn Forte 	vha = kmem_alloc(sizeof (ql_adapter_state_t), KM_SLEEP);
4532fcf3ce44SJohn Forte 
4533fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
4534fcf3ce44SJohn Forte 	bcopy(ha, vha, sizeof (ql_adapter_state_t));
4535fcf3ce44SJohn Forte 	vha->pi_attrs = NULL;
4536fcf3ce44SJohn Forte 	vha->ub_outcnt = 0;
4537fcf3ce44SJohn Forte 	vha->ub_allocated = 0;
4538fcf3ce44SJohn Forte 	vha->flags = 0;
4539fcf3ce44SJohn Forte 	vha->task_daemon_flags = 0;
4540fcf3ce44SJohn Forte 	ha->vp_next = vha;
4541fcf3ce44SJohn Forte 	vha->pha = ha;
4542fcf3ce44SJohn Forte 	vha->vp_index = index;
4543fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
4544fcf3ce44SJohn Forte 
4545fcf3ce44SJohn Forte 	vha->hba.next = NULL;
4546fcf3ce44SJohn Forte 	vha->hba.prev = NULL;
4547fcf3ce44SJohn Forte 	vha->hba.base_address = vha;
4548fcf3ce44SJohn Forte 	vha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
4549fcf3ce44SJohn Forte 	vha->dev = kmem_zalloc(sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE,
4550fcf3ce44SJohn Forte 	    KM_SLEEP);
4551fcf3ce44SJohn Forte 	vha->ub_array = kmem_zalloc(sizeof (*vha->ub_array) * QL_UB_LIMIT,
4552fcf3ce44SJohn Forte 	    KM_SLEEP);
4553fcf3ce44SJohn Forte 
4554*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
4555fcf3ce44SJohn Forte 
4556fcf3ce44SJohn Forte 	return (vha);
4557fcf3ce44SJohn Forte }
4558fcf3ce44SJohn Forte 
4559fcf3ce44SJohn Forte /*
4560fcf3ce44SJohn Forte  * ql_vport_destroy
4561fcf3ce44SJohn Forte  *	Destroys virtual port context.
4562fcf3ce44SJohn Forte  *
4563fcf3ce44SJohn Forte  * Input:
4564fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4565fcf3ce44SJohn Forte  *
4566fcf3ce44SJohn Forte  * Context:
4567fcf3ce44SJohn Forte  *	Kernel context.
4568fcf3ce44SJohn Forte  */
4569fcf3ce44SJohn Forte void
ql_vport_destroy(ql_adapter_state_t * ha)4570fcf3ce44SJohn Forte ql_vport_destroy(ql_adapter_state_t *ha)
4571fcf3ce44SJohn Forte {
4572fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
4573fcf3ce44SJohn Forte 
4574*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
4575fcf3ce44SJohn Forte 
4576fcf3ce44SJohn Forte 	/* Remove port from list. */
4577fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
4578fcf3ce44SJohn Forte 	for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
4579fcf3ce44SJohn Forte 		if (vha->vp_next == ha) {
4580fcf3ce44SJohn Forte 			vha->vp_next = ha->vp_next;
4581fcf3ce44SJohn Forte 			break;
4582fcf3ce44SJohn Forte 		}
4583fcf3ce44SJohn Forte 	}
4584fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
4585fcf3ce44SJohn Forte 
4586fcf3ce44SJohn Forte 	if (ha->ub_array != NULL) {
4587fcf3ce44SJohn Forte 		kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
4588fcf3ce44SJohn Forte 	}
4589fcf3ce44SJohn Forte 	if (ha->dev != NULL) {
4590fcf3ce44SJohn Forte 		kmem_free(ha->dev, sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE);
4591fcf3ce44SJohn Forte 	}
4592fcf3ce44SJohn Forte 	kmem_free(ha, sizeof (ql_adapter_state_t));
4593fcf3ce44SJohn Forte 
4594*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
4595fcf3ce44SJohn Forte }
4596f33c1cdbSDaniel Beauregard 
4597f33c1cdbSDaniel Beauregard /*
4598f33c1cdbSDaniel Beauregard  * ql_mps_reset
4599f33c1cdbSDaniel Beauregard  *	Reset MPS for FCoE functions.
4600f33c1cdbSDaniel Beauregard  *
4601f33c1cdbSDaniel Beauregard  * Input:
4602f33c1cdbSDaniel Beauregard  *	ha = virtual adapter state pointer.
4603f33c1cdbSDaniel Beauregard  *
4604f33c1cdbSDaniel Beauregard  * Context:
4605f33c1cdbSDaniel Beauregard  *	Kernel context.
4606f33c1cdbSDaniel Beauregard  */
4607f33c1cdbSDaniel Beauregard static void
ql_mps_reset(ql_adapter_state_t * ha)4608f33c1cdbSDaniel Beauregard ql_mps_reset(ql_adapter_state_t *ha)
4609f33c1cdbSDaniel Beauregard {
4610f33c1cdbSDaniel Beauregard 	uint32_t	data, dctl = 1000;
4611f33c1cdbSDaniel Beauregard 
4612f33c1cdbSDaniel Beauregard 	do {
4613f33c1cdbSDaniel Beauregard 		if (dctl-- == 0 || ql_wrt_risc_ram_word(ha, 0x7c00, 1) !=
4614f33c1cdbSDaniel Beauregard 		    QL_SUCCESS) {
4615f33c1cdbSDaniel Beauregard 			return;
4616f33c1cdbSDaniel Beauregard 		}
4617f33c1cdbSDaniel Beauregard 		if (ql_rd_risc_ram_word(ha, 0x7c00, &data) != QL_SUCCESS) {
4618c1374a13SSurya Prakki 			(void) ql_wrt_risc_ram_word(ha, 0x7c00, 0);
4619f33c1cdbSDaniel Beauregard 			return;
4620f33c1cdbSDaniel Beauregard 		}
4621f33c1cdbSDaniel Beauregard 	} while (!(data & BIT_0));
4622f33c1cdbSDaniel Beauregard 
4623f33c1cdbSDaniel Beauregard 	if (ql_rd_risc_ram_word(ha, 0x7A15, &data) == QL_SUCCESS) {
4624f33c1cdbSDaniel Beauregard 		dctl = (uint16_t)ql_pci_config_get16(ha, 0x54);
4625*4c3888b8SHans Rosenfeld 		if ((data & 0xe0) < (dctl & 0xe0)) {
4626*4c3888b8SHans Rosenfeld 			data &= 0xff1f;
4627*4c3888b8SHans Rosenfeld 			data |= dctl & 0xe0;
4628*4c3888b8SHans Rosenfeld 			(void) ql_wrt_risc_ram_word(ha, 0x7A15, data);
4629*4c3888b8SHans Rosenfeld 		} else if ((data & 0xe0) != (dctl & 0xe0)) {
4630f33c1cdbSDaniel Beauregard 			data &= 0xff1f;
4631f33c1cdbSDaniel Beauregard 			data |= dctl & 0xe0;
4632c1374a13SSurya Prakki 			(void) ql_wrt_risc_ram_word(ha, 0x7A15, data);
4633f33c1cdbSDaniel Beauregard 		}
4634f33c1cdbSDaniel Beauregard 	}
4635c1374a13SSurya Prakki 	(void) ql_wrt_risc_ram_word(ha, 0x7c00, 0);
4636f33c1cdbSDaniel Beauregard }
4637*4c3888b8SHans Rosenfeld 
4638*4c3888b8SHans Rosenfeld /*
4639*4c3888b8SHans Rosenfeld  * ql_update_dev
4640*4c3888b8SHans Rosenfeld  *	Updates device status on loop reconfigure.
4641*4c3888b8SHans Rosenfeld  *
4642*4c3888b8SHans Rosenfeld  * Input:
4643*4c3888b8SHans Rosenfeld  *	ha:	adapter state pointer.
4644*4c3888b8SHans Rosenfeld  *	index:	list index of device data.
4645*4c3888b8SHans Rosenfeld  *
4646*4c3888b8SHans Rosenfeld  * Context:
4647*4c3888b8SHans Rosenfeld  *	Kernel context.
4648*4c3888b8SHans Rosenfeld  */
4649*4c3888b8SHans Rosenfeld static void
ql_update_dev(ql_adapter_state_t * ha,uint32_t index)4650*4c3888b8SHans Rosenfeld ql_update_dev(ql_adapter_state_t *ha, uint32_t index)
4651*4c3888b8SHans Rosenfeld {
4652*4c3888b8SHans Rosenfeld 	ql_link_t	*link;
4653*4c3888b8SHans Rosenfeld 	ql_tgt_t	*tq;
4654*4c3888b8SHans Rosenfeld 	int		rval;
4655*4c3888b8SHans Rosenfeld 
4656*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
4657*4c3888b8SHans Rosenfeld 
4658*4c3888b8SHans Rosenfeld 	link = ha->dev[index].first;
4659*4c3888b8SHans Rosenfeld 	while (link != NULL) {
4660*4c3888b8SHans Rosenfeld 		tq = link->base_address;
4661*4c3888b8SHans Rosenfeld 		link = link->next;
4662*4c3888b8SHans Rosenfeld 
4663*4c3888b8SHans Rosenfeld 		if (tq->loop_id & PORT_LOST_ID &&
4664*4c3888b8SHans Rosenfeld 		    !(tq->flags & (TQF_INITIATOR_DEVICE | TQF_FABRIC_DEVICE))) {
4665*4c3888b8SHans Rosenfeld 
4666*4c3888b8SHans Rosenfeld 			tq->loop_id &= ~PORT_LOST_ID;
4667*4c3888b8SHans Rosenfeld 
4668*4c3888b8SHans Rosenfeld 			if (VALID_DEVICE_ID(ha, tq->loop_id)) {
4669*4c3888b8SHans Rosenfeld 				/* implicit logo due to fw issue */
4670*4c3888b8SHans Rosenfeld 				rval = ql_get_port_database(ha, tq, PDF_NONE);
4671*4c3888b8SHans Rosenfeld 
4672*4c3888b8SHans Rosenfeld 				if (rval == QL_NOT_LOGGED_IN) {
4673*4c3888b8SHans Rosenfeld 					if (tq->master_state ==
4674*4c3888b8SHans Rosenfeld 					    PD_STATE_PORT_UNAVAILABLE) {
4675*4c3888b8SHans Rosenfeld 						(void) ql_logout_fabric_port(
4676*4c3888b8SHans Rosenfeld 						    ha, tq);
4677*4c3888b8SHans Rosenfeld 						tq->loop_id = PORT_NO_LOOP_ID;
4678*4c3888b8SHans Rosenfeld 					}
4679*4c3888b8SHans Rosenfeld 				} else if (rval == QL_SUCCESS) {
4680*4c3888b8SHans Rosenfeld 					tq->loop_id = PORT_NO_LOOP_ID;
4681*4c3888b8SHans Rosenfeld 				}
4682*4c3888b8SHans Rosenfeld 			}
4683*4c3888b8SHans Rosenfeld 		} else if (ha->topology & QL_NL_PORT &&
4684*4c3888b8SHans Rosenfeld 		    tq->flags & TQF_FABRIC_DEVICE) {
4685*4c3888b8SHans Rosenfeld 
4686*4c3888b8SHans Rosenfeld 			tq->loop_id &= ~PORT_LOST_ID;
4687*4c3888b8SHans Rosenfeld 
4688*4c3888b8SHans Rosenfeld 			if (VALID_DEVICE_ID(ha, tq->loop_id)) {
4689*4c3888b8SHans Rosenfeld 				/* implicit logo due to fw issue */
4690*4c3888b8SHans Rosenfeld 				rval = ql_get_port_database(ha, tq, PDF_NONE);
4691*4c3888b8SHans Rosenfeld 
4692*4c3888b8SHans Rosenfeld 				if (rval == QL_NOT_LOGGED_IN) {
4693*4c3888b8SHans Rosenfeld 					if (tq->master_state ==
4694*4c3888b8SHans Rosenfeld 					    PD_STATE_PORT_UNAVAILABLE) {
4695*4c3888b8SHans Rosenfeld 						(void) ql_logout_fabric_port(
4696*4c3888b8SHans Rosenfeld 						    ha, tq);
4697*4c3888b8SHans Rosenfeld 						/*
4698*4c3888b8SHans Rosenfeld 						 * fabric to AL topo change
4699*4c3888b8SHans Rosenfeld 						 */
4700*4c3888b8SHans Rosenfeld 						tq->loop_id = PORT_NO_LOOP_ID;
4701*4c3888b8SHans Rosenfeld 					}
4702*4c3888b8SHans Rosenfeld 				} else if (rval == QL_SUCCESS) {
4703*4c3888b8SHans Rosenfeld 					/*
4704*4c3888b8SHans Rosenfeld 					 * Normally this is 7fe,
4705*4c3888b8SHans Rosenfeld 					 * Don't issue logo, it causes
4706*4c3888b8SHans Rosenfeld 					 * logo in single tgt AL.
4707*4c3888b8SHans Rosenfeld 					 */
4708*4c3888b8SHans Rosenfeld 					tq->loop_id = PORT_NO_LOOP_ID;
4709*4c3888b8SHans Rosenfeld 				}
4710*4c3888b8SHans Rosenfeld 			}
4711*4c3888b8SHans Rosenfeld 		}
4712*4c3888b8SHans Rosenfeld 	}
4713*4c3888b8SHans Rosenfeld 
4714*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
4715*4c3888b8SHans Rosenfeld }
4716