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 
22c1fad183SDaniel Beauregard /* Copyright 2010 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25*f885d00fSDaniel Beauregard  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28c1fad183SDaniel Beauregard #pragma ident	"Copyright 2010 QLogic Corporation; ql_init.c"
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /*
31fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32fcf3ce44SJohn Forte  *
33fcf3ce44SJohn Forte  * ***********************************************************************
34fcf3ce44SJohn Forte  * *									**
35fcf3ce44SJohn Forte  * *				NOTICE					**
36c1fad183SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
37fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
38fcf3ce44SJohn Forte  * *									**
39fcf3ce44SJohn Forte  * ***********************************************************************
40fcf3ce44SJohn Forte  *
41fcf3ce44SJohn Forte  */
42fcf3ce44SJohn Forte 
43fcf3ce44SJohn Forte #include <ql_apps.h>
44fcf3ce44SJohn Forte #include <ql_api.h>
45fcf3ce44SJohn Forte #include <ql_debug.h>
46fcf3ce44SJohn Forte #include <ql_init.h>
47fcf3ce44SJohn Forte #include <ql_iocb.h>
48fcf3ce44SJohn Forte #include <ql_isr.h>
49fcf3ce44SJohn Forte #include <ql_mbx.h>
50eb82ff87SDaniel Beauregard #include <ql_nx.h>
51fcf3ce44SJohn Forte #include <ql_xioctl.h>
52fcf3ce44SJohn Forte 
53fcf3ce44SJohn Forte /*
54fcf3ce44SJohn Forte  * Local data
55fcf3ce44SJohn Forte  */
56fcf3ce44SJohn Forte 
57fcf3ce44SJohn Forte /*
58fcf3ce44SJohn Forte  * Local prototypes
59fcf3ce44SJohn Forte  */
60fcf3ce44SJohn Forte static uint16_t ql_nvram_request(ql_adapter_state_t *, uint32_t);
61fcf3ce44SJohn Forte static int ql_nvram_24xx_config(ql_adapter_state_t *);
62fcf3ce44SJohn Forte static void ql_23_properties(ql_adapter_state_t *, nvram_t *);
63fcf3ce44SJohn Forte static void ql_24xx_properties(ql_adapter_state_t *, nvram_24xx_t *);
64fcf3ce44SJohn Forte static int ql_check_isp_firmware(ql_adapter_state_t *);
65fcf3ce44SJohn Forte static int ql_chip_diag(ql_adapter_state_t *);
66fcf3ce44SJohn Forte static int ql_load_flash_fw(ql_adapter_state_t *);
67fcf3ce44SJohn Forte static int ql_configure_loop(ql_adapter_state_t *);
68fcf3ce44SJohn Forte static int ql_configure_hba(ql_adapter_state_t *);
69fcf3ce44SJohn Forte static int ql_configure_fabric(ql_adapter_state_t *);
70fcf3ce44SJohn Forte static int ql_configure_device_d_id(ql_adapter_state_t *);
71fcf3ce44SJohn Forte static void ql_set_max_read_req(ql_adapter_state_t *);
725dfd244aSDaniel Beauregard static void ql_configure_n_port_info(ql_adapter_state_t *);
73a2b3ff35SDaniel Beauregard static void ql_clear_mcp(ql_adapter_state_t *);
74f33c1cdbSDaniel Beauregard static void ql_mps_reset(ql_adapter_state_t *);
75a2b3ff35SDaniel Beauregard 
76fcf3ce44SJohn Forte /*
77fcf3ce44SJohn Forte  * ql_initialize_adapter
78fcf3ce44SJohn Forte  *	Initialize board.
79fcf3ce44SJohn Forte  *
80fcf3ce44SJohn Forte  * Input:
81fcf3ce44SJohn Forte  *	ha = adapter state pointer.
82fcf3ce44SJohn Forte  *
83fcf3ce44SJohn Forte  * Returns:
84fcf3ce44SJohn Forte  *	ql local function return status code.
85fcf3ce44SJohn Forte  *
86fcf3ce44SJohn Forte  * Context:
87fcf3ce44SJohn Forte  *	Kernel context.
88fcf3ce44SJohn Forte  */
89fcf3ce44SJohn Forte int
90fcf3ce44SJohn Forte ql_initialize_adapter(ql_adapter_state_t *ha)
91fcf3ce44SJohn Forte {
92fcf3ce44SJohn Forte 	int			rval;
93fcf3ce44SJohn Forte 	class_svc_param_t	*class3_param;
94fcf3ce44SJohn Forte 	caddr_t			msg;
95fcf3ce44SJohn Forte 	la_els_logi_t		*els = &ha->loginparams;
96fcf3ce44SJohn Forte 	int			retries = 5;
97fcf3ce44SJohn Forte 
98fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
99fcf3ce44SJohn Forte 
100fcf3ce44SJohn Forte 	do {
101fcf3ce44SJohn Forte 		/* Clear adapter flags. */
102fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
103fcf3ce44SJohn Forte 		ha->task_daemon_flags &= TASK_DAEMON_STOP_FLG |
104fcf3ce44SJohn Forte 		    TASK_DAEMON_SLEEPING_FLG | TASK_DAEMON_ALIVE_FLG |
105fcf3ce44SJohn Forte 		    TASK_DAEMON_IDLE_CHK_FLG;
106fcf3ce44SJohn Forte 		ha->task_daemon_flags |= LOOP_DOWN;
107fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
108fcf3ce44SJohn Forte 
109fcf3ce44SJohn Forte 		ha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
110fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
11116dd44c2SDaniel Beauregard 		ha->flags |= ABORT_CMDS_LOOP_DOWN_TMO;
112fcf3ce44SJohn Forte 		ha->flags &= ~ONLINE;
113fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
114fcf3ce44SJohn Forte 
115fcf3ce44SJohn Forte 		ha->state = FC_STATE_OFFLINE;
116fcf3ce44SJohn Forte 		msg = "Loop OFFLINE";
117fcf3ce44SJohn Forte 
118fcf3ce44SJohn Forte 		rval = ql_pci_sbus_config(ha);
119fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
120fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
121fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
122fcf3ce44SJohn Forte 				EL(ha, "ql_pci_sbus_cfg, isp_abort_needed\n");
123fcf3ce44SJohn Forte 				ha->task_daemon_flags |= ISP_ABORT_NEEDED;
124fcf3ce44SJohn Forte 			}
125fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
126fcf3ce44SJohn Forte 			continue;
127fcf3ce44SJohn Forte 		}
128fcf3ce44SJohn Forte 
1295dfd244aSDaniel Beauregard 		(void) ql_setup_fcache(ha);
130fcf3ce44SJohn Forte 
131fcf3ce44SJohn Forte 		/* Reset ISP chip. */
132fcf3ce44SJohn Forte 		ql_reset_chip(ha);
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte 		/* Get NVRAM configuration if needed. */
135fcf3ce44SJohn Forte 		if (ha->init_ctrl_blk.cb.version == 0) {
136fcf3ce44SJohn Forte 			(void) ql_nvram_config(ha);
137fcf3ce44SJohn Forte 		}
138fcf3ce44SJohn Forte 
139fcf3ce44SJohn Forte 		/* Set login parameters. */
140eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_24258081)) {
141fcf3ce44SJohn Forte 			els->common_service.rx_bufsize = CHAR_TO_SHORT(
142fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb24.max_frame_length[0],
143fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb24.max_frame_length[1]);
144fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb24.port_name[0],
145fcf3ce44SJohn Forte 			    (void *)&els->nport_ww_name.raw_wwn[0], 8);
146fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb24.node_name[0],
147fcf3ce44SJohn Forte 			    (void *)&els->node_ww_name.raw_wwn[0], 8);
148fcf3ce44SJohn Forte 		} else {
149fcf3ce44SJohn Forte 			els->common_service.rx_bufsize = CHAR_TO_SHORT(
150fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb.max_frame_length[0],
151fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb.max_frame_length[1]);
152fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb.port_name[0],
153fcf3ce44SJohn Forte 			    (void *)&els->nport_ww_name.raw_wwn[0], 8);
154fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb.node_name[0],
155fcf3ce44SJohn Forte 			    (void *)&els->node_ww_name.raw_wwn[0], 8);
156fcf3ce44SJohn Forte 		}
157*f885d00fSDaniel Beauregard 		bcopy(QL_VERSION, ha->adapter_stats->revlvl.qlddv,
158*f885d00fSDaniel Beauregard 		    strlen(QL_VERSION));
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 		/* Determine which RISC code to use. */
161eb82ff87SDaniel Beauregard 		if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) {
162eb82ff87SDaniel Beauregard 			if ((rval = ql_chip_diag(ha)) == QL_SUCCESS) {
163eb82ff87SDaniel Beauregard 				rval = ql_load_isp_firmware(ha);
164eb82ff87SDaniel Beauregard 			}
165fcf3ce44SJohn Forte 		}
166fcf3ce44SJohn Forte 
167fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
1685dfd244aSDaniel Beauregard 		    QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS) {
169fcf3ce44SJohn Forte 
170fcf3ce44SJohn Forte 			(void) ql_fw_ready(ha, ha->fwwait);
171fcf3ce44SJohn Forte 
172fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & QL_SUSPENDED) &&
173fcf3ce44SJohn Forte 			    ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
174fcf3ce44SJohn Forte 				if (ha->topology & QL_LOOP_CONNECTION) {
175fcf3ce44SJohn Forte 					ha->state = ha->state | FC_STATE_LOOP;
176fcf3ce44SJohn Forte 					msg = "Loop ONLINE";
177fcf3ce44SJohn Forte 					ha->task_daemon_flags |= STATE_ONLINE;
178fcf3ce44SJohn Forte 				} else if (ha->topology & QL_P2P_CONNECTION) {
179fcf3ce44SJohn Forte 					ha->state = ha->state |
180fcf3ce44SJohn Forte 					    FC_STATE_ONLINE;
181fcf3ce44SJohn Forte 					msg = "Link ONLINE";
182fcf3ce44SJohn Forte 					ha->task_daemon_flags |= STATE_ONLINE;
183fcf3ce44SJohn Forte 				} else {
184fcf3ce44SJohn Forte 					msg = "Unknown Link state";
185fcf3ce44SJohn Forte 				}
186fcf3ce44SJohn Forte 			}
187fcf3ce44SJohn Forte 		} else {
188fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
189fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
190fcf3ce44SJohn Forte 				EL(ha, "failed, isp_abort_needed\n");
191fcf3ce44SJohn Forte 				ha->task_daemon_flags |= ISP_ABORT_NEEDED |
192fcf3ce44SJohn Forte 				    LOOP_DOWN;
193fcf3ce44SJohn Forte 			}
194fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
195fcf3ce44SJohn Forte 		}
196fcf3ce44SJohn Forte 
197fcf3ce44SJohn Forte 	} while (retries-- != 0 && ha->task_daemon_flags & ISP_ABORT_NEEDED);
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 	cmn_err(CE_NOTE, "!Qlogic %s(%d): %s", QL_NAME, ha->instance, msg);
200fcf3ce44SJohn Forte 
201fcf3ce44SJohn Forte 	/* Enable ISP interrupts and login parameters. */
202eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
203eb82ff87SDaniel Beauregard 		ql_8021_enable_intrs(ha);
204eb82ff87SDaniel Beauregard 	} else if (CFG_IST(ha, CFG_CTRL_242581)) {
205eb82ff87SDaniel Beauregard 		WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
206eb82ff87SDaniel Beauregard 	} else {
207eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
208eb82ff87SDaniel Beauregard 	}
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
211fcf3ce44SJohn Forte 	ha->flags |= (INTERRUPTS_ENABLED | ONLINE);
212fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FC_STATE_CHANGE | RESET_MARKER_NEEDED |
215fcf3ce44SJohn Forte 	    COMMAND_WAIT_NEEDED);
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte 	/*
218fcf3ce44SJohn Forte 	 * Setup login parameters.
219fcf3ce44SJohn Forte 	 */
220fcf3ce44SJohn Forte 	els->common_service.fcph_version = 0x2006;
221fcf3ce44SJohn Forte 	els->common_service.btob_credit = 3;
222fcf3ce44SJohn Forte 	els->common_service.cmn_features = 0x8800;
223fcf3ce44SJohn Forte 	els->common_service.conc_sequences = 0xff;
224fcf3ce44SJohn Forte 	els->common_service.relative_offset = 3;
225fcf3ce44SJohn Forte 	els->common_service.e_d_tov = 0x07d0;
226fcf3ce44SJohn Forte 
227fcf3ce44SJohn Forte 	class3_param = (class_svc_param_t *)&els->class_3;
228fcf3ce44SJohn Forte 	class3_param->class_valid_svc_opt = 0x8800;
229fcf3ce44SJohn Forte 	class3_param->rcv_data_size = els->common_service.rx_bufsize;
230fcf3ce44SJohn Forte 	class3_param->conc_sequences = 0xff;
231fcf3ce44SJohn Forte 
232fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
233fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
234fcf3ce44SJohn Forte 	} else {
235fcf3ce44SJohn Forte 		/*EMPTY*/
236fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
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
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 
260fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
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 |
276fcf3ce44SJohn Forte 		    PCI_COMM_ME | PCI_COMM_MEMWR_INVAL |
277fcf3ce44SJohn Forte 		    PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 		/*
280fcf3ce44SJohn Forte 		 * If this is a 2300 card and not 2312, reset the
281fcf3ce44SJohn Forte 		 * MEMWR_INVAL due to a bug in the 2300. Unfortunately, the
282fcf3ce44SJohn Forte 		 * 2310 also reports itself as a 2300 so we need to get the
283fcf3ce44SJohn Forte 		 * fb revision level -- a 6 indicates it really is a 2300 and
284fcf3ce44SJohn Forte 		 * not a 2310.
285fcf3ce44SJohn Forte 		 */
286fcf3ce44SJohn Forte 
287fcf3ce44SJohn Forte 		if (ha->device_id == 0x2300) {
288fcf3ce44SJohn Forte 			/* Pause RISC. */
289fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
290fcf3ce44SJohn Forte 			for (timer = 0; timer < 30000; timer++) {
291fcf3ce44SJohn Forte 				if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) !=
292fcf3ce44SJohn Forte 				    0) {
293fcf3ce44SJohn Forte 					break;
294fcf3ce44SJohn Forte 				} else {
295fcf3ce44SJohn Forte 					drv_usecwait(MILLISEC);
296fcf3ce44SJohn Forte 				}
297fcf3ce44SJohn Forte 			}
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 			/* Select FPM registers. */
300fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, ctrl_status, 0x20);
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte 			/* Get the fb rev level */
303fcf3ce44SJohn Forte 			if (RD16_IO_REG(ha, fb_cmd) == 6) {
304fcf3ce44SJohn Forte 				cmd = (uint16_t)(cmd & ~PCI_COMM_MEMWR_INVAL);
305fcf3ce44SJohn Forte 			}
306fcf3ce44SJohn Forte 
307fcf3ce44SJohn Forte 			/* Deselect FPM registers. */
308fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, ctrl_status, 0x0);
309fcf3ce44SJohn Forte 
310fcf3ce44SJohn Forte 			/* Release RISC module. */
311fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
312fcf3ce44SJohn Forte 			for (timer = 0; timer < 30000; timer++) {
313fcf3ce44SJohn Forte 				if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) ==
314fcf3ce44SJohn Forte 				    0) {
315fcf3ce44SJohn Forte 					break;
316fcf3ce44SJohn Forte 				} else {
317fcf3ce44SJohn Forte 					drv_usecwait(MILLISEC);
318fcf3ce44SJohn Forte 				}
319fcf3ce44SJohn Forte 			}
320fcf3ce44SJohn Forte 		} else if (ha->device_id == 0x2312) {
321fcf3ce44SJohn Forte 			/*
322fcf3ce44SJohn Forte 			 * cPCI ISP2312 specific code to service function 1
323fcf3ce44SJohn Forte 			 * hot-swap registers.
324fcf3ce44SJohn Forte 			 */
325fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, ctrl_status) & ISP_FUNC_NUM_MASK)
326fcf3ce44SJohn Forte 			    != 0) {
327fcf3ce44SJohn Forte 				ql_pci_config_put8(ha, 0x66, 0xc2);
328fcf3ce44SJohn Forte 			}
329fcf3ce44SJohn Forte 		}
330fcf3ce44SJohn Forte 
331eb82ff87SDaniel Beauregard 		if (!(CFG_IST(ha, CFG_CTRL_8021)) &&
332eb82ff87SDaniel Beauregard 		    ha->pci_max_read_req != 0) {
333fcf3ce44SJohn Forte 			ql_set_max_read_req(ha);
334fcf3ce44SJohn Forte 		}
335fcf3ce44SJohn Forte 
336fcf3ce44SJohn Forte 		ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
337fcf3ce44SJohn Forte 
338fcf3ce44SJohn Forte 		/* Set cache line register. */
339fcf3ce44SJohn Forte 		ql_pci_config_put8(ha, PCI_CONF_CACHE_LINESZ, 0x10);
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 		/* Set latency register. */
342fcf3ce44SJohn Forte 		ql_pci_config_put8(ha, PCI_CONF_LATENCY_TIMER, 0x40);
343fcf3ce44SJohn Forte 
344fcf3ce44SJohn Forte 		/* Reset expansion ROM address decode enable. */
345fcf3ce44SJohn Forte 		w16 = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_ROM);
346fcf3ce44SJohn Forte 		w16 = (uint16_t)(w16 & ~BIT_0);
347fcf3ce44SJohn Forte 		ql_pci_config_put16(ha, PCI_CONF_ROM, w16);
348fcf3ce44SJohn Forte 	}
349fcf3ce44SJohn Forte 
350fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
351fcf3ce44SJohn Forte 
352fcf3ce44SJohn Forte 	return (QL_SUCCESS);
353fcf3ce44SJohn Forte }
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte /*
356fcf3ce44SJohn Forte  * Set the PCI max read request value.
357fcf3ce44SJohn Forte  *
358fcf3ce44SJohn Forte  * Input:
359fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
360fcf3ce44SJohn Forte  *
361fcf3ce44SJohn Forte  * Output:
362fcf3ce44SJohn Forte  *	none.
363fcf3ce44SJohn Forte  *
364fcf3ce44SJohn Forte  * Returns:
365fcf3ce44SJohn Forte  *
366fcf3ce44SJohn Forte  * Context:
367fcf3ce44SJohn Forte  *	Kernel context.
368fcf3ce44SJohn Forte  */
369fcf3ce44SJohn Forte 
370fcf3ce44SJohn Forte static void
371fcf3ce44SJohn Forte ql_set_max_read_req(ql_adapter_state_t *ha)
372fcf3ce44SJohn Forte {
373fcf3ce44SJohn Forte 	uint16_t	read_req, w16;
374fcf3ce44SJohn Forte 	uint16_t	tmp = ha->pci_max_read_req;
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 	if ((ha->device_id == 0x2422) ||
377fcf3ce44SJohn Forte 	    ((ha->device_id & 0xff00) == 0x2300)) {
378fcf3ce44SJohn Forte 		/* check for vaild override value */
379fcf3ce44SJohn Forte 		if (tmp == 512 || tmp == 1024 || tmp == 2048 ||
380fcf3ce44SJohn Forte 		    tmp == 4096) {
381fcf3ce44SJohn Forte 			/* shift away the don't cares */
382fcf3ce44SJohn Forte 			tmp = (uint16_t)(tmp >> 10);
383fcf3ce44SJohn Forte 			/* convert bit pos to request value */
384fcf3ce44SJohn Forte 			for (read_req = 0; tmp != 0; read_req++) {
385fcf3ce44SJohn Forte 				tmp = (uint16_t)(tmp >> 1);
386fcf3ce44SJohn Forte 			}
387fcf3ce44SJohn Forte 			w16 = (uint16_t)ql_pci_config_get16(ha, 0x4e);
388fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 & ~(BIT_3 & BIT_2));
389fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 | (read_req << 2));
390fcf3ce44SJohn Forte 			ql_pci_config_put16(ha, 0x4e, w16);
391fcf3ce44SJohn Forte 		} else {
392fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
393fcf3ce44SJohn Forte 			    "'pci-max-read-request': %d; using system "
394fcf3ce44SJohn Forte 			    "default\n", tmp);
395fcf3ce44SJohn Forte 		}
396fcf3ce44SJohn Forte 	} else if ((ha->device_id == 0x2432) || ((ha->device_id & 0xff00) ==
39716dd44c2SDaniel Beauregard 	    0x2500) || (ha->device_id == 0x8432)) {
398fcf3ce44SJohn Forte 		/* check for vaild override value */
399fcf3ce44SJohn Forte 		if (tmp == 128 || tmp == 256 || tmp == 512 ||
400fcf3ce44SJohn Forte 		    tmp == 1024 || tmp == 2048 || tmp == 4096) {
401fcf3ce44SJohn Forte 			/* shift away the don't cares */
402fcf3ce44SJohn Forte 			tmp = (uint16_t)(tmp >> 8);
403fcf3ce44SJohn Forte 			/* convert bit pos to request value */
404fcf3ce44SJohn Forte 			for (read_req = 0; tmp != 0; read_req++) {
405fcf3ce44SJohn Forte 				tmp = (uint16_t)(tmp >> 1);
406fcf3ce44SJohn Forte 			}
407fcf3ce44SJohn Forte 			w16 = (uint16_t)ql_pci_config_get16(ha, 0x54);
408fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 & ~(BIT_14 | BIT_13 |
409fcf3ce44SJohn Forte 			    BIT_12));
410fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 | (read_req << 12));
411fcf3ce44SJohn Forte 			ql_pci_config_put16(ha, 0x54, w16);
412fcf3ce44SJohn Forte 		} else {
413fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
414fcf3ce44SJohn Forte 			    "'pci-max-read-request': %d; using system "
415fcf3ce44SJohn Forte 			    "default\n", tmp);
416fcf3ce44SJohn Forte 		}
417fcf3ce44SJohn Forte 	}
418fcf3ce44SJohn Forte }
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte /*
421fcf3ce44SJohn Forte  * NVRAM configuration.
422fcf3ce44SJohn Forte  *
423fcf3ce44SJohn Forte  * Input:
424fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
425fcf3ce44SJohn Forte  *	ha->hba_buf = request and response rings
426fcf3ce44SJohn Forte  *
427fcf3ce44SJohn Forte  * Output:
428fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
429fcf3ce44SJohn Forte  *	host adapters parameters in host adapter block
430fcf3ce44SJohn Forte  *
431fcf3ce44SJohn Forte  * Returns:
432fcf3ce44SJohn Forte  *	ql local function return status code.
433fcf3ce44SJohn Forte  *
434fcf3ce44SJohn Forte  * Context:
435fcf3ce44SJohn Forte  *	Kernel context.
436fcf3ce44SJohn Forte  */
437fcf3ce44SJohn Forte int
438fcf3ce44SJohn Forte ql_nvram_config(ql_adapter_state_t *ha)
439fcf3ce44SJohn Forte {
440fcf3ce44SJohn Forte 	uint32_t	cnt;
441fcf3ce44SJohn Forte 	caddr_t		dptr1, dptr2;
442fcf3ce44SJohn Forte 	ql_init_cb_t	*icb = &ha->init_ctrl_blk.cb;
443fcf3ce44SJohn Forte 	ql_ip_init_cb_t	*ip_icb = &ha->ip_init_ctrl_blk.cb;
444fcf3ce44SJohn Forte 	nvram_t		*nv = (nvram_t *)ha->request_ring_bp;
445fcf3ce44SJohn Forte 	uint16_t	*wptr = (uint16_t *)ha->request_ring_bp;
446fcf3ce44SJohn Forte 	uint8_t		chksum = 0;
447fcf3ce44SJohn Forte 	int		rval;
448fcf3ce44SJohn Forte 	int		idpromlen;
449fcf3ce44SJohn Forte 	char		idprombuf[32];
450fcf3ce44SJohn Forte 	uint32_t	start_addr;
451fcf3ce44SJohn Forte 
452fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
453fcf3ce44SJohn Forte 
454eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
455fcf3ce44SJohn Forte 		return (ql_nvram_24xx_config(ha));
456fcf3ce44SJohn Forte 	}
457fcf3ce44SJohn Forte 
458fcf3ce44SJohn Forte 	start_addr = 0;
459fcf3ce44SJohn Forte 	if ((rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) ==
460fcf3ce44SJohn Forte 	    QL_SUCCESS) {
461fcf3ce44SJohn Forte 		/* Verify valid NVRAM checksum. */
462fcf3ce44SJohn Forte 		for (cnt = 0; cnt < sizeof (nvram_t)/2; cnt++) {
463fcf3ce44SJohn Forte 			*wptr = (uint16_t)ql_get_nvram_word(ha,
464fcf3ce44SJohn Forte 			    (uint32_t)(cnt + start_addr));
465fcf3ce44SJohn Forte 			chksum = (uint8_t)(chksum + (uint8_t)*wptr);
466fcf3ce44SJohn Forte 			chksum = (uint8_t)(chksum + (uint8_t)(*wptr >> 8));
467fcf3ce44SJohn Forte 			wptr++;
468fcf3ce44SJohn Forte 		}
469fcf3ce44SJohn Forte 		ql_release_nvram(ha);
470fcf3ce44SJohn Forte 	}
471fcf3ce44SJohn Forte 
472fcf3ce44SJohn Forte 	/* Bad NVRAM data, set defaults parameters. */
473fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
474fcf3ce44SJohn Forte 	    nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
475fcf3ce44SJohn Forte 	    nv->nvram_version < 1) {
476fcf3ce44SJohn Forte 
477fcf3ce44SJohn Forte 		EL(ha, "failed, rval=%xh, checksum=%xh, "
478fcf3ce44SJohn Forte 		    "id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, "
479fcf3ce44SJohn Forte 		    "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
480fcf3ce44SJohn Forte 		    nv->id[2], nv->id[3], ha->xioctl->fdesc.flash_size,
481fcf3ce44SJohn Forte 		    ha->subven_id, nv->nvram_version);
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 		/* Don't print nvram message if it's an on-board 2200 */
484fcf3ce44SJohn Forte 		if (!((CFG_IST(ha, CFG_CTRL_2200)) &&
485fcf3ce44SJohn Forte 		    (ha->xioctl->fdesc.flash_size == 0))) {
486fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed,"
487fcf3ce44SJohn Forte 			    " using driver defaults.", QL_NAME, ha->instance);
488fcf3ce44SJohn Forte 		}
489fcf3ce44SJohn Forte 
490fcf3ce44SJohn Forte 		/* Reset NVRAM data. */
491fcf3ce44SJohn Forte 		bzero((void *)nv, sizeof (nvram_t));
492fcf3ce44SJohn Forte 
493fcf3ce44SJohn Forte 		/*
494fcf3ce44SJohn Forte 		 * Set default initialization control block.
495fcf3ce44SJohn Forte 		 */
496fcf3ce44SJohn Forte 		nv->parameter_block_version = ICB_VERSION;
497fcf3ce44SJohn Forte 		nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
498fcf3ce44SJohn Forte 		nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
499fcf3ce44SJohn Forte 
500fcf3ce44SJohn Forte 		nv->max_frame_length[1] = 4;
501fcf3ce44SJohn Forte 
502fcf3ce44SJohn Forte 		/*
503fcf3ce44SJohn Forte 		 * Allow 2048 byte frames for 2300
504fcf3ce44SJohn Forte 		 */
505fcf3ce44SJohn Forte 		if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
506fcf3ce44SJohn Forte 			nv->max_frame_length[1] = 8;
507fcf3ce44SJohn Forte 		}
508fcf3ce44SJohn Forte 		nv->max_iocb_allocation[1] = 1;
509fcf3ce44SJohn Forte 		nv->execution_throttle[0] = 16;
510fcf3ce44SJohn Forte 		nv->login_retry_count = 8;
511fcf3ce44SJohn Forte 
512fcf3ce44SJohn Forte 		idpromlen = 32;
513fcf3ce44SJohn Forte 
514fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
515fcf3ce44SJohn Forte 		if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
516fcf3ce44SJohn Forte 		    DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
517fcf3ce44SJohn Forte 		    &idpromlen) != DDI_PROP_SUCCESS) {
518fcf3ce44SJohn Forte 
519fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): Unable to read idprom "
520fcf3ce44SJohn Forte 			    "property\n", ha->instance);
521fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
522fcf3ce44SJohn Forte 			    "property", QL_NAME, ha->instance);
523fcf3ce44SJohn Forte 
524fcf3ce44SJohn Forte 			nv->port_name[2] = 33;
525fcf3ce44SJohn Forte 			nv->port_name[3] = 224;
526fcf3ce44SJohn Forte 			nv->port_name[4] = 139;
527fcf3ce44SJohn Forte 			nv->port_name[7] = (uint8_t)
528fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
529fcf3ce44SJohn Forte 		} else {
530fcf3ce44SJohn Forte 
531fcf3ce44SJohn Forte 			nv->port_name[2] = idprombuf[2];
532fcf3ce44SJohn Forte 			nv->port_name[3] = idprombuf[3];
533fcf3ce44SJohn Forte 			nv->port_name[4] = idprombuf[4];
534fcf3ce44SJohn Forte 			nv->port_name[5] = idprombuf[5];
535fcf3ce44SJohn Forte 			nv->port_name[6] = idprombuf[6];
536fcf3ce44SJohn Forte 			nv->port_name[7] = idprombuf[7];
537fcf3ce44SJohn Forte 			nv->port_name[0] = (uint8_t)
538fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
539fcf3ce44SJohn Forte 		}
540fcf3ce44SJohn Forte 
541fcf3ce44SJohn Forte 		/* Don't print nvram message if it's an on-board 2200 */
542fcf3ce44SJohn Forte 		if (!(CFG_IST(ha, CFG_CTRL_2200)) &&
543fcf3ce44SJohn Forte 		    (ha->xioctl->fdesc.flash_size == 0)) {
544fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using"
545fcf3ce44SJohn Forte 			    " default HBA parameters and temporary WWPN:"
546fcf3ce44SJohn Forte 			    " %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
547fcf3ce44SJohn Forte 			    ha->instance, nv->port_name[0], nv->port_name[1],
548fcf3ce44SJohn Forte 			    nv->port_name[2], nv->port_name[3],
549fcf3ce44SJohn Forte 			    nv->port_name[4], nv->port_name[5],
550fcf3ce44SJohn Forte 			    nv->port_name[6], nv->port_name[7]);
551fcf3ce44SJohn Forte 		}
552fcf3ce44SJohn Forte 
553fcf3ce44SJohn Forte 		nv->login_timeout = 4;
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 		/* Set default connection options for the 23xx to 2 */
556fcf3ce44SJohn Forte 		if (!(CFG_IST(ha, CFG_CTRL_2200))) {
557fcf3ce44SJohn Forte 			nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
558fcf3ce44SJohn Forte 			    BIT_5);
559fcf3ce44SJohn Forte 		}
560fcf3ce44SJohn Forte 
561fcf3ce44SJohn Forte 		/*
562fcf3ce44SJohn Forte 		 * Set default host adapter parameters
563fcf3ce44SJohn Forte 		 */
564fcf3ce44SJohn Forte 		nv->host_p[0] = BIT_1;
565fcf3ce44SJohn Forte 		nv->host_p[1] = BIT_2;
566fcf3ce44SJohn Forte 		nv->reset_delay = 5;
567fcf3ce44SJohn Forte 		nv->port_down_retry_count = 8;
568fcf3ce44SJohn Forte 		nv->maximum_luns_per_target[0] = 8;
569fcf3ce44SJohn Forte 
570fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
571fcf3ce44SJohn Forte 	}
572fcf3ce44SJohn Forte 
573fcf3ce44SJohn Forte 	/* Check for adapter node name (big endian). */
574fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 8; cnt++) {
575fcf3ce44SJohn Forte 		if (nv->node_name[cnt] != 0) {
576fcf3ce44SJohn Forte 			break;
577fcf3ce44SJohn Forte 		}
578fcf3ce44SJohn Forte 	}
579fcf3ce44SJohn Forte 
580fcf3ce44SJohn Forte 	/* Copy port name if no node name (big endian). */
581fcf3ce44SJohn Forte 	if (cnt == 8) {
582fcf3ce44SJohn Forte 		bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8);
583fcf3ce44SJohn Forte 		nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
584fcf3ce44SJohn Forte 		nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
585fcf3ce44SJohn Forte 	}
586fcf3ce44SJohn Forte 
587fcf3ce44SJohn Forte 	/* Reset initialization control blocks. */
588fcf3ce44SJohn Forte 	bzero((void *)icb, sizeof (ql_init_cb_t));
589fcf3ce44SJohn Forte 
590fcf3ce44SJohn Forte 	/* Get driver properties. */
591fcf3ce44SJohn Forte 	ql_23_properties(ha, nv);
592fcf3ce44SJohn Forte 
593fcf3ce44SJohn Forte 	cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
594fcf3ce44SJohn Forte 	    "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
595fcf3ce44SJohn Forte 	    QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1],
596fcf3ce44SJohn Forte 	    nv->port_name[2], nv->port_name[3], nv->port_name[4],
597fcf3ce44SJohn Forte 	    nv->port_name[5], nv->port_name[6], nv->port_name[7],
598fcf3ce44SJohn Forte 	    nv->node_name[0], nv->node_name[1], nv->node_name[2],
599fcf3ce44SJohn Forte 	    nv->node_name[3], nv->node_name[4], nv->node_name[5],
600fcf3ce44SJohn Forte 	    nv->node_name[6], nv->node_name[7]);
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte 	/*
603fcf3ce44SJohn Forte 	 * Copy over NVRAM RISC parameter block
604fcf3ce44SJohn Forte 	 * to initialization control block.
605fcf3ce44SJohn Forte 	 */
606fcf3ce44SJohn Forte 	dptr1 = (caddr_t)icb;
607fcf3ce44SJohn Forte 	dptr2 = (caddr_t)&nv->parameter_block_version;
608fcf3ce44SJohn Forte 	cnt = (uint32_t)((uintptr_t)&icb->request_q_outpointer[0] -
609fcf3ce44SJohn Forte 	    (uintptr_t)&icb->version);
610fcf3ce44SJohn Forte 	while (cnt-- != 0) {
611fcf3ce44SJohn Forte 		*dptr1++ = *dptr2++;
612fcf3ce44SJohn Forte 	}
613fcf3ce44SJohn Forte 
614fcf3ce44SJohn Forte 	/* Copy 2nd half. */
615fcf3ce44SJohn Forte 	dptr1 = (caddr_t)&icb->add_fw_opt[0];
616fcf3ce44SJohn Forte 	cnt = (uint32_t)((uintptr_t)&icb->reserved_3[0] -
617fcf3ce44SJohn Forte 	    (uintptr_t)&icb->add_fw_opt[0]);
618fcf3ce44SJohn Forte 
619fcf3ce44SJohn Forte 	while (cnt-- != 0) {
620fcf3ce44SJohn Forte 		*dptr1++ = *dptr2++;
621fcf3ce44SJohn Forte 	}
622fcf3ce44SJohn Forte 
623fcf3ce44SJohn Forte 	/*
624fcf3ce44SJohn Forte 	 * Setup driver firmware options.
625fcf3ce44SJohn Forte 	 */
626fcf3ce44SJohn Forte 	icb->firmware_options[0] = (uint8_t)
627fcf3ce44SJohn Forte 	    (icb->firmware_options[0] | BIT_6 | BIT_1);
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 	/*
630fcf3ce44SJohn Forte 	 * There is no use enabling fast post for SBUS or 2300
6315dfd244aSDaniel Beauregard 	 * Always enable 64bit addressing, except SBUS cards.
632fcf3ce44SJohn Forte 	 */
6335dfd244aSDaniel Beauregard 	ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
634fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_SBUS_CARD | CFG_CTRL_2300 | CFG_CTRL_6322))) {
635fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
636fcf3ce44SJohn Forte 		    (icb->firmware_options[0] & ~BIT_3);
637fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
638fcf3ce44SJohn Forte 			icb->special_options[0] = (uint8_t)
639fcf3ce44SJohn Forte 			    (icb->special_options[0] | BIT_5);
6405dfd244aSDaniel Beauregard 			ha->cfg_flags &= ~CFG_ENABLE_64BIT_ADDRESSING;
641fcf3ce44SJohn Forte 		}
642fcf3ce44SJohn Forte 	} else {
643fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
644fcf3ce44SJohn Forte 		    (icb->firmware_options[0] | BIT_3);
645fcf3ce44SJohn Forte 	}
646fcf3ce44SJohn Forte 	/* RIO and ZIO not supported. */
647fcf3ce44SJohn Forte 	icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] &
648fcf3ce44SJohn Forte 	    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
649fcf3ce44SJohn Forte 
650fcf3ce44SJohn Forte 	icb->firmware_options[1] = (uint8_t)(icb->firmware_options[1] |
651fcf3ce44SJohn Forte 	    BIT_7 | BIT_6 | BIT_5 | BIT_2 | BIT_0);
652fcf3ce44SJohn Forte 	icb->firmware_options[0] = (uint8_t)
653fcf3ce44SJohn Forte 	    (icb->firmware_options[0] & ~(BIT_5 | BIT_4));
654fcf3ce44SJohn Forte 	icb->firmware_options[1] = (uint8_t)
655fcf3ce44SJohn Forte 	    (icb->firmware_options[1] & ~BIT_4);
656fcf3ce44SJohn Forte 
657fcf3ce44SJohn Forte 	icb->add_fw_opt[1] = (uint8_t)(icb->add_fw_opt[1] & ~(BIT_5 | BIT_4));
658fcf3ce44SJohn Forte 	icb->special_options[0] = (uint8_t)(icb->special_options[0] | BIT_1);
659fcf3ce44SJohn Forte 
660fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
661fcf3ce44SJohn Forte 		if ((icb->special_options[1] & 0x20) == 0) {
662fcf3ce44SJohn Forte 			EL(ha, "50 ohm is not set\n");
663fcf3ce44SJohn Forte 		}
664fcf3ce44SJohn Forte 	}
665fcf3ce44SJohn Forte 	icb->execution_throttle[0] = 0xff;
666fcf3ce44SJohn Forte 	icb->execution_throttle[1] = 0xff;
667fcf3ce44SJohn Forte 
668fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
669fcf3ce44SJohn Forte 		icb->firmware_options[1] = (uint8_t)
670fcf3ce44SJohn Forte 		    (icb->firmware_options[1] | BIT_7 | BIT_6);
671fcf3ce44SJohn Forte 		icb->add_fw_opt[1] = (uint8_t)
672fcf3ce44SJohn Forte 		    (icb->add_fw_opt[1] | BIT_5 | BIT_4);
673fcf3ce44SJohn Forte 	}
674fcf3ce44SJohn Forte 
675fcf3ce44SJohn Forte 	/*
676fcf3ce44SJohn Forte 	 * Set host adapter parameters
677fcf3ce44SJohn Forte 	 */
678fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
679fcf3ce44SJohn Forte 	ha->nvram_version = nv->nvram_version;
680fcf3ce44SJohn Forte 	ha->adapter_features = CHAR_TO_SHORT(nv->adapter_features[0],
681fcf3ce44SJohn Forte 	    nv->adapter_features[1]);
682fcf3ce44SJohn Forte 
683fcf3ce44SJohn Forte 	nv->host_p[0] & BIT_4 ? (ha->cfg_flags |= CFG_DISABLE_RISC_CODE_LOAD) :
684fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_DISABLE_RISC_CODE_LOAD);
685fcf3ce44SJohn Forte 	nv->host_p[0] & BIT_5 ? (ha->cfg_flags |= CFG_SET_CACHE_LINE_SIZE_1) :
686fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_SET_CACHE_LINE_SIZE_1);
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_1 ? (ha->cfg_flags |= CFG_ENABLE_LIP_RESET) :
689fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET);
690fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) :
691fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN);
692fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) :
693fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET);
694fcf3ce44SJohn Forte 
695fcf3ce44SJohn Forte 	nv->adapter_features[0] & BIT_3 ?
696fcf3ce44SJohn Forte 	    (ha->cfg_flags |= CFG_MULTI_CHIP_ADAPTER) :
697fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_MULTI_CHIP_ADAPTER);
698fcf3ce44SJohn Forte 
699fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
700fcf3ce44SJohn Forte 
701fcf3ce44SJohn Forte 	ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
702fcf3ce44SJohn Forte 	    nv->execution_throttle[1]);
703fcf3ce44SJohn Forte 	ha->loop_reset_delay = nv->reset_delay;
704fcf3ce44SJohn Forte 	ha->port_down_retry_count = nv->port_down_retry_count;
705fcf3ce44SJohn Forte 	ha->r_a_tov = (uint16_t)(icb->login_timeout < R_A_TOV_DEFAULT ?
706fcf3ce44SJohn Forte 	    R_A_TOV_DEFAULT : icb->login_timeout);
707fcf3ce44SJohn Forte 	ha->maximum_luns_per_target = CHAR_TO_SHORT(
708fcf3ce44SJohn Forte 	    nv->maximum_luns_per_target[0], nv->maximum_luns_per_target[1]);
709fcf3ce44SJohn Forte 	if (ha->maximum_luns_per_target == 0) {
710fcf3ce44SJohn Forte 		ha->maximum_luns_per_target++;
711fcf3ce44SJohn Forte 	}
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte 	/*
714fcf3ce44SJohn Forte 	 * Setup ring parameters in initialization control block
715fcf3ce44SJohn Forte 	 */
716fcf3ce44SJohn Forte 	cnt = REQUEST_ENTRY_CNT;
717fcf3ce44SJohn Forte 	icb->request_q_length[0] = LSB(cnt);
718fcf3ce44SJohn Forte 	icb->request_q_length[1] = MSB(cnt);
719fcf3ce44SJohn Forte 	cnt = RESPONSE_ENTRY_CNT;
720fcf3ce44SJohn Forte 	icb->response_q_length[0] = LSB(cnt);
721fcf3ce44SJohn Forte 	icb->response_q_length[1] = MSB(cnt);
722fcf3ce44SJohn Forte 
723fcf3ce44SJohn Forte 	icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma)));
724fcf3ce44SJohn Forte 	icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma)));
725fcf3ce44SJohn Forte 	icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma)));
726fcf3ce44SJohn Forte 	icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma)));
727fcf3ce44SJohn Forte 	icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma)));
728fcf3ce44SJohn Forte 	icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma)));
729fcf3ce44SJohn Forte 	icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma)));
730fcf3ce44SJohn Forte 	icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma)));
731fcf3ce44SJohn Forte 
732fcf3ce44SJohn Forte 	icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma)));
733fcf3ce44SJohn Forte 	icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma)));
734fcf3ce44SJohn Forte 	icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma)));
735fcf3ce44SJohn Forte 	icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma)));
736fcf3ce44SJohn Forte 	icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma)));
737fcf3ce44SJohn Forte 	icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma)));
738fcf3ce44SJohn Forte 	icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma)));
739fcf3ce44SJohn Forte 	icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma)));
740fcf3ce44SJohn Forte 
741fcf3ce44SJohn Forte 	/*
742fcf3ce44SJohn Forte 	 * Setup IP initialization control block
743fcf3ce44SJohn Forte 	 */
744fcf3ce44SJohn Forte 	ip_icb->version = IP_ICB_VERSION;
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
747fcf3ce44SJohn Forte 		ip_icb->ip_firmware_options[0] = (uint8_t)
748fcf3ce44SJohn Forte 		    (ip_icb->ip_firmware_options[0] | BIT_2 | BIT_0);
749fcf3ce44SJohn Forte 	} else {
750fcf3ce44SJohn Forte 		ip_icb->ip_firmware_options[0] = (uint8_t)
751fcf3ce44SJohn Forte 		    (ip_icb->ip_firmware_options[0] | BIT_2);
752fcf3ce44SJohn Forte 	}
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 	cnt = RCVBUF_CONTAINER_CNT;
755fcf3ce44SJohn Forte 	ip_icb->queue_size[0] = LSB(cnt);
756fcf3ce44SJohn Forte 	ip_icb->queue_size[1] = MSB(cnt);
757fcf3ce44SJohn Forte 
758fcf3ce44SJohn Forte 	ip_icb->queue_address[0] = LSB(LSW(LSD(ha->rcvbuf_dvma)));
759fcf3ce44SJohn Forte 	ip_icb->queue_address[1] = MSB(LSW(LSD(ha->rcvbuf_dvma)));
760fcf3ce44SJohn Forte 	ip_icb->queue_address[2] = LSB(MSW(LSD(ha->rcvbuf_dvma)));
761fcf3ce44SJohn Forte 	ip_icb->queue_address[3] = MSB(MSW(LSD(ha->rcvbuf_dvma)));
762fcf3ce44SJohn Forte 	ip_icb->queue_address[4] = LSB(LSW(MSD(ha->rcvbuf_dvma)));
763fcf3ce44SJohn Forte 	ip_icb->queue_address[5] = MSB(LSW(MSD(ha->rcvbuf_dvma)));
764fcf3ce44SJohn Forte 	ip_icb->queue_address[6] = LSB(MSW(MSD(ha->rcvbuf_dvma)));
765fcf3ce44SJohn Forte 	ip_icb->queue_address[7] = MSB(MSW(MSD(ha->rcvbuf_dvma)));
766fcf3ce44SJohn Forte 
767fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
768fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
769fcf3ce44SJohn Forte 	} else {
770fcf3ce44SJohn Forte 		/*EMPTY*/
771fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
772fcf3ce44SJohn Forte 	}
773fcf3ce44SJohn Forte 	return (rval);
774fcf3ce44SJohn Forte }
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte /*
777fcf3ce44SJohn Forte  * Get NVRAM data word
778fcf3ce44SJohn Forte  *	Calculates word position in NVRAM and calls request routine to
779fcf3ce44SJohn Forte  *	get the word from NVRAM.
780fcf3ce44SJohn Forte  *
781fcf3ce44SJohn Forte  * Input:
782fcf3ce44SJohn Forte  *	ha = adapter state pointer.
783fcf3ce44SJohn Forte  *	address = NVRAM word address.
784fcf3ce44SJohn Forte  *
785fcf3ce44SJohn Forte  * Returns:
786fcf3ce44SJohn Forte  *	data word.
787fcf3ce44SJohn Forte  *
788fcf3ce44SJohn Forte  * Context:
789fcf3ce44SJohn Forte  *	Kernel context.
790fcf3ce44SJohn Forte  */
791fcf3ce44SJohn Forte uint16_t
792fcf3ce44SJohn Forte ql_get_nvram_word(ql_adapter_state_t *ha, uint32_t address)
793fcf3ce44SJohn Forte {
794fcf3ce44SJohn Forte 	uint32_t	nv_cmd;
795fcf3ce44SJohn Forte 	uint16_t	rval;
796fcf3ce44SJohn Forte 
797fcf3ce44SJohn Forte 	QL_PRINT_4(CE_CONT, "(%d): started\n", ha->instance);
798fcf3ce44SJohn Forte 
799fcf3ce44SJohn Forte 	nv_cmd = address << 16;
800fcf3ce44SJohn Forte 	nv_cmd = nv_cmd | NV_READ_OP;
801fcf3ce44SJohn Forte 
802fcf3ce44SJohn Forte 	rval = (uint16_t)ql_nvram_request(ha, nv_cmd);
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 	QL_PRINT_4(CE_CONT, "(%d): NVRAM data = %xh\n", ha->instance, rval);
805fcf3ce44SJohn Forte 
806fcf3ce44SJohn Forte 	return (rval);
807fcf3ce44SJohn Forte }
808fcf3ce44SJohn Forte 
809fcf3ce44SJohn Forte /*
810fcf3ce44SJohn Forte  * NVRAM request
811fcf3ce44SJohn Forte  *	Sends read command to NVRAM and gets data from NVRAM.
812fcf3ce44SJohn Forte  *
813fcf3ce44SJohn Forte  * Input:
814fcf3ce44SJohn Forte  *	ha = adapter state pointer.
815fcf3ce44SJohn Forte  *	nv_cmd = Bit 26= start bit
816fcf3ce44SJohn Forte  *	Bit 25, 24 = opcode
817fcf3ce44SJohn Forte  *	Bit 23-16 = address
818fcf3ce44SJohn Forte  *	Bit 15-0 = write data
819fcf3ce44SJohn Forte  *
820fcf3ce44SJohn Forte  * Returns:
821fcf3ce44SJohn Forte  *	data word.
822fcf3ce44SJohn Forte  *
823fcf3ce44SJohn Forte  * Context:
824fcf3ce44SJohn Forte  *	Kernel context.
825fcf3ce44SJohn Forte  */
826fcf3ce44SJohn Forte static uint16_t
827fcf3ce44SJohn Forte ql_nvram_request(ql_adapter_state_t *ha, uint32_t nv_cmd)
828fcf3ce44SJohn Forte {
829fcf3ce44SJohn Forte 	uint8_t		cnt;
830fcf3ce44SJohn Forte 	uint16_t	reg_data;
831fcf3ce44SJohn Forte 	uint16_t	data = 0;
832fcf3ce44SJohn Forte 
833fcf3ce44SJohn Forte 	/* Send command to NVRAM. */
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 	nv_cmd <<= 5;
836fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 11; cnt++) {
837fcf3ce44SJohn Forte 		if (nv_cmd & BIT_31) {
838fcf3ce44SJohn Forte 			ql_nv_write(ha, NV_DATA_OUT);
839fcf3ce44SJohn Forte 		} else {
840fcf3ce44SJohn Forte 			ql_nv_write(ha, 0);
841fcf3ce44SJohn Forte 		}
842fcf3ce44SJohn Forte 		nv_cmd <<= 1;
843fcf3ce44SJohn Forte 	}
844fcf3ce44SJohn Forte 
845fcf3ce44SJohn Forte 	/* Read data from NVRAM. */
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 16; cnt++) {
848fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, nvram, NV_SELECT+NV_CLOCK);
849fcf3ce44SJohn Forte 		ql_nv_delay();
850fcf3ce44SJohn Forte 		data <<= 1;
851fcf3ce44SJohn Forte 		reg_data = RD16_IO_REG(ha, nvram);
852fcf3ce44SJohn Forte 		if (reg_data & NV_DATA_IN) {
853fcf3ce44SJohn Forte 			data = (uint16_t)(data | BIT_0);
854fcf3ce44SJohn Forte 		}
855fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, nvram, NV_SELECT);
856fcf3ce44SJohn Forte 		ql_nv_delay();
857fcf3ce44SJohn Forte 	}
858fcf3ce44SJohn Forte 
859fcf3ce44SJohn Forte 	/* Deselect chip. */
860fcf3ce44SJohn Forte 
861fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, NV_DESELECT);
862fcf3ce44SJohn Forte 	ql_nv_delay();
863fcf3ce44SJohn Forte 
864fcf3ce44SJohn Forte 	return (data);
865fcf3ce44SJohn Forte }
866fcf3ce44SJohn Forte 
867fcf3ce44SJohn Forte void
868fcf3ce44SJohn Forte ql_nv_write(ql_adapter_state_t *ha, uint16_t data)
869fcf3ce44SJohn Forte {
870fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
871fcf3ce44SJohn Forte 	ql_nv_delay();
872fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT | NV_CLOCK));
873fcf3ce44SJohn Forte 	ql_nv_delay();
874fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
875fcf3ce44SJohn Forte 	ql_nv_delay();
876fcf3ce44SJohn Forte }
877fcf3ce44SJohn Forte 
878fcf3ce44SJohn Forte void
8795dfd244aSDaniel Beauregard ql_nv_delay(void)
8805dfd244aSDaniel Beauregard {
881fcf3ce44SJohn Forte 	drv_usecwait(NV_DELAY_COUNT);
882fcf3ce44SJohn Forte }
883fcf3ce44SJohn Forte 
884fcf3ce44SJohn Forte /*
885fcf3ce44SJohn Forte  * ql_nvram_24xx_config
886fcf3ce44SJohn Forte  *	ISP2400 nvram.
887fcf3ce44SJohn Forte  *
888fcf3ce44SJohn Forte  * Input:
889fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
890fcf3ce44SJohn Forte  *	ha->hba_buf = request and response rings
891fcf3ce44SJohn Forte  *
892fcf3ce44SJohn Forte  * Output:
893fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
894fcf3ce44SJohn Forte  *	host adapters parameters in host adapter block
895fcf3ce44SJohn Forte  *
896fcf3ce44SJohn Forte  * Returns:
897fcf3ce44SJohn Forte  *	ql local function return status code.
898fcf3ce44SJohn Forte  *
899fcf3ce44SJohn Forte  * Context:
900fcf3ce44SJohn Forte  *	Kernel context.
901fcf3ce44SJohn Forte  */
902fcf3ce44SJohn Forte int
903fcf3ce44SJohn Forte ql_nvram_24xx_config(ql_adapter_state_t *ha)
904fcf3ce44SJohn Forte {
905fcf3ce44SJohn Forte 	uint32_t		index, addr, chksum, saved_chksum;
906fcf3ce44SJohn Forte 	uint32_t		*longptr;
907fcf3ce44SJohn Forte 	nvram_24xx_t		nvram;
908fcf3ce44SJohn Forte 	int			idpromlen;
909fcf3ce44SJohn Forte 	char			idprombuf[32];
910fcf3ce44SJohn Forte 	caddr_t			src, dst;
911fcf3ce44SJohn Forte 	uint16_t		w1;
912fcf3ce44SJohn Forte 	int			rval;
913fcf3ce44SJohn Forte 	nvram_24xx_t		*nv = (nvram_24xx_t *)&nvram;
914fcf3ce44SJohn Forte 	ql_init_24xx_cb_t	*icb =
915fcf3ce44SJohn Forte 	    (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24;
916fcf3ce44SJohn Forte 	ql_ip_init_24xx_cb_t	*ip_icb = &ha->ip_init_ctrl_blk.cb24;
917fcf3ce44SJohn Forte 
918fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
919fcf3ce44SJohn Forte 
920fcf3ce44SJohn Forte 	if ((rval = ql_lock_nvram(ha, &addr, LNF_NVRAM_DATA)) == QL_SUCCESS) {
921fcf3ce44SJohn Forte 
922fcf3ce44SJohn Forte 		/* Get NVRAM data and calculate checksum. */
923fcf3ce44SJohn Forte 		longptr = (uint32_t *)nv;
924fcf3ce44SJohn Forte 		chksum = saved_chksum = 0;
925fcf3ce44SJohn Forte 		for (index = 0; index < sizeof (nvram_24xx_t) / 4; index++) {
926fcf3ce44SJohn Forte 			rval = ql_24xx_read_flash(ha, addr++, longptr);
927fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
928fcf3ce44SJohn Forte 				EL(ha, "24xx_read_flash failed=%xh\n", rval);
929fcf3ce44SJohn Forte 				break;
930fcf3ce44SJohn Forte 			}
931fcf3ce44SJohn Forte 			saved_chksum = chksum;
932fcf3ce44SJohn Forte 			chksum += *longptr;
933fcf3ce44SJohn Forte 			LITTLE_ENDIAN_32(longptr);
934fcf3ce44SJohn Forte 			longptr++;
935fcf3ce44SJohn Forte 		}
936fcf3ce44SJohn Forte 
937fcf3ce44SJohn Forte 		ql_release_nvram(ha);
938fcf3ce44SJohn Forte 	}
939fcf3ce44SJohn Forte 
940fcf3ce44SJohn Forte 	/* Bad NVRAM data, set defaults parameters. */
941fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
942fcf3ce44SJohn Forte 	    nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
943fcf3ce44SJohn Forte 	    (nv->nvram_version[0] | nv->nvram_version[1]) == 0) {
944fcf3ce44SJohn Forte 
945fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed, using "
946fcf3ce44SJohn Forte 		    "driver defaults.", QL_NAME, ha->instance);
947fcf3ce44SJohn Forte 
948fcf3ce44SJohn Forte 		EL(ha, "failed, rval=%xh, checksum=%xh, id=%c%c%c%c, "
949fcf3ce44SJohn Forte 		    "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
950fcf3ce44SJohn Forte 		    nv->id[2], nv->id[3], CHAR_TO_SHORT(nv->nvram_version[0],
951fcf3ce44SJohn Forte 		    nv->nvram_version[1]));
952fcf3ce44SJohn Forte 
953fcf3ce44SJohn Forte 		saved_chksum = ~saved_chksum + 1;
954fcf3ce44SJohn Forte 
955fcf3ce44SJohn Forte 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_NVRAM_CHKSUM_ERR, 0,
956fcf3ce44SJohn Forte 		    MSW(saved_chksum), LSW(saved_chksum));
957fcf3ce44SJohn Forte 
958fcf3ce44SJohn Forte 		/* Reset NVRAM data. */
959fcf3ce44SJohn Forte 		bzero((void *)nv, sizeof (nvram_24xx_t));
960fcf3ce44SJohn Forte 
961fcf3ce44SJohn Forte 		/*
962fcf3ce44SJohn Forte 		 * Set default initialization control block.
963fcf3ce44SJohn Forte 		 */
964fcf3ce44SJohn Forte 		nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
965fcf3ce44SJohn Forte 		nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
966fcf3ce44SJohn Forte 
967fcf3ce44SJohn Forte 		nv->version[0] = 1;
968fcf3ce44SJohn Forte 		nv->max_frame_length[1] = 8;
969fcf3ce44SJohn Forte 		nv->execution_throttle[0] = 16;
970eb82ff87SDaniel Beauregard 		nv->exchange_count[0] = 128;
971fcf3ce44SJohn Forte 		nv->max_luns_per_target[0] = 8;
972fcf3ce44SJohn Forte 
973fcf3ce44SJohn Forte 		idpromlen = 32;
974fcf3ce44SJohn Forte 
975fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
97616dd44c2SDaniel Beauregard 		if (rval = ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
977fcf3ce44SJohn Forte 		    DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
978fcf3ce44SJohn Forte 		    &idpromlen) != DDI_PROP_SUCCESS) {
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
98116dd44c2SDaniel Beauregard 			    "property, rval=%x", QL_NAME, ha->instance, rval);
982fcf3ce44SJohn Forte 
983fcf3ce44SJohn Forte 			nv->port_name[0] = 33;
984fcf3ce44SJohn Forte 			nv->port_name[3] = 224;
985fcf3ce44SJohn Forte 			nv->port_name[4] = 139;
986fcf3ce44SJohn Forte 			nv->port_name[7] = (uint8_t)
987fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
988fcf3ce44SJohn Forte 		} else {
989fcf3ce44SJohn Forte 			nv->port_name[2] = idprombuf[2];
990fcf3ce44SJohn Forte 			nv->port_name[3] = idprombuf[3];
991fcf3ce44SJohn Forte 			nv->port_name[4] = idprombuf[4];
992fcf3ce44SJohn Forte 			nv->port_name[5] = idprombuf[5];
993fcf3ce44SJohn Forte 			nv->port_name[6] = idprombuf[6];
994fcf3ce44SJohn Forte 			nv->port_name[7] = idprombuf[7];
995fcf3ce44SJohn Forte 			nv->port_name[0] = (uint8_t)
996fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
997fcf3ce44SJohn Forte 		}
998fcf3ce44SJohn Forte 
999fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using default "
1000fcf3ce44SJohn Forte 		    "HBA parameters and temporary "
1001fcf3ce44SJohn Forte 		    "WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
1002fcf3ce44SJohn Forte 		    ha->instance, nv->port_name[0], nv->port_name[1],
1003fcf3ce44SJohn Forte 		    nv->port_name[2], nv->port_name[3], nv->port_name[4],
1004fcf3ce44SJohn Forte 		    nv->port_name[5], nv->port_name[6], nv->port_name[7]);
1005fcf3ce44SJohn Forte 
1006fcf3ce44SJohn Forte 		nv->login_retry_count[0] = 8;
1007fcf3ce44SJohn Forte 
1008fcf3ce44SJohn Forte 		nv->firmware_options_1[0] = BIT_2 | BIT_1;
1009fcf3ce44SJohn Forte 		nv->firmware_options_1[1] = BIT_5;
1010fcf3ce44SJohn Forte 		nv->firmware_options_2[0] = BIT_5;
1011fcf3ce44SJohn Forte 		nv->firmware_options_2[1] = BIT_4;
1012fcf3ce44SJohn Forte 		nv->firmware_options_3[1] = BIT_6;
1013fcf3ce44SJohn Forte 
1014fcf3ce44SJohn Forte 		/*
1015fcf3ce44SJohn Forte 		 * Set default host adapter parameters
1016fcf3ce44SJohn Forte 		 */
1017fcf3ce44SJohn Forte 		nv->host_p[0] = BIT_4 | BIT_1;
1018fcf3ce44SJohn Forte 		nv->host_p[1] = BIT_3 | BIT_2;
1019fcf3ce44SJohn Forte 		nv->reset_delay = 5;
1020fcf3ce44SJohn Forte 		nv->max_luns_per_target[0] = 128;
1021fcf3ce44SJohn Forte 		nv->port_down_retry_count[0] = 30;
1022fcf3ce44SJohn Forte 		nv->link_down_timeout[0] = 30;
1023fcf3ce44SJohn Forte 
1024eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_8081)) {
10255dfd244aSDaniel Beauregard 			nv->firmware_options_3[2] = BIT_4;
10265dfd244aSDaniel Beauregard 			nv->feature_mask_l[0] = 9;
10275dfd244aSDaniel Beauregard 			nv->ext_blk.version[0] = 1;
10285dfd244aSDaniel Beauregard 			nv->ext_blk.fcf_vlan_match = 1;
10295dfd244aSDaniel Beauregard 			nv->ext_blk.fcf_vlan_id[0] = LSB(1002);
10305dfd244aSDaniel Beauregard 			nv->ext_blk.fcf_vlan_id[1] = MSB(1002);
1031eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[1] = 2;
1032eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[2] = 3;
1033eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[3] = 4;
1034eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[4] = MSB(ha->instance);
1035eb82ff87SDaniel Beauregard 			nv->fw.isp8001.e_node_mac_addr[5] = LSB(ha->instance);
10365dfd244aSDaniel Beauregard 		}
10375dfd244aSDaniel Beauregard 
1038fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
1039fcf3ce44SJohn Forte 	}
1040fcf3ce44SJohn Forte 
1041fcf3ce44SJohn Forte 	/* Check for adapter node name (big endian). */
1042fcf3ce44SJohn Forte 	for (index = 0; index < 8; index++) {
1043fcf3ce44SJohn Forte 		if (nv->node_name[index] != 0) {
1044fcf3ce44SJohn Forte 			break;
1045fcf3ce44SJohn Forte 		}
1046fcf3ce44SJohn Forte 	}
1047fcf3ce44SJohn Forte 
1048fcf3ce44SJohn Forte 	/* Copy port name if no node name (big endian). */
1049fcf3ce44SJohn Forte 	if (index == 8) {
1050fcf3ce44SJohn Forte 		bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8);
1051fcf3ce44SJohn Forte 		nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
1052fcf3ce44SJohn Forte 		nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
1053fcf3ce44SJohn Forte 	}
1054fcf3ce44SJohn Forte 
1055fcf3ce44SJohn Forte 	/* Reset initialization control blocks. */
1056fcf3ce44SJohn Forte 	bzero((void *)icb, sizeof (ql_init_24xx_cb_t));
1057fcf3ce44SJohn Forte 
1058fcf3ce44SJohn Forte 	/* Get driver properties. */
1059fcf3ce44SJohn Forte 	ql_24xx_properties(ha, nv);
1060fcf3ce44SJohn Forte 
1061fcf3ce44SJohn Forte 	cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
1062fcf3ce44SJohn Forte 	    "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
1063fcf3ce44SJohn Forte 	    QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1],
1064fcf3ce44SJohn Forte 	    nv->port_name[2], nv->port_name[3], nv->port_name[4],
1065fcf3ce44SJohn Forte 	    nv->port_name[5], nv->port_name[6], nv->port_name[7],
1066fcf3ce44SJohn Forte 	    nv->node_name[0], nv->node_name[1], nv->node_name[2],
1067fcf3ce44SJohn Forte 	    nv->node_name[3], nv->node_name[4], nv->node_name[5],
1068fcf3ce44SJohn Forte 	    nv->node_name[6], nv->node_name[7]);
1069fcf3ce44SJohn Forte 
1070fcf3ce44SJohn Forte 	/*
1071fcf3ce44SJohn Forte 	 * Copy over NVRAM Firmware Initialization Control Block.
1072fcf3ce44SJohn Forte 	 */
1073fcf3ce44SJohn Forte 	dst = (caddr_t)icb;
1074fcf3ce44SJohn Forte 	src = (caddr_t)&nv->version;
1075fcf3ce44SJohn Forte 	index = (uint32_t)((uintptr_t)&icb->response_q_inpointer[0] -
1076fcf3ce44SJohn Forte 	    (uintptr_t)icb);
1077fcf3ce44SJohn Forte 	while (index--) {
1078fcf3ce44SJohn Forte 		*dst++ = *src++;
1079fcf3ce44SJohn Forte 	}
1080fcf3ce44SJohn Forte 	icb->login_retry_count[0] = nv->login_retry_count[0];
1081fcf3ce44SJohn Forte 	icb->login_retry_count[1] = nv->login_retry_count[1];
1082fcf3ce44SJohn Forte 	icb->link_down_on_nos[0] = nv->link_down_on_nos[0];
1083fcf3ce44SJohn Forte 	icb->link_down_on_nos[1] = nv->link_down_on_nos[1];
1084fcf3ce44SJohn Forte 
1085fcf3ce44SJohn Forte 	dst = (caddr_t)&icb->interrupt_delay_timer;
1086fcf3ce44SJohn Forte 	src = (caddr_t)&nv->interrupt_delay_timer;
10875dfd244aSDaniel Beauregard 	index = (uint32_t)((uintptr_t)&icb->qos -
1088fcf3ce44SJohn Forte 	    (uintptr_t)&icb->interrupt_delay_timer);
1089fcf3ce44SJohn Forte 	while (index--) {
1090fcf3ce44SJohn Forte 		*dst++ = *src++;
1091fcf3ce44SJohn Forte 	}
1092fcf3ce44SJohn Forte 
1093fcf3ce44SJohn Forte 	/*
1094fcf3ce44SJohn Forte 	 * Setup driver firmware options.
1095fcf3ce44SJohn Forte 	 */
1096eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8081)) {
10975dfd244aSDaniel Beauregard 		dst = (caddr_t)icb->enode_mac_addr;
1098a2b3ff35SDaniel Beauregard 		src = (caddr_t)nv->fw.isp8001.e_node_mac_addr;
1099a2b3ff35SDaniel Beauregard 		index = sizeof (nv->fw.isp8001.e_node_mac_addr);
11005dfd244aSDaniel Beauregard 		while (index--) {
11015dfd244aSDaniel Beauregard 			*dst++ = *src++;
11025dfd244aSDaniel Beauregard 		}
11035dfd244aSDaniel Beauregard 		dst = (caddr_t)&icb->ext_blk;
11045dfd244aSDaniel Beauregard 		src = (caddr_t)&nv->ext_blk;
11055dfd244aSDaniel Beauregard 		index = sizeof (ql_ext_icb_8100_t);
11065dfd244aSDaniel Beauregard 		while (index--) {
11075dfd244aSDaniel Beauregard 			*dst++ = *src++;
11085dfd244aSDaniel Beauregard 		}
1109a2b3ff35SDaniel Beauregard 		EL(ha, "e_node_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x\n",
1110a2b3ff35SDaniel Beauregard 		    icb->enode_mac_addr[0], icb->enode_mac_addr[1],
1111a2b3ff35SDaniel Beauregard 		    icb->enode_mac_addr[2], icb->enode_mac_addr[3],
1112a2b3ff35SDaniel Beauregard 		    icb->enode_mac_addr[4], icb->enode_mac_addr[5]);
1113fcf3ce44SJohn Forte 	} else {
1114fcf3ce44SJohn Forte 		icb->firmware_options_1[0] = (uint8_t)
1115fcf3ce44SJohn Forte 		    (icb->firmware_options_1[0] | BIT_1);
11165dfd244aSDaniel Beauregard 		icb->firmware_options_1[1] = (uint8_t)
11175dfd244aSDaniel Beauregard 		    (icb->firmware_options_1[1] | BIT_5 | BIT_2);
11185dfd244aSDaniel Beauregard 		icb->firmware_options_3[0] = (uint8_t)
11195dfd244aSDaniel Beauregard 		    (icb->firmware_options_3[0] | BIT_1);
1120fcf3ce44SJohn Forte 	}
11215dfd244aSDaniel Beauregard 	icb->firmware_options_1[0] = (uint8_t)(icb->firmware_options_1[0] &
11225dfd244aSDaniel Beauregard 	    ~(BIT_5 | BIT_4));
11235dfd244aSDaniel Beauregard 	icb->firmware_options_1[1] = (uint8_t)(icb->firmware_options_1[1] |
11245dfd244aSDaniel Beauregard 	    BIT_6);
11255dfd244aSDaniel Beauregard 	icb->firmware_options_2[0] = (uint8_t)(icb->firmware_options_2[0] &
11265dfd244aSDaniel Beauregard 	    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
1127fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
1128fcf3ce44SJohn Forte 		icb->firmware_options_2[1] = (uint8_t)
1129fcf3ce44SJohn Forte 		    (icb->firmware_options_2[1] | BIT_4);
1130fcf3ce44SJohn Forte 	} else {
1131fcf3ce44SJohn Forte 		icb->firmware_options_2[1] = (uint8_t)
1132fcf3ce44SJohn Forte 		    (icb->firmware_options_2[1] & ~BIT_4);
1133fcf3ce44SJohn Forte 	}
1134fcf3ce44SJohn Forte 
1135fcf3ce44SJohn Forte 	icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] &
1136fcf3ce44SJohn Forte 	    ~BIT_7);
1137fcf3ce44SJohn Forte 
11385dfd244aSDaniel Beauregard 	/* enable special N port 2 N port login behaviour */
11395dfd244aSDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_2425)) {
11405dfd244aSDaniel Beauregard 		icb->firmware_options_3[1] =
11415dfd244aSDaniel Beauregard 		    (uint8_t)(icb->firmware_options_3[1] | BIT_0);
11425dfd244aSDaniel Beauregard 	}
11435dfd244aSDaniel Beauregard 
1144fcf3ce44SJohn Forte 	icb->execution_throttle[0] = 0xff;
1145fcf3ce44SJohn Forte 	icb->execution_throttle[1] = 0xff;
1146fcf3ce44SJohn Forte 
1147fcf3ce44SJohn Forte 	/*
1148fcf3ce44SJohn Forte 	 * Set host adapter parameters
1149fcf3ce44SJohn Forte 	 */
1150fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1151fcf3ce44SJohn Forte 	ha->nvram_version = CHAR_TO_SHORT(nv->nvram_version[0],
1152fcf3ce44SJohn Forte 	    nv->nvram_version[1]);
1153fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) :
1154fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN);
1155fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) :
1156fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET);
1157eb82ff87SDaniel Beauregard 	ha->cfg_flags &= ~(CFG_DISABLE_RISC_CODE_LOAD | CFG_LR_SUPPORT |
1158fcf3ce44SJohn Forte 	    CFG_SET_CACHE_LINE_SIZE_1 | CFG_MULTI_CHIP_ADAPTER);
1159fcf3ce44SJohn Forte 	ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
1160eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_81XX) && nv->enhanced_features[0] & BIT_0) {
1161eb82ff87SDaniel Beauregard 		ha->cfg_flags |= CFG_LR_SUPPORT;
1162eb82ff87SDaniel Beauregard 	}
1163fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1164fcf3ce44SJohn Forte 
1165fcf3ce44SJohn Forte 	ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
1166fcf3ce44SJohn Forte 	    nv->execution_throttle[1]);
1167fcf3ce44SJohn Forte 	ha->loop_reset_delay = nv->reset_delay;
1168fcf3ce44SJohn Forte 	ha->port_down_retry_count = CHAR_TO_SHORT(nv->port_down_retry_count[0],
1169fcf3ce44SJohn Forte 	    nv->port_down_retry_count[1]);
1170fcf3ce44SJohn Forte 	w1 = CHAR_TO_SHORT(icb->login_timeout[0], icb->login_timeout[1]);
1171fcf3ce44SJohn Forte 	ha->r_a_tov = (uint16_t)(w1 < R_A_TOV_DEFAULT ? R_A_TOV_DEFAULT : w1);
1172fcf3ce44SJohn Forte 	ha->maximum_luns_per_target = CHAR_TO_SHORT(
1173fcf3ce44SJohn Forte 	    nv->max_luns_per_target[0], nv->max_luns_per_target[1]);
1174fcf3ce44SJohn Forte 	if (ha->maximum_luns_per_target == 0) {
1175fcf3ce44SJohn Forte 		ha->maximum_luns_per_target++;
1176fcf3ce44SJohn Forte 	}
1177fcf3ce44SJohn Forte 
1178fcf3ce44SJohn Forte 	/* ISP2422 Serial Link Control */
11795dfd244aSDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_2422)) {
11805dfd244aSDaniel Beauregard 		ha->serdes_param[0] = CHAR_TO_SHORT(nv->fw.isp2400.swing_opt[0],
11815dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_opt[1]);
11825dfd244aSDaniel Beauregard 		ha->serdes_param[1] = CHAR_TO_SHORT(nv->fw.isp2400.swing_1g[0],
11835dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_1g[1]);
11845dfd244aSDaniel Beauregard 		ha->serdes_param[2] = CHAR_TO_SHORT(nv->fw.isp2400.swing_2g[0],
11855dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_2g[1]);
11865dfd244aSDaniel Beauregard 		ha->serdes_param[3] = CHAR_TO_SHORT(nv->fw.isp2400.swing_4g[0],
11875dfd244aSDaniel Beauregard 		    nv->fw.isp2400.swing_4g[1]);
11885dfd244aSDaniel Beauregard 	}
1189fcf3ce44SJohn Forte 
1190fcf3ce44SJohn Forte 	/*
1191fcf3ce44SJohn Forte 	 * Setup ring parameters in initialization control block
1192fcf3ce44SJohn Forte 	 */
1193fcf3ce44SJohn Forte 	w1 = REQUEST_ENTRY_CNT;
1194fcf3ce44SJohn Forte 	icb->request_q_length[0] = LSB(w1);
1195fcf3ce44SJohn Forte 	icb->request_q_length[1] = MSB(w1);
1196fcf3ce44SJohn Forte 	w1 = RESPONSE_ENTRY_CNT;
1197fcf3ce44SJohn Forte 	icb->response_q_length[0] = LSB(w1);
1198fcf3ce44SJohn Forte 	icb->response_q_length[1] = MSB(w1);
1199fcf3ce44SJohn Forte 
1200fcf3ce44SJohn Forte 	icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma)));
1201fcf3ce44SJohn Forte 	icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma)));
1202fcf3ce44SJohn Forte 	icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma)));
1203fcf3ce44SJohn Forte 	icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma)));
1204fcf3ce44SJohn Forte 	icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma)));
1205fcf3ce44SJohn Forte 	icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma)));
1206fcf3ce44SJohn Forte 	icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma)));
1207fcf3ce44SJohn Forte 	icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma)));
1208fcf3ce44SJohn Forte 
1209fcf3ce44SJohn Forte 	icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma)));
1210fcf3ce44SJohn Forte 	icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma)));
1211fcf3ce44SJohn Forte 	icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma)));
1212fcf3ce44SJohn Forte 	icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma)));
1213fcf3ce44SJohn Forte 	icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma)));
1214fcf3ce44SJohn Forte 	icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma)));
1215fcf3ce44SJohn Forte 	icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma)));
1216fcf3ce44SJohn Forte 	icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma)));
1217fcf3ce44SJohn Forte 
1218fcf3ce44SJohn Forte 	/*
1219fcf3ce44SJohn Forte 	 * Setup IP initialization control block
1220fcf3ce44SJohn Forte 	 */
1221fcf3ce44SJohn Forte 	ip_icb->version = IP_ICB_24XX_VERSION;
1222fcf3ce44SJohn Forte 
1223fcf3ce44SJohn Forte 	ip_icb->ip_firmware_options[0] = (uint8_t)
1224fcf3ce44SJohn Forte 	    (ip_icb->ip_firmware_options[0] | BIT_2);
1225fcf3ce44SJohn Forte 
1226fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
1227fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
1228fcf3ce44SJohn Forte 	} else {
1229fcf3ce44SJohn Forte 		/*EMPTY*/
1230fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1231fcf3ce44SJohn Forte 	}
1232fcf3ce44SJohn Forte 	return (rval);
1233fcf3ce44SJohn Forte }
1234fcf3ce44SJohn Forte 
1235fcf3ce44SJohn Forte /*
1236fcf3ce44SJohn Forte  * ql_lock_nvram
1237fcf3ce44SJohn Forte  *	Locks NVRAM access and returns starting address of NVRAM.
1238fcf3ce44SJohn Forte  *
1239fcf3ce44SJohn Forte  * Input:
1240fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1241fcf3ce44SJohn Forte  *	addr:	pointer for start address.
1242fcf3ce44SJohn Forte  *	flags:	Are mutually exclusive:
1243fcf3ce44SJohn Forte  *		LNF_NVRAM_DATA --> get nvram
1244fcf3ce44SJohn Forte  *		LNF_VPD_DATA --> get vpd data (24/25xx only).
1245fcf3ce44SJohn Forte  *
1246fcf3ce44SJohn Forte  * Returns:
1247fcf3ce44SJohn Forte  *	ql local function return status code.
1248fcf3ce44SJohn Forte  *
1249fcf3ce44SJohn Forte  * Context:
1250fcf3ce44SJohn Forte  *	Kernel context.
1251fcf3ce44SJohn Forte  */
1252fcf3ce44SJohn Forte int
1253fcf3ce44SJohn Forte ql_lock_nvram(ql_adapter_state_t *ha, uint32_t *addr, uint32_t flags)
1254fcf3ce44SJohn Forte {
1255fcf3ce44SJohn Forte 	int	i;
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 	if ((flags & LNF_NVRAM_DATA) && (flags & LNF_VPD_DATA)) {
1258fcf3ce44SJohn Forte 		EL(ha, "invalid options for function");
1259fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
1260fcf3ce44SJohn Forte 	}
1261fcf3ce44SJohn Forte 
1262fcf3ce44SJohn Forte 	if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
1263fcf3ce44SJohn Forte 		if ((flags & LNF_NVRAM_DATA) == 0) {
1264fcf3ce44SJohn Forte 			EL(ha, "invalid 2312/2322 option for HBA");
1265fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1266fcf3ce44SJohn Forte 		}
1267fcf3ce44SJohn Forte 
1268fcf3ce44SJohn Forte 		/* if function number is non-zero, then adjust offset */
12695dfd244aSDaniel Beauregard 		*addr = ha->flash_nvram_addr;
1270fcf3ce44SJohn Forte 
1271fcf3ce44SJohn Forte 		/* Try to get resource lock. Wait for 10 seconds max */
1272fcf3ce44SJohn Forte 		for (i = 0; i < 10000; i++) {
1273fcf3ce44SJohn Forte 			/* if nvram busy bit is reset, acquire sema */
1274fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, nvram) & 0x8000) == 0) {
1275fcf3ce44SJohn Forte 				WRT16_IO_REG(ha, host_to_host_sema, 1);
1276fcf3ce44SJohn Forte 				drv_usecwait(MILLISEC);
1277fcf3ce44SJohn Forte 				if (RD16_IO_REG(ha, host_to_host_sema) & 1) {
1278fcf3ce44SJohn Forte 					break;
1279fcf3ce44SJohn Forte 				}
1280fcf3ce44SJohn Forte 			}
1281fcf3ce44SJohn Forte 			drv_usecwait(MILLISEC);
1282fcf3ce44SJohn Forte 		}
1283fcf3ce44SJohn Forte 		if ((RD16_IO_REG(ha, host_to_host_sema) & 1) == 0) {
1284fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): unable to get NVRAM lock",
1285fcf3ce44SJohn Forte 			    QL_NAME, ha->instance);
1286fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1287fcf3ce44SJohn Forte 		}
1288fcf3ce44SJohn Forte 	} else if (CFG_IST(ha, CFG_CTRL_2422)) {
1289fcf3ce44SJohn Forte 		if (flags & LNF_VPD_DATA) {
12905dfd244aSDaniel Beauregard 			*addr = NVRAM_DATA_ADDR | ha->flash_vpd_addr;
1291fcf3ce44SJohn Forte 		} else if (flags & LNF_NVRAM_DATA) {
12925dfd244aSDaniel Beauregard 			*addr = NVRAM_DATA_ADDR | ha->flash_nvram_addr;
1293fcf3ce44SJohn Forte 		} else {
12945dfd244aSDaniel Beauregard 			EL(ha, "invalid 2422 option for HBA");
1295fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1296fcf3ce44SJohn Forte 		}
1297fcf3ce44SJohn Forte 
1298fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1299eb82ff87SDaniel Beauregard 	} else if (CFG_IST(ha, CFG_CTRL_258081)) {
1300fcf3ce44SJohn Forte 		if (flags & LNF_VPD_DATA) {
13015dfd244aSDaniel Beauregard 			*addr = ha->flash_data_addr | ha->flash_vpd_addr;
1302fcf3ce44SJohn Forte 		} else if (flags & LNF_NVRAM_DATA) {
13035dfd244aSDaniel Beauregard 			*addr = ha->flash_data_addr | ha->flash_nvram_addr;
1304fcf3ce44SJohn Forte 		} else {
13055dfd244aSDaniel Beauregard 			EL(ha, "invalid 2581 option for HBA");
1306fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1307fcf3ce44SJohn Forte 		}
1308fcf3ce44SJohn Forte 
1309fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1310fcf3ce44SJohn Forte 	} else {
1311fcf3ce44SJohn Forte 		if ((flags & LNF_NVRAM_DATA) == 0) {
1312fcf3ce44SJohn Forte 			EL(ha, "invalid option for HBA");
1313fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1314fcf3ce44SJohn Forte 		}
1315fcf3ce44SJohn Forte 		*addr = 0;
1316fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1317fcf3ce44SJohn Forte 	}
1318fcf3ce44SJohn Forte 
1319fcf3ce44SJohn Forte 	return (QL_SUCCESS);
1320fcf3ce44SJohn Forte }
1321fcf3ce44SJohn Forte 
1322fcf3ce44SJohn Forte /*
1323fcf3ce44SJohn Forte  * ql_release_nvram
1324fcf3ce44SJohn Forte  *	Releases NVRAM access.
1325fcf3ce44SJohn Forte  *
1326fcf3ce44SJohn Forte  * Input:
1327fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1328fcf3ce44SJohn Forte  *
1329fcf3ce44SJohn Forte  * Context:
1330fcf3ce44SJohn Forte  *	Kernel context.
1331fcf3ce44SJohn Forte  */
1332fcf3ce44SJohn Forte void
1333fcf3ce44SJohn Forte ql_release_nvram(ql_adapter_state_t *ha)
1334fcf3ce44SJohn Forte {
1335fcf3ce44SJohn Forte 	if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
1336fcf3ce44SJohn Forte 		/* Release resource lock */
1337fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, host_to_host_sema, 0);
1338fcf3ce44SJohn Forte 	} else {
1339fcf3ce44SJohn Forte 		GLOBAL_HW_UNLOCK();
1340fcf3ce44SJohn Forte 	}
1341fcf3ce44SJohn Forte }
1342fcf3ce44SJohn Forte 
1343fcf3ce44SJohn Forte /*
1344fcf3ce44SJohn Forte  * ql_23_properties
1345fcf3ce44SJohn Forte  *	Copies driver properties to NVRAM or adapter structure.
1346fcf3ce44SJohn Forte  *
1347fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1348fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1349fcf3ce44SJohn Forte  *	override the default values using driver.conf
1350fcf3ce44SJohn Forte  *
1351fcf3ce44SJohn Forte  * Input:
1352fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1353fcf3ce44SJohn Forte  *	nv:	NVRAM structure pointer.
1354fcf3ce44SJohn Forte  *
1355fcf3ce44SJohn Forte  * Context:
1356fcf3ce44SJohn Forte  *	Kernel context.
1357fcf3ce44SJohn Forte  */
1358fcf3ce44SJohn Forte static void
1359fcf3ce44SJohn Forte ql_23_properties(ql_adapter_state_t *ha, nvram_t *nv)
1360fcf3ce44SJohn Forte {
1361fcf3ce44SJohn Forte 	uint32_t	data, cnt;
1362fcf3ce44SJohn Forte 
1363fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1364fcf3ce44SJohn Forte 
1365fcf3ce44SJohn Forte 	/* Get frame payload size. */
1366fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
1367fcf3ce44SJohn Forte 		data = 2048;
1368fcf3ce44SJohn Forte 	}
1369fcf3ce44SJohn Forte 	if (data == 512 || data == 1024 || data == 2048) {
1370fcf3ce44SJohn Forte 		nv->max_frame_length[0] = LSB(data);
1371fcf3ce44SJohn Forte 		nv->max_frame_length[1] = MSB(data);
1372fcf3ce44SJohn Forte 	} else {
1373fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'max-frame-length': "
1374fcf3ce44SJohn Forte 		    "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1375fcf3ce44SJohn Forte 		    nv->max_frame_length[0], nv->max_frame_length[1]));
1376fcf3ce44SJohn Forte 	}
1377fcf3ce44SJohn Forte 
1378fcf3ce44SJohn Forte 	/* Get max IOCB allocation. */
1379fcf3ce44SJohn Forte 	nv->max_iocb_allocation[0] = 0;
1380fcf3ce44SJohn Forte 	nv->max_iocb_allocation[1] = 1;
1381fcf3ce44SJohn Forte 
1382fcf3ce44SJohn Forte 	/* Get execution throttle. */
1383fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
1384fcf3ce44SJohn Forte 		data = 32;
1385fcf3ce44SJohn Forte 	}
1386fcf3ce44SJohn Forte 	if (data != 0 && data < 65536) {
1387fcf3ce44SJohn Forte 		nv->execution_throttle[0] = LSB(data);
1388fcf3ce44SJohn Forte 		nv->execution_throttle[1] = MSB(data);
1389fcf3ce44SJohn Forte 	} else {
1390fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'execution-throttle': "
1391fcf3ce44SJohn Forte 		    "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1392fcf3ce44SJohn Forte 		    nv->execution_throttle[0], nv->execution_throttle[1]));
1393fcf3ce44SJohn Forte 	}
1394fcf3ce44SJohn Forte 
1395fcf3ce44SJohn Forte 	/* Get Login timeout. */
1396fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
1397fcf3ce44SJohn Forte 		data = 3;
1398fcf3ce44SJohn Forte 	}
1399fcf3ce44SJohn Forte 	if (data < 256) {
1400fcf3ce44SJohn Forte 		nv->login_timeout = (uint8_t)data;
1401fcf3ce44SJohn Forte 	} else {
1402fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-timeout': "
1403fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data, nv->login_timeout);
1404fcf3ce44SJohn Forte 	}
1405fcf3ce44SJohn Forte 
1406fcf3ce44SJohn Forte 	/* Get retry count. */
1407fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
1408fcf3ce44SJohn Forte 		data = 4;
1409fcf3ce44SJohn Forte 	}
1410fcf3ce44SJohn Forte 	if (data < 256) {
1411fcf3ce44SJohn Forte 		nv->login_retry_count = (uint8_t)data;
1412fcf3ce44SJohn Forte 	} else {
1413fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-retry-count': "
1414fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data,
1415fcf3ce44SJohn Forte 		    nv->login_retry_count);
1416fcf3ce44SJohn Forte 	}
1417fcf3ce44SJohn Forte 
1418fcf3ce44SJohn Forte 	/* Get adapter hard loop ID enable. */
1419fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "enable-adapter-hard-loop-ID");
1420fcf3ce44SJohn Forte 	if (data == 0) {
1421fcf3ce44SJohn Forte 		nv->firmware_options[0] =
1422fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options[0] & ~BIT_0);
1423fcf3ce44SJohn Forte 	} else if (data == 1) {
1424fcf3ce44SJohn Forte 		nv->firmware_options[0] =
1425fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options[0] | BIT_0);
1426fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1427fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1428fcf3ce44SJohn Forte 		    "'enable-adapter-hard-loop-ID': %d; using nvram value "
1429fcf3ce44SJohn Forte 		    "of %d\n", data, nv->firmware_options[0] & BIT_0 ? 1 : 0);
1430fcf3ce44SJohn Forte 	}
1431fcf3ce44SJohn Forte 
1432fcf3ce44SJohn Forte 	/* Get adapter hard loop ID. */
1433fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "adapter-hard-loop-ID");
1434fcf3ce44SJohn Forte 	if (data < 126) {
1435fcf3ce44SJohn Forte 		nv->hard_address[0] = (uint8_t)data;
1436fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1437fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'adapter-hard-loop-ID': "
143816dd44c2SDaniel Beauregard 		    "%d; using nvram value of %d\n",
143916dd44c2SDaniel Beauregard 		    data, nv->hard_address[0]);
1440fcf3ce44SJohn Forte 	}
1441fcf3ce44SJohn Forte 
1442fcf3ce44SJohn Forte 	/* Get LIP reset. */
1443fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
1444fcf3ce44SJohn Forte 	    0xffffffff) {
1445fcf3ce44SJohn Forte 		data = 0;
1446fcf3ce44SJohn Forte 	}
1447fcf3ce44SJohn Forte 	if (data == 0) {
1448fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_1);
1449fcf3ce44SJohn Forte 	} else if (data == 1) {
1450fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_1);
1451fcf3ce44SJohn Forte 	} else {
1452fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1453fcf3ce44SJohn Forte 		    "'enable-LIP-reset-on-bus-reset': %d; using nvram value "
1454fcf3ce44SJohn Forte 		    "of %d\n", data, nv->host_p[1] & BIT_1 ? 1 : 0);
1455fcf3ce44SJohn Forte 	}
1456fcf3ce44SJohn Forte 
1457fcf3ce44SJohn Forte 	/* Get LIP full login. */
1458fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
1459fcf3ce44SJohn Forte 	    0xffffffff) {
1460fcf3ce44SJohn Forte 		data = 1;
1461fcf3ce44SJohn Forte 	}
1462fcf3ce44SJohn Forte 	if (data == 0) {
1463fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2);
1464fcf3ce44SJohn Forte 	} else if (data == 1) {
1465fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2);
1466fcf3ce44SJohn Forte 	} else {
1467fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1468fcf3ce44SJohn Forte 		    "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
1469fcf3ce44SJohn Forte 		    "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0);
1470fcf3ce44SJohn Forte 	}
1471fcf3ce44SJohn Forte 
1472fcf3ce44SJohn Forte 	/* Get target reset. */
1473fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
1474fcf3ce44SJohn Forte 	    0xffffffff) {
1475fcf3ce44SJohn Forte 		data = 0;
1476fcf3ce44SJohn Forte 	}
1477fcf3ce44SJohn Forte 	if (data == 0) {
1478fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3);
1479fcf3ce44SJohn Forte 	} else if (data == 1) {
1480fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3);
1481fcf3ce44SJohn Forte 	} else {
1482fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1483fcf3ce44SJohn Forte 		    "'enable-target-reset-on-bus-reset': %d; using nvram "
1484fcf3ce44SJohn Forte 		    "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0);
1485fcf3ce44SJohn Forte 	}
1486fcf3ce44SJohn Forte 
1487fcf3ce44SJohn Forte 	/* Get reset delay. */
1488fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
1489fcf3ce44SJohn Forte 		data = 5;
1490fcf3ce44SJohn Forte 	}
1491fcf3ce44SJohn Forte 	if (data != 0 && data < 256) {
1492fcf3ce44SJohn Forte 		nv->reset_delay = (uint8_t)data;
1493fcf3ce44SJohn Forte 	} else {
1494fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'reset-delay': %d; "
1495fcf3ce44SJohn Forte 		    "using nvram value of %d", data, nv->reset_delay);
1496fcf3ce44SJohn Forte 	}
1497fcf3ce44SJohn Forte 
1498fcf3ce44SJohn Forte 	/* Get port down retry count. */
1499fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
1500fcf3ce44SJohn Forte 		data = 8;
1501fcf3ce44SJohn Forte 	}
1502fcf3ce44SJohn Forte 	if (data < 256) {
1503fcf3ce44SJohn Forte 		nv->port_down_retry_count = (uint8_t)data;
1504fcf3ce44SJohn Forte 	} else {
1505fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-count':"
1506fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data,
1507fcf3ce44SJohn Forte 		    nv->port_down_retry_count);
1508fcf3ce44SJohn Forte 	}
1509fcf3ce44SJohn Forte 
1510fcf3ce44SJohn Forte 	/* Get connection mode setting. */
1511fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) {
1512fcf3ce44SJohn Forte 		data = 2;
1513fcf3ce44SJohn Forte 	}
1514fcf3ce44SJohn Forte 	cnt = CFG_IST(ha, CFG_CTRL_2200) ? 3 : 2;
1515fcf3ce44SJohn Forte 	if (data <= cnt) {
1516fcf3ce44SJohn Forte 		nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] &
1517fcf3ce44SJohn Forte 		    ~(BIT_6 | BIT_5 | BIT_4));
1518fcf3ce44SJohn Forte 		nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
1519fcf3ce44SJohn Forte 		    (uint8_t)(data << 4));
1520fcf3ce44SJohn Forte 	} else {
1521fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'connection-options': "
1522fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data,
1523fcf3ce44SJohn Forte 		    (nv->add_fw_opt[0] >> 4) & 0x3);
1524fcf3ce44SJohn Forte 	}
1525fcf3ce44SJohn Forte 
1526fcf3ce44SJohn Forte 	/* Get data rate setting. */
1527fcf3ce44SJohn Forte 	if ((CFG_IST(ha, CFG_CTRL_2200)) == 0) {
1528fcf3ce44SJohn Forte 		if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
1529fcf3ce44SJohn Forte 			data = 2;
1530fcf3ce44SJohn Forte 		}
1531fcf3ce44SJohn Forte 		if (data < 3) {
1532fcf3ce44SJohn Forte 			nv->special_options[1] = (uint8_t)
1533fcf3ce44SJohn Forte 			    (nv->special_options[1] & 0x3f);
1534fcf3ce44SJohn Forte 			nv->special_options[1] = (uint8_t)
1535fcf3ce44SJohn Forte 			    (nv->special_options[1] | (uint8_t)(data << 6));
1536fcf3ce44SJohn Forte 		} else {
1537fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for 'fc-data-rate': "
1538fcf3ce44SJohn Forte 			    "%d; using nvram value of %d\n", data,
1539fcf3ce44SJohn Forte 			    (nv->special_options[1] >> 6) & 0x3);
1540fcf3ce44SJohn Forte 		}
1541fcf3ce44SJohn Forte 	}
1542fcf3ce44SJohn Forte 
1543fcf3ce44SJohn Forte 	/* Get adapter id string for Sun branded 23xx only */
1544fcf3ce44SJohn Forte 	if ((CFG_IST(ha, CFG_CTRL_2300)) && nv->adapInfo[0] != 0) {
1545fcf3ce44SJohn Forte 		(void) snprintf((int8_t *)ha->adapInfo, 16, "%s",
1546fcf3ce44SJohn Forte 		    nv->adapInfo);
1547fcf3ce44SJohn Forte 	}
1548fcf3ce44SJohn Forte 
1549fcf3ce44SJohn Forte 	/* Get IP FW container count. */
1550fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.cc[0] = LSB(ql_ip_buffer_count);
1551fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.cc[1] = MSB(ql_ip_buffer_count);
1552fcf3ce44SJohn Forte 
1553fcf3ce44SJohn Forte 	/* Get IP low water mark. */
1554fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.low_water_mark[0] = LSB(ql_ip_low_water);
1555fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.low_water_mark[1] = MSB(ql_ip_low_water);
1556fcf3ce44SJohn Forte 
1557fcf3ce44SJohn Forte 	/* Get IP fast register post count. */
1558fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.fast_post_reg_count[0] =
1559fcf3ce44SJohn Forte 	    ql_ip_fast_post_count;
1560fcf3ce44SJohn Forte 
1561fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1562fcf3ce44SJohn Forte 
1563fcf3ce44SJohn Forte 	ql_common_properties(ha);
1564fcf3ce44SJohn Forte 
1565fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1566fcf3ce44SJohn Forte 
1567fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1568fcf3ce44SJohn Forte }
1569fcf3ce44SJohn Forte 
1570fcf3ce44SJohn Forte /*
1571fcf3ce44SJohn Forte  * ql_common_properties
1572fcf3ce44SJohn Forte  *	Driver properties adapter structure.
1573fcf3ce44SJohn Forte  *
1574fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1575fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1576fcf3ce44SJohn Forte  *	override the default values using driver.conf
1577fcf3ce44SJohn Forte  *
1578fcf3ce44SJohn Forte  * Input:
1579fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1580fcf3ce44SJohn Forte  *
1581fcf3ce44SJohn Forte  * Context:
1582fcf3ce44SJohn Forte  *	Kernel context.
1583fcf3ce44SJohn Forte  */
1584fcf3ce44SJohn Forte void
1585fcf3ce44SJohn Forte ql_common_properties(ql_adapter_state_t *ha)
1586fcf3ce44SJohn Forte {
1587fcf3ce44SJohn Forte 	uint32_t	data;
1588fcf3ce44SJohn Forte 
1589fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1590fcf3ce44SJohn Forte 
159116dd44c2SDaniel Beauregard 	/* Get extended logging trace buffer size. */
159216dd44c2SDaniel Beauregard 	if ((data = ql_get_prop(ha, "set-ext-log-buffer-size")) !=
159316dd44c2SDaniel Beauregard 	    0xffffffff && data != 0) {
159416dd44c2SDaniel Beauregard 		char		*new_trace;
159516dd44c2SDaniel Beauregard 		uint32_t	new_size;
159616dd44c2SDaniel Beauregard 
159716dd44c2SDaniel Beauregard 		if (ha->el_trace_desc->trace_buffer != NULL) {
159816dd44c2SDaniel Beauregard 			new_size = 1024 * data;
159916dd44c2SDaniel Beauregard 			new_trace = (char *)kmem_zalloc(new_size, KM_SLEEP);
160016dd44c2SDaniel Beauregard 
160116dd44c2SDaniel Beauregard 			if (new_trace == NULL) {
160216dd44c2SDaniel Beauregard 				cmn_err(CE_WARN, "%s(%d): can't get new"
160316dd44c2SDaniel Beauregard 				    " trace buffer",
160416dd44c2SDaniel Beauregard 				    QL_NAME, ha->instance);
160516dd44c2SDaniel Beauregard 			} else {
160616dd44c2SDaniel Beauregard 				/* free the previous */
160716dd44c2SDaniel Beauregard 				kmem_free(ha->el_trace_desc->trace_buffer,
160816dd44c2SDaniel Beauregard 				    ha->el_trace_desc->trace_buffer_size);
160916dd44c2SDaniel Beauregard 				/* Use the new one */
161016dd44c2SDaniel Beauregard 				ha->el_trace_desc->trace_buffer = new_trace;
161116dd44c2SDaniel Beauregard 				ha->el_trace_desc->trace_buffer_size = new_size;
161216dd44c2SDaniel Beauregard 			}
161316dd44c2SDaniel Beauregard 		}
161416dd44c2SDaniel Beauregard 
161516dd44c2SDaniel Beauregard 	}
161616dd44c2SDaniel Beauregard 
161716dd44c2SDaniel Beauregard 	/* Get extended logging enable. */
161816dd44c2SDaniel Beauregard 	if ((data = ql_get_prop(ha, "extended-logging")) == 0xffffffff ||
161916dd44c2SDaniel Beauregard 	    data == 0) {
162016dd44c2SDaniel Beauregard 		ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
162116dd44c2SDaniel Beauregard 	} else if (data == 1) {
162216dd44c2SDaniel Beauregard 		ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
162316dd44c2SDaniel Beauregard 	} else {
162416dd44c2SDaniel Beauregard 		EL(ha, "invalid parameter value for 'extended-logging': %d;"
162516dd44c2SDaniel Beauregard 		    " using default value of 0\n", data);
162616dd44c2SDaniel Beauregard 		ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
162716dd44c2SDaniel Beauregard 	}
162816dd44c2SDaniel Beauregard 
162916dd44c2SDaniel Beauregard 	/* Get extended logging trace disable. */
163016dd44c2SDaniel Beauregard 	if ((data = ql_get_prop(ha, "disable-extended-logging-trace")) ==
163116dd44c2SDaniel Beauregard 	    0xffffffff || data == 0) {
163216dd44c2SDaniel Beauregard 		ha->cfg_flags &= ~CFG_DISABLE_EXTENDED_LOGGING_TRACE;
163316dd44c2SDaniel Beauregard 	} else if (data == 1) {
163416dd44c2SDaniel Beauregard 		ha->cfg_flags |= CFG_DISABLE_EXTENDED_LOGGING_TRACE;
163516dd44c2SDaniel Beauregard 	} else {
163616dd44c2SDaniel Beauregard 		EL(ha, "invalid parameter value for "
163716dd44c2SDaniel Beauregard 		    "'disable-extended-logging-trace': %d;"
163816dd44c2SDaniel Beauregard 		    " using default value of 0\n", data);
163916dd44c2SDaniel Beauregard 		ha->cfg_flags &= ~CFG_DISABLE_EXTENDED_LOGGING_TRACE;
164016dd44c2SDaniel Beauregard 	}
164116dd44c2SDaniel Beauregard 
1642fcf3ce44SJohn Forte 	/* Get FCP 2 Error Recovery. */
1643fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-FCP-2-error-recovery")) ==
1644fcf3ce44SJohn Forte 	    0xffffffff || data == 1) {
1645fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
1646fcf3ce44SJohn Forte 	} else if (data == 0) {
1647fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_FCP_2_SUPPORT;
1648fcf3ce44SJohn Forte 	} else {
1649fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1650fcf3ce44SJohn Forte 		    "'enable-FCP-2-error-recovery': %d; using nvram value of "
1651fcf3ce44SJohn Forte 		    "1\n", data);
1652fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
1653fcf3ce44SJohn Forte 	}
1654fcf3ce44SJohn Forte 
1655fcf3ce44SJohn Forte #ifdef QL_DEBUG_LEVEL_2
1656fcf3ce44SJohn Forte 	ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
1657fcf3ce44SJohn Forte #endif
1658fcf3ce44SJohn Forte 
1659fcf3ce44SJohn Forte 	/* Get port down retry delay. */
1660fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-delay")) == 0xffffffff) {
1661fcf3ce44SJohn Forte 		ha->port_down_retry_delay = PORT_RETRY_TIME;
1662fcf3ce44SJohn Forte 	} else if (data < 256) {
1663fcf3ce44SJohn Forte 		ha->port_down_retry_delay = (uint8_t)data;
1664fcf3ce44SJohn Forte 	} else {
1665fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-delay':"
1666fcf3ce44SJohn Forte 		    " %d; using default value of %d", data, PORT_RETRY_TIME);
1667fcf3ce44SJohn Forte 		ha->port_down_retry_delay = PORT_RETRY_TIME;
1668fcf3ce44SJohn Forte 	}
1669fcf3ce44SJohn Forte 
1670fcf3ce44SJohn Forte 	/* Get queue full retry count. */
1671fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "queue-full-retry-count")) == 0xffffffff) {
1672fcf3ce44SJohn Forte 		ha->qfull_retry_count = 16;
1673fcf3ce44SJohn Forte 	} else if (data < 256) {
1674fcf3ce44SJohn Forte 		ha->qfull_retry_count = (uint8_t)data;
1675fcf3ce44SJohn Forte 	} else {
1676fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'queue-full-retry-count':"
1677fcf3ce44SJohn Forte 		    " %d; using default value of 16", data);
1678fcf3ce44SJohn Forte 		ha->qfull_retry_count = 16;
1679fcf3ce44SJohn Forte 	}
1680fcf3ce44SJohn Forte 
1681fcf3ce44SJohn Forte 	/* Get queue full retry delay. */
1682fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "queue-full-retry-delay")) == 0xffffffff) {
1683fcf3ce44SJohn Forte 		ha->qfull_retry_delay = PORT_RETRY_TIME;
1684fcf3ce44SJohn Forte 	} else if (data < 256) {
1685fcf3ce44SJohn Forte 		ha->qfull_retry_delay = (uint8_t)data;
1686fcf3ce44SJohn Forte 	} else {
1687fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'queue-full-retry-delay':"
1688fcf3ce44SJohn Forte 		    " %d; using default value of %d", data, PORT_RETRY_TIME);
1689fcf3ce44SJohn Forte 		ha->qfull_retry_delay = PORT_RETRY_TIME;
1690fcf3ce44SJohn Forte 	}
1691fcf3ce44SJohn Forte 
1692fcf3ce44SJohn Forte 	/* Get loop down timeout. */
1693fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "link-down-timeout")) == 0xffffffff) {
1694fcf3ce44SJohn Forte 		data = 0;
1695fcf3ce44SJohn Forte 	} else if (data > 255) {
1696fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'link-down-timeout': %d;"
1697fcf3ce44SJohn Forte 		    " using nvram value of 0\n", data);
1698fcf3ce44SJohn Forte 		data = 0;
1699fcf3ce44SJohn Forte 	}
1700fcf3ce44SJohn Forte 	ha->loop_down_abort_time = (uint8_t)(LOOP_DOWN_TIMER_START - data);
1701fcf3ce44SJohn Forte 	if (ha->loop_down_abort_time == LOOP_DOWN_TIMER_START) {
1702fcf3ce44SJohn Forte 		ha->loop_down_abort_time--;
1703fcf3ce44SJohn Forte 	} else if (ha->loop_down_abort_time <= LOOP_DOWN_TIMER_END) {
1704fcf3ce44SJohn Forte 		ha->loop_down_abort_time = LOOP_DOWN_TIMER_END + 1;
1705fcf3ce44SJohn Forte 	}
1706fcf3ce44SJohn Forte 
1707fcf3ce44SJohn Forte 	/* Get link down error enable. */
1708fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-link-down-error")) == 0xffffffff ||
1709fcf3ce44SJohn Forte 	    data == 1) {
1710fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_LINK_DOWN_REPORTING;
1711fcf3ce44SJohn Forte 	} else if (data == 0) {
1712fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_LINK_DOWN_REPORTING;
1713fcf3ce44SJohn Forte 	} else {
1714fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'link-down-error': %d;"
1715fcf3ce44SJohn Forte 		    " using default value of 1\n", data);
1716fcf3ce44SJohn Forte 	}
1717fcf3ce44SJohn Forte 
1718fcf3ce44SJohn Forte 	/*
1719fcf3ce44SJohn Forte 	 * Get firmware dump flags.
1720fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT		BIT_0
1721fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR	BIT_1
1722fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT	BIT_2
1723fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT	BIT_3
1724fcf3ce44SJohn Forte 	 */
1725fcf3ce44SJohn Forte 	ha->cfg_flags &= ~(CFG_DUMP_MAILBOX_TIMEOUT |
1726fcf3ce44SJohn Forte 	    CFG_DUMP_ISP_SYSTEM_ERROR | CFG_DUMP_DRIVER_COMMAND_TIMEOUT |
1727fcf3ce44SJohn Forte 	    CFG_DUMP_LOOP_OFFLINE_TIMEOUT);
1728fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "firmware-dump-flags")) != 0xffffffff) {
1729fcf3ce44SJohn Forte 		if (data & BIT_0) {
1730fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_MAILBOX_TIMEOUT;
1731fcf3ce44SJohn Forte 		}
1732fcf3ce44SJohn Forte 		if (data & BIT_1) {
1733fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_ISP_SYSTEM_ERROR;
1734fcf3ce44SJohn Forte 		}
1735fcf3ce44SJohn Forte 		if (data & BIT_2) {
1736fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_DRIVER_COMMAND_TIMEOUT;
1737fcf3ce44SJohn Forte 		}
1738fcf3ce44SJohn Forte 		if (data & BIT_3) {
1739fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_LOOP_OFFLINE_TIMEOUT;
1740fcf3ce44SJohn Forte 		}
1741fcf3ce44SJohn Forte 	}
1742fcf3ce44SJohn Forte 
1743fcf3ce44SJohn Forte 	/* Get the PCI max read request size override. */
1744fcf3ce44SJohn Forte 	ha->pci_max_read_req = 0;
1745fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "pci-max-read-request")) != 0xffffffff &&
1746fcf3ce44SJohn Forte 	    data != 0) {
1747fcf3ce44SJohn Forte 		ha->pci_max_read_req = (uint16_t)(data);
1748fcf3ce44SJohn Forte 	}
1749fcf3ce44SJohn Forte 
1750a2b3ff35SDaniel Beauregard 	/*
1751a2b3ff35SDaniel Beauregard 	 * Set default fw wait, adjusted for slow FCF's.
1752a2b3ff35SDaniel Beauregard 	 * Revisit when FCF's as fast as FC switches.
1753a2b3ff35SDaniel Beauregard 	 */
1754eb82ff87SDaniel Beauregard 	ha->fwwait = (uint8_t)(CFG_IST(ha, CFG_CTRL_8081) ? 45 : 10);
1755fcf3ce44SJohn Forte 	/* Get the attach fw_ready override value. */
1756fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "init-loop-sync-wait")) != 0xffffffff) {
1757fcf3ce44SJohn Forte 		if (data > 0 && data <= 240) {
1758fcf3ce44SJohn Forte 			ha->fwwait = (uint8_t)data;
1759fcf3ce44SJohn Forte 		} else {
1760fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
1761fcf3ce44SJohn Forte 			    "'init-loop-sync-wait': %d; using default "
1762fcf3ce44SJohn Forte 			    "value of %d\n", data, ha->fwwait);
1763fcf3ce44SJohn Forte 		}
1764fcf3ce44SJohn Forte 	}
1765fcf3ce44SJohn Forte 
1766fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1767fcf3ce44SJohn Forte }
1768fcf3ce44SJohn Forte 
1769fcf3ce44SJohn Forte /*
1770fcf3ce44SJohn Forte  * ql_24xx_properties
1771fcf3ce44SJohn Forte  *	Copies driver properties to NVRAM or adapter structure.
1772fcf3ce44SJohn Forte  *
1773fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1774fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1775fcf3ce44SJohn Forte  *	override the default values using /etc/system.
1776fcf3ce44SJohn Forte  *
1777fcf3ce44SJohn Forte  * Input:
1778fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1779fcf3ce44SJohn Forte  *	nv:	NVRAM structure pointer.
1780fcf3ce44SJohn Forte  *
1781fcf3ce44SJohn Forte  * Context:
1782fcf3ce44SJohn Forte  *	Kernel context.
1783fcf3ce44SJohn Forte  */
1784fcf3ce44SJohn Forte static void
1785fcf3ce44SJohn Forte ql_24xx_properties(ql_adapter_state_t *ha, nvram_24xx_t *nv)
1786fcf3ce44SJohn Forte {
1787fcf3ce44SJohn Forte 	uint32_t	data;
1788fcf3ce44SJohn Forte 
1789fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1790fcf3ce44SJohn Forte 
1791fcf3ce44SJohn Forte 	/* Get frame size */
1792fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
1793fcf3ce44SJohn Forte 		data = 2048;
1794fcf3ce44SJohn Forte 	}
1795eb82ff87SDaniel Beauregard 	if (data == 512 || data == 1024 || data == 2048 || data == 2112) {
1796fcf3ce44SJohn Forte 		nv->max_frame_length[0] = LSB(data);
1797fcf3ce44SJohn Forte 		nv->max_frame_length[1] = MSB(data);
1798fcf3ce44SJohn Forte 	} else {
1799fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'max-frame-length': %d;"
1800fcf3ce44SJohn Forte 		    " using nvram default of %d\n", data, CHAR_TO_SHORT(
1801fcf3ce44SJohn Forte 		    nv->max_frame_length[0], nv->max_frame_length[1]));
1802fcf3ce44SJohn Forte 	}
1803fcf3ce44SJohn Forte 
1804fcf3ce44SJohn Forte 	/* Get execution throttle. */
1805fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
1806fcf3ce44SJohn Forte 		data = 32;
1807fcf3ce44SJohn Forte 	}
1808fcf3ce44SJohn Forte 	if (data != 0 && data < 65536) {
1809fcf3ce44SJohn Forte 		nv->execution_throttle[0] = LSB(data);
1810fcf3ce44SJohn Forte 		nv->execution_throttle[1] = MSB(data);
1811fcf3ce44SJohn Forte 	} else {
1812fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'execution-throttle':"
1813fcf3ce44SJohn Forte 		    " %d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1814fcf3ce44SJohn Forte 		    nv->execution_throttle[0], nv->execution_throttle[1]));
1815fcf3ce44SJohn Forte 	}
1816fcf3ce44SJohn Forte 
1817fcf3ce44SJohn Forte 	/* Get Login timeout. */
1818fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
1819fcf3ce44SJohn Forte 		data = 3;
1820fcf3ce44SJohn Forte 	}
1821fcf3ce44SJohn Forte 	if (data < 65536) {
1822fcf3ce44SJohn Forte 		nv->login_timeout[0] = LSB(data);
1823fcf3ce44SJohn Forte 		nv->login_timeout[1] = MSB(data);
1824fcf3ce44SJohn Forte 	} else {
1825fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-timeout': %d; "
1826fcf3ce44SJohn Forte 		    "using nvram value of %d\n", data, CHAR_TO_SHORT(
1827fcf3ce44SJohn Forte 		    nv->login_timeout[0], nv->login_timeout[1]));
1828fcf3ce44SJohn Forte 	}
1829fcf3ce44SJohn Forte 
1830fcf3ce44SJohn Forte 	/* Get retry count. */
1831fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
1832fcf3ce44SJohn Forte 		data = 4;
1833fcf3ce44SJohn Forte 	}
1834fcf3ce44SJohn Forte 	if (data < 65536) {
1835fcf3ce44SJohn Forte 		nv->login_retry_count[0] = LSB(data);
1836fcf3ce44SJohn Forte 		nv->login_retry_count[1] = MSB(data);
1837fcf3ce44SJohn Forte 	} else {
1838fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-retry-count': "
1839fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1840fcf3ce44SJohn Forte 		    nv->login_retry_count[0], nv->login_retry_count[1]));
1841fcf3ce44SJohn Forte 	}
1842fcf3ce44SJohn Forte 
1843fcf3ce44SJohn Forte 	/* Get adapter hard loop ID enable. */
1844fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "enable-adapter-hard-loop-ID");
1845fcf3ce44SJohn Forte 	if (data == 0) {
1846fcf3ce44SJohn Forte 		nv->firmware_options_1[0] =
1847fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options_1[0] & ~BIT_0);
1848fcf3ce44SJohn Forte 	} else if (data == 1) {
1849fcf3ce44SJohn Forte 		nv->firmware_options_1[0] =
1850fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options_1[0] | BIT_0);
1851fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1852fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1853fcf3ce44SJohn Forte 		    "'enable-adapter-hard-loop-ID': %d; using nvram value "
1854fcf3ce44SJohn Forte 		    "of %d\n", data,
1855fcf3ce44SJohn Forte 		    nv->firmware_options_1[0] & BIT_0 ? 1 : 0);
1856fcf3ce44SJohn Forte 	}
1857fcf3ce44SJohn Forte 
1858fcf3ce44SJohn Forte 	/* Get adapter hard loop ID. */
1859fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "adapter-hard-loop-ID");
1860fcf3ce44SJohn Forte 	if (data < 126) {
1861fcf3ce44SJohn Forte 		nv->hard_address[0] = LSB(data);
1862fcf3ce44SJohn Forte 		nv->hard_address[1] = MSB(data);
1863fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1864fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'adapter-hard-loop-ID':"
1865fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1866fcf3ce44SJohn Forte 		    nv->hard_address[0], nv->hard_address[1]));
1867fcf3ce44SJohn Forte 	}
1868fcf3ce44SJohn Forte 
1869fcf3ce44SJohn Forte 	/* Get LIP reset. */
1870fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
1871fcf3ce44SJohn Forte 	    0xffffffff) {
1872fcf3ce44SJohn Forte 		data = 0;
1873fcf3ce44SJohn Forte 	}
1874fcf3ce44SJohn Forte 	if (data == 0) {
1875fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET;
1876fcf3ce44SJohn Forte 	} else if (data == 1) {
1877fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_LIP_RESET;
1878fcf3ce44SJohn Forte 	} else {
1879fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1880fcf3ce44SJohn Forte 		    "'enable-LIP-reset-on-bus-reset': %d; using value of 0\n",
1881fcf3ce44SJohn Forte 		    data);
1882fcf3ce44SJohn Forte 	}
1883fcf3ce44SJohn Forte 
1884fcf3ce44SJohn Forte 	/* Get LIP full login. */
1885fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
1886fcf3ce44SJohn Forte 	    0xffffffff) {
1887fcf3ce44SJohn Forte 		data = 1;
1888fcf3ce44SJohn Forte 	}
1889fcf3ce44SJohn Forte 	if (data == 0) {
1890fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2);
1891fcf3ce44SJohn Forte 	} else if (data == 1) {
1892fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2);
1893fcf3ce44SJohn Forte 	} else {
1894fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1895fcf3ce44SJohn Forte 		    "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
1896fcf3ce44SJohn Forte 		    "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0);
1897fcf3ce44SJohn Forte 	}
1898fcf3ce44SJohn Forte 
1899fcf3ce44SJohn Forte 	/* Get target reset. */
1900fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
1901fcf3ce44SJohn Forte 	    0xffffffff) {
1902fcf3ce44SJohn Forte 		data = 0;
1903fcf3ce44SJohn Forte 	}
1904fcf3ce44SJohn Forte 	if (data == 0) {
1905fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3);
1906fcf3ce44SJohn Forte 	} else if (data == 1) {
1907fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3);
1908fcf3ce44SJohn Forte 	} else {
1909fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1910fcf3ce44SJohn Forte 		    "'enable-target-reset-on-bus-reset': %d; using nvram "
1911fcf3ce44SJohn Forte 		    "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0);
1912fcf3ce44SJohn Forte 	}
1913fcf3ce44SJohn Forte 
1914fcf3ce44SJohn Forte 	/* Get reset delay. */
1915fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
1916fcf3ce44SJohn Forte 		data = 5;
1917fcf3ce44SJohn Forte 	}
1918fcf3ce44SJohn Forte 	if (data != 0 && data < 256) {
1919fcf3ce44SJohn Forte 		nv->reset_delay = (uint8_t)data;
1920fcf3ce44SJohn Forte 	} else {
1921fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'reset-delay': %d; "
1922fcf3ce44SJohn Forte 		    "using nvram value of %d", data, nv->reset_delay);
1923fcf3ce44SJohn Forte 	}
1924fcf3ce44SJohn Forte 
1925fcf3ce44SJohn Forte 	/* Get port down retry count. */
1926fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
1927fcf3ce44SJohn Forte 		data = 8;
1928fcf3ce44SJohn Forte 	}
1929fcf3ce44SJohn Forte 	if (data < 256) {
1930fcf3ce44SJohn Forte 		nv->port_down_retry_count[0] = LSB(data);
1931fcf3ce44SJohn Forte 		nv->port_down_retry_count[1] = MSB(data);
1932fcf3ce44SJohn Forte 	} else {
1933fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-count':"
1934fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1935fcf3ce44SJohn Forte 		    nv->port_down_retry_count[0],
1936fcf3ce44SJohn Forte 		    nv->port_down_retry_count[1]));
1937fcf3ce44SJohn Forte 	}
1938fcf3ce44SJohn Forte 
1939eb82ff87SDaniel Beauregard 	if (!(CFG_IST(ha, CFG_CTRL_8081))) {
1940eb82ff87SDaniel Beauregard 		/* Get connection mode setting. */
1941eb82ff87SDaniel Beauregard 		if ((data = ql_get_prop(ha, "connection-options")) ==
1942eb82ff87SDaniel Beauregard 		    0xffffffff) {
1943eb82ff87SDaniel Beauregard 			data = 2;
1944eb82ff87SDaniel Beauregard 		}
1945eb82ff87SDaniel Beauregard 		if (data <= 2) {
1946eb82ff87SDaniel Beauregard 			nv->firmware_options_2[0] = (uint8_t)
1947eb82ff87SDaniel Beauregard 			    (nv->firmware_options_2[0] &
1948eb82ff87SDaniel Beauregard 			    ~(BIT_6 | BIT_5 | BIT_4));
1949eb82ff87SDaniel Beauregard 			nv->firmware_options_2[0] = (uint8_t)
1950eb82ff87SDaniel Beauregard 			    (nv->firmware_options_2[0] | (uint8_t)(data << 4));
1951eb82ff87SDaniel Beauregard 		} else {
1952eb82ff87SDaniel Beauregard 			EL(ha, "invalid parameter value for 'connection-"
1953eb82ff87SDaniel Beauregard 			    "options': %d; using nvram value of %d\n", data,
1954eb82ff87SDaniel Beauregard 			    (nv->firmware_options_2[0] >> 4) & 0x3);
1955eb82ff87SDaniel Beauregard 		}
1956fcf3ce44SJohn Forte 
1957eb82ff87SDaniel Beauregard 		/* Get data rate setting. */
1958eb82ff87SDaniel Beauregard 		if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
1959eb82ff87SDaniel Beauregard 			data = 2;
1960eb82ff87SDaniel Beauregard 		}
1961eb82ff87SDaniel Beauregard 		if ((CFG_IST(ha, CFG_CTRL_2422) && data < 4) ||
1962eb82ff87SDaniel Beauregard 		    (CFG_IST(ha, CFG_CTRL_258081) && data < 5)) {
1963eb82ff87SDaniel Beauregard 			nv->firmware_options_3[1] = (uint8_t)
1964eb82ff87SDaniel Beauregard 			    (nv->firmware_options_3[1] & 0x1f);
1965eb82ff87SDaniel Beauregard 			nv->firmware_options_3[1] = (uint8_t)
1966eb82ff87SDaniel Beauregard 			    (nv->firmware_options_3[1] | (uint8_t)(data << 5));
1967eb82ff87SDaniel Beauregard 		} else {
1968eb82ff87SDaniel Beauregard 			EL(ha, "invalid parameter value for 'fc-data-rate': "
1969eb82ff87SDaniel Beauregard 			    "%d; using nvram value of %d\n", data,
1970eb82ff87SDaniel Beauregard 			    (nv->firmware_options_3[1] >> 5) & 0x7);
1971eb82ff87SDaniel Beauregard 		}
1972fcf3ce44SJohn Forte 	}
1973fcf3ce44SJohn Forte 
1974fcf3ce44SJohn Forte 	/* Get IP FW container count. */
1975fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.cc[0] = LSB(ql_ip_buffer_count);
1976fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.cc[1] = MSB(ql_ip_buffer_count);
1977fcf3ce44SJohn Forte 
1978fcf3ce44SJohn Forte 	/* Get IP low water mark. */
1979fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.low_water_mark[0] = LSB(ql_ip_low_water);
1980fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.low_water_mark[1] = MSB(ql_ip_low_water);
1981fcf3ce44SJohn Forte 
1982fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1983fcf3ce44SJohn Forte 
1984fcf3ce44SJohn Forte 	/* Get enable flash load. */
1985fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-flash-load")) == 0xffffffff ||
1986fcf3ce44SJohn Forte 	    data == 0) {
1987fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_LOAD_FLASH_FW;
1988fcf3ce44SJohn Forte 	} else if (data == 1) {
1989fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_LOAD_FLASH_FW;
1990fcf3ce44SJohn Forte 	} else {
1991fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'enable-flash-load': "
1992fcf3ce44SJohn Forte 		    "%d; using default value of 0\n", data);
1993fcf3ce44SJohn Forte 	}
1994fcf3ce44SJohn Forte 
1995fcf3ce44SJohn Forte 	/* Enable firmware extended tracing */
1996fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-fwexttrace")) != 0xffffffff) {
1997fcf3ce44SJohn Forte 		if (data != 0) {
1998fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_ENABLE_FWEXTTRACE;
1999fcf3ce44SJohn Forte 		}
2000fcf3ce44SJohn Forte 	}
2001fcf3ce44SJohn Forte 
2002fcf3ce44SJohn Forte 	/* Enable firmware fc tracing */
2003fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-fwfcetrace")) != 0xffffffff) {
2004fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FWFCETRACE;
2005fcf3ce44SJohn Forte 		ha->fwfcetraceopt = data;
2006fcf3ce44SJohn Forte 	}
2007fcf3ce44SJohn Forte 
2008c1fad183SDaniel Beauregard 	/* Enable fast timeout */
2009c1fad183SDaniel Beauregard 	if ((data = ql_get_prop(ha, "enable-fasttimeout")) != 0xffffffff) {
2010c1fad183SDaniel Beauregard 		if (data != 0) {
2011c1fad183SDaniel Beauregard 			ha->cfg_flags |= CFG_FAST_TIMEOUT;
2012c1fad183SDaniel Beauregard 		}
2013c1fad183SDaniel Beauregard 	}
2014c1fad183SDaniel Beauregard 
2015fcf3ce44SJohn Forte 	ql_common_properties(ha);
2016fcf3ce44SJohn Forte 
2017fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
2018fcf3ce44SJohn Forte 
2019fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2020fcf3ce44SJohn Forte }
2021fcf3ce44SJohn Forte 
2022fcf3ce44SJohn Forte /*
2023fcf3ce44SJohn Forte  * ql_get_prop
2024fcf3ce44SJohn Forte  *	Get property value from configuration file.
2025fcf3ce44SJohn Forte  *
2026fcf3ce44SJohn Forte  * Input:
2027fcf3ce44SJohn Forte  *	ha= adapter state pointer.
2028fcf3ce44SJohn Forte  *	string = property string pointer.
2029fcf3ce44SJohn Forte  *
2030fcf3ce44SJohn Forte  * Returns:
2031fcf3ce44SJohn Forte  *	0xFFFFFFFF = no property else property value.
2032fcf3ce44SJohn Forte  *
2033fcf3ce44SJohn Forte  * Context:
2034fcf3ce44SJohn Forte  *	Kernel context.
2035fcf3ce44SJohn Forte  */
2036fcf3ce44SJohn Forte uint32_t
2037fcf3ce44SJohn Forte ql_get_prop(ql_adapter_state_t *ha, char *string)
2038fcf3ce44SJohn Forte {
2039fcf3ce44SJohn Forte 	char		buf[256];
204016dd44c2SDaniel Beauregard 	uint32_t	data = 0xffffffff;
204116dd44c2SDaniel Beauregard 
204216dd44c2SDaniel Beauregard 	/*
204316dd44c2SDaniel Beauregard 	 * Look for a adapter instance NPIV (virtual port) specific parameter
204416dd44c2SDaniel Beauregard 	 */
2045eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
204616dd44c2SDaniel Beauregard 		(void) sprintf(buf, "hba%d-vp%d-%s", ha->instance,
204716dd44c2SDaniel Beauregard 		    ha->vp_index, string);
204816dd44c2SDaniel Beauregard 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
204916dd44c2SDaniel Beauregard 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
205016dd44c2SDaniel Beauregard 		    buf, (int)0xffffffff);
205116dd44c2SDaniel Beauregard 	}
2052fcf3ce44SJohn Forte 
205316dd44c2SDaniel Beauregard 	/*
205416dd44c2SDaniel Beauregard 	 * Get adapter instance parameter if a vp specific one isn't found.
205516dd44c2SDaniel Beauregard 	 */
205616dd44c2SDaniel Beauregard 	if (data == 0xffffffff) {
205716dd44c2SDaniel Beauregard 		(void) sprintf(buf, "hba%d-%s", ha->instance, string);
205816dd44c2SDaniel Beauregard 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
205916dd44c2SDaniel Beauregard 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip,
206016dd44c2SDaniel Beauregard 		    0, buf, (int)0xffffffff);
206116dd44c2SDaniel Beauregard 	}
2062fcf3ce44SJohn Forte 
2063fcf3ce44SJohn Forte 	/* Adapter instance parameter found? */
2064fcf3ce44SJohn Forte 	if (data == 0xffffffff) {
2065fcf3ce44SJohn Forte 		/* No, get default parameter. */
2066fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
2067fcf3ce44SJohn Forte 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
2068fcf3ce44SJohn Forte 		    string, (int)0xffffffff);
2069fcf3ce44SJohn Forte 	}
2070fcf3ce44SJohn Forte 
2071fcf3ce44SJohn Forte 	return (data);
2072fcf3ce44SJohn Forte }
2073fcf3ce44SJohn Forte 
2074fcf3ce44SJohn Forte /*
2075fcf3ce44SJohn Forte  * ql_check_isp_firmware
2076fcf3ce44SJohn Forte  *	Checks if using already loaded RISC code or drivers copy.
2077fcf3ce44SJohn Forte  *	If using already loaded code, save a copy of it.
2078fcf3ce44SJohn Forte  *
2079fcf3ce44SJohn Forte  * Input:
2080fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2081fcf3ce44SJohn Forte  *
2082fcf3ce44SJohn Forte  * Returns:
2083fcf3ce44SJohn Forte  *	ql local function return status code.
2084fcf3ce44SJohn Forte  *
2085fcf3ce44SJohn Forte  * Context:
2086fcf3ce44SJohn Forte  *	Kernel context.
2087fcf3ce44SJohn Forte  */
2088fcf3ce44SJohn Forte static int
2089fcf3ce44SJohn Forte ql_check_isp_firmware(ql_adapter_state_t *ha)
2090fcf3ce44SJohn Forte {
2091fcf3ce44SJohn Forte 	int		rval;
2092fcf3ce44SJohn Forte 	uint16_t	word_count;
2093fcf3ce44SJohn Forte 	uint32_t	byte_count;
2094fcf3ce44SJohn Forte 	uint32_t	fw_size, *lptr;
2095fcf3ce44SJohn Forte 	caddr_t		bufp;
2096fcf3ce44SJohn Forte 	uint16_t	risc_address = (uint16_t)ha->risc_fw[0].addr;
2097fcf3ce44SJohn Forte 
2098fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2099fcf3ce44SJohn Forte 
2100eb82ff87SDaniel Beauregard 	/* Test for firmware running. */
2101eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
2102eb82ff87SDaniel Beauregard 		if (ql_8021_idc_handler(ha) != NX_DEV_READY) {
2103eb82ff87SDaniel Beauregard 			rval = QL_FUNCTION_FAILED;
2104eb82ff87SDaniel Beauregard 		} else {
2105eb82ff87SDaniel Beauregard 			rval = ql_start_firmware(ha);
2106eb82ff87SDaniel Beauregard 		}
2107eb82ff87SDaniel Beauregard 	} else if (CFG_IST(ha, CFG_DISABLE_RISC_CODE_LOAD)) {
2108fcf3ce44SJohn Forte 		if (ha->risc_code != NULL) {
2109fcf3ce44SJohn Forte 			kmem_free(ha->risc_code, ha->risc_code_size);
2110fcf3ce44SJohn Forte 			ha->risc_code = NULL;
2111fcf3ce44SJohn Forte 			ha->risc_code_size = 0;
2112fcf3ce44SJohn Forte 		}
2113fcf3ce44SJohn Forte 
2114fcf3ce44SJohn Forte 		/* Get RISC code length. */
2115fcf3ce44SJohn Forte 		rval = ql_rd_risc_ram(ha, risc_address + 3, ha->request_dvma,
2116fcf3ce44SJohn Forte 		    1);
2117fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2118fcf3ce44SJohn Forte 			lptr = (uint32_t *)ha->request_ring_bp;
2119fcf3ce44SJohn Forte 			fw_size = *lptr << 1;
2120fcf3ce44SJohn Forte 
2121fcf3ce44SJohn Forte 			if ((bufp = kmem_alloc(fw_size, KM_SLEEP)) != NULL) {
2122fcf3ce44SJohn Forte 				ha->risc_code_size = fw_size;
2123fcf3ce44SJohn Forte 				ha->risc_code = bufp;
2124fcf3ce44SJohn Forte 				ha->fw_transfer_size = 128;
2125fcf3ce44SJohn Forte 
2126fcf3ce44SJohn Forte 				/* Dump RISC code. */
2127fcf3ce44SJohn Forte 				do {
2128fcf3ce44SJohn Forte 					if (fw_size > ha->fw_transfer_size) {
2129fcf3ce44SJohn Forte 						byte_count =
2130fcf3ce44SJohn Forte 						    ha->fw_transfer_size;
2131fcf3ce44SJohn Forte 					} else {
2132fcf3ce44SJohn Forte 						byte_count = fw_size;
2133fcf3ce44SJohn Forte 					}
2134fcf3ce44SJohn Forte 
2135fcf3ce44SJohn Forte 					word_count =
2136fcf3ce44SJohn Forte 					    (uint16_t)(byte_count >> 1);
2137fcf3ce44SJohn Forte 
2138fcf3ce44SJohn Forte 					rval = ql_rd_risc_ram(ha, risc_address,
2139fcf3ce44SJohn Forte 					    ha->request_dvma, word_count);
2140fcf3ce44SJohn Forte 					if (rval != QL_SUCCESS) {
2141fcf3ce44SJohn Forte 						kmem_free(ha->risc_code,
2142fcf3ce44SJohn Forte 						    ha->risc_code_size);
2143fcf3ce44SJohn Forte 						ha->risc_code = NULL;
2144fcf3ce44SJohn Forte 						ha->risc_code_size = 0;
2145fcf3ce44SJohn Forte 						break;
2146fcf3ce44SJohn Forte 					}
2147fcf3ce44SJohn Forte 
2148fcf3ce44SJohn Forte 					(void) ddi_dma_sync(
2149fcf3ce44SJohn Forte 					    ha->hba_buf.dma_handle,
2150fcf3ce44SJohn Forte 					    REQUEST_Q_BUFFER_OFFSET,
2151fcf3ce44SJohn Forte 					    byte_count,
2152fcf3ce44SJohn Forte 					    DDI_DMA_SYNC_FORKERNEL);
2153fcf3ce44SJohn Forte 					ddi_rep_get16(ha->hba_buf.acc_handle,
2154fcf3ce44SJohn Forte 					    (uint16_t *)bufp,
2155fcf3ce44SJohn Forte 					    (uint16_t *)ha->request_ring_bp,
2156fcf3ce44SJohn Forte 					    word_count, DDI_DEV_AUTOINCR);
2157fcf3ce44SJohn Forte 
2158fcf3ce44SJohn Forte 					risc_address += word_count;
2159fcf3ce44SJohn Forte 					fw_size -= byte_count;
2160fcf3ce44SJohn Forte 					bufp	+= byte_count;
2161fcf3ce44SJohn Forte 				} while (fw_size != 0);
2162fcf3ce44SJohn Forte 			}
2163eb82ff87SDaniel Beauregard 			rval = QL_FUNCTION_FAILED;
2164fcf3ce44SJohn Forte 		}
2165fcf3ce44SJohn Forte 	} else {
2166fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
2167fcf3ce44SJohn Forte 	}
2168fcf3ce44SJohn Forte 
2169fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2170fcf3ce44SJohn Forte 		EL(ha, "Load RISC code\n");
2171fcf3ce44SJohn Forte 	} else {
2172fcf3ce44SJohn Forte 		/*EMPTY*/
2173fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2174fcf3ce44SJohn Forte 	}
2175fcf3ce44SJohn Forte 	return (rval);
2176fcf3ce44SJohn Forte }
2177fcf3ce44SJohn Forte 
2178fcf3ce44SJohn Forte /*
2179fcf3ce44SJohn Forte  * Chip diagnostics
2180fcf3ce44SJohn Forte  *	Test chip for proper operation.
2181fcf3ce44SJohn Forte  *
2182fcf3ce44SJohn Forte  * Input:
2183fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2184fcf3ce44SJohn Forte  *
2185fcf3ce44SJohn Forte  * Returns:
2186fcf3ce44SJohn Forte  *	ql local function return status code.
2187fcf3ce44SJohn Forte  *
2188fcf3ce44SJohn Forte  * Context:
2189fcf3ce44SJohn Forte  *	Kernel context.
2190fcf3ce44SJohn Forte  */
2191fcf3ce44SJohn Forte static int
2192fcf3ce44SJohn Forte ql_chip_diag(ql_adapter_state_t *ha)
2193fcf3ce44SJohn Forte {
2194fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
2195eb82ff87SDaniel Beauregard 	int		rval;
2196fcf3ce44SJohn Forte 	int32_t		retries = 4;
2197fcf3ce44SJohn Forte 	uint16_t	id;
2198fcf3ce44SJohn Forte 
2199fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2200fcf3ce44SJohn Forte 
2201fcf3ce44SJohn Forte 	do {
2202fcf3ce44SJohn Forte 		/* Reset ISP chip. */
2203fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2204fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
2205fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2206fcf3ce44SJohn Forte 
2207fcf3ce44SJohn Forte 		/* For ISP2200A reduce firmware load size. */
2208fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_2200) &&
2209eb82ff87SDaniel Beauregard 		    RD16_IO_REG(ha, mailbox_out[7]) == 4) {
2210fcf3ce44SJohn Forte 			ha->fw_transfer_size = 128;
2211fcf3ce44SJohn Forte 		} else {
2212fcf3ce44SJohn Forte 			ha->fw_transfer_size = REQUEST_QUEUE_SIZE;
2213fcf3ce44SJohn Forte 		}
2214fcf3ce44SJohn Forte 
2215eb82ff87SDaniel Beauregard 		rval = QL_SUCCESS;
2216eb82ff87SDaniel Beauregard 		if (!(CFG_IST(ha, CFG_CTRL_8021))) {
2217eb82ff87SDaniel Beauregard 			ql_reset_chip(ha);
2218eb82ff87SDaniel Beauregard 
2219eb82ff87SDaniel Beauregard 			/* Check product ID of chip */
2220eb82ff87SDaniel Beauregard 			mr.mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
2221eb82ff87SDaniel Beauregard 			mr.mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
2222eb82ff87SDaniel Beauregard 			mr.mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
2223fcf3ce44SJohn Forte 
2224eb82ff87SDaniel Beauregard 			if (ha->device_id == 0x5432 ||
2225eb82ff87SDaniel Beauregard 			    ha->device_id == 0x8432) {
2226eb82ff87SDaniel Beauregard 				id = 0x2432;
2227eb82ff87SDaniel Beauregard 			} else if (ha->device_id == 0x5422 ||
2228eb82ff87SDaniel Beauregard 			    ha->device_id == 0x8422) {
2229eb82ff87SDaniel Beauregard 				id = 0x2422;
2230eb82ff87SDaniel Beauregard 			} else {
2231eb82ff87SDaniel Beauregard 				id = ha->device_id;
2232eb82ff87SDaniel Beauregard 			}
2233fcf3ce44SJohn Forte 
2234eb82ff87SDaniel Beauregard 			if (mr.mb[1] == PROD_ID_1 &&
2235eb82ff87SDaniel Beauregard 			    (mr.mb[2] == PROD_ID_2 || mr.mb[2] == PROD_ID_2a) &&
2236eb82ff87SDaniel Beauregard 			    (mr.mb[3] == PROD_ID_3 || mr.mb[3] == id)) {
2237eb82ff87SDaniel Beauregard 				ha->adapter_stats->revlvl.isp2200 =
2238eb82ff87SDaniel Beauregard 				    RD16_IO_REG(ha, mailbox_out[4]);
2239eb82ff87SDaniel Beauregard 				ha->adapter_stats->revlvl.risc =
2240eb82ff87SDaniel Beauregard 				    RD16_IO_REG(ha, mailbox_out[5]);
2241eb82ff87SDaniel Beauregard 				ha->adapter_stats->revlvl.frmbfr =
2242eb82ff87SDaniel Beauregard 				    RD16_IO_REG(ha, mailbox_out[6]);
2243eb82ff87SDaniel Beauregard 				ha->adapter_stats->revlvl.riscrom =
2244eb82ff87SDaniel Beauregard 				    RD16_IO_REG(ha, mailbox_out[7]);
2245eb82ff87SDaniel Beauregard 			} else {
2246eb82ff87SDaniel Beauregard 				cmn_err(CE_WARN, "%s(%d) - prod id failed!, "
2247eb82ff87SDaniel Beauregard 				    "mb1=%xh, mb2=%xh, mb3=%xh", QL_NAME,
2248eb82ff87SDaniel Beauregard 				    ha->instance, mr.mb[1], mr.mb[2], mr.mb[3]);
2249eb82ff87SDaniel Beauregard 				rval = QL_FUNCTION_FAILED;
2250eb82ff87SDaniel Beauregard 			}
2251eb82ff87SDaniel Beauregard 		} else if (!(ha->task_daemon_flags & FIRMWARE_LOADED)) {
2252eb82ff87SDaniel Beauregard 			break;
2253eb82ff87SDaniel Beauregard 		}
2254fcf3ce44SJohn Forte 
2255eb82ff87SDaniel Beauregard 		if (rval == QL_SUCCESS) {
2256fcf3ce44SJohn Forte 			/* Wrap Incoming Mailboxes Test. */
2257fcf3ce44SJohn Forte 			mr.mb[1] = 0xAAAA;
2258fcf3ce44SJohn Forte 			mr.mb[2] = 0x5555;
2259fcf3ce44SJohn Forte 			mr.mb[3] = 0xAA55;
2260fcf3ce44SJohn Forte 			mr.mb[4] = 0x55AA;
2261fcf3ce44SJohn Forte 			mr.mb[5] = 0xA5A5;
2262fcf3ce44SJohn Forte 			mr.mb[6] = 0x5A5A;
2263fcf3ce44SJohn Forte 			mr.mb[7] = 0x2525;
2264fcf3ce44SJohn Forte 			rval = ql_mbx_wrap_test(ha, &mr);
2265fcf3ce44SJohn Forte 			if (rval == QL_SUCCESS) {
2266fcf3ce44SJohn Forte 				if (mr.mb[1] != 0xAAAA ||
2267fcf3ce44SJohn Forte 				    mr.mb[2] != 0x5555 ||
2268fcf3ce44SJohn Forte 				    mr.mb[3] != 0xAA55 ||
2269fcf3ce44SJohn Forte 				    mr.mb[4] != 0x55AA ||
2270fcf3ce44SJohn Forte 				    mr.mb[5] != 0xA5A5 ||
2271fcf3ce44SJohn Forte 				    mr.mb[6] != 0x5A5A ||
2272fcf3ce44SJohn Forte 				    mr.mb[7] != 0x2525) {
2273fcf3ce44SJohn Forte 					rval = QL_FUNCTION_FAILED;
2274fcf3ce44SJohn Forte 					(void) ql_flash_errlog(ha,
2275fcf3ce44SJohn Forte 					    FLASH_ERRLOG_ISP_ERR, 0,
2276fcf3ce44SJohn Forte 					    RD16_IO_REG(ha, hccr),
2277fcf3ce44SJohn Forte 					    RD16_IO_REG(ha, istatus));
2278fcf3ce44SJohn Forte 				}
2279fcf3ce44SJohn Forte 			} else {
2280fcf3ce44SJohn Forte 				cmn_err(CE_WARN, "%s(%d) - reg test failed="
2281fcf3ce44SJohn Forte 				    "%xh!", QL_NAME, ha->instance, rval);
2282fcf3ce44SJohn Forte 			}
2283fcf3ce44SJohn Forte 		}
2284fcf3ce44SJohn Forte 	} while ((retries-- != 0) && (rval != QL_SUCCESS));
2285fcf3ce44SJohn Forte 
2286fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2287fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2288fcf3ce44SJohn Forte 	} else {
2289fcf3ce44SJohn Forte 		/*EMPTY*/
2290fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2291fcf3ce44SJohn Forte 	}
2292fcf3ce44SJohn Forte 	return (rval);
2293fcf3ce44SJohn Forte }
2294fcf3ce44SJohn Forte 
2295fcf3ce44SJohn Forte /*
2296fcf3ce44SJohn Forte  * ql_load_isp_firmware
2297fcf3ce44SJohn Forte  *	Load and start RISC firmware.
2298fcf3ce44SJohn Forte  *	Uses request ring for DMA buffer.
2299fcf3ce44SJohn Forte  *
2300fcf3ce44SJohn Forte  * Input:
2301fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2302fcf3ce44SJohn Forte  *
2303fcf3ce44SJohn Forte  * Returns:
2304fcf3ce44SJohn Forte  *	ql local function return status code.
2305fcf3ce44SJohn Forte  *
2306fcf3ce44SJohn Forte  * Context:
2307fcf3ce44SJohn Forte  *	Kernel context.
2308fcf3ce44SJohn Forte  */
2309fcf3ce44SJohn Forte int
2310fcf3ce44SJohn Forte ql_load_isp_firmware(ql_adapter_state_t *vha)
2311fcf3ce44SJohn Forte {
2312fcf3ce44SJohn Forte 	caddr_t			risc_code_address;
2313fcf3ce44SJohn Forte 	uint32_t		risc_address, risc_code_size;
2314fcf3ce44SJohn Forte 	int			rval;
2315fcf3ce44SJohn Forte 	uint32_t		word_count, cnt;
2316fcf3ce44SJohn Forte 	size_t			byte_count;
2317fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
2318fcf3ce44SJohn Forte 
2319eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
2320eb82ff87SDaniel Beauregard 		rval = ql_8021_load_risc(ha);
2321eb82ff87SDaniel Beauregard 	} else {
2322eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_81XX)) {
2323eb82ff87SDaniel Beauregard 			ql_mps_reset(ha);
2324eb82ff87SDaniel Beauregard 		}
2325f33c1cdbSDaniel Beauregard 
2326eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) {
2327eb82ff87SDaniel Beauregard 			return (ql_load_flash_fw(ha));
2328eb82ff87SDaniel Beauregard 		}
2329fcf3ce44SJohn Forte 
2330eb82ff87SDaniel Beauregard 		QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2331fcf3ce44SJohn Forte 
2332eb82ff87SDaniel Beauregard 		/* Load firmware segments */
2333eb82ff87SDaniel Beauregard 		for (cnt = 0; cnt < MAX_RISC_CODE_SEGMENTS &&
2334eb82ff87SDaniel Beauregard 		    ha->risc_fw[cnt].code != NULL; cnt++) {
2335fcf3ce44SJohn Forte 
2336eb82ff87SDaniel Beauregard 			risc_code_address = ha->risc_fw[cnt].code;
2337eb82ff87SDaniel Beauregard 			risc_address = ha->risc_fw[cnt].addr;
2338eb82ff87SDaniel Beauregard 			risc_code_size = ha->risc_fw[cnt].length;
2339fcf3ce44SJohn Forte 
2340eb82ff87SDaniel Beauregard 			while (risc_code_size) {
2341eb82ff87SDaniel Beauregard 				if (CFG_IST(ha, CFG_CTRL_242581)) {
2342eb82ff87SDaniel Beauregard 					word_count = ha->fw_transfer_size >> 2;
2343eb82ff87SDaniel Beauregard 					if (word_count > risc_code_size) {
2344eb82ff87SDaniel Beauregard 						word_count = risc_code_size;
2345eb82ff87SDaniel Beauregard 					}
2346eb82ff87SDaniel Beauregard 					byte_count = word_count << 2;
2347fcf3ce44SJohn Forte 
2348eb82ff87SDaniel Beauregard 					ddi_rep_put32(ha->hba_buf.acc_handle,
2349eb82ff87SDaniel Beauregard 					    (uint32_t *)risc_code_address,
2350eb82ff87SDaniel Beauregard 					    (uint32_t *)ha->request_ring_bp,
2351eb82ff87SDaniel Beauregard 					    word_count, DDI_DEV_AUTOINCR);
2352eb82ff87SDaniel Beauregard 				} else {
2353eb82ff87SDaniel Beauregard 					word_count = ha->fw_transfer_size >> 1;
2354eb82ff87SDaniel Beauregard 					if (word_count > risc_code_size) {
2355eb82ff87SDaniel Beauregard 						word_count = risc_code_size;
2356eb82ff87SDaniel Beauregard 					}
2357eb82ff87SDaniel Beauregard 					byte_count = word_count << 1;
2358eb82ff87SDaniel Beauregard 
2359eb82ff87SDaniel Beauregard 					ddi_rep_put16(ha->hba_buf.acc_handle,
2360eb82ff87SDaniel Beauregard 					    (uint16_t *)risc_code_address,
2361eb82ff87SDaniel Beauregard 					    (uint16_t *)ha->request_ring_bp,
2362eb82ff87SDaniel Beauregard 					    word_count, DDI_DEV_AUTOINCR);
2363fcf3ce44SJohn Forte 				}
2364fcf3ce44SJohn Forte 
2365eb82ff87SDaniel Beauregard 				(void) ddi_dma_sync(ha->hba_buf.dma_handle,
2366eb82ff87SDaniel Beauregard 				    REQUEST_Q_BUFFER_OFFSET, byte_count,
2367eb82ff87SDaniel Beauregard 				    DDI_DMA_SYNC_FORDEV);
2368fcf3ce44SJohn Forte 
2369eb82ff87SDaniel Beauregard 				rval = ql_wrt_risc_ram(ha, risc_address,
2370eb82ff87SDaniel Beauregard 				    ha->request_dvma, word_count);
2371eb82ff87SDaniel Beauregard 				if (rval != QL_SUCCESS) {
2372eb82ff87SDaniel Beauregard 					EL(ha, "failed, load=%xh\n", rval);
2373eb82ff87SDaniel Beauregard 					cnt = MAX_RISC_CODE_SEGMENTS;
2374eb82ff87SDaniel Beauregard 					break;
2375eb82ff87SDaniel Beauregard 				}
2376fcf3ce44SJohn Forte 
2377eb82ff87SDaniel Beauregard 				risc_address += word_count;
2378eb82ff87SDaniel Beauregard 				risc_code_size -= word_count;
2379eb82ff87SDaniel Beauregard 				risc_code_address += byte_count;
2380fcf3ce44SJohn Forte 			}
2381fcf3ce44SJohn Forte 		}
2382fcf3ce44SJohn Forte 	}
2383fcf3ce44SJohn Forte 
2384fcf3ce44SJohn Forte 	/* Start firmware. */
2385fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2386fcf3ce44SJohn Forte 		rval = ql_start_firmware(ha);
2387fcf3ce44SJohn Forte 	}
2388fcf3ce44SJohn Forte 
2389fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2390fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2391fcf3ce44SJohn Forte 	} else {
2392fcf3ce44SJohn Forte 		/*EMPTY*/
2393fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2394fcf3ce44SJohn Forte 	}
2395fcf3ce44SJohn Forte 
2396fcf3ce44SJohn Forte 	return (rval);
2397fcf3ce44SJohn Forte }
2398fcf3ce44SJohn Forte 
2399fcf3ce44SJohn Forte /*
2400fcf3ce44SJohn Forte  * ql_load_flash_fw
2401fcf3ce44SJohn Forte  *	Gets ISP24xx firmware from flash and loads ISP.
2402fcf3ce44SJohn Forte  *
2403fcf3ce44SJohn Forte  * Input:
2404fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
2405fcf3ce44SJohn Forte  *
2406fcf3ce44SJohn Forte  * Returns:
24075dfd244aSDaniel Beauregard  *	ql local function return status code.
2408fcf3ce44SJohn Forte  */
2409fcf3ce44SJohn Forte static int
2410fcf3ce44SJohn Forte ql_load_flash_fw(ql_adapter_state_t *ha)
2411fcf3ce44SJohn Forte {
2412fcf3ce44SJohn Forte 	int		rval;
2413fcf3ce44SJohn Forte 	uint8_t		seg_cnt;
2414fcf3ce44SJohn Forte 	uint32_t	risc_address, xfer_size, count,	*bp, faddr;
2415fcf3ce44SJohn Forte 	uint32_t	risc_code_size = 0;
2416fcf3ce44SJohn Forte 
2417fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2418fcf3ce44SJohn Forte 
24195dfd244aSDaniel Beauregard 	faddr = ha->flash_data_addr | ha->flash_fw_addr;
2420fcf3ce44SJohn Forte 
2421fcf3ce44SJohn Forte 	for (seg_cnt = 0; seg_cnt < 2; seg_cnt++) {
2422fcf3ce44SJohn Forte 		xfer_size = ha->fw_transfer_size >> 2;
2423fcf3ce44SJohn Forte 		do {
2424fcf3ce44SJohn Forte 			GLOBAL_HW_LOCK();
2425fcf3ce44SJohn Forte 
2426fcf3ce44SJohn Forte 			/* Read data from flash. */
2427fcf3ce44SJohn Forte 			bp = (uint32_t *)ha->request_ring_bp;
2428fcf3ce44SJohn Forte 			for (count = 0; count < xfer_size; count++) {
2429fcf3ce44SJohn Forte 				rval = ql_24xx_read_flash(ha, faddr++, bp);
2430fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS) {
2431fcf3ce44SJohn Forte 					break;
2432fcf3ce44SJohn Forte 				}
2433fcf3ce44SJohn Forte 				ql_chg_endian((uint8_t *)bp++, 4);
2434fcf3ce44SJohn Forte 			}
2435fcf3ce44SJohn Forte 
2436fcf3ce44SJohn Forte 			GLOBAL_HW_UNLOCK();
2437fcf3ce44SJohn Forte 
2438fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2439fcf3ce44SJohn Forte 				EL(ha, "24xx_read_flash failed=%xh\n", rval);
2440fcf3ce44SJohn Forte 				break;
2441fcf3ce44SJohn Forte 			}
2442fcf3ce44SJohn Forte 
2443fcf3ce44SJohn Forte 			if (risc_code_size == 0) {
2444fcf3ce44SJohn Forte 				bp = (uint32_t *)ha->request_ring_bp;
2445fcf3ce44SJohn Forte 				risc_address = bp[2];
2446fcf3ce44SJohn Forte 				risc_code_size = bp[3];
2447fcf3ce44SJohn Forte 				ha->risc_fw[seg_cnt].addr = risc_address;
2448fcf3ce44SJohn Forte 			}
2449fcf3ce44SJohn Forte 
2450fcf3ce44SJohn Forte 			if (risc_code_size < xfer_size) {
24515dfd244aSDaniel Beauregard 				faddr -= xfer_size - risc_code_size;
2452fcf3ce44SJohn Forte 				xfer_size = risc_code_size;
2453fcf3ce44SJohn Forte 			}
2454fcf3ce44SJohn Forte 
2455fcf3ce44SJohn Forte 			(void) ddi_dma_sync(ha->hba_buf.dma_handle,
2456fcf3ce44SJohn Forte 			    REQUEST_Q_BUFFER_OFFSET, xfer_size << 2,
2457fcf3ce44SJohn Forte 			    DDI_DMA_SYNC_FORDEV);
2458fcf3ce44SJohn Forte 
2459fcf3ce44SJohn Forte 			rval = ql_wrt_risc_ram(ha, risc_address,
2460fcf3ce44SJohn Forte 			    ha->request_dvma, xfer_size);
2461fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2462fcf3ce44SJohn Forte 				EL(ha, "ql_wrt_risc_ram failed=%xh\n", rval);
2463fcf3ce44SJohn Forte 				break;
2464fcf3ce44SJohn Forte 			}
2465fcf3ce44SJohn Forte 
2466fcf3ce44SJohn Forte 			risc_address += xfer_size;
2467fcf3ce44SJohn Forte 			risc_code_size -= xfer_size;
2468fcf3ce44SJohn Forte 		} while (risc_code_size);
2469fcf3ce44SJohn Forte 
2470fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
2471fcf3ce44SJohn Forte 			break;
2472fcf3ce44SJohn Forte 		}
2473fcf3ce44SJohn Forte 	}
2474fcf3ce44SJohn Forte 
2475fcf3ce44SJohn Forte 	/* Start firmware. */
2476fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2477fcf3ce44SJohn Forte 		rval = ql_start_firmware(ha);
2478fcf3ce44SJohn Forte 	}
2479fcf3ce44SJohn Forte 
2480fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2481fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2482fcf3ce44SJohn Forte 	} else {
2483fcf3ce44SJohn Forte 		/*EMPTY*/
2484fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2485fcf3ce44SJohn Forte 	}
2486fcf3ce44SJohn Forte 	return (rval);
2487fcf3ce44SJohn Forte }
2488fcf3ce44SJohn Forte 
2489fcf3ce44SJohn Forte /*
2490fcf3ce44SJohn Forte  * ql_start_firmware
2491fcf3ce44SJohn Forte  *	Starts RISC code.
2492fcf3ce44SJohn Forte  *
2493fcf3ce44SJohn Forte  * Input:
2494fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2495fcf3ce44SJohn Forte  *
2496fcf3ce44SJohn Forte  * Returns:
2497fcf3ce44SJohn Forte  *	ql local function return status code.
2498fcf3ce44SJohn Forte  *
2499fcf3ce44SJohn Forte  * Context:
2500fcf3ce44SJohn Forte  *	Kernel context.
2501fcf3ce44SJohn Forte  */
2502fcf3ce44SJohn Forte int
2503fcf3ce44SJohn Forte ql_start_firmware(ql_adapter_state_t *vha)
2504fcf3ce44SJohn Forte {
25055dfd244aSDaniel Beauregard 	int			rval, rval2;
25065dfd244aSDaniel Beauregard 	uint32_t		data;
2507fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
2508fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
2509fcf3ce44SJohn Forte 
2510fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2511fcf3ce44SJohn Forte 
2512eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
2513eb82ff87SDaniel Beauregard 		/* Save firmware version. */
2514eb82ff87SDaniel Beauregard 		rval = ql_get_fw_version(ha, &mr, MAILBOX_TOV);
2515eb82ff87SDaniel Beauregard 		ha->fw_major_version = mr.mb[1];
2516eb82ff87SDaniel Beauregard 		ha->fw_minor_version = mr.mb[2];
2517eb82ff87SDaniel Beauregard 		ha->fw_subminor_version = mr.mb[3];
2518*f885d00fSDaniel Beauregard 		ha->fw_attributes = mr.mb[6];
2519eb82ff87SDaniel Beauregard 	} else if ((rval = ql_verify_checksum(ha)) == QL_SUCCESS) {
2520eb82ff87SDaniel Beauregard 		/* Verify checksum of loaded RISC code. */
2521fcf3ce44SJohn Forte 		/* Start firmware execution. */
2522fcf3ce44SJohn Forte 		(void) ql_execute_fw(ha);
2523fcf3ce44SJohn Forte 
2524fcf3ce44SJohn Forte 		/* Save firmware version. */
2525eb82ff87SDaniel Beauregard 		(void) ql_get_fw_version(ha, &mr, MAILBOX_TOV);
2526fcf3ce44SJohn Forte 		ha->fw_major_version = mr.mb[1];
2527fcf3ce44SJohn Forte 		ha->fw_minor_version = mr.mb[2];
2528fcf3ce44SJohn Forte 		ha->fw_subminor_version = mr.mb[3];
2529fcf3ce44SJohn Forte 		ha->fw_ext_memory_size = ((SHORT_TO_LONG(mr.mb[4], mr.mb[5]) -
2530fcf3ce44SJohn Forte 		    0x100000) + 1) * 4;
2531fcf3ce44SJohn Forte 		ha->fw_attributes = mr.mb[6];
2532fcf3ce44SJohn Forte 
25335dfd244aSDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_81XX)) {
25345dfd244aSDaniel Beauregard 			ha->phy_fw_major_version = LSB(mr.mb[8]);
25355dfd244aSDaniel Beauregard 			ha->phy_fw_minor_version = MSB(mr.mb[9]);
25365dfd244aSDaniel Beauregard 			ha->phy_fw_subminor_version = LSB(mr.mb[9]);
25375dfd244aSDaniel Beauregard 			ha->mpi_fw_major_version = LSB(mr.mb[10]);
25385dfd244aSDaniel Beauregard 			ha->mpi_fw_minor_version = MSB(mr.mb[11]);
25395dfd244aSDaniel Beauregard 			ha->mpi_fw_subminor_version = LSB(mr.mb[11]);
25405dfd244aSDaniel Beauregard 			ha->mpi_capability_list = SHORT_TO_LONG(mr.mb[13],
25415dfd244aSDaniel Beauregard 			    mr.mb[12]);
25425dfd244aSDaniel Beauregard 			if ((rval2 = ql_flash_access(ha, FAC_GET_SECTOR_SIZE,
25435dfd244aSDaniel Beauregard 			    0, 0, &data)) == QL_SUCCESS) {
25445dfd244aSDaniel Beauregard 				ha->xioctl->fdesc.block_size = data << 2;
25455dfd244aSDaniel Beauregard 				QL_PRINT_10(CE_CONT, "(%d): fdesc.block_size="
25465dfd244aSDaniel Beauregard 				    "%xh\n", ha->instance,
25475dfd244aSDaniel Beauregard 				    ha->xioctl->fdesc.block_size);
25485dfd244aSDaniel Beauregard 			} else {
25495dfd244aSDaniel Beauregard 				EL(ha, "flash_access status=%xh\n", rval2);
25505dfd244aSDaniel Beauregard 			}
25515dfd244aSDaniel Beauregard 		}
25525dfd244aSDaniel Beauregard 
2553fcf3ce44SJohn Forte 		/* Set Serdes Transmit Parameters. */
25545dfd244aSDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_2422) && ha->serdes_param[0] & BIT_0) {
2555fcf3ce44SJohn Forte 			mr.mb[1] = ha->serdes_param[0];
2556fcf3ce44SJohn Forte 			mr.mb[2] = ha->serdes_param[1];
2557fcf3ce44SJohn Forte 			mr.mb[3] = ha->serdes_param[2];
2558fcf3ce44SJohn Forte 			mr.mb[4] = ha->serdes_param[3];
2559fcf3ce44SJohn Forte 			(void) ql_serdes_param(ha, &mr);
2560fcf3ce44SJohn Forte 		}
2561fcf3ce44SJohn Forte 	}
2562*f885d00fSDaniel Beauregard 	/* ETS workaround */
2563*f885d00fSDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_81XX) && ql_enable_ets) {
2564*f885d00fSDaniel Beauregard 		if (ql_get_firmware_option(ha, &mr) == QL_SUCCESS) {
2565*f885d00fSDaniel Beauregard 			mr.mb[2] = (uint16_t)
2566*f885d00fSDaniel Beauregard 			    (mr.mb[2] | FO2_FCOE_512_MAX_MEM_WR_BURST);
2567*f885d00fSDaniel Beauregard 			(void) ql_set_firmware_option(ha, &mr);
2568*f885d00fSDaniel Beauregard 		}
2569*f885d00fSDaniel Beauregard 	}
2570fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2571fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~FIRMWARE_LOADED;
2572fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2573fcf3ce44SJohn Forte 	} else {
2574fcf3ce44SJohn Forte 		ha->task_daemon_flags |= FIRMWARE_LOADED;
2575fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2576fcf3ce44SJohn Forte 	}
2577fcf3ce44SJohn Forte 	return (rval);
2578fcf3ce44SJohn Forte }
2579fcf3ce44SJohn Forte 
2580fcf3ce44SJohn Forte /*
2581fcf3ce44SJohn Forte  * ql_set_cache_line
2582fcf3ce44SJohn Forte  *	Sets PCI cache line parameter.
2583fcf3ce44SJohn Forte  *
2584fcf3ce44SJohn Forte  * Input:
2585fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2586fcf3ce44SJohn Forte  *
2587fcf3ce44SJohn Forte  * Returns:
2588fcf3ce44SJohn Forte  *	ql local function return status code.
2589fcf3ce44SJohn Forte  *
2590fcf3ce44SJohn Forte  * Context:
2591fcf3ce44SJohn Forte  *	Kernel context.
2592fcf3ce44SJohn Forte  */
2593fcf3ce44SJohn Forte int
2594fcf3ce44SJohn Forte ql_set_cache_line(ql_adapter_state_t *ha)
2595fcf3ce44SJohn Forte {
2596fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2597fcf3ce44SJohn Forte 
2598fcf3ce44SJohn Forte 	/* Set the cache line. */
2599fcf3ce44SJohn Forte 	if (CFG_IST(ha->pha, CFG_SET_CACHE_LINE_SIZE_1)) {
2600fcf3ce44SJohn Forte 		/* Set cache line register. */
2601fcf3ce44SJohn Forte 		ql_pci_config_put8(ha->pha, PCI_CONF_CACHE_LINESZ, 1);
2602fcf3ce44SJohn Forte 	}
2603fcf3ce44SJohn Forte 
2604fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2605fcf3ce44SJohn Forte 
2606fcf3ce44SJohn Forte 	return (QL_SUCCESS);
2607fcf3ce44SJohn Forte }
2608fcf3ce44SJohn Forte 
2609fcf3ce44SJohn Forte /*
2610fcf3ce44SJohn Forte  * ql_init_rings
2611fcf3ce44SJohn Forte  *	Initializes firmware and ring pointers.
2612fcf3ce44SJohn Forte  *
2613fcf3ce44SJohn Forte  *	Beginning of response ring has initialization control block
2614fcf3ce44SJohn Forte  *	already built by nvram config routine.
2615fcf3ce44SJohn Forte  *
2616fcf3ce44SJohn Forte  * Input:
2617fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2618fcf3ce44SJohn Forte  *	ha->hba_buf = request and response rings
2619fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
2620fcf3ce44SJohn Forte  *
2621fcf3ce44SJohn Forte  * Returns:
2622fcf3ce44SJohn Forte  *	ql local function return status code.
2623fcf3ce44SJohn Forte  *
2624fcf3ce44SJohn Forte  * Context:
2625fcf3ce44SJohn Forte  *	Kernel context.
2626fcf3ce44SJohn Forte  */
2627fcf3ce44SJohn Forte int
2628fcf3ce44SJohn Forte ql_init_rings(ql_adapter_state_t *vha2)
2629fcf3ce44SJohn Forte {
2630fcf3ce44SJohn Forte 	int			rval, rval2;
2631fcf3ce44SJohn Forte 	uint16_t		index;
2632fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
2633fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha2->pha;
2634fcf3ce44SJohn Forte 
2635fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2636fcf3ce44SJohn Forte 
2637fcf3ce44SJohn Forte 	/* Clear outstanding commands array. */
2638fcf3ce44SJohn Forte 	for (index = 0; index < MAX_OUTSTANDING_COMMANDS; index++) {
2639fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
2640fcf3ce44SJohn Forte 	}
2641fcf3ce44SJohn Forte 	ha->osc_index = 1;
2642fcf3ce44SJohn Forte 
2643fcf3ce44SJohn Forte 	ha->pending_cmds.first = NULL;
2644fcf3ce44SJohn Forte 	ha->pending_cmds.last = NULL;
2645fcf3ce44SJohn Forte 
2646fcf3ce44SJohn Forte 	/* Initialize firmware. */
2647fcf3ce44SJohn Forte 	ha->request_ring_ptr = ha->request_ring_bp;
2648fcf3ce44SJohn Forte 	ha->req_ring_index = 0;
2649fcf3ce44SJohn Forte 	ha->req_q_cnt = REQUEST_ENTRY_CNT - 1;
2650fcf3ce44SJohn Forte 	ha->response_ring_ptr = ha->response_ring_bp;
2651fcf3ce44SJohn Forte 	ha->rsp_ring_index = 0;
2652fcf3ce44SJohn Forte 
2653fcf3ce44SJohn Forte 	if (ha->flags & VP_ENABLED) {
2654fcf3ce44SJohn Forte 		ql_adapter_state_t	*vha;
2655fcf3ce44SJohn Forte 		uint16_t		cnt;
2656fcf3ce44SJohn Forte 		uint32_t		max_vports;
2657fcf3ce44SJohn Forte 		ql_init_24xx_cb_t	*icb = &ha->init_ctrl_blk.cb24;
2658fcf3ce44SJohn Forte 
2659fcf3ce44SJohn Forte 		max_vports = (CFG_IST(ha, CFG_CTRL_2422) ?
2660fcf3ce44SJohn Forte 		    MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS);
2661fcf3ce44SJohn Forte 		bzero(icb->vp_count,
2662fcf3ce44SJohn Forte 		    ((uintptr_t)icb + sizeof (ql_init_24xx_cb_t)) -
2663fcf3ce44SJohn Forte 		    (uintptr_t)icb->vp_count);
2664fcf3ce44SJohn Forte 		icb->vp_count[0] = (uint8_t)max_vports;
2665fcf3ce44SJohn Forte 
2666fcf3ce44SJohn Forte 		/* Allow connection option 2. */
2667fcf3ce44SJohn Forte 		icb->global_vp_option[0] = BIT_1;
2668fcf3ce44SJohn Forte 
2669fcf3ce44SJohn Forte 		for (cnt = 0, vha = ha->vp_next; cnt < max_vports &&
2670fcf3ce44SJohn Forte 		    vha != NULL; vha = vha->vp_next, cnt++) {
2671fcf3ce44SJohn Forte 
2672fcf3ce44SJohn Forte 			index = (uint8_t)(vha->vp_index - 1);
2673fcf3ce44SJohn Forte 			bcopy(vha->loginparams.node_ww_name.raw_wwn,
2674fcf3ce44SJohn Forte 			    icb->vpc[index].node_name, 8);
2675fcf3ce44SJohn Forte 			bcopy(vha->loginparams.nport_ww_name.raw_wwn,
2676fcf3ce44SJohn Forte 			    icb->vpc[index].port_name, 8);
2677fcf3ce44SJohn Forte 
2678fcf3ce44SJohn Forte 			icb->vpc[index].options = VPO_TARGET_MODE_DISABLED |
2679fcf3ce44SJohn Forte 			    VPO_INITIATOR_MODE_ENABLED;
2680fcf3ce44SJohn Forte 			if (vha->flags & VP_ENABLED) {
2681fcf3ce44SJohn Forte 				icb->vpc[index].options = (uint8_t)
2682fcf3ce44SJohn Forte 				    (icb->vpc[index].options | VPO_ENABLED);
2683fcf3ce44SJohn Forte 			}
2684fcf3ce44SJohn Forte 		}
2685fcf3ce44SJohn Forte 	}
2686fcf3ce44SJohn Forte 
2687eb82ff87SDaniel Beauregard 	for (index = 0; index < 2; index++) {
2688eb82ff87SDaniel Beauregard 		rval = ql_init_firmware(ha);
2689eb82ff87SDaniel Beauregard 		if (rval == QL_COMMAND_ERROR) {
2690eb82ff87SDaniel Beauregard 			EL(ha, "stopping firmware\n");
2691eb82ff87SDaniel Beauregard 			(void) ql_stop_firmware(ha);
2692eb82ff87SDaniel Beauregard 		} else {
2693eb82ff87SDaniel Beauregard 			break;
2694eb82ff87SDaniel Beauregard 		}
2695eb82ff87SDaniel Beauregard 	}
2696fcf3ce44SJohn Forte 
2697eb82ff87SDaniel Beauregard 	if (rval == QL_SUCCESS && (CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2698fcf3ce44SJohn Forte 		/* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */
2699fcf3ce44SJohn Forte 		rval = ql_get_firmware_option(ha, &mr);
2700fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2701fcf3ce44SJohn Forte 			mr.mb[1] = (uint16_t)(mr.mb[1] | BIT_9);
2702fcf3ce44SJohn Forte 			mr.mb[2] = 0;
2703fcf3ce44SJohn Forte 			mr.mb[3] = BIT_10;
2704fcf3ce44SJohn Forte 			rval = ql_set_firmware_option(ha, &mr);
2705fcf3ce44SJohn Forte 		}
2706fcf3ce44SJohn Forte 	}
2707fcf3ce44SJohn Forte 
2708fcf3ce44SJohn Forte 	if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWFCETRACE))) {
270916dd44c2SDaniel Beauregard 		/* Firmware Fibre Channel Event Trace Buffer */
271016dd44c2SDaniel Beauregard 		if ((rval2 = ql_get_dma_mem(ha, &ha->fwfcetracebuf, FWFCESIZE,
271116dd44c2SDaniel Beauregard 		    LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
2712fcf3ce44SJohn Forte 			EL(ha, "fcetrace buffer alloc failed: %xh\n", rval2);
2713fcf3ce44SJohn Forte 		} else {
2714fcf3ce44SJohn Forte 			if ((rval2 = ql_fw_etrace(ha, &ha->fwfcetracebuf,
271516dd44c2SDaniel Beauregard 			    FTO_FCE_TRACE_ENABLE)) != QL_SUCCESS) {
2716fcf3ce44SJohn Forte 				EL(ha, "fcetrace enable failed: %xh\n", rval2);
2717fcf3ce44SJohn Forte 				ql_free_phys(ha, &ha->fwfcetracebuf);
2718fcf3ce44SJohn Forte 			}
2719fcf3ce44SJohn Forte 		}
2720fcf3ce44SJohn Forte 	}
2721fcf3ce44SJohn Forte 
2722fcf3ce44SJohn Forte 	if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE))) {
272316dd44c2SDaniel Beauregard 		/* Firmware Extended Trace Buffer */
272416dd44c2SDaniel Beauregard 		if ((rval2 = ql_get_dma_mem(ha, &ha->fwexttracebuf, FWEXTSIZE,
272516dd44c2SDaniel Beauregard 		    LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
2726fcf3ce44SJohn Forte 			EL(ha, "exttrace buffer alloc failed: %xh\n", rval2);
2727fcf3ce44SJohn Forte 		} else {
2728fcf3ce44SJohn Forte 			if ((rval2 = ql_fw_etrace(ha, &ha->fwexttracebuf,
272916dd44c2SDaniel Beauregard 			    FTO_EXT_TRACE_ENABLE)) != QL_SUCCESS) {
2730fcf3ce44SJohn Forte 				EL(ha, "exttrace enable failed: %xh\n", rval2);
2731fcf3ce44SJohn Forte 				ql_free_phys(ha, &ha->fwexttracebuf);
2732fcf3ce44SJohn Forte 			}
2733fcf3ce44SJohn Forte 		}
2734fcf3ce44SJohn Forte 	}
2735fcf3ce44SJohn Forte 
2736fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && CFG_IST(ha, CFG_CTRL_MENLO)) {
2737fcf3ce44SJohn Forte 		ql_mbx_iocb_t	*pkt;
2738fcf3ce44SJohn Forte 		clock_t		timer;
2739fcf3ce44SJohn Forte 
2740fcf3ce44SJohn Forte 		/* Wait for firmware login of menlo. */
2741fcf3ce44SJohn Forte 		for (timer = 3000; timer; timer--) {
2742fcf3ce44SJohn Forte 			if (ha->flags & MENLO_LOGIN_OPERATIONAL) {
2743fcf3ce44SJohn Forte 				break;
2744fcf3ce44SJohn Forte 			}
2745fcf3ce44SJohn Forte 
2746fcf3ce44SJohn Forte 			if (!(ha->flags & INTERRUPTS_ENABLED) ||
2747fcf3ce44SJohn Forte 			    ddi_in_panic()) {
2748eb82ff87SDaniel Beauregard 				if (INTERRUPT_PENDING(ha)) {
2749fcf3ce44SJohn Forte 					(void) ql_isr((caddr_t)ha);
2750fcf3ce44SJohn Forte 					INTR_LOCK(ha);
2751fcf3ce44SJohn Forte 					ha->intr_claimed = B_TRUE;
2752fcf3ce44SJohn Forte 					INTR_UNLOCK(ha);
2753fcf3ce44SJohn Forte 				}
2754fcf3ce44SJohn Forte 			}
2755fcf3ce44SJohn Forte 
2756fcf3ce44SJohn Forte 			/* Delay for 1 tick (10 milliseconds). */
2757fcf3ce44SJohn Forte 			ql_delay(ha, 10000);
2758fcf3ce44SJohn Forte 		}
2759fcf3ce44SJohn Forte 
2760fcf3ce44SJohn Forte 		if (timer == 0) {
2761fcf3ce44SJohn Forte 			rval = QL_FUNCTION_TIMEOUT;
2762fcf3ce44SJohn Forte 		} else {
2763fcf3ce44SJohn Forte 			pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
2764fcf3ce44SJohn Forte 			if (pkt == NULL) {
2765fcf3ce44SJohn Forte 				EL(ha, "failed, kmem_zalloc\n");
2766fcf3ce44SJohn Forte 				rval = QL_MEMORY_ALLOC_FAILED;
2767fcf3ce44SJohn Forte 			} else {
2768fcf3ce44SJohn Forte 				pkt->mvfy.entry_type = VERIFY_MENLO_TYPE;
2769fcf3ce44SJohn Forte 				pkt->mvfy.entry_count = 1;
2770fcf3ce44SJohn Forte 				pkt->mvfy.options_status =
2771fcf3ce44SJohn Forte 				    LE_16(VMF_DO_NOT_UPDATE_FW);
2772fcf3ce44SJohn Forte 
2773fcf3ce44SJohn Forte 				rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
2774fcf3ce44SJohn Forte 				    sizeof (ql_mbx_iocb_t));
2775fcf3ce44SJohn Forte 				LITTLE_ENDIAN_16(&pkt->mvfy.options_status);
2776fcf3ce44SJohn Forte 				LITTLE_ENDIAN_16(&pkt->mvfy.failure_code);
2777fcf3ce44SJohn Forte 
2778fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS ||
2779fcf3ce44SJohn Forte 				    (pkt->mvfy.entry_status & 0x3c) != 0 ||
2780fcf3ce44SJohn Forte 				    pkt->mvfy.options_status != CS_COMPLETE) {
2781fcf3ce44SJohn Forte 					EL(ha, "failed, status=%xh, es=%xh, "
2782fcf3ce44SJohn Forte 					    "cs=%xh, fc=%xh\n", rval,
2783fcf3ce44SJohn Forte 					    pkt->mvfy.entry_status & 0x3c,
2784fcf3ce44SJohn Forte 					    pkt->mvfy.options_status,
2785fcf3ce44SJohn Forte 					    pkt->mvfy.failure_code);
2786fcf3ce44SJohn Forte 					if (rval == QL_SUCCESS) {
2787fcf3ce44SJohn Forte 						rval = QL_FUNCTION_FAILED;
2788fcf3ce44SJohn Forte 					}
2789fcf3ce44SJohn Forte 				}
2790fcf3ce44SJohn Forte 
2791fcf3ce44SJohn Forte 				kmem_free(pkt, sizeof (ql_mbx_iocb_t));
2792fcf3ce44SJohn Forte 			}
2793fcf3ce44SJohn Forte 		}
2794fcf3ce44SJohn Forte 	}
2795fcf3ce44SJohn Forte 
2796fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2797fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2798fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~FIRMWARE_UP;
2799fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2800fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2801fcf3ce44SJohn Forte 	} else {
2802fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2803fcf3ce44SJohn Forte 		ha->task_daemon_flags |= FIRMWARE_UP;
2804fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2805fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2806fcf3ce44SJohn Forte 	}
2807fcf3ce44SJohn Forte 	return (rval);
2808fcf3ce44SJohn Forte }
2809fcf3ce44SJohn Forte 
2810fcf3ce44SJohn Forte /*
2811fcf3ce44SJohn Forte  * ql_fw_ready
2812fcf3ce44SJohn Forte  *	Waits for firmware ready. If firmware becomes ready
2813fcf3ce44SJohn Forte  *	device queues and RISC code are synchronized.
2814fcf3ce44SJohn Forte  *
2815fcf3ce44SJohn Forte  * Input:
2816fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2817fcf3ce44SJohn Forte  *	secs = max wait time, in seconds (0-255).
2818fcf3ce44SJohn Forte  *
2819fcf3ce44SJohn Forte  * Returns:
2820fcf3ce44SJohn Forte  *	ql local function return status code.
2821fcf3ce44SJohn Forte  *
2822fcf3ce44SJohn Forte  * Context:
2823fcf3ce44SJohn Forte  *	Kernel context.
2824fcf3ce44SJohn Forte  */
2825fcf3ce44SJohn Forte int
2826fcf3ce44SJohn Forte ql_fw_ready(ql_adapter_state_t *ha, uint8_t secs)
2827fcf3ce44SJohn Forte {
2828fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
2829fcf3ce44SJohn Forte 	clock_t		timer;
2830fcf3ce44SJohn Forte 	clock_t		dly = 250000;
2831fcf3ce44SJohn Forte 	clock_t		sec_delay = MICROSEC / dly;
2832fcf3ce44SJohn Forte 	clock_t		wait = secs * sec_delay;
2833fcf3ce44SJohn Forte 	int		rval = QL_FUNCTION_FAILED;
2834fcf3ce44SJohn Forte 	uint16_t	state = 0xffff;
2835fcf3ce44SJohn Forte 
2836fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2837fcf3ce44SJohn Forte 
2838fcf3ce44SJohn Forte 	timer = ha->r_a_tov < secs ? secs : ha->r_a_tov;
2839fcf3ce44SJohn Forte 	timer = (timer + 2) * sec_delay;
2840fcf3ce44SJohn Forte 
2841fcf3ce44SJohn Forte 	/* Wait for ISP to finish LIP */
2842fcf3ce44SJohn Forte 	while (timer != 0 && wait != 0 &&
2843fcf3ce44SJohn Forte 	    !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
2844fcf3ce44SJohn Forte 
2845fcf3ce44SJohn Forte 		rval = ql_get_firmware_state(ha, &mr);
2846fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2847fcf3ce44SJohn Forte 			if (ha->task_daemon_flags & (ISP_ABORT_NEEDED |
2848fcf3ce44SJohn Forte 			    LOOP_DOWN)) {
2849fcf3ce44SJohn Forte 				wait--;
2850fcf3ce44SJohn Forte 			} else if (mr.mb[1] != FSTATE_READY) {
2851fcf3ce44SJohn Forte 				if (mr.mb[1] != FSTATE_WAIT_LOGIN) {
2852fcf3ce44SJohn Forte 					wait--;
2853fcf3ce44SJohn Forte 				}
2854fcf3ce44SJohn Forte 				rval = QL_FUNCTION_FAILED;
2855fcf3ce44SJohn Forte 			} else {
2856fcf3ce44SJohn Forte 				/* Firmware is ready. Get 2 * R_A_TOV. */
2857fcf3ce44SJohn Forte 				rval = ql_get_timeout_parameters(ha,
2858fcf3ce44SJohn Forte 				    &ha->r_a_tov);
2859fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS) {
2860fcf3ce44SJohn Forte 					EL(ha, "failed, get_timeout_param"
2861fcf3ce44SJohn Forte 					    "=%xh\n", rval);
2862fcf3ce44SJohn Forte 				}
2863fcf3ce44SJohn Forte 
2864fcf3ce44SJohn Forte 				/* Configure loop. */
2865fcf3ce44SJohn Forte 				rval = ql_configure_loop(ha);
2866fcf3ce44SJohn Forte 				(void) ql_marker(ha, 0, 0, MK_SYNC_ALL);
2867fcf3ce44SJohn Forte 
2868fcf3ce44SJohn Forte 				if (ha->task_daemon_flags &
2869fcf3ce44SJohn Forte 				    LOOP_RESYNC_NEEDED) {
2870fcf3ce44SJohn Forte 					wait--;
2871fcf3ce44SJohn Forte 					EL(ha, "loop trans; tdf=%xh\n",
2872fcf3ce44SJohn Forte 					    ha->task_daemon_flags);
2873fcf3ce44SJohn Forte 				} else {
2874fcf3ce44SJohn Forte 					break;
2875fcf3ce44SJohn Forte 				}
2876fcf3ce44SJohn Forte 			}
2877fcf3ce44SJohn Forte 		} else {
2878fcf3ce44SJohn Forte 			wait--;
2879fcf3ce44SJohn Forte 		}
2880fcf3ce44SJohn Forte 
2881fcf3ce44SJohn Forte 		if (state != mr.mb[1]) {
2882fcf3ce44SJohn Forte 			EL(ha, "mailbox_reg[1] = %xh\n", mr.mb[1]);
2883fcf3ce44SJohn Forte 			state = mr.mb[1];
2884fcf3ce44SJohn Forte 		}
2885fcf3ce44SJohn Forte 
2886fcf3ce44SJohn Forte 		/* Delay for a tick if waiting. */
2887fcf3ce44SJohn Forte 		if (timer-- != 0 && wait != 0) {
2888fcf3ce44SJohn Forte 			if (timer % 4 == 0) {
2889fcf3ce44SJohn Forte 				delay(drv_usectohz(dly));
2890fcf3ce44SJohn Forte 			} else {
2891fcf3ce44SJohn Forte 				drv_usecwait(dly);
2892fcf3ce44SJohn Forte 			}
2893fcf3ce44SJohn Forte 		} else {
2894fcf3ce44SJohn Forte 			rval = QL_FUNCTION_TIMEOUT;
2895fcf3ce44SJohn Forte 		}
2896fcf3ce44SJohn Forte 	}
2897fcf3ce44SJohn Forte 
2898fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2899fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2900fcf3ce44SJohn Forte 	} else {
2901fcf3ce44SJohn Forte 		/*EMPTY*/
2902fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2903fcf3ce44SJohn Forte 	}
2904fcf3ce44SJohn Forte 	return (rval);
2905fcf3ce44SJohn Forte }
2906fcf3ce44SJohn Forte 
2907fcf3ce44SJohn Forte /*
2908fcf3ce44SJohn Forte  * ql_configure_loop
2909fcf3ce44SJohn Forte  *	Setup configurations based on loop.
2910fcf3ce44SJohn Forte  *
2911fcf3ce44SJohn Forte  * Input:
2912fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2913fcf3ce44SJohn Forte  *
2914fcf3ce44SJohn Forte  * Returns:
2915fcf3ce44SJohn Forte  *	ql local function return status code.
2916fcf3ce44SJohn Forte  *
2917fcf3ce44SJohn Forte  * Context:
2918fcf3ce44SJohn Forte  *	Kernel context.
2919fcf3ce44SJohn Forte  */
2920fcf3ce44SJohn Forte static int
2921fcf3ce44SJohn Forte ql_configure_loop(ql_adapter_state_t *ha)
2922fcf3ce44SJohn Forte {
2923fcf3ce44SJohn Forte 	int			rval;
2924fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
2925fcf3ce44SJohn Forte 
2926fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2927fcf3ce44SJohn Forte 
2928fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
2929fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2930fcf3ce44SJohn Forte 		if (!(vha->task_daemon_flags & LOOP_RESYNC_NEEDED) &&
2931fcf3ce44SJohn Forte 		    vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
2932fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
2933fcf3ce44SJohn Forte 			continue;
2934fcf3ce44SJohn Forte 		}
2935fcf3ce44SJohn Forte 		vha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED;
2936fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2937fcf3ce44SJohn Forte 
2938fcf3ce44SJohn Forte 		rval = ql_configure_hba(vha);
2939fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
2940fcf3ce44SJohn Forte 		    (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
2941fcf3ce44SJohn Forte 			rval = ql_configure_device_d_id(vha);
2942fcf3ce44SJohn Forte 			if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
2943fcf3ce44SJohn Forte 			    (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
2944fcf3ce44SJohn Forte 				(void) ql_configure_fabric(vha);
2945fcf3ce44SJohn Forte 			}
2946fcf3ce44SJohn Forte 		}
2947fcf3ce44SJohn Forte 	}
2948fcf3ce44SJohn Forte 
2949fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2950fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2951fcf3ce44SJohn Forte 	} else {
2952fcf3ce44SJohn Forte 		/*EMPTY*/
2953fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2954fcf3ce44SJohn Forte 	}
2955fcf3ce44SJohn Forte 	return (rval);
2956fcf3ce44SJohn Forte }
2957fcf3ce44SJohn Forte 
29585dfd244aSDaniel Beauregard /*
29595dfd244aSDaniel Beauregard  * ql_configure_n_port_info
29605dfd244aSDaniel Beauregard  *	Setup configurations based on N port 2 N port topology.
29615dfd244aSDaniel Beauregard  *
29625dfd244aSDaniel Beauregard  * Input:
29635dfd244aSDaniel Beauregard  *	ha = adapter state pointer.
29645dfd244aSDaniel Beauregard  *
29655dfd244aSDaniel Beauregard  * Returns:
29665dfd244aSDaniel Beauregard  *	ql local function return status code.
29675dfd244aSDaniel Beauregard  *
29685dfd244aSDaniel Beauregard  * Context:
29695dfd244aSDaniel Beauregard  *	Kernel context.
29705dfd244aSDaniel Beauregard  */
29715dfd244aSDaniel Beauregard static void
29725dfd244aSDaniel Beauregard ql_configure_n_port_info(ql_adapter_state_t *ha)
29735dfd244aSDaniel Beauregard {
29745dfd244aSDaniel Beauregard 	ql_tgt_t	tmp_tq;
29755dfd244aSDaniel Beauregard 	ql_tgt_t	*tq;
29765dfd244aSDaniel Beauregard 	uint8_t		*cb_port_name;
29775dfd244aSDaniel Beauregard 	ql_link_t	*link;
29785dfd244aSDaniel Beauregard 	int		index, rval;
29795dfd244aSDaniel Beauregard 
29805dfd244aSDaniel Beauregard 	tq = &tmp_tq;
29815dfd244aSDaniel Beauregard 
29825dfd244aSDaniel Beauregard 	/* Free existing target queues. */
29835dfd244aSDaniel Beauregard 	for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
29845dfd244aSDaniel Beauregard 		link = ha->dev[index].first;
29855dfd244aSDaniel Beauregard 		while (link != NULL) {
29865dfd244aSDaniel Beauregard 			tq = link->base_address;
29875dfd244aSDaniel Beauregard 			link = link->next;
29885dfd244aSDaniel Beauregard 			ql_remove_link(&ha->dev[index], &tq->device);
29895dfd244aSDaniel Beauregard 			ql_dev_free(ha, tq);
29905dfd244aSDaniel Beauregard 		}
29915dfd244aSDaniel Beauregard 	}
29925dfd244aSDaniel Beauregard 
29935dfd244aSDaniel Beauregard 	/*
29945dfd244aSDaniel Beauregard 	 * If the N_Port's WWPN is larger than our's then it has the
29955dfd244aSDaniel Beauregard 	 * N_Port login initiative.  It will have determined that and
29965dfd244aSDaniel Beauregard 	 * logged in with the firmware.  This results in a device
29975dfd244aSDaniel Beauregard 	 * database entry.  In this situation we will later send up a PLOGI
29985dfd244aSDaniel Beauregard 	 * by proxy for the N_Port to get things going.
29995dfd244aSDaniel Beauregard 	 *
30005dfd244aSDaniel Beauregard 	 * If the N_Ports WWPN is smaller then the firmware has the
30015dfd244aSDaniel Beauregard 	 * N_Port login initiative and does a FLOGI in order to obtain the
30025dfd244aSDaniel Beauregard 	 * N_Ports WWNN and WWPN.  These names are required later
30035dfd244aSDaniel Beauregard 	 * during Leadvilles FLOGI.  No PLOGI is done by the firmware in
30045dfd244aSDaniel Beauregard 	 * anticipation of a PLOGI via the driver from the upper layers.
30055dfd244aSDaniel Beauregard 	 * Upon reciept of said PLOGI the driver issues an ELS PLOGI
30065dfd244aSDaniel Beauregard 	 * pass-through command and the firmware assumes the s_id
30075dfd244aSDaniel Beauregard 	 * and the N_Port assumes the d_id and Bob's your uncle.
30085dfd244aSDaniel Beauregard 	 */
30095dfd244aSDaniel Beauregard 
30105dfd244aSDaniel Beauregard 	/*
30115dfd244aSDaniel Beauregard 	 * In N port 2 N port topology the FW provides a port database entry at
30125dfd244aSDaniel Beauregard 	 * loop_id 0x7fe which allows us to acquire the Ports WWPN.
30135dfd244aSDaniel Beauregard 	 */
30145dfd244aSDaniel Beauregard 	tq->d_id.b.al_pa = 0;
30155dfd244aSDaniel Beauregard 	tq->d_id.b.area = 0;
30165dfd244aSDaniel Beauregard 	tq->d_id.b.domain = 0;
30175dfd244aSDaniel Beauregard 	tq->loop_id = 0x7fe;
30185dfd244aSDaniel Beauregard 
30195dfd244aSDaniel Beauregard 	rval = ql_get_port_database(ha, tq, PDF_NONE);
30205dfd244aSDaniel Beauregard 	if (rval == QL_SUCCESS || rval == QL_NOT_LOGGED_IN) {
30215dfd244aSDaniel Beauregard 		ql_dev_id_list_t	*list;
30225dfd244aSDaniel Beauregard 		uint32_t		list_size;
30235dfd244aSDaniel Beauregard 		ql_mbx_data_t		mr;
30245dfd244aSDaniel Beauregard 		port_id_t		d_id = {0, 0, 0, 0};
30255dfd244aSDaniel Beauregard 		uint16_t		loop_id = 0;
30265dfd244aSDaniel Beauregard 
3027eb82ff87SDaniel Beauregard 		cb_port_name = (uint8_t *)(CFG_IST(ha, CFG_CTRL_24258081) ?
30285dfd244aSDaniel Beauregard 		    &ha->init_ctrl_blk.cb24.port_name[0] :
30295dfd244aSDaniel Beauregard 		    &ha->init_ctrl_blk.cb.port_name[0]);
30305dfd244aSDaniel Beauregard 
30315dfd244aSDaniel Beauregard 		if ((ql_wwn_cmp(ha, (la_wwn_t *)&tq->port_name[0],
30325dfd244aSDaniel Beauregard 		    (la_wwn_t *)cb_port_name) == 1)) {
30335dfd244aSDaniel Beauregard 			EL(ha, "target port has N_Port login initiative\n");
30345dfd244aSDaniel Beauregard 		} else {
30355dfd244aSDaniel Beauregard 			EL(ha, "host port has N_Port login initiative\n");
30365dfd244aSDaniel Beauregard 		}
30375dfd244aSDaniel Beauregard 
30385dfd244aSDaniel Beauregard 		/* Capture the N Ports WWPN */
30395dfd244aSDaniel Beauregard 
30405dfd244aSDaniel Beauregard 		bcopy((void *)&tq->port_name[0],
30415dfd244aSDaniel Beauregard 		    (void *)&ha->n_port->port_name[0], 8);
30425dfd244aSDaniel Beauregard 		bcopy((void *)&tq->node_name[0],
30435dfd244aSDaniel Beauregard 		    (void *)&ha->n_port->node_name[0], 8);
30445dfd244aSDaniel Beauregard 
30455dfd244aSDaniel Beauregard 		/* Resolve an n_port_handle */
30465dfd244aSDaniel Beauregard 		ha->n_port->n_port_handle = 0x7fe;
30475dfd244aSDaniel Beauregard 
30485dfd244aSDaniel Beauregard 		list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
30495dfd244aSDaniel Beauregard 		list = (ql_dev_id_list_t *)kmem_zalloc(list_size, KM_SLEEP);
30505dfd244aSDaniel Beauregard 
30515dfd244aSDaniel Beauregard 		if (list != NULL &&
30525dfd244aSDaniel Beauregard 		    ql_get_id_list(ha, (caddr_t)list, list_size, &mr) ==
30535dfd244aSDaniel Beauregard 		    QL_SUCCESS) {
30545dfd244aSDaniel Beauregard 			if (mr.mb[1]) {
30555dfd244aSDaniel Beauregard 				EL(ha, "id list entries = %d\n", mr.mb[1]);
30565dfd244aSDaniel Beauregard 				for (index = 0; index < mr.mb[1]; index++) {
30575dfd244aSDaniel Beauregard 					ql_dev_list(ha, list, index,
30585dfd244aSDaniel Beauregard 					    &d_id, &loop_id);
30595dfd244aSDaniel Beauregard 					ha->n_port->n_port_handle = loop_id;
30605dfd244aSDaniel Beauregard 				}
30615dfd244aSDaniel Beauregard 			} else {
30625dfd244aSDaniel Beauregard 				for (index = 0; index <= LAST_LOCAL_LOOP_ID;
30635dfd244aSDaniel Beauregard 				    index++) {
30645dfd244aSDaniel Beauregard 					/* resuse tq */
30655dfd244aSDaniel Beauregard 					tq->loop_id = (uint16_t)index;
30665dfd244aSDaniel Beauregard 					rval = ql_get_port_database(ha, tq,
30675dfd244aSDaniel Beauregard 					    PDF_NONE);
30685dfd244aSDaniel Beauregard 					if (rval == QL_NOT_LOGGED_IN) {
30695dfd244aSDaniel Beauregard 						if (tq->master_state ==
30705dfd244aSDaniel Beauregard 						    PD_STATE_PLOGI_PENDING) {
30715dfd244aSDaniel Beauregard 							ha->n_port->
30725dfd244aSDaniel Beauregard 							    n_port_handle =
30735dfd244aSDaniel Beauregard 							    tq->loop_id;
30745dfd244aSDaniel Beauregard 							break;
30755dfd244aSDaniel Beauregard 						}
30765dfd244aSDaniel Beauregard 					} else {
30775dfd244aSDaniel Beauregard 						ha->n_port->n_port_handle =
30785dfd244aSDaniel Beauregard 						    tq->loop_id;
30795dfd244aSDaniel Beauregard 						break;
30805dfd244aSDaniel Beauregard 					}
30815dfd244aSDaniel Beauregard 				}
30825dfd244aSDaniel Beauregard 			}
30835dfd244aSDaniel Beauregard 		} else {
30845dfd244aSDaniel Beauregard 			cmn_err(CE_WARN, "!%s(%d) didn't get list for %xh",
30855dfd244aSDaniel Beauregard 			    QL_NAME, ha->instance, d_id.b24);
30865dfd244aSDaniel Beauregard 		}
30875dfd244aSDaniel Beauregard 		if (list != NULL) {
30885dfd244aSDaniel Beauregard 			kmem_free(list, list_size);
30895dfd244aSDaniel Beauregard 		}
30905dfd244aSDaniel Beauregard 	}
30915dfd244aSDaniel Beauregard }
30925dfd244aSDaniel Beauregard 
30935dfd244aSDaniel Beauregard 
3094fcf3ce44SJohn Forte /*
3095fcf3ce44SJohn Forte  * ql_configure_hba
3096fcf3ce44SJohn Forte  *	Setup adapter context.
3097fcf3ce44SJohn Forte  *
3098fcf3ce44SJohn Forte  * Input:
3099fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3100fcf3ce44SJohn Forte  *
3101fcf3ce44SJohn Forte  * Returns:
3102fcf3ce44SJohn Forte  *	ql local function return status code.
3103fcf3ce44SJohn Forte  *
3104fcf3ce44SJohn Forte  * Context:
3105fcf3ce44SJohn Forte  *	Kernel context.
3106fcf3ce44SJohn Forte  */
3107fcf3ce44SJohn Forte static int
3108fcf3ce44SJohn Forte ql_configure_hba(ql_adapter_state_t *ha)
3109fcf3ce44SJohn Forte {
3110fcf3ce44SJohn Forte 	uint8_t		*bp;
3111fcf3ce44SJohn Forte 	int		rval;
3112fcf3ce44SJohn Forte 	uint32_t	state;
3113fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
3114fcf3ce44SJohn Forte 
3115fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3116fcf3ce44SJohn Forte 
3117fcf3ce44SJohn Forte 	/* Get host addresses. */
3118fcf3ce44SJohn Forte 	rval = ql_get_adapter_id(ha, &mr);
3119fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
3120fcf3ce44SJohn Forte 		ha->topology = (uint8_t)(ha->topology &
3121fcf3ce44SJohn Forte 		    ~(QL_N_PORT | QL_NL_PORT | QL_F_PORT | QL_FL_PORT));
3122fcf3ce44SJohn Forte 
3123fcf3ce44SJohn Forte 		/* Save Host d_id, alpa, loop ID. */
3124fcf3ce44SJohn Forte 		ha->loop_id = mr.mb[1];
3125fcf3ce44SJohn Forte 		ha->d_id.b.al_pa = LSB(mr.mb[2]);
3126fcf3ce44SJohn Forte 		ha->d_id.b.area = MSB(mr.mb[2]);
3127fcf3ce44SJohn Forte 		ha->d_id.b.domain = LSB(mr.mb[3]);
3128fcf3ce44SJohn Forte 
3129fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3130fcf3ce44SJohn Forte 		ha->flags &= ~FDISC_ENABLED;
3131fcf3ce44SJohn Forte 
3132fcf3ce44SJohn Forte 		/* Get loop topology. */
3133fcf3ce44SJohn Forte 		switch (mr.mb[6]) {
3134fcf3ce44SJohn Forte 		case CNX_LOOP_NO_FABRIC:
3135fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_NL_PORT);
3136fcf3ce44SJohn Forte 			break;
3137fcf3ce44SJohn Forte 		case CNX_FLPORT_IN_LOOP:
3138fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_FL_PORT);
3139fcf3ce44SJohn Forte 			break;
3140fcf3ce44SJohn Forte 		case CNX_NPORT_2_NPORT_P2P:
3141fcf3ce44SJohn Forte 		case CNX_NPORT_2_NPORT_NO_TGT_RSP:
3142fcf3ce44SJohn Forte 			ha->flags |= POINT_TO_POINT;
3143fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_N_PORT);
31445dfd244aSDaniel Beauregard 			if (CFG_IST(ha, CFG_CTRL_2425)) {
31455dfd244aSDaniel Beauregard 				ql_configure_n_port_info(ha);
31465dfd244aSDaniel Beauregard 			}
3147fcf3ce44SJohn Forte 			break;
3148fcf3ce44SJohn Forte 		case CNX_FLPORT_P2P:
3149fcf3ce44SJohn Forte 			ha->flags |= POINT_TO_POINT;
3150fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_F_PORT);
3151fcf3ce44SJohn Forte 
3152fcf3ce44SJohn Forte 			/* Get supported option. */
3153eb82ff87SDaniel Beauregard 			if (CFG_IST(ha, CFG_CTRL_24258081) &&
31545dfd244aSDaniel Beauregard 			    mr.mb[7] & GID_FP_NPIV_SUPPORT) {
3155fcf3ce44SJohn Forte 				ha->flags |= FDISC_ENABLED;
3156fcf3ce44SJohn Forte 			}
31577a2b99c0SDaniel Beauregard 			/* Get VLAN ID, mac address */
3158eb82ff87SDaniel Beauregard 			if (CFG_IST(ha, CFG_CTRL_8081)) {
31597a2b99c0SDaniel Beauregard 				ha->fabric_params = mr.mb[7];
31607a2b99c0SDaniel Beauregard 				ha->fcoe_vlan_id = (uint16_t)(mr.mb[9] & 0xfff);
31617a2b99c0SDaniel Beauregard 				ha->fcoe_fcf_idx = mr.mb[10];
31627a2b99c0SDaniel Beauregard 				ha->fcoe_vnport_mac[0] = MSB(mr.mb[11]);
31637a2b99c0SDaniel Beauregard 				ha->fcoe_vnport_mac[1] = LSB(mr.mb[11]);
31647a2b99c0SDaniel Beauregard 				ha->fcoe_vnport_mac[2] = MSB(mr.mb[12]);
31657a2b99c0SDaniel Beauregard 				ha->fcoe_vnport_mac[3] = LSB(mr.mb[12]);
31667a2b99c0SDaniel Beauregard 				ha->fcoe_vnport_mac[4] = MSB(mr.mb[13]);
31677a2b99c0SDaniel Beauregard 				ha->fcoe_vnport_mac[5] = LSB(mr.mb[13]);
31687a2b99c0SDaniel Beauregard 			}
3169fcf3ce44SJohn Forte 			break;
3170fcf3ce44SJohn Forte 		default:
3171fcf3ce44SJohn Forte 			QL_PRINT_2(CE_CONT, "(%d,%d): UNKNOWN topology=%xh, "
3172fcf3ce44SJohn Forte 			    "d_id=%xh\n", ha->instance, ha->vp_index, mr.mb[6],
3173fcf3ce44SJohn Forte 			    ha->d_id.b24);
3174fcf3ce44SJohn Forte 			rval = QL_FUNCTION_FAILED;
3175fcf3ce44SJohn Forte 			break;
3176fcf3ce44SJohn Forte 		}
3177fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3178fcf3ce44SJohn Forte 
31795dfd244aSDaniel Beauregard 		if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 |
3180eb82ff87SDaniel Beauregard 		    CFG_CTRL_24258081))) {
3181fcf3ce44SJohn Forte 			mr.mb[1] = 0;
3182fcf3ce44SJohn Forte 			mr.mb[2] = 0;
3183fcf3ce44SJohn Forte 			rval = ql_data_rate(ha, &mr);
3184fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
3185fcf3ce44SJohn Forte 				EL(ha, "data_rate status=%xh\n", rval);
3186fcf3ce44SJohn Forte 				state = FC_STATE_FULL_SPEED;
3187fcf3ce44SJohn Forte 			} else {
3188*f885d00fSDaniel Beauregard 				ha->iidma_rate = mr.mb[1];
31895dfd244aSDaniel Beauregard 				if (mr.mb[1] == IIDMA_RATE_1GB) {
3190fcf3ce44SJohn Forte 					state = FC_STATE_1GBIT_SPEED;
31915dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_2GB) {
3192fcf3ce44SJohn Forte 					state = FC_STATE_2GBIT_SPEED;
31935dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_4GB) {
3194fcf3ce44SJohn Forte 					state = FC_STATE_4GBIT_SPEED;
31955dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_8GB) {
3196fcf3ce44SJohn Forte 					state = FC_STATE_8GBIT_SPEED;
31975dfd244aSDaniel Beauregard 				} else if (mr.mb[1] == IIDMA_RATE_10GB) {
31985dfd244aSDaniel Beauregard 					state = FC_STATE_10GBIT_SPEED;
3199fcf3ce44SJohn Forte 				} else {
3200fcf3ce44SJohn Forte 					state = 0;
3201fcf3ce44SJohn Forte 				}
3202fcf3ce44SJohn Forte 			}
3203fcf3ce44SJohn Forte 		} else {
3204*f885d00fSDaniel Beauregard 			ha->iidma_rate = IIDMA_RATE_1GB;
3205fcf3ce44SJohn Forte 			state = FC_STATE_FULL_SPEED;
3206fcf3ce44SJohn Forte 		}
3207fcf3ce44SJohn Forte 		ha->state = FC_PORT_STATE_MASK(ha->state) | state;
320816dd44c2SDaniel Beauregard 	} else if (rval == MBS_COMMAND_ERROR) {
320916dd44c2SDaniel Beauregard 		EL(ha, "mbox cmd error, rval = %xh, mr.mb[1]=%hx\n",
321016dd44c2SDaniel Beauregard 		    rval, mr.mb[1]);
3211fcf3ce44SJohn Forte 	}
3212fcf3ce44SJohn Forte 
3213fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3214fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3215fcf3ce44SJohn Forte 	} else {
3216fcf3ce44SJohn Forte 		bp = ha->loginparams.nport_ww_name.raw_wwn;
3217fcf3ce44SJohn Forte 		EL(ha, "topology=%xh, d_id=%xh, "
3218fcf3ce44SJohn Forte 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n",
3219fcf3ce44SJohn Forte 		    ha->topology, ha->d_id.b24, bp[0], bp[1],
3220fcf3ce44SJohn Forte 		    bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]);
3221fcf3ce44SJohn Forte 	}
3222fcf3ce44SJohn Forte 	return (rval);
3223fcf3ce44SJohn Forte }
3224fcf3ce44SJohn Forte 
3225fcf3ce44SJohn Forte /*
3226fcf3ce44SJohn Forte  * ql_configure_device_d_id
3227fcf3ce44SJohn Forte  *	Updates device loop ID.
3228fcf3ce44SJohn Forte  *	Also adds to device queue any new devices found on private loop.
3229fcf3ce44SJohn Forte  *
3230fcf3ce44SJohn Forte  * Input:
3231fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3232fcf3ce44SJohn Forte  *
3233fcf3ce44SJohn Forte  * Returns:
3234fcf3ce44SJohn Forte  *	ql local function return status code.
3235fcf3ce44SJohn Forte  *
3236fcf3ce44SJohn Forte  * Context:
3237fcf3ce44SJohn Forte  *	Kernel context.
3238fcf3ce44SJohn Forte  */
3239fcf3ce44SJohn Forte static int
3240fcf3ce44SJohn Forte ql_configure_device_d_id(ql_adapter_state_t *ha)
3241fcf3ce44SJohn Forte {
3242fcf3ce44SJohn Forte 	port_id_t		d_id;
3243fcf3ce44SJohn Forte 	ql_link_t		*link;
3244fcf3ce44SJohn Forte 	int			rval;
3245fcf3ce44SJohn Forte 	int			loop;
3246fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
3247fcf3ce44SJohn Forte 	ql_dev_id_list_t	*list;
3248fcf3ce44SJohn Forte 	uint32_t		list_size;
3249fcf3ce44SJohn Forte 	uint16_t		index, loop_id;
3250fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
3251fcf3ce44SJohn Forte 	uint8_t			retries = MAX_DEVICE_LOST_RETRY;
3252fcf3ce44SJohn Forte 
3253fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3254fcf3ce44SJohn Forte 
3255fcf3ce44SJohn Forte 	list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
3256fcf3ce44SJohn Forte 	list = kmem_zalloc(list_size, KM_SLEEP);
3257fcf3ce44SJohn Forte 	if (list == NULL) {
3258fcf3ce44SJohn Forte 		rval = QL_MEMORY_ALLOC_FAILED;
3259fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3260fcf3ce44SJohn Forte 		return (rval);
3261fcf3ce44SJohn Forte 	}
3262fcf3ce44SJohn Forte 
3263fcf3ce44SJohn Forte 	do {
3264fcf3ce44SJohn Forte 		/*
3265fcf3ce44SJohn Forte 		 * Get data from RISC code d_id list to init each device queue.
3266fcf3ce44SJohn Forte 		 */
3267fcf3ce44SJohn Forte 		rval = ql_get_id_list(ha, (caddr_t)list, list_size, &mr);
3268fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
3269fcf3ce44SJohn Forte 			kmem_free(list, list_size);
3270fcf3ce44SJohn Forte 			EL(ha, "failed, rval = %xh\n", rval);
3271fcf3ce44SJohn Forte 			return (rval);
3272fcf3ce44SJohn Forte 		}
3273fcf3ce44SJohn Forte 
3274fcf3ce44SJohn Forte 		/* Acquire adapter state lock. */
3275fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3276fcf3ce44SJohn Forte 
3277fcf3ce44SJohn Forte 		/* Mark all queues as unusable. */
3278fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3279fcf3ce44SJohn Forte 			for (link = ha->dev[index].first; link != NULL;
3280fcf3ce44SJohn Forte 			    link = link->next) {
3281fcf3ce44SJohn Forte 				tq = link->base_address;
3282fcf3ce44SJohn Forte 				DEVICE_QUEUE_LOCK(tq);
32835dfd244aSDaniel Beauregard 				if (!(tq->flags & TQF_PLOGI_PROGRS) &&
32845dfd244aSDaniel Beauregard 				    !(ha->topology & QL_N_PORT)) {
3285fcf3ce44SJohn Forte 					tq->loop_id = (uint16_t)
3286fcf3ce44SJohn Forte 					    (tq->loop_id | PORT_LOST_ID);
3287fcf3ce44SJohn Forte 				}
3288fcf3ce44SJohn Forte 				DEVICE_QUEUE_UNLOCK(tq);
3289fcf3ce44SJohn Forte 			}
3290fcf3ce44SJohn Forte 		}
3291fcf3ce44SJohn Forte 
3292fcf3ce44SJohn Forte 		/* If device not in queues add new queue. */
3293fcf3ce44SJohn Forte 		for (index = 0; index < mr.mb[1]; index++) {
3294fcf3ce44SJohn Forte 			ql_dev_list(ha, list, index, &d_id, &loop_id);
3295fcf3ce44SJohn Forte 
3296fcf3ce44SJohn Forte 			if (VALID_DEVICE_ID(ha, loop_id)) {
3297fcf3ce44SJohn Forte 				tq = ql_dev_init(ha, d_id, loop_id);
3298fcf3ce44SJohn Forte 				if (tq != NULL) {
3299fcf3ce44SJohn Forte 					tq->loop_id = loop_id;
3300fcf3ce44SJohn Forte 
3301fcf3ce44SJohn Forte 					/* Test for fabric device. */
3302fcf3ce44SJohn Forte 					if (d_id.b.domain !=
3303fcf3ce44SJohn Forte 					    ha->d_id.b.domain ||
3304fcf3ce44SJohn Forte 					    d_id.b.area != ha->d_id.b.area) {
3305fcf3ce44SJohn Forte 						tq->flags |= TQF_FABRIC_DEVICE;
3306fcf3ce44SJohn Forte 					}
3307fcf3ce44SJohn Forte 
3308fcf3ce44SJohn Forte 					ADAPTER_STATE_UNLOCK(ha);
3309fcf3ce44SJohn Forte 					if (ql_get_port_database(ha, tq,
3310fcf3ce44SJohn Forte 					    PDF_NONE) == QL_SUCCESS) {
3311fcf3ce44SJohn Forte 						ADAPTER_STATE_LOCK(ha);
3312fcf3ce44SJohn Forte 						tq->loop_id = (uint16_t)
3313fcf3ce44SJohn Forte 						    (tq->loop_id &
3314fcf3ce44SJohn Forte 						    ~PORT_LOST_ID);
3315fcf3ce44SJohn Forte 					} else {
3316fcf3ce44SJohn Forte 						ADAPTER_STATE_LOCK(ha);
3317fcf3ce44SJohn Forte 					}
3318fcf3ce44SJohn Forte 				}
3319fcf3ce44SJohn Forte 			}
3320fcf3ce44SJohn Forte 		}
3321fcf3ce44SJohn Forte 
3322fcf3ce44SJohn Forte 		/* 24xx does not report switch devices in ID list. */
3323eb82ff87SDaniel Beauregard 		if ((CFG_IST(ha, CFG_CTRL_24258081)) &&
3324fcf3ce44SJohn Forte 		    ha->topology & (QL_F_PORT | QL_FL_PORT)) {
3325fcf3ce44SJohn Forte 			d_id.b24 = 0xfffffe;
3326fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, FL_PORT_24XX_HDL);
3327fcf3ce44SJohn Forte 			if (tq != NULL) {
332816dd44c2SDaniel Beauregard 				tq->flags |= TQF_FABRIC_DEVICE;
3329fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3330fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3331fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3332fcf3ce44SJohn Forte 			}
3333fcf3ce44SJohn Forte 			d_id.b24 = 0xfffffc;
3334fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, SNS_24XX_HDL);
3335fcf3ce44SJohn Forte 			if (tq != NULL) {
333616dd44c2SDaniel Beauregard 				tq->flags |= TQF_FABRIC_DEVICE;
3337fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3338fcf3ce44SJohn Forte 				if (ha->vp_index != 0) {
3339fcf3ce44SJohn Forte 					(void) ql_login_fport(ha, tq,
3340fcf3ce44SJohn Forte 					    SNS_24XX_HDL, LFF_NONE, NULL);
3341fcf3ce44SJohn Forte 				}
3342fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3343fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3344fcf3ce44SJohn Forte 			}
3345fcf3ce44SJohn Forte 		}
3346fcf3ce44SJohn Forte 
3347fcf3ce44SJohn Forte 		/* If F_port exists, allocate queue for FL_Port. */
3348fcf3ce44SJohn Forte 		index = ql_alpa_to_index[0xfe];
3349fcf3ce44SJohn Forte 		d_id.b24 = 0;
3350fcf3ce44SJohn Forte 		if (ha->dev[index].first != NULL) {
3351fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, (uint16_t)
3352eb82ff87SDaniel Beauregard 			    (CFG_IST(ha, CFG_CTRL_24258081) ?
3353fcf3ce44SJohn Forte 			    FL_PORT_24XX_HDL : FL_PORT_LOOP_ID));
3354fcf3ce44SJohn Forte 			if (tq != NULL) {
335516dd44c2SDaniel Beauregard 				tq->flags |= TQF_FABRIC_DEVICE;
3356fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3357fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3358fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3359fcf3ce44SJohn Forte 			}
3360fcf3ce44SJohn Forte 		}
3361fcf3ce44SJohn Forte 
3362fcf3ce44SJohn Forte 		/* Allocate queue for broadcast. */
3363fcf3ce44SJohn Forte 		d_id.b24 = 0xffffff;
3364fcf3ce44SJohn Forte 		(void) ql_dev_init(ha, d_id, (uint16_t)
3365eb82ff87SDaniel Beauregard 		    (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL :
3366fcf3ce44SJohn Forte 		    IP_BROADCAST_LOOP_ID));
3367fcf3ce44SJohn Forte 
3368fcf3ce44SJohn Forte 		/* Check for any devices lost. */
3369fcf3ce44SJohn Forte 		loop = FALSE;
3370fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3371fcf3ce44SJohn Forte 			for (link = ha->dev[index].first; link != NULL;
3372fcf3ce44SJohn Forte 			    link = link->next) {
3373fcf3ce44SJohn Forte 				tq = link->base_address;
3374fcf3ce44SJohn Forte 
3375fcf3ce44SJohn Forte 				if ((tq->loop_id & PORT_LOST_ID) &&
3376fcf3ce44SJohn Forte 				    !(tq->flags & (TQF_INITIATOR_DEVICE |
3377fcf3ce44SJohn Forte 				    TQF_FABRIC_DEVICE))) {
3378fcf3ce44SJohn Forte 					loop = TRUE;
3379fcf3ce44SJohn Forte 				}
3380fcf3ce44SJohn Forte 			}
3381fcf3ce44SJohn Forte 		}
3382fcf3ce44SJohn Forte 
3383fcf3ce44SJohn Forte 		/* Release adapter state lock. */
3384fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3385fcf3ce44SJohn Forte 
3386fcf3ce44SJohn Forte 		/* Give devices time to recover. */
3387fcf3ce44SJohn Forte 		if (loop == TRUE) {
3388fcf3ce44SJohn Forte 			drv_usecwait(1000000);
3389fcf3ce44SJohn Forte 		}
3390fcf3ce44SJohn Forte 	} while (retries-- && loop == TRUE &&
3391fcf3ce44SJohn Forte 	    !(ha->pha->task_daemon_flags & LOOP_RESYNC_NEEDED));
3392fcf3ce44SJohn Forte 
3393fcf3ce44SJohn Forte 	kmem_free(list, list_size);
3394fcf3ce44SJohn Forte 
3395fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3396fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
3397fcf3ce44SJohn Forte 	} else {
3398fcf3ce44SJohn Forte 		/*EMPTY*/
3399fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3400fcf3ce44SJohn Forte 	}
3401fcf3ce44SJohn Forte 
3402fcf3ce44SJohn Forte 	return (rval);
3403fcf3ce44SJohn Forte }
3404fcf3ce44SJohn Forte 
3405fcf3ce44SJohn Forte /*
3406fcf3ce44SJohn Forte  * ql_dev_list
3407fcf3ce44SJohn Forte  *	Gets device d_id and loop ID from firmware device list.
3408fcf3ce44SJohn Forte  *
3409fcf3ce44SJohn Forte  * Input:
3410fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
3411fcf3ce44SJohn Forte  *	list	device list pointer.
3412fcf3ce44SJohn Forte  *	index:	list index of device data.
3413fcf3ce44SJohn Forte  *	d_id:	pointer for d_id data.
3414fcf3ce44SJohn Forte  *	id:	pointer for loop ID.
3415fcf3ce44SJohn Forte  *
3416fcf3ce44SJohn Forte  * Context:
3417fcf3ce44SJohn Forte  *	Kernel context.
3418fcf3ce44SJohn Forte  */
3419fcf3ce44SJohn Forte void
3420fcf3ce44SJohn Forte ql_dev_list(ql_adapter_state_t *ha, union ql_dev_id_list *list,
3421fcf3ce44SJohn Forte     uint32_t index, port_id_t *d_id, uint16_t *id)
3422fcf3ce44SJohn Forte {
3423eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
3424fcf3ce44SJohn Forte 		struct ql_24_dev_id	*list24 = (struct ql_24_dev_id *)list;
3425fcf3ce44SJohn Forte 
3426fcf3ce44SJohn Forte 		d_id->b.al_pa = list24[index].al_pa;
3427fcf3ce44SJohn Forte 		d_id->b.area = list24[index].area;
3428fcf3ce44SJohn Forte 		d_id->b.domain = list24[index].domain;
3429fcf3ce44SJohn Forte 		*id = CHAR_TO_SHORT(list24[index].n_port_hdl_l,
3430fcf3ce44SJohn Forte 		    list24[index].n_port_hdl_h);
3431fcf3ce44SJohn Forte 
3432fcf3ce44SJohn Forte 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
3433fcf3ce44SJohn Forte 		struct ql_ex_dev_id	*list23 = (struct ql_ex_dev_id *)list;
3434fcf3ce44SJohn Forte 
3435fcf3ce44SJohn Forte 		d_id->b.al_pa = list23[index].al_pa;
3436fcf3ce44SJohn Forte 		d_id->b.area = list23[index].area;
3437fcf3ce44SJohn Forte 		d_id->b.domain = list23[index].domain;
3438fcf3ce44SJohn Forte 		*id = CHAR_TO_SHORT(list23[index].loop_id_l,
3439fcf3ce44SJohn Forte 		    list23[index].loop_id_h);
3440fcf3ce44SJohn Forte 
3441fcf3ce44SJohn Forte 	} else {
3442fcf3ce44SJohn Forte 		struct ql_dev_id	*list22 = (struct ql_dev_id *)list;
3443fcf3ce44SJohn Forte 
3444fcf3ce44SJohn Forte 		d_id->b.al_pa = list22[index].al_pa;
3445fcf3ce44SJohn Forte 		d_id->b.area = list22[index].area;
3446fcf3ce44SJohn Forte 		d_id->b.domain = list22[index].domain;
3447fcf3ce44SJohn Forte 		*id = (uint16_t)list22[index].loop_id;
3448fcf3ce44SJohn Forte 	}
3449fcf3ce44SJohn Forte }
3450fcf3ce44SJohn Forte 
3451fcf3ce44SJohn Forte /*
3452fcf3ce44SJohn Forte  * ql_configure_fabric
3453fcf3ce44SJohn Forte  *	Setup fabric context.
3454fcf3ce44SJohn Forte  *
3455fcf3ce44SJohn Forte  * Input:
3456fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3457fcf3ce44SJohn Forte  *
3458fcf3ce44SJohn Forte  * Returns:
3459fcf3ce44SJohn Forte  *	ql local function return status code.
3460fcf3ce44SJohn Forte  *
3461fcf3ce44SJohn Forte  * Context:
3462fcf3ce44SJohn Forte  *	Kernel context.
3463fcf3ce44SJohn Forte  */
3464fcf3ce44SJohn Forte static int
3465fcf3ce44SJohn Forte ql_configure_fabric(ql_adapter_state_t *ha)
3466fcf3ce44SJohn Forte {
3467fcf3ce44SJohn Forte 	port_id_t	d_id;
3468fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3469fcf3ce44SJohn Forte 	int		rval = QL_FUNCTION_FAILED;
3470fcf3ce44SJohn Forte 
3471fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3472fcf3ce44SJohn Forte 
3473fcf3ce44SJohn Forte 	ha->topology = (uint8_t)(ha->topology & ~QL_SNS_CONNECTION);
3474fcf3ce44SJohn Forte 
3475fcf3ce44SJohn Forte 	/* Test switch fabric controller present. */
3476fcf3ce44SJohn Forte 	d_id.b24 = FS_FABRIC_F_PORT;
3477fcf3ce44SJohn Forte 	tq = ql_d_id_to_queue(ha, d_id);
3478fcf3ce44SJohn Forte 	if (tq != NULL) {
3479fcf3ce44SJohn Forte 		/* Get port/node names of F_Port. */
3480fcf3ce44SJohn Forte 		(void) ql_get_port_database(ha, tq, PDF_NONE);
3481fcf3ce44SJohn Forte 
3482fcf3ce44SJohn Forte 		d_id.b24 = FS_NAME_SERVER;
3483fcf3ce44SJohn Forte 		tq = ql_d_id_to_queue(ha, d_id);
3484fcf3ce44SJohn Forte 		if (tq != NULL) {
3485fcf3ce44SJohn Forte 			(void) ql_get_port_database(ha, tq, PDF_NONE);
3486fcf3ce44SJohn Forte 			ha->topology = (uint8_t)
3487fcf3ce44SJohn Forte 			    (ha->topology | QL_SNS_CONNECTION);
3488fcf3ce44SJohn Forte 			rval = QL_SUCCESS;
3489fcf3ce44SJohn Forte 		}
3490fcf3ce44SJohn Forte 	}
3491fcf3ce44SJohn Forte 
3492fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3493fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
3494fcf3ce44SJohn Forte 	} else {
3495fcf3ce44SJohn Forte 		/*EMPTY*/
3496fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3497fcf3ce44SJohn Forte 	}
3498fcf3ce44SJohn Forte 	return (rval);
3499fcf3ce44SJohn Forte }
3500fcf3ce44SJohn Forte 
3501fcf3ce44SJohn Forte /*
3502fcf3ce44SJohn Forte  * ql_reset_chip
3503fcf3ce44SJohn Forte  *	Reset ISP chip.
3504fcf3ce44SJohn Forte  *
3505fcf3ce44SJohn Forte  * Input:
3506fcf3ce44SJohn Forte  *	ha = adapter block pointer.
3507fcf3ce44SJohn Forte  *	All activity on chip must be already stopped.
3508fcf3ce44SJohn Forte  *	ADAPTER_STATE_LOCK must be released.
3509fcf3ce44SJohn Forte  *
3510fcf3ce44SJohn Forte  * Context:
3511fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3512fcf3ce44SJohn Forte  */
3513fcf3ce44SJohn Forte void
3514fcf3ce44SJohn Forte ql_reset_chip(ql_adapter_state_t *vha)
3515fcf3ce44SJohn Forte {
3516fcf3ce44SJohn Forte 	uint32_t		cnt;
3517fcf3ce44SJohn Forte 	uint16_t		cmd;
3518fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
3519fcf3ce44SJohn Forte 
3520fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3521fcf3ce44SJohn Forte 
3522fcf3ce44SJohn Forte 	/*
3523fcf3ce44SJohn Forte 	 * accessing pci space while not powered can cause panic's
3524fcf3ce44SJohn Forte 	 * on some platforms (i.e. Sunblade 1000's)
3525fcf3ce44SJohn Forte 	 */
3526fcf3ce44SJohn Forte 	if (ha->power_level == PM_LEVEL_D3) {
3527fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "(%d): Low Power exit\n", ha->instance);
3528fcf3ce44SJohn Forte 		return;
3529fcf3ce44SJohn Forte 	}
3530fcf3ce44SJohn Forte 
3531fcf3ce44SJohn Forte 	/* Reset all outbound mailbox registers */
3532fcf3ce44SJohn Forte 	for (cnt = 0; cnt < ha->reg_off->mbox_cnt; cnt++) {
3533eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0);
3534eb82ff87SDaniel Beauregard 	}
3535eb82ff87SDaniel Beauregard 
3536eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
3537*f885d00fSDaniel Beauregard 		ha->timeout_cnt = 0;
3538eb82ff87SDaniel Beauregard 		ql_8021_reset_chip(ha);
3539eb82ff87SDaniel Beauregard 		QL_PRINT_3(CE_CONT, "(%d): 8021 exit\n", ha->instance);
3540eb82ff87SDaniel Beauregard 		return;
3541fcf3ce44SJohn Forte 	}
3542fcf3ce44SJohn Forte 
3543fcf3ce44SJohn Forte 	/* Disable ISP interrupts. */
3544fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ictrl, 0);
3545fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
3546fcf3ce44SJohn Forte 	ha->flags &= ~INTERRUPTS_ENABLED;
3547fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
3548fcf3ce44SJohn Forte 
35495dfd244aSDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_242581)) {
3550fcf3ce44SJohn Forte 		RD32_IO_REG(ha, ictrl);
3551fcf3ce44SJohn Forte 		ql_reset_24xx_chip(ha);
3552fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): 24xx exit\n", ha->instance);
3553fcf3ce44SJohn Forte 		return;
3554fcf3ce44SJohn Forte 	}
3555fcf3ce44SJohn Forte 
3556fcf3ce44SJohn Forte 	/*
3557fcf3ce44SJohn Forte 	 * We are going to reset the chip in case of 2300. That might cause
3558fcf3ce44SJohn Forte 	 * a PBM ERR if a DMA transaction is in progress. One way of
3559fcf3ce44SJohn Forte 	 * avoiding it is to disable Bus Master operation before we start
3560fcf3ce44SJohn Forte 	 * the reset activity.
3561fcf3ce44SJohn Forte 	 */
3562fcf3ce44SJohn Forte 	cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
3563fcf3ce44SJohn Forte 	cmd = (uint16_t)(cmd & ~PCI_COMM_ME);
3564fcf3ce44SJohn Forte 	ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3565fcf3ce44SJohn Forte 
3566fcf3ce44SJohn Forte 	/* Pause RISC. */
3567fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
3568fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 30000; cnt++) {
3569fcf3ce44SJohn Forte 		if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
3570fcf3ce44SJohn Forte 			break;
3571fcf3ce44SJohn Forte 		}
3572fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3573fcf3ce44SJohn Forte 	}
3574fcf3ce44SJohn Forte 
3575fcf3ce44SJohn Forte 	/*
3576fcf3ce44SJohn Forte 	 * A call to ql_isr() can still happen through
3577fcf3ce44SJohn Forte 	 * ql_mailbox_command(). So Mark that we are/(will-be)
3578fcf3ce44SJohn Forte 	 * running from rom code now.
3579fcf3ce44SJohn Forte 	 */
3580fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
3581fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FIRMWARE_UP | FIRMWARE_LOADED);
3582fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
3583fcf3ce44SJohn Forte 
3584fcf3ce44SJohn Forte 	/* Select FPM registers. */
3585fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0x20);
3586fcf3ce44SJohn Forte 
3587fcf3ce44SJohn Forte 	/* FPM Soft Reset. */
3588fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, fpm_diag_config, 0x100);
3589fcf3ce44SJohn Forte 
3590fcf3ce44SJohn Forte 	/* Toggle FPM reset for 2300 */
3591fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
3592fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fpm_diag_config, 0);
3593fcf3ce44SJohn Forte 	}
3594fcf3ce44SJohn Forte 
3595fcf3ce44SJohn Forte 	/* Select frame buffer registers. */
3596fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0x10);
3597fcf3ce44SJohn Forte 
3598fcf3ce44SJohn Forte 	/* Reset frame buffer FIFOs. */
3599fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
3600fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fb_cmd, 0x00fc);
3601fcf3ce44SJohn Forte 		/* read back fb_cmd until zero or 3 seconds max */
3602fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 300000; cnt++) {
3603fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, fb_cmd) & 0xff) == 0) {
3604fcf3ce44SJohn Forte 				break;
3605fcf3ce44SJohn Forte 			}
3606fcf3ce44SJohn Forte 			drv_usecwait(10);
3607fcf3ce44SJohn Forte 		}
3608fcf3ce44SJohn Forte 	} else  {
3609fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fb_cmd, 0xa000);
3610fcf3ce44SJohn Forte 	}
3611fcf3ce44SJohn Forte 
3612fcf3ce44SJohn Forte 	/* Select RISC module registers. */
3613fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0);
3614fcf3ce44SJohn Forte 
3615fcf3ce44SJohn Forte 	/* Reset RISC module. */
3616fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
3617fcf3ce44SJohn Forte 
3618fcf3ce44SJohn Forte 	/* Reset ISP semaphore. */
3619fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, semaphore, 0);
3620fcf3ce44SJohn Forte 
3621fcf3ce44SJohn Forte 	/* Release RISC module. */
3622fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3623fcf3ce44SJohn Forte 
3624fcf3ce44SJohn Forte 	/* Insure mailbox registers are free. */
3625fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
3626fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_CLR_HOST_INT);
3627a2b3ff35SDaniel Beauregard 
3628a2b3ff35SDaniel Beauregard 	/* clear the mailbox command pointer. */
3629a2b3ff35SDaniel Beauregard 	ql_clear_mcp(ha);
3630a2b3ff35SDaniel Beauregard 
3631fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
3632fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
3633fcf3ce44SJohn Forte 
3634fcf3ce44SJohn Forte 	/* Bus Master is disabled so chip reset is safe. */
3635fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
3636fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, ISP_RESET);
3637fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3638fcf3ce44SJohn Forte 
3639fcf3ce44SJohn Forte 		/* Wait for reset to finish. */
3640fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 30000; cnt++) {
3641fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
3642fcf3ce44SJohn Forte 				break;
3643fcf3ce44SJohn Forte 			}
3644fcf3ce44SJohn Forte 			drv_usecwait(MILLISEC);
3645fcf3ce44SJohn Forte 		}
3646fcf3ce44SJohn Forte 	}
3647fcf3ce44SJohn Forte 
3648fcf3ce44SJohn Forte 	/* Wait for RISC to recover from reset. */
3649fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 30000; cnt++) {
3650eb82ff87SDaniel Beauregard 		if (RD16_IO_REG(ha, mailbox_out[0]) != MBS_BUSY) {
3651fcf3ce44SJohn Forte 			break;
3652fcf3ce44SJohn Forte 		}
3653fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3654fcf3ce44SJohn Forte 	}
3655fcf3ce44SJohn Forte 
3656fcf3ce44SJohn Forte 	/* restore bus master */
3657fcf3ce44SJohn Forte 	cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
3658fcf3ce44SJohn Forte 	cmd = (uint16_t)(cmd | PCI_COMM_ME);
3659fcf3ce44SJohn Forte 	ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3660fcf3ce44SJohn Forte 
3661fcf3ce44SJohn Forte 	/* Disable RISC pause on FPM parity error. */
3662fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_DISABLE_PARITY_PAUSE);
3663fcf3ce44SJohn Forte 
3664fcf3ce44SJohn Forte 	/* Initialize probe registers */
3665fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
3666fcf3ce44SJohn Forte 		/* Pause RISC. */
3667fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
3668fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 30000; cnt++) {
3669fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
3670fcf3ce44SJohn Forte 				break;
3671fcf3ce44SJohn Forte 			} else {
3672fcf3ce44SJohn Forte 				drv_usecwait(MILLISEC);
3673fcf3ce44SJohn Forte 			}
3674fcf3ce44SJohn Forte 		}
3675fcf3ce44SJohn Forte 
3676fcf3ce44SJohn Forte 		/* Select FPM registers. */
3677fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, 0x30);
3678fcf3ce44SJohn Forte 
3679fcf3ce44SJohn Forte 		/* Set probe register */
3680eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[23], 0x204c);
3681fcf3ce44SJohn Forte 
3682fcf3ce44SJohn Forte 		/* Select RISC module registers. */
3683fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, 0);
3684fcf3ce44SJohn Forte 
3685fcf3ce44SJohn Forte 		/* Release RISC module. */
3686fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3687fcf3ce44SJohn Forte 	}
3688fcf3ce44SJohn Forte 
3689fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3690fcf3ce44SJohn Forte }
3691fcf3ce44SJohn Forte 
3692fcf3ce44SJohn Forte /*
3693fcf3ce44SJohn Forte  * ql_reset_24xx_chip
3694fcf3ce44SJohn Forte  *	Reset ISP24xx chip.
3695fcf3ce44SJohn Forte  *
3696fcf3ce44SJohn Forte  * Input:
3697fcf3ce44SJohn Forte  *	ha = adapter block pointer.
3698fcf3ce44SJohn Forte  *	All activity on chip must be already stopped.
3699fcf3ce44SJohn Forte  *
3700fcf3ce44SJohn Forte  * Context:
3701fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3702fcf3ce44SJohn Forte  */
3703fcf3ce44SJohn Forte void
3704fcf3ce44SJohn Forte ql_reset_24xx_chip(ql_adapter_state_t *ha)
3705fcf3ce44SJohn Forte {
3706fcf3ce44SJohn Forte 	uint32_t	timer, stat;
3707fcf3ce44SJohn Forte 
3708fcf3ce44SJohn Forte 	/* Shutdown DMA. */
3709fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN | MWB_4096_BYTES);
3710fcf3ce44SJohn Forte 
3711fcf3ce44SJohn Forte 	/* Wait for DMA to stop. */
3712fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3713fcf3ce44SJohn Forte 		if ((RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE) == 0) {
3714fcf3ce44SJohn Forte 			break;
3715fcf3ce44SJohn Forte 		}
3716fcf3ce44SJohn Forte 		drv_usecwait(100);
3717fcf3ce44SJohn Forte 	}
3718fcf3ce44SJohn Forte 
3719fcf3ce44SJohn Forte 	/* Stop the firmware. */
3720fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3721eb82ff87SDaniel Beauregard 	WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
3722fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
3723fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3724eb82ff87SDaniel Beauregard 		stat = RD32_IO_REG(ha, risc2host);
3725fcf3ce44SJohn Forte 		if (stat & BIT_15) {
3726fcf3ce44SJohn Forte 			if ((stat & 0xff) < 0x12) {
3727fcf3ce44SJohn Forte 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3728fcf3ce44SJohn Forte 				break;
3729fcf3ce44SJohn Forte 			}
3730fcf3ce44SJohn Forte 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3731fcf3ce44SJohn Forte 		}
3732fcf3ce44SJohn Forte 		drv_usecwait(100);
3733fcf3ce44SJohn Forte 	}
3734fcf3ce44SJohn Forte 
3735fcf3ce44SJohn Forte 	/* Reset the chip. */
3736fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN |
3737fcf3ce44SJohn Forte 	    MWB_4096_BYTES);
3738fcf3ce44SJohn Forte 	drv_usecwait(100);
3739fcf3ce44SJohn Forte 
3740fcf3ce44SJohn Forte 	/* Wait for idle status from ROM firmware. */
3741fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3742eb82ff87SDaniel Beauregard 		if (RD16_IO_REG(ha, mailbox_out[0]) == 0) {
3743fcf3ce44SJohn Forte 			break;
3744fcf3ce44SJohn Forte 		}
3745fcf3ce44SJohn Forte 		drv_usecwait(100);
3746fcf3ce44SJohn Forte 	}
3747fcf3ce44SJohn Forte 
3748fcf3ce44SJohn Forte 	/* Wait for reset to finish. */
3749fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3750fcf3ce44SJohn Forte 		if ((RD32_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
3751fcf3ce44SJohn Forte 			break;
3752fcf3ce44SJohn Forte 		}
3753fcf3ce44SJohn Forte 		drv_usecwait(100);
3754fcf3ce44SJohn Forte 	}
3755fcf3ce44SJohn Forte 
3756a2b3ff35SDaniel Beauregard 	/* clear the mailbox command pointer. */
3757a2b3ff35SDaniel Beauregard 	ql_clear_mcp(ha);
3758a2b3ff35SDaniel Beauregard 
3759fcf3ce44SJohn Forte 	/* Insure mailbox registers are free. */
3760fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
3761fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
3762fcf3ce44SJohn Forte 
37634f8b8adcSDaniel Beauregard 	if (ha->flags & MPI_RESET_NEEDED) {
37644f8b8adcSDaniel Beauregard 		WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3765eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[0], MBC_RESTART_MPI);
37664f8b8adcSDaniel Beauregard 		WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
37674f8b8adcSDaniel Beauregard 		for (timer = 0; timer < 30000; timer++) {
3768eb82ff87SDaniel Beauregard 			stat = RD32_IO_REG(ha, risc2host);
37694f8b8adcSDaniel Beauregard 			if (stat & BIT_15) {
37704f8b8adcSDaniel Beauregard 				if ((stat & 0xff) < 0x12) {
37714f8b8adcSDaniel Beauregard 					WRT32_IO_REG(ha, hccr,
37724f8b8adcSDaniel Beauregard 					    HC24_CLR_RISC_INT);
37734f8b8adcSDaniel Beauregard 					break;
37744f8b8adcSDaniel Beauregard 				}
37754f8b8adcSDaniel Beauregard 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
37764f8b8adcSDaniel Beauregard 			}
37774f8b8adcSDaniel Beauregard 			drv_usecwait(100);
37784f8b8adcSDaniel Beauregard 		}
37794f8b8adcSDaniel Beauregard 		ADAPTER_STATE_LOCK(ha);
37804f8b8adcSDaniel Beauregard 		ha->flags &= ~MPI_RESET_NEEDED;
37814f8b8adcSDaniel Beauregard 		ADAPTER_STATE_UNLOCK(ha);
37824f8b8adcSDaniel Beauregard 	}
37834f8b8adcSDaniel Beauregard 
3784fcf3ce44SJohn Forte 	/*
3785fcf3ce44SJohn Forte 	 * Set flash write-protection.
3786fcf3ce44SJohn Forte 	 */
3787fcf3ce44SJohn Forte 	if ((ha->flags & ONLINE) == 0) {
3788fcf3ce44SJohn Forte 		ql_24xx_protect_flash(ha);
3789fcf3ce44SJohn Forte 	}
3790fcf3ce44SJohn Forte }
3791fcf3ce44SJohn Forte 
3792a2b3ff35SDaniel Beauregard /*
3793a2b3ff35SDaniel Beauregard  * ql_clear_mcp
3794a2b3ff35SDaniel Beauregard  *	Carefully clear the mailbox command pointer in the ha struct.
3795a2b3ff35SDaniel Beauregard  *
3796a2b3ff35SDaniel Beauregard  * Input:
3797a2b3ff35SDaniel Beauregard  *	ha = adapter block pointer.
3798a2b3ff35SDaniel Beauregard  *
3799a2b3ff35SDaniel Beauregard  * Context:
3800a2b3ff35SDaniel Beauregard  *	Interrupt or Kernel context, no mailbox commands allowed.
3801a2b3ff35SDaniel Beauregard  */
3802a2b3ff35SDaniel Beauregard 
3803a2b3ff35SDaniel Beauregard static void
3804a2b3ff35SDaniel Beauregard ql_clear_mcp(ql_adapter_state_t *ha)
3805a2b3ff35SDaniel Beauregard {
3806a2b3ff35SDaniel Beauregard 	uint32_t cnt;
3807a2b3ff35SDaniel Beauregard 
3808a2b3ff35SDaniel Beauregard 	/* Don't null ha->mcp without the lock, but don't hang either. */
3809a2b3ff35SDaniel Beauregard 	if (MBX_REGISTER_LOCK_OWNER(ha) == curthread) {
3810a2b3ff35SDaniel Beauregard 		ha->mcp = NULL;
3811a2b3ff35SDaniel Beauregard 	} else {
3812a2b3ff35SDaniel Beauregard 		for (cnt = 0; cnt < 300000; cnt++) {
3813a2b3ff35SDaniel Beauregard 			if (TRY_MBX_REGISTER_LOCK(ha) != 0) {
3814a2b3ff35SDaniel Beauregard 				ha->mcp = NULL;
3815a2b3ff35SDaniel Beauregard 				MBX_REGISTER_UNLOCK(ha);
3816a2b3ff35SDaniel Beauregard 				break;
3817a2b3ff35SDaniel Beauregard 			} else {
3818a2b3ff35SDaniel Beauregard 				drv_usecwait(10);
3819a2b3ff35SDaniel Beauregard 			}
3820a2b3ff35SDaniel Beauregard 		}
3821a2b3ff35SDaniel Beauregard 	}
3822a2b3ff35SDaniel Beauregard }
3823a2b3ff35SDaniel Beauregard 
3824a2b3ff35SDaniel Beauregard 
3825fcf3ce44SJohn Forte /*
3826fcf3ce44SJohn Forte  * ql_abort_isp
3827fcf3ce44SJohn Forte  *	Resets ISP and aborts all outstanding commands.
3828fcf3ce44SJohn Forte  *
3829fcf3ce44SJohn Forte  * Input:
3830fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3831fcf3ce44SJohn Forte  *	DEVICE_QUEUE_LOCK must be released.
3832fcf3ce44SJohn Forte  *
3833fcf3ce44SJohn Forte  * Returns:
3834fcf3ce44SJohn Forte  *	ql local function return status code.
3835fcf3ce44SJohn Forte  *
3836fcf3ce44SJohn Forte  * Context:
3837fcf3ce44SJohn Forte  *	Kernel context.
3838fcf3ce44SJohn Forte  */
3839fcf3ce44SJohn Forte int
3840fcf3ce44SJohn Forte ql_abort_isp(ql_adapter_state_t *vha)
3841fcf3ce44SJohn Forte {
3842fcf3ce44SJohn Forte 	ql_link_t		*link, *link2;
3843fcf3ce44SJohn Forte 	ddi_devstate_t		state;
3844fcf3ce44SJohn Forte 	uint16_t		index;
3845fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
3846fcf3ce44SJohn Forte 	ql_lun_t		*lq;
3847fcf3ce44SJohn Forte 	ql_srb_t		*sp;
3848fcf3ce44SJohn Forte 	int			rval = QL_SUCCESS;
3849fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
3850fcf3ce44SJohn Forte 
3851fcf3ce44SJohn Forte 	QL_PRINT_2(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3852fcf3ce44SJohn Forte 
3853fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
3854fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
3855fcf3ce44SJohn Forte 	if (ha->task_daemon_flags & ABORT_ISP_ACTIVE ||
3856fcf3ce44SJohn Forte 	    (ha->flags & ONLINE) == 0 || ha->flags & ADAPTER_SUSPENDED) {
3857fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
3858fcf3ce44SJohn Forte 		return (rval);
3859fcf3ce44SJohn Forte 	}
3860fcf3ce44SJohn Forte 
3861fcf3ce44SJohn Forte 	ha->task_daemon_flags |= ABORT_ISP_ACTIVE;
3862fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(RESET_MARKER_NEEDED | FIRMWARE_UP |
3863fcf3ce44SJohn Forte 	    FIRMWARE_LOADED);
3864fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
3865fcf3ce44SJohn Forte 		vha->task_daemon_flags |= LOOP_DOWN;
3866fcf3ce44SJohn Forte 		vha->task_daemon_flags &= ~(COMMAND_WAIT_NEEDED |
3867fcf3ce44SJohn Forte 		    LOOP_RESYNC_NEEDED);
3868fcf3ce44SJohn Forte 	}
3869fcf3ce44SJohn Forte 
3870fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
3871fcf3ce44SJohn Forte 
3872fcf3ce44SJohn Forte 	if (ha->mailbox_flags & MBX_BUSY_FLG) {
3873fcf3ce44SJohn Forte 		/* Acquire mailbox register lock. */
3874fcf3ce44SJohn Forte 		MBX_REGISTER_LOCK(ha);
3875fcf3ce44SJohn Forte 
3876fcf3ce44SJohn Forte 		/* Wake up mailbox box routine. */
3877fcf3ce44SJohn Forte 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_ABORT);
3878fcf3ce44SJohn Forte 		cv_broadcast(&ha->cv_mbx_intr);
3879fcf3ce44SJohn Forte 
3880fcf3ce44SJohn Forte 		/* Release mailbox register lock. */
3881fcf3ce44SJohn Forte 		MBX_REGISTER_UNLOCK(ha);
3882fcf3ce44SJohn Forte 
3883fcf3ce44SJohn Forte 		/* Wait for mailbox. */
3884fcf3ce44SJohn Forte 		for (index = 100; index &&
3885fcf3ce44SJohn Forte 		    ha->mailbox_flags & MBX_ABORT; index--) {
3886fcf3ce44SJohn Forte 			drv_usecwait(50000);
3887fcf3ce44SJohn Forte 		}
3888fcf3ce44SJohn Forte 	}
3889fcf3ce44SJohn Forte 
3890fcf3ce44SJohn Forte 	/* Wait for commands to end gracefully if not in panic. */
3891fcf3ce44SJohn Forte 	if (ha->flags & PARITY_ERROR) {
3892fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3893fcf3ce44SJohn Forte 		ha->flags &= ~PARITY_ERROR;
3894fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3895fcf3ce44SJohn Forte 	} else if (ddi_in_panic() == 0) {
3896fcf3ce44SJohn Forte 		ql_cmd_wait(ha);
3897fcf3ce44SJohn Forte 	}
3898fcf3ce44SJohn Forte 
3899fcf3ce44SJohn Forte 	/* Shutdown IP. */
3900fcf3ce44SJohn Forte 	if (ha->flags & IP_INITIALIZED) {
3901fcf3ce44SJohn Forte 		(void) ql_shutdown_ip(ha);
3902fcf3ce44SJohn Forte 	}
3903fcf3ce44SJohn Forte 
3904fcf3ce44SJohn Forte 	/* Reset the chip. */
3905fcf3ce44SJohn Forte 	ql_reset_chip(ha);
3906fcf3ce44SJohn Forte 
3907a2b3ff35SDaniel Beauregard 	/*
3908a2b3ff35SDaniel Beauregard 	 * Even though we have waited for outstanding commands to complete,
3909a2b3ff35SDaniel Beauregard 	 * except for ones marked SRB_COMMAND_TIMEOUT, and reset the ISP,
3910a2b3ff35SDaniel Beauregard 	 * there could still be an interrupt thread active.  The interrupt
3911a2b3ff35SDaniel Beauregard 	 * lock will prevent us from getting an sp from the outstanding
3912a2b3ff35SDaniel Beauregard 	 * cmds array that the ISR may be using.
3913a2b3ff35SDaniel Beauregard 	 */
3914a2b3ff35SDaniel Beauregard 
3915fcf3ce44SJohn Forte 	/* Place all commands in outstanding cmd list on device queue. */
3916fcf3ce44SJohn Forte 	for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
3917fcf3ce44SJohn Forte 		REQUEST_RING_LOCK(ha);
3918a2b3ff35SDaniel Beauregard 		INTR_LOCK(ha);
3919fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) != NULL) {
3920fcf3ce44SJohn Forte 			sp = link->base_address;
3921fcf3ce44SJohn Forte 			ql_remove_link(&ha->pending_cmds, &sp->cmd);
3922fcf3ce44SJohn Forte 
3923fcf3ce44SJohn Forte 			REQUEST_RING_UNLOCK(ha);
3924fcf3ce44SJohn Forte 			index = 0;
3925fcf3ce44SJohn Forte 		} else {
3926fcf3ce44SJohn Forte 			REQUEST_RING_UNLOCK(ha);
3927fcf3ce44SJohn Forte 			if ((sp = ha->outstanding_cmds[index]) == NULL) {
3928a2b3ff35SDaniel Beauregard 				INTR_UNLOCK(ha);
3929fcf3ce44SJohn Forte 				continue;
3930fcf3ce44SJohn Forte 			}
3931fcf3ce44SJohn Forte 		}
3932fcf3ce44SJohn Forte 
3933a2b3ff35SDaniel Beauregard 		/*
3934a2b3ff35SDaniel Beauregard 		 * It's not obvious but the index for commands pulled from
3935a2b3ff35SDaniel Beauregard 		 * pending will be zero and that entry in the outstanding array
3936a2b3ff35SDaniel Beauregard 		 * is not used so nulling it is "no harm, no foul".
3937a2b3ff35SDaniel Beauregard 		 */
3938a2b3ff35SDaniel Beauregard 
3939a2b3ff35SDaniel Beauregard 		ha->outstanding_cmds[index] = NULL;
3940a2b3ff35SDaniel Beauregard 		sp->handle = 0;
3941a2b3ff35SDaniel Beauregard 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
3942a2b3ff35SDaniel Beauregard 
3943a2b3ff35SDaniel Beauregard 		INTR_UNLOCK(ha);
3944a2b3ff35SDaniel Beauregard 
3945fcf3ce44SJohn Forte 		/* If command timeout. */
3946fcf3ce44SJohn Forte 		if (sp->flags & SRB_COMMAND_TIMEOUT) {
3947fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_TIMEOUT;
3948fcf3ce44SJohn Forte 			sp->flags &= ~SRB_RETRY;
3949fcf3ce44SJohn Forte 			sp->flags |= SRB_ISP_COMPLETED;
3950fcf3ce44SJohn Forte 
3951fcf3ce44SJohn Forte 			/* Call done routine to handle completion. */
3952fcf3ce44SJohn Forte 			ql_done(&sp->cmd);
3953fcf3ce44SJohn Forte 			continue;
3954fcf3ce44SJohn Forte 		}
3955fcf3ce44SJohn Forte 
3956fcf3ce44SJohn Forte 		/* Acquire target queue lock. */
3957fcf3ce44SJohn Forte 		lq = sp->lun_queue;
3958fcf3ce44SJohn Forte 		tq = lq->target_queue;
3959fcf3ce44SJohn Forte 		DEVICE_QUEUE_LOCK(tq);
3960fcf3ce44SJohn Forte 
3961fcf3ce44SJohn Forte 		/* Reset watchdog time. */
3962fcf3ce44SJohn Forte 		sp->wdg_q_time = sp->init_wdg_q_time;
3963fcf3ce44SJohn Forte 
3964fcf3ce44SJohn Forte 		/* Place request back on top of device queue. */
3965fcf3ce44SJohn Forte 		sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED |
3966fcf3ce44SJohn Forte 		    SRB_RETRY);
3967fcf3ce44SJohn Forte 
3968fcf3ce44SJohn Forte 		ql_add_link_t(&lq->cmd, &sp->cmd);
3969fcf3ce44SJohn Forte 		sp->flags |= SRB_IN_DEVICE_QUEUE;
3970fcf3ce44SJohn Forte 
3971fcf3ce44SJohn Forte 		/* Release target queue lock. */
3972fcf3ce44SJohn Forte 		DEVICE_QUEUE_UNLOCK(tq);
3973fcf3ce44SJohn Forte 	}
3974fcf3ce44SJohn Forte 
3975fcf3ce44SJohn Forte 	/*
3976fcf3ce44SJohn Forte 	 * Clear per LUN active count, because there should not be
3977fcf3ce44SJohn Forte 	 * any IO outstanding at this time.
3978fcf3ce44SJohn Forte 	 */
3979fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
3980fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3981fcf3ce44SJohn Forte 			link = vha->dev[index].first;
3982fcf3ce44SJohn Forte 			while (link != NULL) {
3983fcf3ce44SJohn Forte 				tq = link->base_address;
3984fcf3ce44SJohn Forte 				link = link->next;
3985fcf3ce44SJohn Forte 				DEVICE_QUEUE_LOCK(tq);
3986fcf3ce44SJohn Forte 				tq->outcnt = 0;
3987fcf3ce44SJohn Forte 				tq->flags &= ~TQF_QUEUE_SUSPENDED;
3988fcf3ce44SJohn Forte 				for (link2 = tq->lun_queues.first;
3989fcf3ce44SJohn Forte 				    link2 != NULL; link2 = link2->next) {
3990fcf3ce44SJohn Forte 					lq = link2->base_address;
3991fcf3ce44SJohn Forte 					lq->lun_outcnt = 0;
3992fcf3ce44SJohn Forte 					lq->flags &= ~LQF_UNTAGGED_PENDING;
3993fcf3ce44SJohn Forte 				}
3994fcf3ce44SJohn Forte 				DEVICE_QUEUE_UNLOCK(tq);
3995fcf3ce44SJohn Forte 			}
3996fcf3ce44SJohn Forte 		}
3997fcf3ce44SJohn Forte 	}
3998fcf3ce44SJohn Forte 
3999eb82ff87SDaniel Beauregard 	if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) {
4000eb82ff87SDaniel Beauregard 		if ((rval = ql_chip_diag(ha)) == QL_SUCCESS) {
4001eb82ff87SDaniel Beauregard 			rval = ql_load_isp_firmware(ha);
4002eb82ff87SDaniel Beauregard 		}
4003fcf3ce44SJohn Forte 	}
4004fcf3ce44SJohn Forte 
4005fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
4006fcf3ce44SJohn Forte 	    QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS &&
4007fcf3ce44SJohn Forte 	    (rval = ql_fw_ready(ha, 10)) == QL_SUCCESS) {
4008fcf3ce44SJohn Forte 
4009fcf3ce44SJohn Forte 		/* If reset abort needed that may have been set. */
4010fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
4011fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED |
4012fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE);
4013fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
4014fcf3ce44SJohn Forte 
4015fcf3ce44SJohn Forte 		/* Enable ISP interrupts. */
4016eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_8021)) {
4017eb82ff87SDaniel Beauregard 			ql_8021_enable_intrs(ha);
4018eb82ff87SDaniel Beauregard 		} else if (CFG_IST(ha, CFG_CTRL_242581)) {
4019eb82ff87SDaniel Beauregard 			WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
4020eb82ff87SDaniel Beauregard 		} else {
4021eb82ff87SDaniel Beauregard 			WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
4022eb82ff87SDaniel Beauregard 		}
4023fcf3ce44SJohn Forte 
4024fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
4025fcf3ce44SJohn Forte 		ha->flags |= INTERRUPTS_ENABLED;
4026fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
4027fcf3ce44SJohn Forte 
4028fcf3ce44SJohn Forte 		/* Set loop online, if it really is. */
4029fcf3ce44SJohn Forte 		ql_loop_online(ha);
4030fcf3ce44SJohn Forte 
4031fcf3ce44SJohn Forte 		state = ddi_get_devstate(ha->dip);
4032fcf3ce44SJohn Forte 		if (state != DDI_DEVSTATE_UP) {
4033fcf3ce44SJohn Forte 			/*EMPTY*/
4034fcf3ce44SJohn Forte 			ddi_dev_report_fault(ha->dip, DDI_SERVICE_RESTORED,
4035fcf3ce44SJohn Forte 			    DDI_DEVICE_FAULT, "Device reset succeeded");
4036fcf3ce44SJohn Forte 		}
4037fcf3ce44SJohn Forte 	} else {
4038fcf3ce44SJohn Forte 		/* Enable ISP interrupts. */
4039eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_8021)) {
4040eb82ff87SDaniel Beauregard 			ql_8021_enable_intrs(ha);
4041eb82ff87SDaniel Beauregard 		} else if (CFG_IST(ha, CFG_CTRL_242581)) {
4042eb82ff87SDaniel Beauregard 			WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
4043eb82ff87SDaniel Beauregard 		} else {
4044eb82ff87SDaniel Beauregard 			WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
4045eb82ff87SDaniel Beauregard 		}
4046fcf3ce44SJohn Forte 
4047fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
4048fcf3ce44SJohn Forte 		ha->flags |= INTERRUPTS_ENABLED;
4049fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
4050fcf3ce44SJohn Forte 
4051fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
4052fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE);
4053fcf3ce44SJohn Forte 		ha->task_daemon_flags |= LOOP_DOWN;
4054fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
4055fcf3ce44SJohn Forte 
4056fcf3ce44SJohn Forte 		ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
4057fcf3ce44SJohn Forte 	}
4058fcf3ce44SJohn Forte 
4059fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
4060fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
4061fcf3ce44SJohn Forte 	} else {
4062fcf3ce44SJohn Forte 		/*EMPTY*/
4063fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "(%d): done\n", ha->instance);
4064fcf3ce44SJohn Forte 	}
4065fcf3ce44SJohn Forte 	return (rval);
4066fcf3ce44SJohn Forte }
4067fcf3ce44SJohn Forte 
4068fcf3ce44SJohn Forte /*
4069fcf3ce44SJohn Forte  * ql_vport_control
4070fcf3ce44SJohn Forte  *	Issue Virtual Port Control command.
4071fcf3ce44SJohn Forte  *
4072fcf3ce44SJohn Forte  * Input:
4073fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4074fcf3ce44SJohn Forte  *	cmd = control command.
4075fcf3ce44SJohn Forte  *
4076fcf3ce44SJohn Forte  * Returns:
4077fcf3ce44SJohn Forte  *	ql local function return status code.
4078fcf3ce44SJohn Forte  *
4079fcf3ce44SJohn Forte  * Context:
4080fcf3ce44SJohn Forte  *	Kernel context.
4081fcf3ce44SJohn Forte  */
4082fcf3ce44SJohn Forte int
4083fcf3ce44SJohn Forte ql_vport_control(ql_adapter_state_t *ha, uint8_t cmd)
4084fcf3ce44SJohn Forte {
4085fcf3ce44SJohn Forte 	ql_mbx_iocb_t	*pkt;
4086fcf3ce44SJohn Forte 	uint8_t		bit;
4087fcf3ce44SJohn Forte 	int		rval;
4088fcf3ce44SJohn Forte 	uint32_t	pkt_size;
4089fcf3ce44SJohn Forte 
4090fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
4091fcf3ce44SJohn Forte 
4092fcf3ce44SJohn Forte 	if (ha->vp_index != 0) {
4093fcf3ce44SJohn Forte 		pkt_size = sizeof (ql_mbx_iocb_t);
4094fcf3ce44SJohn Forte 		pkt = kmem_zalloc(pkt_size, KM_SLEEP);
4095fcf3ce44SJohn Forte 		if (pkt == NULL) {
4096fcf3ce44SJohn Forte 			EL(ha, "failed, kmem_zalloc\n");
4097fcf3ce44SJohn Forte 			return (QL_MEMORY_ALLOC_FAILED);
4098fcf3ce44SJohn Forte 		}
4099fcf3ce44SJohn Forte 
4100fcf3ce44SJohn Forte 		pkt->vpc.entry_type = VP_CONTROL_TYPE;
4101fcf3ce44SJohn Forte 		pkt->vpc.entry_count = 1;
4102fcf3ce44SJohn Forte 		pkt->vpc.command = cmd;
4103fcf3ce44SJohn Forte 		pkt->vpc.vp_count = 1;
4104fcf3ce44SJohn Forte 		bit = (uint8_t)(ha->vp_index - 1);
4105fcf3ce44SJohn Forte 		pkt->vpc.vp_index[bit / 8] = (uint8_t)
4106fcf3ce44SJohn Forte 		    (pkt->vpc.vp_index[bit / 8] | BIT_0 << bit % 8);
4107fcf3ce44SJohn Forte 
4108fcf3ce44SJohn Forte 		rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
4109fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && pkt->vpc.status != 0) {
4110fcf3ce44SJohn Forte 			rval = QL_COMMAND_ERROR;
4111fcf3ce44SJohn Forte 		}
4112fcf3ce44SJohn Forte 
4113fcf3ce44SJohn Forte 		kmem_free(pkt, pkt_size);
4114fcf3ce44SJohn Forte 	} else {
4115fcf3ce44SJohn Forte 		rval = QL_SUCCESS;
4116fcf3ce44SJohn Forte 	}
4117fcf3ce44SJohn Forte 
4118fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
4119fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
4120fcf3ce44SJohn Forte 	} else {
4121fcf3ce44SJohn Forte 		/*EMPTY*/
4122fcf3ce44SJohn Forte 		QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
4123fcf3ce44SJohn Forte 		    ha->vp_index);
4124fcf3ce44SJohn Forte 	}
4125fcf3ce44SJohn Forte 	return (rval);
4126fcf3ce44SJohn Forte }
4127fcf3ce44SJohn Forte 
4128fcf3ce44SJohn Forte /*
4129fcf3ce44SJohn Forte  * ql_vport_modify
4130fcf3ce44SJohn Forte  *	Issue of Modify Virtual Port command.
4131fcf3ce44SJohn Forte  *
4132fcf3ce44SJohn Forte  * Input:
4133fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4134fcf3ce44SJohn Forte  *	cmd = command.
4135fcf3ce44SJohn Forte  *	opt = option.
4136fcf3ce44SJohn Forte  *
4137fcf3ce44SJohn Forte  * Context:
4138fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
4139fcf3ce44SJohn Forte  */
4140fcf3ce44SJohn Forte int
4141fcf3ce44SJohn Forte ql_vport_modify(ql_adapter_state_t *ha, uint8_t cmd, uint8_t opt)
4142fcf3ce44SJohn Forte {
4143fcf3ce44SJohn Forte 	ql_mbx_iocb_t	*pkt;
4144fcf3ce44SJohn Forte 	int		rval;
4145fcf3ce44SJohn Forte 	uint32_t	pkt_size;
4146fcf3ce44SJohn Forte 
4147fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
4148fcf3ce44SJohn Forte 
4149fcf3ce44SJohn Forte 	pkt_size = sizeof (ql_mbx_iocb_t);
4150fcf3ce44SJohn Forte 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
4151fcf3ce44SJohn Forte 	if (pkt == NULL) {
4152fcf3ce44SJohn Forte 		EL(ha, "failed, kmem_zalloc\n");
4153fcf3ce44SJohn Forte 		return (QL_MEMORY_ALLOC_FAILED);
4154fcf3ce44SJohn Forte 	}
4155fcf3ce44SJohn Forte 
4156fcf3ce44SJohn Forte 	pkt->vpm.entry_type = VP_MODIFY_TYPE;
4157fcf3ce44SJohn Forte 	pkt->vpm.entry_count = 1;
4158fcf3ce44SJohn Forte 	pkt->vpm.command = cmd;
4159fcf3ce44SJohn Forte 	pkt->vpm.vp_count = 1;
4160fcf3ce44SJohn Forte 	pkt->vpm.first_vp_index = ha->vp_index;
4161fcf3ce44SJohn Forte 	pkt->vpm.first_options = opt;
4162fcf3ce44SJohn Forte 	bcopy(ha->loginparams.nport_ww_name.raw_wwn, pkt->vpm.first_port_name,
4163fcf3ce44SJohn Forte 	    8);
4164fcf3ce44SJohn Forte 	bcopy(ha->loginparams.node_ww_name.raw_wwn, pkt->vpm.first_node_name,
4165fcf3ce44SJohn Forte 	    8);
4166fcf3ce44SJohn Forte 
4167fcf3ce44SJohn Forte 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
4168fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && pkt->vpm.status != 0) {
4169fcf3ce44SJohn Forte 		EL(ha, "failed, ql_issue_mbx_iocb=%xh, status=%xh\n", rval,
4170fcf3ce44SJohn Forte 		    pkt->vpm.status);
4171fcf3ce44SJohn Forte 		rval = QL_COMMAND_ERROR;
4172fcf3ce44SJohn Forte 	}
4173fcf3ce44SJohn Forte 
4174fcf3ce44SJohn Forte 	kmem_free(pkt, pkt_size);
4175fcf3ce44SJohn Forte 
4176fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
4177fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
4178fcf3ce44SJohn Forte 	} else {
4179fcf3ce44SJohn Forte 		/*EMPTY*/
4180fcf3ce44SJohn Forte 		QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
4181fcf3ce44SJohn Forte 		    ha->vp_index);
4182fcf3ce44SJohn Forte 	}
4183fcf3ce44SJohn Forte 	return (rval);
4184fcf3ce44SJohn Forte }
4185fcf3ce44SJohn Forte 
4186fcf3ce44SJohn Forte /*
4187fcf3ce44SJohn Forte  * ql_vport_enable
4188fcf3ce44SJohn Forte  *	Enable virtual port.
4189fcf3ce44SJohn Forte  *
4190fcf3ce44SJohn Forte  * Input:
4191fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4192fcf3ce44SJohn Forte  *
4193fcf3ce44SJohn Forte  * Context:
4194fcf3ce44SJohn Forte  *	Kernel context.
4195fcf3ce44SJohn Forte  */
4196fcf3ce44SJohn Forte int
4197fcf3ce44SJohn Forte ql_vport_enable(ql_adapter_state_t *ha)
4198fcf3ce44SJohn Forte {
4199fcf3ce44SJohn Forte 	int	timer;
4200fcf3ce44SJohn Forte 
4201fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
4202fcf3ce44SJohn Forte 
4203fcf3ce44SJohn Forte 	ha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
4204fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
4205fcf3ce44SJohn Forte 	ha->task_daemon_flags |= LOOP_DOWN;
4206fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FC_STATE_CHANGE | STATE_ONLINE);
4207fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
4208fcf3ce44SJohn Forte 
4209fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
4210fcf3ce44SJohn Forte 	ha->flags |= VP_ENABLED;
4211fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
4212fcf3ce44SJohn Forte 
4213fcf3ce44SJohn Forte 	if (ql_vport_modify(ha, VPM_MODIFY_ENABLE, VPO_TARGET_MODE_DISABLED |
4214fcf3ce44SJohn Forte 	    VPO_INITIATOR_MODE_ENABLED | VPO_ENABLED) != QL_SUCCESS) {
4215fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "(%d): failed to enable virtual port=%d\n",
4216fcf3ce44SJohn Forte 		    ha->instance, ha->vp_index);
4217fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
4218fcf3ce44SJohn Forte 	}
4219fcf3ce44SJohn Forte 	if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) {
4220fcf3ce44SJohn Forte 		/* Wait for loop to come up. */
4221fcf3ce44SJohn Forte 		for (timer = 0; timer < 3000 &&
4222fcf3ce44SJohn Forte 		    !(ha->task_daemon_flags & STATE_ONLINE);
4223fcf3ce44SJohn Forte 		    timer++) {
4224fcf3ce44SJohn Forte 			delay(1);
4225fcf3ce44SJohn Forte 		}
4226fcf3ce44SJohn Forte 	}
4227fcf3ce44SJohn Forte 
4228fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
4229fcf3ce44SJohn Forte 
4230fcf3ce44SJohn Forte 	return (QL_SUCCESS);
4231fcf3ce44SJohn Forte }
4232fcf3ce44SJohn Forte 
4233fcf3ce44SJohn Forte /*
4234fcf3ce44SJohn Forte  * ql_vport_create
4235fcf3ce44SJohn Forte  *	Create virtual port context.
4236fcf3ce44SJohn Forte  *
4237fcf3ce44SJohn Forte  * Input:
4238fcf3ce44SJohn Forte  *	ha:	parent adapter state pointer.
4239fcf3ce44SJohn Forte  *	index:	virtual port index number.
4240fcf3ce44SJohn Forte  *
4241fcf3ce44SJohn Forte  * Context:
4242fcf3ce44SJohn Forte  *	Kernel context.
4243fcf3ce44SJohn Forte  */
4244fcf3ce44SJohn Forte ql_adapter_state_t *
4245fcf3ce44SJohn Forte ql_vport_create(ql_adapter_state_t *ha, uint8_t index)
4246fcf3ce44SJohn Forte {
4247fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
4248fcf3ce44SJohn Forte 
4249fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
4250fcf3ce44SJohn Forte 
4251fcf3ce44SJohn Forte 	/* Inherit the parents data. */
4252fcf3ce44SJohn Forte 	vha = kmem_alloc(sizeof (ql_adapter_state_t), KM_SLEEP);
4253fcf3ce44SJohn Forte 
4254fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
4255fcf3ce44SJohn Forte 	bcopy(ha, vha, sizeof (ql_adapter_state_t));
4256fcf3ce44SJohn Forte 	vha->pi_attrs = NULL;
4257fcf3ce44SJohn Forte 	vha->ub_outcnt = 0;
4258fcf3ce44SJohn Forte 	vha->ub_allocated = 0;
4259fcf3ce44SJohn Forte 	vha->flags = 0;
4260fcf3ce44SJohn Forte 	vha->task_daemon_flags = 0;
4261fcf3ce44SJohn Forte 	ha->vp_next = vha;
4262fcf3ce44SJohn Forte 	vha->pha = ha;
4263fcf3ce44SJohn Forte 	vha->vp_index = index;
4264fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
4265fcf3ce44SJohn Forte 
4266fcf3ce44SJohn Forte 	vha->hba.next = NULL;
4267fcf3ce44SJohn Forte 	vha->hba.prev = NULL;
4268fcf3ce44SJohn Forte 	vha->hba.base_address = vha;
4269fcf3ce44SJohn Forte 	vha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
4270fcf3ce44SJohn Forte 	vha->dev = kmem_zalloc(sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE,
4271fcf3ce44SJohn Forte 	    KM_SLEEP);
4272fcf3ce44SJohn Forte 	vha->ub_array = kmem_zalloc(sizeof (*vha->ub_array) * QL_UB_LIMIT,
4273fcf3ce44SJohn Forte 	    KM_SLEEP);
4274fcf3ce44SJohn Forte 
4275fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
4276fcf3ce44SJohn Forte 
4277fcf3ce44SJohn Forte 	return (vha);
4278fcf3ce44SJohn Forte }
4279fcf3ce44SJohn Forte 
4280fcf3ce44SJohn Forte /*
4281fcf3ce44SJohn Forte  * ql_vport_destroy
4282fcf3ce44SJohn Forte  *	Destroys virtual port context.
4283fcf3ce44SJohn Forte  *
4284fcf3ce44SJohn Forte  * Input:
4285fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
4286fcf3ce44SJohn Forte  *
4287fcf3ce44SJohn Forte  * Context:
4288fcf3ce44SJohn Forte  *	Kernel context.
4289fcf3ce44SJohn Forte  */
4290fcf3ce44SJohn Forte void
4291fcf3ce44SJohn Forte ql_vport_destroy(ql_adapter_state_t *ha)
4292fcf3ce44SJohn Forte {
4293fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
4294fcf3ce44SJohn Forte 
4295fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
4296fcf3ce44SJohn Forte 
4297fcf3ce44SJohn Forte 	/* Remove port from list. */
4298fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
4299fcf3ce44SJohn Forte 	for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
4300fcf3ce44SJohn Forte 		if (vha->vp_next == ha) {
4301fcf3ce44SJohn Forte 			vha->vp_next = ha->vp_next;
4302fcf3ce44SJohn Forte 			break;
4303fcf3ce44SJohn Forte 		}
4304fcf3ce44SJohn Forte 	}
4305fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
4306fcf3ce44SJohn Forte 
4307fcf3ce44SJohn Forte 	if (ha->ub_array != NULL) {
4308fcf3ce44SJohn Forte 		kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
4309fcf3ce44SJohn Forte 	}
4310fcf3ce44SJohn Forte 	if (ha->dev != NULL) {
4311fcf3ce44SJohn Forte 		kmem_free(ha->dev, sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE);
4312fcf3ce44SJohn Forte 	}
4313fcf3ce44SJohn Forte 	kmem_free(ha, sizeof (ql_adapter_state_t));
4314fcf3ce44SJohn Forte 
4315fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
4316fcf3ce44SJohn Forte }
4317f33c1cdbSDaniel Beauregard 
4318f33c1cdbSDaniel Beauregard /*
4319f33c1cdbSDaniel Beauregard  * ql_mps_reset
4320f33c1cdbSDaniel Beauregard  *	Reset MPS for FCoE functions.
4321f33c1cdbSDaniel Beauregard  *
4322f33c1cdbSDaniel Beauregard  * Input:
4323f33c1cdbSDaniel Beauregard  *	ha = virtual adapter state pointer.
4324f33c1cdbSDaniel Beauregard  *
4325f33c1cdbSDaniel Beauregard  * Context:
4326f33c1cdbSDaniel Beauregard  *	Kernel context.
4327f33c1cdbSDaniel Beauregard  */
4328f33c1cdbSDaniel Beauregard static void
4329f33c1cdbSDaniel Beauregard ql_mps_reset(ql_adapter_state_t *ha)
4330f33c1cdbSDaniel Beauregard {
4331f33c1cdbSDaniel Beauregard 	uint32_t	data, dctl = 1000;
4332f33c1cdbSDaniel Beauregard 
4333f33c1cdbSDaniel Beauregard 	do {
4334f33c1cdbSDaniel Beauregard 		if (dctl-- == 0 || ql_wrt_risc_ram_word(ha, 0x7c00, 1) !=
4335f33c1cdbSDaniel Beauregard 		    QL_SUCCESS) {
4336f33c1cdbSDaniel Beauregard 			return;
4337f33c1cdbSDaniel Beauregard 		}
4338f33c1cdbSDaniel Beauregard 		if (ql_rd_risc_ram_word(ha, 0x7c00, &data) != QL_SUCCESS) {
4339c1374a13SSurya Prakki 			(void) ql_wrt_risc_ram_word(ha, 0x7c00, 0);
4340f33c1cdbSDaniel Beauregard 			return;
4341f33c1cdbSDaniel Beauregard 		}
4342f33c1cdbSDaniel Beauregard 	} while (!(data & BIT_0));
4343f33c1cdbSDaniel Beauregard 
4344f33c1cdbSDaniel Beauregard 	if (ql_rd_risc_ram_word(ha, 0x7A15, &data) == QL_SUCCESS) {
4345f33c1cdbSDaniel Beauregard 		dctl = (uint16_t)ql_pci_config_get16(ha, 0x54);
4346f33c1cdbSDaniel Beauregard 		if ((data & 0xe0) != (dctl & 0xe0)) {
4347f33c1cdbSDaniel Beauregard 			data &= 0xff1f;
4348f33c1cdbSDaniel Beauregard 			data |= dctl & 0xe0;
4349c1374a13SSurya Prakki 			(void) ql_wrt_risc_ram_word(ha, 0x7A15, data);
4350f33c1cdbSDaniel Beauregard 		}
4351f33c1cdbSDaniel Beauregard 	}
4352c1374a13SSurya Prakki 	(void) ql_wrt_risc_ram_word(ha, 0x7c00, 0);
4353f33c1cdbSDaniel Beauregard }
4354