1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte 
22*fcf3ce44SJohn Forte /* Copyright 2008 QLogic Corporation */
23*fcf3ce44SJohn Forte 
24*fcf3ce44SJohn Forte /*
25*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
26*fcf3ce44SJohn Forte  * Use is subject to license terms.
27*fcf3ce44SJohn Forte  */
28*fcf3ce44SJohn Forte 
29*fcf3ce44SJohn Forte #pragma ident	"Copyright 2008 QLogic Corporation; ql_init.c"
30*fcf3ce44SJohn Forte 
31*fcf3ce44SJohn Forte /*
32*fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33*fcf3ce44SJohn Forte  *
34*fcf3ce44SJohn Forte  * ***********************************************************************
35*fcf3ce44SJohn Forte  * *									**
36*fcf3ce44SJohn Forte  * *				NOTICE					**
37*fcf3ce44SJohn Forte  * *		COPYRIGHT (C) 1996-2008 QLOGIC CORPORATION		**
38*fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
39*fcf3ce44SJohn Forte  * *									**
40*fcf3ce44SJohn Forte  * ***********************************************************************
41*fcf3ce44SJohn Forte  *
42*fcf3ce44SJohn Forte  */
43*fcf3ce44SJohn Forte 
44*fcf3ce44SJohn Forte #include <ql_apps.h>
45*fcf3ce44SJohn Forte #include <ql_api.h>
46*fcf3ce44SJohn Forte #include <ql_debug.h>
47*fcf3ce44SJohn Forte #include <ql_init.h>
48*fcf3ce44SJohn Forte #include <ql_iocb.h>
49*fcf3ce44SJohn Forte #include <ql_isr.h>
50*fcf3ce44SJohn Forte #include <ql_mbx.h>
51*fcf3ce44SJohn Forte #include <ql_xioctl.h>
52*fcf3ce44SJohn Forte 
53*fcf3ce44SJohn Forte /*
54*fcf3ce44SJohn Forte  * Local data
55*fcf3ce44SJohn Forte  */
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte /*
58*fcf3ce44SJohn Forte  * Local prototypes
59*fcf3ce44SJohn Forte  */
60*fcf3ce44SJohn Forte static uint16_t ql_nvram_request(ql_adapter_state_t *, uint32_t);
61*fcf3ce44SJohn Forte static int ql_nvram_24xx_config(ql_adapter_state_t *);
62*fcf3ce44SJohn Forte static void ql_23_properties(ql_adapter_state_t *, nvram_t *);
63*fcf3ce44SJohn Forte static void ql_24xx_properties(ql_adapter_state_t *, nvram_24xx_t *);
64*fcf3ce44SJohn Forte static int ql_check_isp_firmware(ql_adapter_state_t *);
65*fcf3ce44SJohn Forte static int ql_chip_diag(ql_adapter_state_t *);
66*fcf3ce44SJohn Forte static int ql_load_flash_fw(ql_adapter_state_t *);
67*fcf3ce44SJohn Forte static int ql_configure_loop(ql_adapter_state_t *);
68*fcf3ce44SJohn Forte static int ql_configure_hba(ql_adapter_state_t *);
69*fcf3ce44SJohn Forte static int ql_configure_fabric(ql_adapter_state_t *);
70*fcf3ce44SJohn Forte static int ql_configure_device_d_id(ql_adapter_state_t *);
71*fcf3ce44SJohn Forte static void ql_set_max_read_req(ql_adapter_state_t *);
72*fcf3ce44SJohn Forte /*
73*fcf3ce44SJohn Forte  * ql_initialize_adapter
74*fcf3ce44SJohn Forte  *	Initialize board.
75*fcf3ce44SJohn Forte  *
76*fcf3ce44SJohn Forte  * Input:
77*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
78*fcf3ce44SJohn Forte  *
79*fcf3ce44SJohn Forte  * Returns:
80*fcf3ce44SJohn Forte  *	ql local function return status code.
81*fcf3ce44SJohn Forte  *
82*fcf3ce44SJohn Forte  * Context:
83*fcf3ce44SJohn Forte  *	Kernel context.
84*fcf3ce44SJohn Forte  */
85*fcf3ce44SJohn Forte int
86*fcf3ce44SJohn Forte ql_initialize_adapter(ql_adapter_state_t *ha)
87*fcf3ce44SJohn Forte {
88*fcf3ce44SJohn Forte 	int			rval;
89*fcf3ce44SJohn Forte 	class_svc_param_t	*class3_param;
90*fcf3ce44SJohn Forte 	caddr_t			msg;
91*fcf3ce44SJohn Forte 	la_els_logi_t		*els = &ha->loginparams;
92*fcf3ce44SJohn Forte 	int			retries = 5;
93*fcf3ce44SJohn Forte 
94*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
95*fcf3ce44SJohn Forte 
96*fcf3ce44SJohn Forte 	do {
97*fcf3ce44SJohn Forte 		/* Clear adapter flags. */
98*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
99*fcf3ce44SJohn Forte 		ha->task_daemon_flags &= TASK_DAEMON_STOP_FLG |
100*fcf3ce44SJohn Forte 		    TASK_DAEMON_SLEEPING_FLG | TASK_DAEMON_ALIVE_FLG |
101*fcf3ce44SJohn Forte 		    TASK_DAEMON_IDLE_CHK_FLG;
102*fcf3ce44SJohn Forte 		ha->task_daemon_flags |= LOOP_DOWN;
103*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
104*fcf3ce44SJohn Forte 
105*fcf3ce44SJohn Forte 		ha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
106*fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
107*fcf3ce44SJohn Forte 		ha->flags |= COMMAND_ABORT_TIMEOUT;
108*fcf3ce44SJohn Forte 		ha->flags &= ~ONLINE;
109*fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
110*fcf3ce44SJohn Forte 
111*fcf3ce44SJohn Forte 		ha->state = FC_STATE_OFFLINE;
112*fcf3ce44SJohn Forte 		msg = "Loop OFFLINE";
113*fcf3ce44SJohn Forte 
114*fcf3ce44SJohn Forte 		rval = ql_pci_sbus_config(ha);
115*fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
116*fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
117*fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
118*fcf3ce44SJohn Forte 				EL(ha, "ql_pci_sbus_cfg, isp_abort_needed\n");
119*fcf3ce44SJohn Forte 				ha->task_daemon_flags |= ISP_ABORT_NEEDED;
120*fcf3ce44SJohn Forte 			}
121*fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
122*fcf3ce44SJohn Forte 			continue;
123*fcf3ce44SJohn Forte 		}
124*fcf3ce44SJohn Forte 
125*fcf3ce44SJohn Forte 		ql_setup_fcache(ha);
126*fcf3ce44SJohn Forte 
127*fcf3ce44SJohn Forte 		/* Reset ISP chip. */
128*fcf3ce44SJohn Forte 		ql_reset_chip(ha);
129*fcf3ce44SJohn Forte 
130*fcf3ce44SJohn Forte 		/* Get NVRAM configuration if needed. */
131*fcf3ce44SJohn Forte 		if (ha->init_ctrl_blk.cb.version == 0) {
132*fcf3ce44SJohn Forte 			(void) ql_nvram_config(ha);
133*fcf3ce44SJohn Forte 		}
134*fcf3ce44SJohn Forte 
135*fcf3ce44SJohn Forte 		/* Set login parameters. */
136*fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_2425)) {
137*fcf3ce44SJohn Forte 			els->common_service.rx_bufsize = CHAR_TO_SHORT(
138*fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb24.max_frame_length[0],
139*fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb24.max_frame_length[1]);
140*fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb24.port_name[0],
141*fcf3ce44SJohn Forte 			    (void *)&els->nport_ww_name.raw_wwn[0], 8);
142*fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb24.node_name[0],
143*fcf3ce44SJohn Forte 			    (void *)&els->node_ww_name.raw_wwn[0], 8);
144*fcf3ce44SJohn Forte 		} else {
145*fcf3ce44SJohn Forte 			els->common_service.rx_bufsize = CHAR_TO_SHORT(
146*fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb.max_frame_length[0],
147*fcf3ce44SJohn Forte 			    ha->init_ctrl_blk.cb.max_frame_length[1]);
148*fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb.port_name[0],
149*fcf3ce44SJohn Forte 			    (void *)&els->nport_ww_name.raw_wwn[0], 8);
150*fcf3ce44SJohn Forte 			bcopy((void *)&ha->init_ctrl_blk.cb.node_name[0],
151*fcf3ce44SJohn Forte 			    (void *)&els->node_ww_name.raw_wwn[0], 8);
152*fcf3ce44SJohn Forte 		}
153*fcf3ce44SJohn Forte 
154*fcf3ce44SJohn Forte 		/* Determine which RISC code to use. */
155*fcf3ce44SJohn Forte 		(void) ql_check_isp_firmware(ha);
156*fcf3ce44SJohn Forte 
157*fcf3ce44SJohn Forte 		rval = ql_chip_diag(ha);
158*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
159*fcf3ce44SJohn Forte 			rval = ql_load_isp_firmware(ha);
160*fcf3ce44SJohn Forte 		}
161*fcf3ce44SJohn Forte 
162*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
163*fcf3ce44SJohn Forte 		    QL_SUCCESS && (rval = ql_init_rings(ha)) ==
164*fcf3ce44SJohn Forte 		    QL_SUCCESS) {
165*fcf3ce44SJohn Forte 
166*fcf3ce44SJohn Forte 			(void) ql_fw_ready(ha, ha->fwwait);
167*fcf3ce44SJohn Forte 
168*fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & QL_SUSPENDED) &&
169*fcf3ce44SJohn Forte 			    ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
170*fcf3ce44SJohn Forte 				if (ha->topology & QL_LOOP_CONNECTION) {
171*fcf3ce44SJohn Forte 					ha->state = ha->state | FC_STATE_LOOP;
172*fcf3ce44SJohn Forte 					msg = "Loop ONLINE";
173*fcf3ce44SJohn Forte 					ha->task_daemon_flags |= STATE_ONLINE;
174*fcf3ce44SJohn Forte 				} else if (ha->topology & QL_P2P_CONNECTION) {
175*fcf3ce44SJohn Forte 					ha->state = ha->state |
176*fcf3ce44SJohn Forte 					    FC_STATE_ONLINE;
177*fcf3ce44SJohn Forte 					msg = "Link ONLINE";
178*fcf3ce44SJohn Forte 					ha->task_daemon_flags |= STATE_ONLINE;
179*fcf3ce44SJohn Forte 				} else {
180*fcf3ce44SJohn Forte 					msg = "Unknown Link state";
181*fcf3ce44SJohn Forte 				}
182*fcf3ce44SJohn Forte 			}
183*fcf3ce44SJohn Forte 		} else {
184*fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
185*fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
186*fcf3ce44SJohn Forte 				EL(ha, "failed, isp_abort_needed\n");
187*fcf3ce44SJohn Forte 				ha->task_daemon_flags |= ISP_ABORT_NEEDED |
188*fcf3ce44SJohn Forte 				    LOOP_DOWN;
189*fcf3ce44SJohn Forte 			}
190*fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
191*fcf3ce44SJohn Forte 		}
192*fcf3ce44SJohn Forte 
193*fcf3ce44SJohn Forte 	} while (retries-- != 0 && ha->task_daemon_flags & ISP_ABORT_NEEDED);
194*fcf3ce44SJohn Forte 
195*fcf3ce44SJohn Forte 	cmn_err(CE_NOTE, "!Qlogic %s(%d): %s", QL_NAME, ha->instance, msg);
196*fcf3ce44SJohn Forte 
197*fcf3ce44SJohn Forte 	/* Enable ISP interrupts and login parameters. */
198*fcf3ce44SJohn Forte 	CFG_IST(ha, CFG_CTRL_2425) ? WRT32_IO_REG(ha, ictrl, ISP_EN_RISC):
199*fcf3ce44SJohn Forte 	    WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
200*fcf3ce44SJohn Forte 
201*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
202*fcf3ce44SJohn Forte 	ha->flags |= (INTERRUPTS_ENABLED | ONLINE);
203*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
204*fcf3ce44SJohn Forte 
205*fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FC_STATE_CHANGE | RESET_MARKER_NEEDED |
206*fcf3ce44SJohn Forte 	    COMMAND_WAIT_NEEDED);
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte 	/*
209*fcf3ce44SJohn Forte 	 * Setup login parameters.
210*fcf3ce44SJohn Forte 	 */
211*fcf3ce44SJohn Forte 	els->common_service.fcph_version = 0x2006;
212*fcf3ce44SJohn Forte 	els->common_service.btob_credit = 3;
213*fcf3ce44SJohn Forte 	els->common_service.cmn_features = 0x8800;
214*fcf3ce44SJohn Forte 	els->common_service.conc_sequences = 0xff;
215*fcf3ce44SJohn Forte 	els->common_service.relative_offset = 3;
216*fcf3ce44SJohn Forte 	els->common_service.e_d_tov = 0x07d0;
217*fcf3ce44SJohn Forte 
218*fcf3ce44SJohn Forte 	class3_param = (class_svc_param_t *)&els->class_3;
219*fcf3ce44SJohn Forte 	class3_param->class_valid_svc_opt = 0x8800;
220*fcf3ce44SJohn Forte 	class3_param->rcv_data_size = els->common_service.rx_bufsize;
221*fcf3ce44SJohn Forte 	class3_param->conc_sequences = 0xff;
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
224*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
225*fcf3ce44SJohn Forte 	} else {
226*fcf3ce44SJohn Forte 		/*EMPTY*/
227*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
228*fcf3ce44SJohn Forte 	}
229*fcf3ce44SJohn Forte 	return (rval);
230*fcf3ce44SJohn Forte }
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte /*
233*fcf3ce44SJohn Forte  * ql_pci_sbus_config
234*fcf3ce44SJohn Forte  *	Setup device PCI/SBUS configuration registers.
235*fcf3ce44SJohn Forte  *
236*fcf3ce44SJohn Forte  * Input:
237*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
238*fcf3ce44SJohn Forte  *
239*fcf3ce44SJohn Forte  * Returns:
240*fcf3ce44SJohn Forte  *	ql local function return status code.
241*fcf3ce44SJohn Forte  *
242*fcf3ce44SJohn Forte  * Context:
243*fcf3ce44SJohn Forte  *	Kernel context.
244*fcf3ce44SJohn Forte  */
245*fcf3ce44SJohn Forte int
246*fcf3ce44SJohn Forte ql_pci_sbus_config(ql_adapter_state_t *ha)
247*fcf3ce44SJohn Forte {
248*fcf3ce44SJohn Forte 	uint32_t	timer;
249*fcf3ce44SJohn Forte 	uint16_t	cmd, w16;
250*fcf3ce44SJohn Forte 
251*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
252*fcf3ce44SJohn Forte 
253*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
254*fcf3ce44SJohn Forte 		w16 = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle,
255*fcf3ce44SJohn Forte 		    (uint16_t *)(ha->sbus_fpga_iobase + FPGA_REVISION));
256*fcf3ce44SJohn Forte 		EL(ha, "FPGA rev is %d.%d", (w16 & 0xf0) >> 4,
257*fcf3ce44SJohn Forte 		    w16 & 0xf);
258*fcf3ce44SJohn Forte 	} else {
259*fcf3ce44SJohn Forte 		/*
260*fcf3ce44SJohn Forte 		 * we want to respect framework's setting of PCI
261*fcf3ce44SJohn Forte 		 * configuration space command register and also
262*fcf3ce44SJohn Forte 		 * want to make sure that all bits of interest to us
263*fcf3ce44SJohn Forte 		 * are properly set in command register.
264*fcf3ce44SJohn Forte 		 */
265*fcf3ce44SJohn Forte 		cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
266*fcf3ce44SJohn Forte 		cmd = (uint16_t)(cmd | PCI_COMM_IO | PCI_COMM_MAE |
267*fcf3ce44SJohn Forte 		    PCI_COMM_ME | PCI_COMM_MEMWR_INVAL |
268*fcf3ce44SJohn Forte 		    PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
269*fcf3ce44SJohn Forte 
270*fcf3ce44SJohn Forte 		/*
271*fcf3ce44SJohn Forte 		 * If this is a 2300 card and not 2312, reset the
272*fcf3ce44SJohn Forte 		 * MEMWR_INVAL due to a bug in the 2300. Unfortunately, the
273*fcf3ce44SJohn Forte 		 * 2310 also reports itself as a 2300 so we need to get the
274*fcf3ce44SJohn Forte 		 * fb revision level -- a 6 indicates it really is a 2300 and
275*fcf3ce44SJohn Forte 		 * not a 2310.
276*fcf3ce44SJohn Forte 		 */
277*fcf3ce44SJohn Forte 
278*fcf3ce44SJohn Forte 		if (ha->device_id == 0x2300) {
279*fcf3ce44SJohn Forte 			/* Pause RISC. */
280*fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
281*fcf3ce44SJohn Forte 			for (timer = 0; timer < 30000; timer++) {
282*fcf3ce44SJohn Forte 				if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) !=
283*fcf3ce44SJohn Forte 				    0) {
284*fcf3ce44SJohn Forte 					break;
285*fcf3ce44SJohn Forte 				} else {
286*fcf3ce44SJohn Forte 					drv_usecwait(MILLISEC);
287*fcf3ce44SJohn Forte 				}
288*fcf3ce44SJohn Forte 			}
289*fcf3ce44SJohn Forte 
290*fcf3ce44SJohn Forte 			/* Select FPM registers. */
291*fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, ctrl_status, 0x20);
292*fcf3ce44SJohn Forte 
293*fcf3ce44SJohn Forte 			/* Get the fb rev level */
294*fcf3ce44SJohn Forte 			if (RD16_IO_REG(ha, fb_cmd) == 6) {
295*fcf3ce44SJohn Forte 				cmd = (uint16_t)(cmd & ~PCI_COMM_MEMWR_INVAL);
296*fcf3ce44SJohn Forte 			}
297*fcf3ce44SJohn Forte 
298*fcf3ce44SJohn Forte 			/* Deselect FPM registers. */
299*fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, ctrl_status, 0x0);
300*fcf3ce44SJohn Forte 
301*fcf3ce44SJohn Forte 			/* Release RISC module. */
302*fcf3ce44SJohn Forte 			WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
303*fcf3ce44SJohn Forte 			for (timer = 0; timer < 30000; timer++) {
304*fcf3ce44SJohn Forte 				if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) ==
305*fcf3ce44SJohn Forte 				    0) {
306*fcf3ce44SJohn Forte 					break;
307*fcf3ce44SJohn Forte 				} else {
308*fcf3ce44SJohn Forte 					drv_usecwait(MILLISEC);
309*fcf3ce44SJohn Forte 				}
310*fcf3ce44SJohn Forte 			}
311*fcf3ce44SJohn Forte 		} else if (ha->device_id == 0x2312) {
312*fcf3ce44SJohn Forte 			/*
313*fcf3ce44SJohn Forte 			 * cPCI ISP2312 specific code to service function 1
314*fcf3ce44SJohn Forte 			 * hot-swap registers.
315*fcf3ce44SJohn Forte 			 */
316*fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, ctrl_status) & ISP_FUNC_NUM_MASK)
317*fcf3ce44SJohn Forte 			    != 0) {
318*fcf3ce44SJohn Forte 				ql_pci_config_put8(ha, 0x66, 0xc2);
319*fcf3ce44SJohn Forte 			}
320*fcf3ce44SJohn Forte 		}
321*fcf3ce44SJohn Forte 
322*fcf3ce44SJohn Forte 		/* max memory read byte cnt override */
323*fcf3ce44SJohn Forte 		if (ha->pci_max_read_req != 0) {
324*fcf3ce44SJohn Forte 			ql_set_max_read_req(ha);
325*fcf3ce44SJohn Forte 		}
326*fcf3ce44SJohn Forte 
327*fcf3ce44SJohn Forte 		ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
328*fcf3ce44SJohn Forte 
329*fcf3ce44SJohn Forte 		/* Set cache line register. */
330*fcf3ce44SJohn Forte 		ql_pci_config_put8(ha, PCI_CONF_CACHE_LINESZ, 0x10);
331*fcf3ce44SJohn Forte 
332*fcf3ce44SJohn Forte 		/* Set latency register. */
333*fcf3ce44SJohn Forte 		ql_pci_config_put8(ha, PCI_CONF_LATENCY_TIMER, 0x40);
334*fcf3ce44SJohn Forte 
335*fcf3ce44SJohn Forte 		/* Reset expansion ROM address decode enable. */
336*fcf3ce44SJohn Forte 		w16 = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_ROM);
337*fcf3ce44SJohn Forte 		w16 = (uint16_t)(w16 & ~BIT_0);
338*fcf3ce44SJohn Forte 		ql_pci_config_put16(ha, PCI_CONF_ROM, w16);
339*fcf3ce44SJohn Forte 	}
340*fcf3ce44SJohn Forte 
341*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
342*fcf3ce44SJohn Forte 
343*fcf3ce44SJohn Forte 	return (QL_SUCCESS);
344*fcf3ce44SJohn Forte }
345*fcf3ce44SJohn Forte 
346*fcf3ce44SJohn Forte /*
347*fcf3ce44SJohn Forte  * Set the PCI max read request value.
348*fcf3ce44SJohn Forte  *
349*fcf3ce44SJohn Forte  * Input:
350*fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
351*fcf3ce44SJohn Forte  *
352*fcf3ce44SJohn Forte  * Output:
353*fcf3ce44SJohn Forte  *	none.
354*fcf3ce44SJohn Forte  *
355*fcf3ce44SJohn Forte  * Returns:
356*fcf3ce44SJohn Forte  *
357*fcf3ce44SJohn Forte  * Context:
358*fcf3ce44SJohn Forte  *	Kernel context.
359*fcf3ce44SJohn Forte  */
360*fcf3ce44SJohn Forte 
361*fcf3ce44SJohn Forte static void
362*fcf3ce44SJohn Forte ql_set_max_read_req(ql_adapter_state_t *ha)
363*fcf3ce44SJohn Forte {
364*fcf3ce44SJohn Forte 	uint16_t	read_req, w16;
365*fcf3ce44SJohn Forte 	uint16_t	tmp = ha->pci_max_read_req;
366*fcf3ce44SJohn Forte 
367*fcf3ce44SJohn Forte 	if ((ha->device_id == 0x2422) ||
368*fcf3ce44SJohn Forte 	    ((ha->device_id & 0xff00) == 0x2300)) {
369*fcf3ce44SJohn Forte 		/* check for vaild override value */
370*fcf3ce44SJohn Forte 		if (tmp == 512 || tmp == 1024 || tmp == 2048 ||
371*fcf3ce44SJohn Forte 		    tmp == 4096) {
372*fcf3ce44SJohn Forte 			/* shift away the don't cares */
373*fcf3ce44SJohn Forte 			tmp = (uint16_t)(tmp >> 10);
374*fcf3ce44SJohn Forte 			/* convert bit pos to request value */
375*fcf3ce44SJohn Forte 			for (read_req = 0; tmp != 0; read_req++) {
376*fcf3ce44SJohn Forte 				tmp = (uint16_t)(tmp >> 1);
377*fcf3ce44SJohn Forte 			}
378*fcf3ce44SJohn Forte 			w16 = (uint16_t)ql_pci_config_get16(ha, 0x4e);
379*fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 & ~(BIT_3 & BIT_2));
380*fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 | (read_req << 2));
381*fcf3ce44SJohn Forte 			ql_pci_config_put16(ha, 0x4e, w16);
382*fcf3ce44SJohn Forte 		} else {
383*fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
384*fcf3ce44SJohn Forte 			    "'pci-max-read-request': %d; using system "
385*fcf3ce44SJohn Forte 			    "default\n", tmp);
386*fcf3ce44SJohn Forte 		}
387*fcf3ce44SJohn Forte 	} else if ((ha->device_id == 0x2432) || ((ha->device_id & 0xff00) ==
388*fcf3ce44SJohn Forte 	    0x2500)) {
389*fcf3ce44SJohn Forte 		/* check for vaild override value */
390*fcf3ce44SJohn Forte 		if (tmp == 128 || tmp == 256 || tmp == 512 ||
391*fcf3ce44SJohn Forte 		    tmp == 1024 || tmp == 2048 || tmp == 4096) {
392*fcf3ce44SJohn Forte 			/* shift away the don't cares */
393*fcf3ce44SJohn Forte 			tmp = (uint16_t)(tmp >> 8);
394*fcf3ce44SJohn Forte 			/* convert bit pos to request value */
395*fcf3ce44SJohn Forte 			for (read_req = 0; tmp != 0; read_req++) {
396*fcf3ce44SJohn Forte 				tmp = (uint16_t)(tmp >> 1);
397*fcf3ce44SJohn Forte 			}
398*fcf3ce44SJohn Forte 			w16 = (uint16_t)ql_pci_config_get16(ha, 0x54);
399*fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 & ~(BIT_14 | BIT_13 |
400*fcf3ce44SJohn Forte 			    BIT_12));
401*fcf3ce44SJohn Forte 			w16 = (uint16_t)(w16 | (read_req << 12));
402*fcf3ce44SJohn Forte 			ql_pci_config_put16(ha, 0x54, w16);
403*fcf3ce44SJohn Forte 		} else {
404*fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
405*fcf3ce44SJohn Forte 			    "'pci-max-read-request': %d; using system "
406*fcf3ce44SJohn Forte 			    "default\n", tmp);
407*fcf3ce44SJohn Forte 		}
408*fcf3ce44SJohn Forte 	}
409*fcf3ce44SJohn Forte }
410*fcf3ce44SJohn Forte 
411*fcf3ce44SJohn Forte /*
412*fcf3ce44SJohn Forte  * NVRAM configuration.
413*fcf3ce44SJohn Forte  *
414*fcf3ce44SJohn Forte  * Input:
415*fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
416*fcf3ce44SJohn Forte  *	ha->hba_buf = request and response rings
417*fcf3ce44SJohn Forte  *
418*fcf3ce44SJohn Forte  * Output:
419*fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
420*fcf3ce44SJohn Forte  *	host adapters parameters in host adapter block
421*fcf3ce44SJohn Forte  *
422*fcf3ce44SJohn Forte  * Returns:
423*fcf3ce44SJohn Forte  *	ql local function return status code.
424*fcf3ce44SJohn Forte  *
425*fcf3ce44SJohn Forte  * Context:
426*fcf3ce44SJohn Forte  *	Kernel context.
427*fcf3ce44SJohn Forte  */
428*fcf3ce44SJohn Forte int
429*fcf3ce44SJohn Forte ql_nvram_config(ql_adapter_state_t *ha)
430*fcf3ce44SJohn Forte {
431*fcf3ce44SJohn Forte 	uint32_t	cnt;
432*fcf3ce44SJohn Forte 	caddr_t		dptr1, dptr2;
433*fcf3ce44SJohn Forte 	ql_init_cb_t	*icb = &ha->init_ctrl_blk.cb;
434*fcf3ce44SJohn Forte 	ql_ip_init_cb_t	*ip_icb = &ha->ip_init_ctrl_blk.cb;
435*fcf3ce44SJohn Forte 	nvram_t		*nv = (nvram_t *)ha->request_ring_bp;
436*fcf3ce44SJohn Forte 	uint16_t	*wptr = (uint16_t *)ha->request_ring_bp;
437*fcf3ce44SJohn Forte 	uint8_t		chksum = 0;
438*fcf3ce44SJohn Forte 	int		rval;
439*fcf3ce44SJohn Forte 	int		idpromlen;
440*fcf3ce44SJohn Forte 	char		idprombuf[32];
441*fcf3ce44SJohn Forte 	uint32_t	start_addr;
442*fcf3ce44SJohn Forte 
443*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
444*fcf3ce44SJohn Forte 
445*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_CTRL_2425)) {
446*fcf3ce44SJohn Forte 		return (ql_nvram_24xx_config(ha));
447*fcf3ce44SJohn Forte 	}
448*fcf3ce44SJohn Forte 
449*fcf3ce44SJohn Forte 	start_addr = 0;
450*fcf3ce44SJohn Forte 	if ((rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) ==
451*fcf3ce44SJohn Forte 	    QL_SUCCESS) {
452*fcf3ce44SJohn Forte 		/* Verify valid NVRAM checksum. */
453*fcf3ce44SJohn Forte 		for (cnt = 0; cnt < sizeof (nvram_t)/2; cnt++) {
454*fcf3ce44SJohn Forte 			*wptr = (uint16_t)ql_get_nvram_word(ha,
455*fcf3ce44SJohn Forte 			    (uint32_t)(cnt + start_addr));
456*fcf3ce44SJohn Forte 			chksum = (uint8_t)(chksum + (uint8_t)*wptr);
457*fcf3ce44SJohn Forte 			chksum = (uint8_t)(chksum + (uint8_t)(*wptr >> 8));
458*fcf3ce44SJohn Forte 			wptr++;
459*fcf3ce44SJohn Forte 		}
460*fcf3ce44SJohn Forte 		ql_release_nvram(ha);
461*fcf3ce44SJohn Forte 	}
462*fcf3ce44SJohn Forte 
463*fcf3ce44SJohn Forte 	/* Bad NVRAM data, set defaults parameters. */
464*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
465*fcf3ce44SJohn Forte 	    nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
466*fcf3ce44SJohn Forte 	    nv->nvram_version < 1) {
467*fcf3ce44SJohn Forte 
468*fcf3ce44SJohn Forte 		EL(ha, "failed, rval=%xh, checksum=%xh, "
469*fcf3ce44SJohn Forte 		    "id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, "
470*fcf3ce44SJohn Forte 		    "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
471*fcf3ce44SJohn Forte 		    nv->id[2], nv->id[3], ha->xioctl->fdesc.flash_size,
472*fcf3ce44SJohn Forte 		    ha->subven_id, nv->nvram_version);
473*fcf3ce44SJohn Forte 
474*fcf3ce44SJohn Forte 		/* Don't print nvram message if it's an on-board 2200 */
475*fcf3ce44SJohn Forte 		if (!((CFG_IST(ha, CFG_CTRL_2200)) &&
476*fcf3ce44SJohn Forte 		    (ha->xioctl->fdesc.flash_size == 0))) {
477*fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed,"
478*fcf3ce44SJohn Forte 			    " using driver defaults.", QL_NAME, ha->instance);
479*fcf3ce44SJohn Forte 		}
480*fcf3ce44SJohn Forte 
481*fcf3ce44SJohn Forte 		/* Reset NVRAM data. */
482*fcf3ce44SJohn Forte 		bzero((void *)nv, sizeof (nvram_t));
483*fcf3ce44SJohn Forte 
484*fcf3ce44SJohn Forte 		/*
485*fcf3ce44SJohn Forte 		 * Set default initialization control block.
486*fcf3ce44SJohn Forte 		 */
487*fcf3ce44SJohn Forte 		nv->parameter_block_version = ICB_VERSION;
488*fcf3ce44SJohn Forte 		nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
489*fcf3ce44SJohn Forte 		nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
490*fcf3ce44SJohn Forte 
491*fcf3ce44SJohn Forte 		nv->max_frame_length[1] = 4;
492*fcf3ce44SJohn Forte 
493*fcf3ce44SJohn Forte 		/*
494*fcf3ce44SJohn Forte 		 * Allow 2048 byte frames for 2300
495*fcf3ce44SJohn Forte 		 */
496*fcf3ce44SJohn Forte 		if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
497*fcf3ce44SJohn Forte 			nv->max_frame_length[1] = 8;
498*fcf3ce44SJohn Forte 		}
499*fcf3ce44SJohn Forte 		nv->max_iocb_allocation[1] = 1;
500*fcf3ce44SJohn Forte 		nv->execution_throttle[0] = 16;
501*fcf3ce44SJohn Forte 		nv->login_retry_count = 8;
502*fcf3ce44SJohn Forte 
503*fcf3ce44SJohn Forte 		idpromlen = 32;
504*fcf3ce44SJohn Forte 
505*fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
506*fcf3ce44SJohn Forte 		if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
507*fcf3ce44SJohn Forte 		    DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
508*fcf3ce44SJohn Forte 		    &idpromlen) != DDI_PROP_SUCCESS) {
509*fcf3ce44SJohn Forte 
510*fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): Unable to read idprom "
511*fcf3ce44SJohn Forte 			    "property\n", ha->instance);
512*fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
513*fcf3ce44SJohn Forte 			    "property", QL_NAME, ha->instance);
514*fcf3ce44SJohn Forte 
515*fcf3ce44SJohn Forte 			nv->port_name[2] = 33;
516*fcf3ce44SJohn Forte 			nv->port_name[3] = 224;
517*fcf3ce44SJohn Forte 			nv->port_name[4] = 139;
518*fcf3ce44SJohn Forte 			nv->port_name[7] = (uint8_t)
519*fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
520*fcf3ce44SJohn Forte 
521*fcf3ce44SJohn Forte 		} else {
522*fcf3ce44SJohn Forte 
523*fcf3ce44SJohn Forte 			nv->port_name[2] = idprombuf[2];
524*fcf3ce44SJohn Forte 			nv->port_name[3] = idprombuf[3];
525*fcf3ce44SJohn Forte 			nv->port_name[4] = idprombuf[4];
526*fcf3ce44SJohn Forte 			nv->port_name[5] = idprombuf[5];
527*fcf3ce44SJohn Forte 			nv->port_name[6] = idprombuf[6];
528*fcf3ce44SJohn Forte 			nv->port_name[7] = idprombuf[7];
529*fcf3ce44SJohn Forte 			nv->port_name[0] = (uint8_t)
530*fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
531*fcf3ce44SJohn Forte 
532*fcf3ce44SJohn Forte 		}
533*fcf3ce44SJohn Forte 
534*fcf3ce44SJohn Forte 		/* Don't print nvram message if it's an on-board 2200 */
535*fcf3ce44SJohn Forte 		if (!(CFG_IST(ha, CFG_CTRL_2200)) &&
536*fcf3ce44SJohn Forte 		    (ha->xioctl->fdesc.flash_size == 0)) {
537*fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using"
538*fcf3ce44SJohn Forte 			    " default HBA parameters and temporary WWPN:"
539*fcf3ce44SJohn Forte 			    " %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
540*fcf3ce44SJohn Forte 			    ha->instance, nv->port_name[0], nv->port_name[1],
541*fcf3ce44SJohn Forte 			    nv->port_name[2], nv->port_name[3],
542*fcf3ce44SJohn Forte 			    nv->port_name[4], nv->port_name[5],
543*fcf3ce44SJohn Forte 			    nv->port_name[6], nv->port_name[7]);
544*fcf3ce44SJohn Forte 		}
545*fcf3ce44SJohn Forte 
546*fcf3ce44SJohn Forte 		nv->login_timeout = 4;
547*fcf3ce44SJohn Forte 
548*fcf3ce44SJohn Forte 		/* Set default connection options for the 23xx to 2 */
549*fcf3ce44SJohn Forte 		if (!(CFG_IST(ha, CFG_CTRL_2200))) {
550*fcf3ce44SJohn Forte 			nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
551*fcf3ce44SJohn Forte 			    BIT_5);
552*fcf3ce44SJohn Forte 		}
553*fcf3ce44SJohn Forte 
554*fcf3ce44SJohn Forte 		/*
555*fcf3ce44SJohn Forte 		 * Set default host adapter parameters
556*fcf3ce44SJohn Forte 		 */
557*fcf3ce44SJohn Forte 		nv->host_p[0] = BIT_1;
558*fcf3ce44SJohn Forte 		nv->host_p[1] = BIT_2;
559*fcf3ce44SJohn Forte 		nv->reset_delay = 5;
560*fcf3ce44SJohn Forte 		nv->port_down_retry_count = 8;
561*fcf3ce44SJohn Forte 		nv->maximum_luns_per_target[0] = 8;
562*fcf3ce44SJohn Forte 
563*fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
564*fcf3ce44SJohn Forte 	}
565*fcf3ce44SJohn Forte 
566*fcf3ce44SJohn Forte 	/* Check for adapter node name (big endian). */
567*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 8; cnt++) {
568*fcf3ce44SJohn Forte 		if (nv->node_name[cnt] != 0) {
569*fcf3ce44SJohn Forte 			break;
570*fcf3ce44SJohn Forte 		}
571*fcf3ce44SJohn Forte 	}
572*fcf3ce44SJohn Forte 
573*fcf3ce44SJohn Forte 	/* Copy port name if no node name (big endian). */
574*fcf3ce44SJohn Forte 	if (cnt == 8) {
575*fcf3ce44SJohn Forte 		bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8);
576*fcf3ce44SJohn Forte 		nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
577*fcf3ce44SJohn Forte 		nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
578*fcf3ce44SJohn Forte 	}
579*fcf3ce44SJohn Forte 
580*fcf3ce44SJohn Forte 	/* Reset initialization control blocks. */
581*fcf3ce44SJohn Forte 	bzero((void *)icb, sizeof (ql_init_cb_t));
582*fcf3ce44SJohn Forte 
583*fcf3ce44SJohn Forte 	/* Get driver properties. */
584*fcf3ce44SJohn Forte 	ql_23_properties(ha, nv);
585*fcf3ce44SJohn Forte 
586*fcf3ce44SJohn Forte 	cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
587*fcf3ce44SJohn Forte 	    "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
588*fcf3ce44SJohn Forte 	    QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1],
589*fcf3ce44SJohn Forte 	    nv->port_name[2], nv->port_name[3], nv->port_name[4],
590*fcf3ce44SJohn Forte 	    nv->port_name[5], nv->port_name[6], nv->port_name[7],
591*fcf3ce44SJohn Forte 	    nv->node_name[0], nv->node_name[1], nv->node_name[2],
592*fcf3ce44SJohn Forte 	    nv->node_name[3], nv->node_name[4], nv->node_name[5],
593*fcf3ce44SJohn Forte 	    nv->node_name[6], nv->node_name[7]);
594*fcf3ce44SJohn Forte 
595*fcf3ce44SJohn Forte 	/*
596*fcf3ce44SJohn Forte 	 * Copy over NVRAM RISC parameter block
597*fcf3ce44SJohn Forte 	 * to initialization control block.
598*fcf3ce44SJohn Forte 	 */
599*fcf3ce44SJohn Forte 	dptr1 = (caddr_t)icb;
600*fcf3ce44SJohn Forte 	dptr2 = (caddr_t)&nv->parameter_block_version;
601*fcf3ce44SJohn Forte 	cnt = (uint32_t)((uintptr_t)&icb->request_q_outpointer[0] -
602*fcf3ce44SJohn Forte 	    (uintptr_t)&icb->version);
603*fcf3ce44SJohn Forte 	while (cnt-- != 0) {
604*fcf3ce44SJohn Forte 		*dptr1++ = *dptr2++;
605*fcf3ce44SJohn Forte 	}
606*fcf3ce44SJohn Forte 
607*fcf3ce44SJohn Forte 	/* Copy 2nd half. */
608*fcf3ce44SJohn Forte 	dptr1 = (caddr_t)&icb->add_fw_opt[0];
609*fcf3ce44SJohn Forte 	cnt = (uint32_t)((uintptr_t)&icb->reserved_3[0] -
610*fcf3ce44SJohn Forte 	    (uintptr_t)&icb->add_fw_opt[0]);
611*fcf3ce44SJohn Forte 
612*fcf3ce44SJohn Forte 	while (cnt-- != 0) {
613*fcf3ce44SJohn Forte 		*dptr1++ = *dptr2++;
614*fcf3ce44SJohn Forte 	}
615*fcf3ce44SJohn Forte 
616*fcf3ce44SJohn Forte 	/*
617*fcf3ce44SJohn Forte 	 * Setup driver firmware options.
618*fcf3ce44SJohn Forte 	 */
619*fcf3ce44SJohn Forte 	icb->firmware_options[0] = (uint8_t)
620*fcf3ce44SJohn Forte 	    (icb->firmware_options[0] | BIT_6 | BIT_1);
621*fcf3ce44SJohn Forte 
622*fcf3ce44SJohn Forte 	/*
623*fcf3ce44SJohn Forte 	 * There is no use enabling fast post for SBUS or 2300
624*fcf3ce44SJohn Forte 	 */
625*fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_SBUS_CARD | CFG_CTRL_2300 | CFG_CTRL_6322))) {
626*fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
627*fcf3ce44SJohn Forte 		    (icb->firmware_options[0] & ~BIT_3);
628*fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
629*fcf3ce44SJohn Forte 			icb->special_options[0] = (uint8_t)
630*fcf3ce44SJohn Forte 			    (icb->special_options[0] | BIT_5);
631*fcf3ce44SJohn Forte 		}
632*fcf3ce44SJohn Forte 	} else {
633*fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
634*fcf3ce44SJohn Forte 		    (icb->firmware_options[0] | BIT_3);
635*fcf3ce44SJohn Forte 	}
636*fcf3ce44SJohn Forte 	/* RIO and ZIO not supported. */
637*fcf3ce44SJohn Forte 	icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] &
638*fcf3ce44SJohn Forte 	    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
639*fcf3ce44SJohn Forte 
640*fcf3ce44SJohn Forte 	icb->firmware_options[1] = (uint8_t)(icb->firmware_options[1] |
641*fcf3ce44SJohn Forte 	    BIT_7 | BIT_6 | BIT_5 | BIT_2 | BIT_0);
642*fcf3ce44SJohn Forte 	icb->firmware_options[0] = (uint8_t)
643*fcf3ce44SJohn Forte 	    (icb->firmware_options[0] & ~(BIT_5 | BIT_4));
644*fcf3ce44SJohn Forte 	icb->firmware_options[1] = (uint8_t)
645*fcf3ce44SJohn Forte 	    (icb->firmware_options[1] & ~BIT_4);
646*fcf3ce44SJohn Forte 
647*fcf3ce44SJohn Forte 	icb->add_fw_opt[1] = (uint8_t)(icb->add_fw_opt[1] & ~(BIT_5 | BIT_4));
648*fcf3ce44SJohn Forte 	icb->special_options[0] = (uint8_t)(icb->special_options[0] | BIT_1);
649*fcf3ce44SJohn Forte 
650*fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
651*fcf3ce44SJohn Forte 		if ((icb->special_options[1] & 0x20) == 0) {
652*fcf3ce44SJohn Forte 			EL(ha, "50 ohm is not set\n");
653*fcf3ce44SJohn Forte 		}
654*fcf3ce44SJohn Forte 	}
655*fcf3ce44SJohn Forte 	icb->execution_throttle[0] = 0xff;
656*fcf3ce44SJohn Forte 	icb->execution_throttle[1] = 0xff;
657*fcf3ce44SJohn Forte 
658*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_TARGET_MODE_ENABLE)) {
659*fcf3ce44SJohn Forte 		icb->firmware_options[0] = (uint8_t)
660*fcf3ce44SJohn Forte 		    (icb->firmware_options[0] | BIT_4 | BIT_7);
661*fcf3ce44SJohn Forte 		icb->inquiry = 0x1F;
662*fcf3ce44SJohn Forte 		EL(ha, "Target mode enabled");
663*fcf3ce44SJohn Forte 	}
664*fcf3ce44SJohn Forte 
665*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
666*fcf3ce44SJohn Forte 		icb->firmware_options[1] = (uint8_t)
667*fcf3ce44SJohn Forte 		    (icb->firmware_options[1] | BIT_7 | BIT_6);
668*fcf3ce44SJohn Forte 		icb->add_fw_opt[1] = (uint8_t)
669*fcf3ce44SJohn Forte 		    (icb->add_fw_opt[1] | BIT_5 | BIT_4);
670*fcf3ce44SJohn Forte 	}
671*fcf3ce44SJohn Forte 
672*fcf3ce44SJohn Forte 	/*
673*fcf3ce44SJohn Forte 	 * Set host adapter parameters
674*fcf3ce44SJohn Forte 	 */
675*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
676*fcf3ce44SJohn Forte 	ha->nvram_version = nv->nvram_version;
677*fcf3ce44SJohn Forte 	ha->adapter_features = CHAR_TO_SHORT(nv->adapter_features[0],
678*fcf3ce44SJohn Forte 	    nv->adapter_features[1]);
679*fcf3ce44SJohn Forte 
680*fcf3ce44SJohn Forte 	nv->host_p[0] & BIT_4 ? (ha->cfg_flags |= CFG_DISABLE_RISC_CODE_LOAD) :
681*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_DISABLE_RISC_CODE_LOAD);
682*fcf3ce44SJohn Forte 	nv->host_p[0] & BIT_5 ? (ha->cfg_flags |= CFG_SET_CACHE_LINE_SIZE_1) :
683*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_SET_CACHE_LINE_SIZE_1);
684*fcf3ce44SJohn Forte 
685*fcf3ce44SJohn Forte 	/* Always enable 64bit addressing, except SBUS cards. */
686*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
687*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_64BIT_ADDRESSING;
688*fcf3ce44SJohn Forte 		ha->cmd_segs = CMD_TYPE_2_DATA_SEGMENTS;
689*fcf3ce44SJohn Forte 		ha->cmd_cont_segs = CONT_TYPE_0_DATA_SEGMENTS;
690*fcf3ce44SJohn Forte 	} else {
691*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
692*fcf3ce44SJohn Forte 		ha->cmd_segs = CMD_TYPE_3_DATA_SEGMENTS;
693*fcf3ce44SJohn Forte 		ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
694*fcf3ce44SJohn Forte 	}
695*fcf3ce44SJohn Forte 
696*fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_1 ? (ha->cfg_flags |= CFG_ENABLE_LIP_RESET) :
697*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET);
698*fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) :
699*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN);
700*fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) :
701*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET);
702*fcf3ce44SJohn Forte 
703*fcf3ce44SJohn Forte 	nv->adapter_features[0] & BIT_3 ?
704*fcf3ce44SJohn Forte 	    (ha->cfg_flags |= CFG_MULTI_CHIP_ADAPTER) :
705*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_MULTI_CHIP_ADAPTER);
706*fcf3ce44SJohn Forte 
707*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
708*fcf3ce44SJohn Forte 
709*fcf3ce44SJohn Forte 	ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
710*fcf3ce44SJohn Forte 	    nv->execution_throttle[1]);
711*fcf3ce44SJohn Forte 	ha->loop_reset_delay = nv->reset_delay;
712*fcf3ce44SJohn Forte 	ha->port_down_retry_count = nv->port_down_retry_count;
713*fcf3ce44SJohn Forte 	ha->r_a_tov = (uint16_t)(icb->login_timeout < R_A_TOV_DEFAULT ?
714*fcf3ce44SJohn Forte 	    R_A_TOV_DEFAULT : icb->login_timeout);
715*fcf3ce44SJohn Forte 	ha->maximum_luns_per_target = CHAR_TO_SHORT(
716*fcf3ce44SJohn Forte 	    nv->maximum_luns_per_target[0], nv->maximum_luns_per_target[1]);
717*fcf3ce44SJohn Forte 	if (ha->maximum_luns_per_target == 0) {
718*fcf3ce44SJohn Forte 		ha->maximum_luns_per_target++;
719*fcf3ce44SJohn Forte 	}
720*fcf3ce44SJohn Forte 
721*fcf3ce44SJohn Forte 	/*
722*fcf3ce44SJohn Forte 	 * Setup ring parameters in initialization control block
723*fcf3ce44SJohn Forte 	 */
724*fcf3ce44SJohn Forte 	cnt = REQUEST_ENTRY_CNT;
725*fcf3ce44SJohn Forte 	icb->request_q_length[0] = LSB(cnt);
726*fcf3ce44SJohn Forte 	icb->request_q_length[1] = MSB(cnt);
727*fcf3ce44SJohn Forte 	cnt = RESPONSE_ENTRY_CNT;
728*fcf3ce44SJohn Forte 	icb->response_q_length[0] = LSB(cnt);
729*fcf3ce44SJohn Forte 	icb->response_q_length[1] = MSB(cnt);
730*fcf3ce44SJohn Forte 
731*fcf3ce44SJohn Forte 	icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma)));
732*fcf3ce44SJohn Forte 	icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma)));
733*fcf3ce44SJohn Forte 	icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma)));
734*fcf3ce44SJohn Forte 	icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma)));
735*fcf3ce44SJohn Forte 	icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma)));
736*fcf3ce44SJohn Forte 	icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma)));
737*fcf3ce44SJohn Forte 	icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma)));
738*fcf3ce44SJohn Forte 	icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma)));
739*fcf3ce44SJohn Forte 
740*fcf3ce44SJohn Forte 	icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma)));
741*fcf3ce44SJohn Forte 	icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma)));
742*fcf3ce44SJohn Forte 	icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma)));
743*fcf3ce44SJohn Forte 	icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma)));
744*fcf3ce44SJohn Forte 	icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma)));
745*fcf3ce44SJohn Forte 	icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma)));
746*fcf3ce44SJohn Forte 	icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma)));
747*fcf3ce44SJohn Forte 	icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma)));
748*fcf3ce44SJohn Forte 
749*fcf3ce44SJohn Forte 	/*
750*fcf3ce44SJohn Forte 	 * Setup IP initialization control block
751*fcf3ce44SJohn Forte 	 */
752*fcf3ce44SJohn Forte 	ip_icb->version = IP_ICB_VERSION;
753*fcf3ce44SJohn Forte 
754*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
755*fcf3ce44SJohn Forte 		ip_icb->ip_firmware_options[0] = (uint8_t)
756*fcf3ce44SJohn Forte 		    (ip_icb->ip_firmware_options[0] | BIT_2 | BIT_0);
757*fcf3ce44SJohn Forte 	} else {
758*fcf3ce44SJohn Forte 		ip_icb->ip_firmware_options[0] = (uint8_t)
759*fcf3ce44SJohn Forte 		    (ip_icb->ip_firmware_options[0] | BIT_2);
760*fcf3ce44SJohn Forte 	}
761*fcf3ce44SJohn Forte 
762*fcf3ce44SJohn Forte 	cnt = RCVBUF_CONTAINER_CNT;
763*fcf3ce44SJohn Forte 	ip_icb->queue_size[0] = LSB(cnt);
764*fcf3ce44SJohn Forte 	ip_icb->queue_size[1] = MSB(cnt);
765*fcf3ce44SJohn Forte 
766*fcf3ce44SJohn Forte 	ip_icb->queue_address[0] = LSB(LSW(LSD(ha->rcvbuf_dvma)));
767*fcf3ce44SJohn Forte 	ip_icb->queue_address[1] = MSB(LSW(LSD(ha->rcvbuf_dvma)));
768*fcf3ce44SJohn Forte 	ip_icb->queue_address[2] = LSB(MSW(LSD(ha->rcvbuf_dvma)));
769*fcf3ce44SJohn Forte 	ip_icb->queue_address[3] = MSB(MSW(LSD(ha->rcvbuf_dvma)));
770*fcf3ce44SJohn Forte 	ip_icb->queue_address[4] = LSB(LSW(MSD(ha->rcvbuf_dvma)));
771*fcf3ce44SJohn Forte 	ip_icb->queue_address[5] = MSB(LSW(MSD(ha->rcvbuf_dvma)));
772*fcf3ce44SJohn Forte 	ip_icb->queue_address[6] = LSB(MSW(MSD(ha->rcvbuf_dvma)));
773*fcf3ce44SJohn Forte 	ip_icb->queue_address[7] = MSB(MSW(MSD(ha->rcvbuf_dvma)));
774*fcf3ce44SJohn Forte 
775*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
776*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
777*fcf3ce44SJohn Forte 	} else {
778*fcf3ce44SJohn Forte 		/*EMPTY*/
779*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
780*fcf3ce44SJohn Forte 	}
781*fcf3ce44SJohn Forte 	return (rval);
782*fcf3ce44SJohn Forte }
783*fcf3ce44SJohn Forte 
784*fcf3ce44SJohn Forte /*
785*fcf3ce44SJohn Forte  * Get NVRAM data word
786*fcf3ce44SJohn Forte  *	Calculates word position in NVRAM and calls request routine to
787*fcf3ce44SJohn Forte  *	get the word from NVRAM.
788*fcf3ce44SJohn Forte  *
789*fcf3ce44SJohn Forte  * Input:
790*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
791*fcf3ce44SJohn Forte  *	address = NVRAM word address.
792*fcf3ce44SJohn Forte  *
793*fcf3ce44SJohn Forte  * Returns:
794*fcf3ce44SJohn Forte  *	data word.
795*fcf3ce44SJohn Forte  *
796*fcf3ce44SJohn Forte  * Context:
797*fcf3ce44SJohn Forte  *	Kernel context.
798*fcf3ce44SJohn Forte  */
799*fcf3ce44SJohn Forte uint16_t
800*fcf3ce44SJohn Forte ql_get_nvram_word(ql_adapter_state_t *ha, uint32_t address)
801*fcf3ce44SJohn Forte {
802*fcf3ce44SJohn Forte 	uint32_t	nv_cmd;
803*fcf3ce44SJohn Forte 	uint16_t	rval;
804*fcf3ce44SJohn Forte 
805*fcf3ce44SJohn Forte 	QL_PRINT_4(CE_CONT, "(%d): started\n", ha->instance);
806*fcf3ce44SJohn Forte 
807*fcf3ce44SJohn Forte 	nv_cmd = address << 16;
808*fcf3ce44SJohn Forte 	nv_cmd = nv_cmd | NV_READ_OP;
809*fcf3ce44SJohn Forte 
810*fcf3ce44SJohn Forte 	rval = (uint16_t)ql_nvram_request(ha, nv_cmd);
811*fcf3ce44SJohn Forte 
812*fcf3ce44SJohn Forte 	QL_PRINT_4(CE_CONT, "(%d): NVRAM data = %xh\n", ha->instance, rval);
813*fcf3ce44SJohn Forte 
814*fcf3ce44SJohn Forte 	return (rval);
815*fcf3ce44SJohn Forte }
816*fcf3ce44SJohn Forte 
817*fcf3ce44SJohn Forte /*
818*fcf3ce44SJohn Forte  * NVRAM request
819*fcf3ce44SJohn Forte  *	Sends read command to NVRAM and gets data from NVRAM.
820*fcf3ce44SJohn Forte  *
821*fcf3ce44SJohn Forte  * Input:
822*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
823*fcf3ce44SJohn Forte  *	nv_cmd = Bit 26= start bit
824*fcf3ce44SJohn Forte  *	Bit 25, 24 = opcode
825*fcf3ce44SJohn Forte  *	Bit 23-16 = address
826*fcf3ce44SJohn Forte  *	Bit 15-0 = write data
827*fcf3ce44SJohn Forte  *
828*fcf3ce44SJohn Forte  * Returns:
829*fcf3ce44SJohn Forte  *	data word.
830*fcf3ce44SJohn Forte  *
831*fcf3ce44SJohn Forte  * Context:
832*fcf3ce44SJohn Forte  *	Kernel context.
833*fcf3ce44SJohn Forte  */
834*fcf3ce44SJohn Forte static uint16_t
835*fcf3ce44SJohn Forte ql_nvram_request(ql_adapter_state_t *ha, uint32_t nv_cmd)
836*fcf3ce44SJohn Forte {
837*fcf3ce44SJohn Forte 	uint8_t		cnt;
838*fcf3ce44SJohn Forte 	uint16_t	reg_data;
839*fcf3ce44SJohn Forte 	uint16_t	data = 0;
840*fcf3ce44SJohn Forte 
841*fcf3ce44SJohn Forte 	/* Send command to NVRAM. */
842*fcf3ce44SJohn Forte 
843*fcf3ce44SJohn Forte 	nv_cmd <<= 5;
844*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 11; cnt++) {
845*fcf3ce44SJohn Forte 		if (nv_cmd & BIT_31) {
846*fcf3ce44SJohn Forte 			ql_nv_write(ha, NV_DATA_OUT);
847*fcf3ce44SJohn Forte 		} else {
848*fcf3ce44SJohn Forte 			ql_nv_write(ha, 0);
849*fcf3ce44SJohn Forte 		}
850*fcf3ce44SJohn Forte 		nv_cmd <<= 1;
851*fcf3ce44SJohn Forte 	}
852*fcf3ce44SJohn Forte 
853*fcf3ce44SJohn Forte 	/* Read data from NVRAM. */
854*fcf3ce44SJohn Forte 
855*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 16; cnt++) {
856*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, nvram, NV_SELECT+NV_CLOCK);
857*fcf3ce44SJohn Forte 		ql_nv_delay();
858*fcf3ce44SJohn Forte 		data <<= 1;
859*fcf3ce44SJohn Forte 		reg_data = RD16_IO_REG(ha, nvram);
860*fcf3ce44SJohn Forte 		if (reg_data & NV_DATA_IN) {
861*fcf3ce44SJohn Forte 			data = (uint16_t)(data | BIT_0);
862*fcf3ce44SJohn Forte 		}
863*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, nvram, NV_SELECT);
864*fcf3ce44SJohn Forte 		ql_nv_delay();
865*fcf3ce44SJohn Forte 	}
866*fcf3ce44SJohn Forte 
867*fcf3ce44SJohn Forte 	/* Deselect chip. */
868*fcf3ce44SJohn Forte 
869*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, NV_DESELECT);
870*fcf3ce44SJohn Forte 	ql_nv_delay();
871*fcf3ce44SJohn Forte 
872*fcf3ce44SJohn Forte 	return (data);
873*fcf3ce44SJohn Forte }
874*fcf3ce44SJohn Forte 
875*fcf3ce44SJohn Forte void
876*fcf3ce44SJohn Forte ql_nv_write(ql_adapter_state_t *ha, uint16_t data)
877*fcf3ce44SJohn Forte {
878*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
879*fcf3ce44SJohn Forte 	ql_nv_delay();
880*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT | NV_CLOCK));
881*fcf3ce44SJohn Forte 	ql_nv_delay();
882*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
883*fcf3ce44SJohn Forte 	ql_nv_delay();
884*fcf3ce44SJohn Forte }
885*fcf3ce44SJohn Forte 
886*fcf3ce44SJohn Forte void
887*fcf3ce44SJohn Forte ql_nv_delay(void) {
888*fcf3ce44SJohn Forte 	drv_usecwait(NV_DELAY_COUNT);
889*fcf3ce44SJohn Forte }
890*fcf3ce44SJohn Forte 
891*fcf3ce44SJohn Forte /*
892*fcf3ce44SJohn Forte  * ql_nvram_24xx_config
893*fcf3ce44SJohn Forte  *	ISP2400 nvram.
894*fcf3ce44SJohn Forte  *
895*fcf3ce44SJohn Forte  * Input:
896*fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
897*fcf3ce44SJohn Forte  *	ha->hba_buf = request and response rings
898*fcf3ce44SJohn Forte  *
899*fcf3ce44SJohn Forte  * Output:
900*fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
901*fcf3ce44SJohn Forte  *	host adapters parameters in host adapter block
902*fcf3ce44SJohn Forte  *
903*fcf3ce44SJohn Forte  * Returns:
904*fcf3ce44SJohn Forte  *	ql local function return status code.
905*fcf3ce44SJohn Forte  *
906*fcf3ce44SJohn Forte  * Context:
907*fcf3ce44SJohn Forte  *	Kernel context.
908*fcf3ce44SJohn Forte  */
909*fcf3ce44SJohn Forte int
910*fcf3ce44SJohn Forte ql_nvram_24xx_config(ql_adapter_state_t *ha)
911*fcf3ce44SJohn Forte {
912*fcf3ce44SJohn Forte 	uint32_t		index, addr, chksum, saved_chksum;
913*fcf3ce44SJohn Forte 	uint32_t		*longptr;
914*fcf3ce44SJohn Forte 	nvram_24xx_t		nvram;
915*fcf3ce44SJohn Forte 	int			idpromlen;
916*fcf3ce44SJohn Forte 	char			idprombuf[32];
917*fcf3ce44SJohn Forte 	caddr_t			src, dst;
918*fcf3ce44SJohn Forte 	uint16_t		w1;
919*fcf3ce44SJohn Forte 	int			rval;
920*fcf3ce44SJohn Forte 	nvram_24xx_t		*nv = (nvram_24xx_t *)&nvram;
921*fcf3ce44SJohn Forte 	ql_init_24xx_cb_t	*icb =
922*fcf3ce44SJohn Forte 	    (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24;
923*fcf3ce44SJohn Forte 	ql_ip_init_24xx_cb_t	*ip_icb = &ha->ip_init_ctrl_blk.cb24;
924*fcf3ce44SJohn Forte 
925*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
926*fcf3ce44SJohn Forte 
927*fcf3ce44SJohn Forte 	if ((rval = ql_lock_nvram(ha, &addr, LNF_NVRAM_DATA)) == QL_SUCCESS) {
928*fcf3ce44SJohn Forte 
929*fcf3ce44SJohn Forte 		/* Get NVRAM data and calculate checksum. */
930*fcf3ce44SJohn Forte 		longptr = (uint32_t *)nv;
931*fcf3ce44SJohn Forte 		chksum = saved_chksum = 0;
932*fcf3ce44SJohn Forte 		for (index = 0; index < sizeof (nvram_24xx_t) / 4; index++) {
933*fcf3ce44SJohn Forte 			rval = ql_24xx_read_flash(ha, addr++, longptr);
934*fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
935*fcf3ce44SJohn Forte 				EL(ha, "24xx_read_flash failed=%xh\n", rval);
936*fcf3ce44SJohn Forte 				break;
937*fcf3ce44SJohn Forte 			}
938*fcf3ce44SJohn Forte 			saved_chksum = chksum;
939*fcf3ce44SJohn Forte 			chksum += *longptr;
940*fcf3ce44SJohn Forte 			LITTLE_ENDIAN_32(longptr);
941*fcf3ce44SJohn Forte 			longptr++;
942*fcf3ce44SJohn Forte 		}
943*fcf3ce44SJohn Forte 
944*fcf3ce44SJohn Forte 		ql_release_nvram(ha);
945*fcf3ce44SJohn Forte 	}
946*fcf3ce44SJohn Forte 
947*fcf3ce44SJohn Forte 	/* Bad NVRAM data, set defaults parameters. */
948*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
949*fcf3ce44SJohn Forte 	    nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
950*fcf3ce44SJohn Forte 	    (nv->nvram_version[0] | nv->nvram_version[1]) == 0) {
951*fcf3ce44SJohn Forte 
952*fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed, using "
953*fcf3ce44SJohn Forte 		    "driver defaults.", QL_NAME, ha->instance);
954*fcf3ce44SJohn Forte 
955*fcf3ce44SJohn Forte 		EL(ha, "failed, rval=%xh, checksum=%xh, id=%c%c%c%c, "
956*fcf3ce44SJohn Forte 		    "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
957*fcf3ce44SJohn Forte 		    nv->id[2], nv->id[3], CHAR_TO_SHORT(nv->nvram_version[0],
958*fcf3ce44SJohn Forte 		    nv->nvram_version[1]));
959*fcf3ce44SJohn Forte 
960*fcf3ce44SJohn Forte 		saved_chksum = ~saved_chksum + 1;
961*fcf3ce44SJohn Forte 
962*fcf3ce44SJohn Forte 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_NVRAM_CHKSUM_ERR, 0,
963*fcf3ce44SJohn Forte 		    MSW(saved_chksum), LSW(saved_chksum));
964*fcf3ce44SJohn Forte 
965*fcf3ce44SJohn Forte 		/* Reset NVRAM data. */
966*fcf3ce44SJohn Forte 		bzero((void *)nv, sizeof (nvram_24xx_t));
967*fcf3ce44SJohn Forte 
968*fcf3ce44SJohn Forte 		/*
969*fcf3ce44SJohn Forte 		 * Set default initialization control block.
970*fcf3ce44SJohn Forte 		 */
971*fcf3ce44SJohn Forte 		nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
972*fcf3ce44SJohn Forte 		nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
973*fcf3ce44SJohn Forte 
974*fcf3ce44SJohn Forte 		nv->version[0] = 1;
975*fcf3ce44SJohn Forte 		nv->max_frame_length[1] = 8;
976*fcf3ce44SJohn Forte 		nv->execution_throttle[0] = 16;
977*fcf3ce44SJohn Forte 		nv->max_luns_per_target[0] = 8;
978*fcf3ce44SJohn Forte 
979*fcf3ce44SJohn Forte 		idpromlen = 32;
980*fcf3ce44SJohn Forte 
981*fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
982*fcf3ce44SJohn Forte 		if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
983*fcf3ce44SJohn Forte 		    DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
984*fcf3ce44SJohn Forte 		    &idpromlen) != DDI_PROP_SUCCESS) {
985*fcf3ce44SJohn Forte 
986*fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
987*fcf3ce44SJohn Forte 			    "property", QL_NAME, ha->instance);
988*fcf3ce44SJohn Forte 
989*fcf3ce44SJohn Forte 			nv->port_name[0] = 33;
990*fcf3ce44SJohn Forte 			nv->port_name[3] = 224;
991*fcf3ce44SJohn Forte 			nv->port_name[4] = 139;
992*fcf3ce44SJohn Forte 			nv->port_name[7] = (uint8_t)
993*fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
994*fcf3ce44SJohn Forte 
995*fcf3ce44SJohn Forte 		} else {
996*fcf3ce44SJohn Forte 			nv->port_name[2] = idprombuf[2];
997*fcf3ce44SJohn Forte 			nv->port_name[3] = idprombuf[3];
998*fcf3ce44SJohn Forte 			nv->port_name[4] = idprombuf[4];
999*fcf3ce44SJohn Forte 			nv->port_name[5] = idprombuf[5];
1000*fcf3ce44SJohn Forte 			nv->port_name[6] = idprombuf[6];
1001*fcf3ce44SJohn Forte 			nv->port_name[7] = idprombuf[7];
1002*fcf3ce44SJohn Forte 			nv->port_name[0] = (uint8_t)
1003*fcf3ce44SJohn Forte 			    (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
1004*fcf3ce44SJohn Forte 
1005*fcf3ce44SJohn Forte 		}
1006*fcf3ce44SJohn Forte 
1007*fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using default "
1008*fcf3ce44SJohn Forte 		    "HBA parameters and temporary "
1009*fcf3ce44SJohn Forte 		    "WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
1010*fcf3ce44SJohn Forte 		    ha->instance, nv->port_name[0], nv->port_name[1],
1011*fcf3ce44SJohn Forte 		    nv->port_name[2], nv->port_name[3], nv->port_name[4],
1012*fcf3ce44SJohn Forte 		    nv->port_name[5], nv->port_name[6], nv->port_name[7]);
1013*fcf3ce44SJohn Forte 
1014*fcf3ce44SJohn Forte 
1015*fcf3ce44SJohn Forte 		nv->login_retry_count[0] = 8;
1016*fcf3ce44SJohn Forte 
1017*fcf3ce44SJohn Forte 		nv->firmware_options_1[0] = BIT_2 | BIT_1;
1018*fcf3ce44SJohn Forte 		nv->firmware_options_1[1] = BIT_5;
1019*fcf3ce44SJohn Forte 		nv->firmware_options_2[0] = BIT_5;
1020*fcf3ce44SJohn Forte 		nv->firmware_options_2[1] = BIT_4;
1021*fcf3ce44SJohn Forte 		nv->firmware_options_3[1] = BIT_6;
1022*fcf3ce44SJohn Forte 
1023*fcf3ce44SJohn Forte 		/*
1024*fcf3ce44SJohn Forte 		 * Set default host adapter parameters
1025*fcf3ce44SJohn Forte 		 */
1026*fcf3ce44SJohn Forte 		nv->host_p[0] = BIT_4 | BIT_1;
1027*fcf3ce44SJohn Forte 		nv->host_p[1] = BIT_3 | BIT_2;
1028*fcf3ce44SJohn Forte 		nv->reset_delay = 5;
1029*fcf3ce44SJohn Forte 		nv->max_luns_per_target[0] = 128;
1030*fcf3ce44SJohn Forte 		nv->port_down_retry_count[0] = 30;
1031*fcf3ce44SJohn Forte 		nv->link_down_timeout[0] = 30;
1032*fcf3ce44SJohn Forte 
1033*fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
1034*fcf3ce44SJohn Forte 	}
1035*fcf3ce44SJohn Forte 
1036*fcf3ce44SJohn Forte 	/* Check for adapter node name (big endian). */
1037*fcf3ce44SJohn Forte 	for (index = 0; index < 8; index++) {
1038*fcf3ce44SJohn Forte 		if (nv->node_name[index] != 0) {
1039*fcf3ce44SJohn Forte 			break;
1040*fcf3ce44SJohn Forte 		}
1041*fcf3ce44SJohn Forte 	}
1042*fcf3ce44SJohn Forte 
1043*fcf3ce44SJohn Forte 	/* Copy port name if no node name (big endian). */
1044*fcf3ce44SJohn Forte 	if (index == 8) {
1045*fcf3ce44SJohn Forte 		bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8);
1046*fcf3ce44SJohn Forte 		nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
1047*fcf3ce44SJohn Forte 		nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
1048*fcf3ce44SJohn Forte 	}
1049*fcf3ce44SJohn Forte 
1050*fcf3ce44SJohn Forte 	/* Reset initialization control blocks. */
1051*fcf3ce44SJohn Forte 	bzero((void *)icb, sizeof (ql_init_24xx_cb_t));
1052*fcf3ce44SJohn Forte 
1053*fcf3ce44SJohn Forte 	/* Get driver properties. */
1054*fcf3ce44SJohn Forte 	ql_24xx_properties(ha, nv);
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte 	cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
1057*fcf3ce44SJohn Forte 	    "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
1058*fcf3ce44SJohn Forte 	    QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1],
1059*fcf3ce44SJohn Forte 	    nv->port_name[2], nv->port_name[3], nv->port_name[4],
1060*fcf3ce44SJohn Forte 	    nv->port_name[5], nv->port_name[6], nv->port_name[7],
1061*fcf3ce44SJohn Forte 	    nv->node_name[0], nv->node_name[1], nv->node_name[2],
1062*fcf3ce44SJohn Forte 	    nv->node_name[3], nv->node_name[4], nv->node_name[5],
1063*fcf3ce44SJohn Forte 	    nv->node_name[6], nv->node_name[7]);
1064*fcf3ce44SJohn Forte 
1065*fcf3ce44SJohn Forte 	/*
1066*fcf3ce44SJohn Forte 	 * Copy over NVRAM Firmware Initialization Control Block.
1067*fcf3ce44SJohn Forte 	 */
1068*fcf3ce44SJohn Forte 	dst = (caddr_t)icb;
1069*fcf3ce44SJohn Forte 	src = (caddr_t)&nv->version;
1070*fcf3ce44SJohn Forte 	index = (uint32_t)((uintptr_t)&icb->response_q_inpointer[0] -
1071*fcf3ce44SJohn Forte 	    (uintptr_t)icb);
1072*fcf3ce44SJohn Forte 	while (index--) {
1073*fcf3ce44SJohn Forte 		*dst++ = *src++;
1074*fcf3ce44SJohn Forte 	}
1075*fcf3ce44SJohn Forte 	icb->login_retry_count[0] = nv->login_retry_count[0];
1076*fcf3ce44SJohn Forte 	icb->login_retry_count[1] = nv->login_retry_count[1];
1077*fcf3ce44SJohn Forte 	icb->link_down_on_nos[0] = nv->link_down_on_nos[0];
1078*fcf3ce44SJohn Forte 	icb->link_down_on_nos[1] = nv->link_down_on_nos[1];
1079*fcf3ce44SJohn Forte 
1080*fcf3ce44SJohn Forte 	dst = (caddr_t)&icb->interrupt_delay_timer;
1081*fcf3ce44SJohn Forte 	src = (caddr_t)&nv->interrupt_delay_timer;
1082*fcf3ce44SJohn Forte 	index = (uint32_t)((uintptr_t)&icb->reserved_3 -
1083*fcf3ce44SJohn Forte 	    (uintptr_t)&icb->interrupt_delay_timer);
1084*fcf3ce44SJohn Forte 	while (index--) {
1085*fcf3ce44SJohn Forte 		*dst++ = *src++;
1086*fcf3ce44SJohn Forte 	}
1087*fcf3ce44SJohn Forte 
1088*fcf3ce44SJohn Forte 	/*
1089*fcf3ce44SJohn Forte 	 * Setup driver firmware options.
1090*fcf3ce44SJohn Forte 	 */
1091*fcf3ce44SJohn Forte 	icb->firmware_options_1[0] = (uint8_t)(icb->firmware_options_1[0] &
1092*fcf3ce44SJohn Forte 	    ~(BIT_5 | BIT_4));
1093*fcf3ce44SJohn Forte 	icb->firmware_options_1[1] = (uint8_t)(icb->firmware_options_1[1] |
1094*fcf3ce44SJohn Forte 	    BIT_6 | BIT_5 | BIT_2);
1095*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_TARGET_MODE_ENABLE)) {
1096*fcf3ce44SJohn Forte 		icb->firmware_options_1[0] = (uint8_t)
1097*fcf3ce44SJohn Forte 		    (icb->firmware_options_1[0] | BIT_4 | BIT_1);
1098*fcf3ce44SJohn Forte 		EL(ha, "Target mode enabled\n");
1099*fcf3ce44SJohn Forte 	} else {
1100*fcf3ce44SJohn Forte 		icb->firmware_options_1[0] = (uint8_t)
1101*fcf3ce44SJohn Forte 		    (icb->firmware_options_1[0] | BIT_1);
1102*fcf3ce44SJohn Forte 	}
1103*fcf3ce44SJohn Forte 
1104*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
1105*fcf3ce44SJohn Forte 		icb->firmware_options_2[1] = (uint8_t)
1106*fcf3ce44SJohn Forte 		    (icb->firmware_options_2[1] | BIT_4);
1107*fcf3ce44SJohn Forte 	} else {
1108*fcf3ce44SJohn Forte 		icb->firmware_options_2[1] = (uint8_t)
1109*fcf3ce44SJohn Forte 		    (icb->firmware_options_2[1] & ~BIT_4);
1110*fcf3ce44SJohn Forte 	}
1111*fcf3ce44SJohn Forte 
1112*fcf3ce44SJohn Forte 	icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] |
1113*fcf3ce44SJohn Forte 	    BIT_1);
1114*fcf3ce44SJohn Forte 	icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] &
1115*fcf3ce44SJohn Forte 	    ~BIT_7);
1116*fcf3ce44SJohn Forte 
1117*fcf3ce44SJohn Forte 	icb->execution_throttle[0] = 0xff;
1118*fcf3ce44SJohn Forte 	icb->execution_throttle[1] = 0xff;
1119*fcf3ce44SJohn Forte 
1120*fcf3ce44SJohn Forte 	/*
1121*fcf3ce44SJohn Forte 	 * Set host adapter parameters
1122*fcf3ce44SJohn Forte 	 */
1123*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1124*fcf3ce44SJohn Forte 	ha->nvram_version = CHAR_TO_SHORT(nv->nvram_version[0],
1125*fcf3ce44SJohn Forte 	    nv->nvram_version[1]);
1126*fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) :
1127*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN);
1128*fcf3ce44SJohn Forte 	nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) :
1129*fcf3ce44SJohn Forte 	    (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET);
1130*fcf3ce44SJohn Forte 	ha->cfg_flags &= ~(CFG_DISABLE_RISC_CODE_LOAD |
1131*fcf3ce44SJohn Forte 	    CFG_SET_CACHE_LINE_SIZE_1 | CFG_MULTI_CHIP_ADAPTER);
1132*fcf3ce44SJohn Forte 	ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
1133*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1134*fcf3ce44SJohn Forte 
1135*fcf3ce44SJohn Forte 	ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1136*fcf3ce44SJohn Forte 	ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1137*fcf3ce44SJohn Forte 
1138*fcf3ce44SJohn Forte 	ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
1139*fcf3ce44SJohn Forte 	    nv->execution_throttle[1]);
1140*fcf3ce44SJohn Forte 	ha->loop_reset_delay = nv->reset_delay;
1141*fcf3ce44SJohn Forte 	ha->port_down_retry_count = CHAR_TO_SHORT(nv->port_down_retry_count[0],
1142*fcf3ce44SJohn Forte 	    nv->port_down_retry_count[1]);
1143*fcf3ce44SJohn Forte 	w1 = CHAR_TO_SHORT(icb->login_timeout[0], icb->login_timeout[1]);
1144*fcf3ce44SJohn Forte 	ha->r_a_tov = (uint16_t)(w1 < R_A_TOV_DEFAULT ? R_A_TOV_DEFAULT : w1);
1145*fcf3ce44SJohn Forte 	ha->maximum_luns_per_target = CHAR_TO_SHORT(
1146*fcf3ce44SJohn Forte 	    nv->max_luns_per_target[0], nv->max_luns_per_target[1]);
1147*fcf3ce44SJohn Forte 	if (ha->maximum_luns_per_target == 0) {
1148*fcf3ce44SJohn Forte 		ha->maximum_luns_per_target++;
1149*fcf3ce44SJohn Forte 	}
1150*fcf3ce44SJohn Forte 
1151*fcf3ce44SJohn Forte 	/* ISP2422 Serial Link Control */
1152*fcf3ce44SJohn Forte 	ha->serdes_param[0] = CHAR_TO_SHORT(nv->swing_opt[0],
1153*fcf3ce44SJohn Forte 	    nv->swing_opt[1]);
1154*fcf3ce44SJohn Forte 	ha->serdes_param[1] = CHAR_TO_SHORT(nv->swing_1g[0], nv->swing_1g[1]);
1155*fcf3ce44SJohn Forte 	ha->serdes_param[2] = CHAR_TO_SHORT(nv->swing_2g[0], nv->swing_2g[1]);
1156*fcf3ce44SJohn Forte 	ha->serdes_param[3] = CHAR_TO_SHORT(nv->swing_4g[0], nv->swing_4g[1]);
1157*fcf3ce44SJohn Forte 
1158*fcf3ce44SJohn Forte 	/*
1159*fcf3ce44SJohn Forte 	 * Setup ring parameters in initialization control block
1160*fcf3ce44SJohn Forte 	 */
1161*fcf3ce44SJohn Forte 	w1 = REQUEST_ENTRY_CNT;
1162*fcf3ce44SJohn Forte 	icb->request_q_length[0] = LSB(w1);
1163*fcf3ce44SJohn Forte 	icb->request_q_length[1] = MSB(w1);
1164*fcf3ce44SJohn Forte 	w1 = RESPONSE_ENTRY_CNT;
1165*fcf3ce44SJohn Forte 	icb->response_q_length[0] = LSB(w1);
1166*fcf3ce44SJohn Forte 	icb->response_q_length[1] = MSB(w1);
1167*fcf3ce44SJohn Forte 
1168*fcf3ce44SJohn Forte 	icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma)));
1169*fcf3ce44SJohn Forte 	icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma)));
1170*fcf3ce44SJohn Forte 	icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma)));
1171*fcf3ce44SJohn Forte 	icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma)));
1172*fcf3ce44SJohn Forte 	icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma)));
1173*fcf3ce44SJohn Forte 	icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma)));
1174*fcf3ce44SJohn Forte 	icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma)));
1175*fcf3ce44SJohn Forte 	icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma)));
1176*fcf3ce44SJohn Forte 
1177*fcf3ce44SJohn Forte 	icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma)));
1178*fcf3ce44SJohn Forte 	icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma)));
1179*fcf3ce44SJohn Forte 	icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma)));
1180*fcf3ce44SJohn Forte 	icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma)));
1181*fcf3ce44SJohn Forte 	icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma)));
1182*fcf3ce44SJohn Forte 	icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma)));
1183*fcf3ce44SJohn Forte 	icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma)));
1184*fcf3ce44SJohn Forte 	icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma)));
1185*fcf3ce44SJohn Forte 
1186*fcf3ce44SJohn Forte 	/*
1187*fcf3ce44SJohn Forte 	 * Setup IP initialization control block
1188*fcf3ce44SJohn Forte 	 */
1189*fcf3ce44SJohn Forte 	ip_icb->version = IP_ICB_24XX_VERSION;
1190*fcf3ce44SJohn Forte 
1191*fcf3ce44SJohn Forte 	ip_icb->ip_firmware_options[0] = (uint8_t)
1192*fcf3ce44SJohn Forte 	    (ip_icb->ip_firmware_options[0] | BIT_2);
1193*fcf3ce44SJohn Forte 
1194*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
1195*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
1196*fcf3ce44SJohn Forte 	} else {
1197*fcf3ce44SJohn Forte 		/*EMPTY*/
1198*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1199*fcf3ce44SJohn Forte 	}
1200*fcf3ce44SJohn Forte 	return (rval);
1201*fcf3ce44SJohn Forte }
1202*fcf3ce44SJohn Forte 
1203*fcf3ce44SJohn Forte /*
1204*fcf3ce44SJohn Forte  * ql_lock_nvram
1205*fcf3ce44SJohn Forte  *	Locks NVRAM access and returns starting address of NVRAM.
1206*fcf3ce44SJohn Forte  *
1207*fcf3ce44SJohn Forte  * Input:
1208*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1209*fcf3ce44SJohn Forte  *	addr:	pointer for start address.
1210*fcf3ce44SJohn Forte  *	flags:	Are mutually exclusive:
1211*fcf3ce44SJohn Forte  *		LNF_NVRAM_DATA --> get nvram
1212*fcf3ce44SJohn Forte  *		LNF_VPD_DATA --> get vpd data (24/25xx only).
1213*fcf3ce44SJohn Forte  *
1214*fcf3ce44SJohn Forte  * Returns:
1215*fcf3ce44SJohn Forte  *	ql local function return status code.
1216*fcf3ce44SJohn Forte  *
1217*fcf3ce44SJohn Forte  * Context:
1218*fcf3ce44SJohn Forte  *	Kernel context.
1219*fcf3ce44SJohn Forte  */
1220*fcf3ce44SJohn Forte int
1221*fcf3ce44SJohn Forte ql_lock_nvram(ql_adapter_state_t *ha, uint32_t *addr, uint32_t flags)
1222*fcf3ce44SJohn Forte {
1223*fcf3ce44SJohn Forte 	int	i;
1224*fcf3ce44SJohn Forte 
1225*fcf3ce44SJohn Forte 	if ((flags & LNF_NVRAM_DATA) && (flags & LNF_VPD_DATA)) {
1226*fcf3ce44SJohn Forte 		EL(ha, "invalid options for function");
1227*fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
1228*fcf3ce44SJohn Forte 	}
1229*fcf3ce44SJohn Forte 
1230*fcf3ce44SJohn Forte 	if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
1231*fcf3ce44SJohn Forte 		if ((flags & LNF_NVRAM_DATA) == 0) {
1232*fcf3ce44SJohn Forte 			EL(ha, "invalid 2312/2322 option for HBA");
1233*fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1234*fcf3ce44SJohn Forte 		}
1235*fcf3ce44SJohn Forte 
1236*fcf3ce44SJohn Forte 		/* if function number is non-zero, then adjust offset */
1237*fcf3ce44SJohn Forte 		*addr = RD16_IO_REG(ha, ctrl_status) & 0xc000 ? 128 : 0;
1238*fcf3ce44SJohn Forte 
1239*fcf3ce44SJohn Forte 		/* Try to get resource lock. Wait for 10 seconds max */
1240*fcf3ce44SJohn Forte 		for (i = 0; i < 10000; i++) {
1241*fcf3ce44SJohn Forte 			/* if nvram busy bit is reset, acquire sema */
1242*fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, nvram) & 0x8000) == 0) {
1243*fcf3ce44SJohn Forte 				WRT16_IO_REG(ha, host_to_host_sema, 1);
1244*fcf3ce44SJohn Forte 				drv_usecwait(MILLISEC);
1245*fcf3ce44SJohn Forte 				if (RD16_IO_REG(ha, host_to_host_sema) & 1) {
1246*fcf3ce44SJohn Forte 					break;
1247*fcf3ce44SJohn Forte 				}
1248*fcf3ce44SJohn Forte 			}
1249*fcf3ce44SJohn Forte 			drv_usecwait(MILLISEC);
1250*fcf3ce44SJohn Forte 		}
1251*fcf3ce44SJohn Forte 		if ((RD16_IO_REG(ha, host_to_host_sema) & 1) == 0) {
1252*fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): unable to get NVRAM lock",
1253*fcf3ce44SJohn Forte 			    QL_NAME, ha->instance);
1254*fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1255*fcf3ce44SJohn Forte 		}
1256*fcf3ce44SJohn Forte 	} else if (CFG_IST(ha, CFG_CTRL_2422)) {
1257*fcf3ce44SJohn Forte 		if (flags & LNF_VPD_DATA) {
1258*fcf3ce44SJohn Forte 			*addr = RD32_IO_REG(ha, ctrl_status) &
1259*fcf3ce44SJohn Forte 			    FUNCTION_NUMBER ? VPD_24XX_FUNC1_ADDR :
1260*fcf3ce44SJohn Forte 			    VPD_24XX_FUNC0_ADDR;
1261*fcf3ce44SJohn Forte 		} else if (flags & LNF_NVRAM_DATA) {
1262*fcf3ce44SJohn Forte 			*addr = RD32_IO_REG(ha, ctrl_status) &
1263*fcf3ce44SJohn Forte 			    FUNCTION_NUMBER ? NVRAM_24XX_FUNC1_ADDR :
1264*fcf3ce44SJohn Forte 			    NVRAM_24XX_FUNC0_ADDR;
1265*fcf3ce44SJohn Forte 		} else {
1266*fcf3ce44SJohn Forte 			EL(ha, "invalid 24xx option for HBA");
1267*fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1268*fcf3ce44SJohn Forte 		}
1269*fcf3ce44SJohn Forte 
1270*fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1271*fcf3ce44SJohn Forte 	} else if (CFG_IST(ha, CFG_CTRL_25XX)) {
1272*fcf3ce44SJohn Forte 		if (flags & LNF_VPD_DATA) {
1273*fcf3ce44SJohn Forte 			*addr = RD32_IO_REG(ha, ctrl_status) &
1274*fcf3ce44SJohn Forte 			    FUNCTION_NUMBER ? VPD_25XX_FUNC1_ADDR :
1275*fcf3ce44SJohn Forte 			    VPD_25XX_FUNC0_ADDR;
1276*fcf3ce44SJohn Forte 		} else if (flags & LNF_NVRAM_DATA) {
1277*fcf3ce44SJohn Forte 			*addr = RD32_IO_REG(ha, ctrl_status) &
1278*fcf3ce44SJohn Forte 			    FUNCTION_NUMBER ? NVRAM_25XX_FUNC1_ADDR :
1279*fcf3ce44SJohn Forte 			    NVRAM_25XX_FUNC0_ADDR;
1280*fcf3ce44SJohn Forte 		} else {
1281*fcf3ce44SJohn Forte 			EL(ha, "invalid 25xx option for HBA");
1282*fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1283*fcf3ce44SJohn Forte 		}
1284*fcf3ce44SJohn Forte 
1285*fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1286*fcf3ce44SJohn Forte 	} else {
1287*fcf3ce44SJohn Forte 		if ((flags & LNF_NVRAM_DATA) == 0) {
1288*fcf3ce44SJohn Forte 			EL(ha, "invalid option for HBA");
1289*fcf3ce44SJohn Forte 			return (QL_FUNCTION_FAILED);
1290*fcf3ce44SJohn Forte 		}
1291*fcf3ce44SJohn Forte 		*addr = 0;
1292*fcf3ce44SJohn Forte 		GLOBAL_HW_LOCK();
1293*fcf3ce44SJohn Forte 	}
1294*fcf3ce44SJohn Forte 
1295*fcf3ce44SJohn Forte 	return (QL_SUCCESS);
1296*fcf3ce44SJohn Forte }
1297*fcf3ce44SJohn Forte 
1298*fcf3ce44SJohn Forte /*
1299*fcf3ce44SJohn Forte  * ql_release_nvram
1300*fcf3ce44SJohn Forte  *	Releases NVRAM access.
1301*fcf3ce44SJohn Forte  *
1302*fcf3ce44SJohn Forte  * Input:
1303*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1304*fcf3ce44SJohn Forte  *
1305*fcf3ce44SJohn Forte  * Context:
1306*fcf3ce44SJohn Forte  *	Kernel context.
1307*fcf3ce44SJohn Forte  */
1308*fcf3ce44SJohn Forte void
1309*fcf3ce44SJohn Forte ql_release_nvram(ql_adapter_state_t *ha)
1310*fcf3ce44SJohn Forte {
1311*fcf3ce44SJohn Forte 	if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
1312*fcf3ce44SJohn Forte 		/* Release resource lock */
1313*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, host_to_host_sema, 0);
1314*fcf3ce44SJohn Forte 	} else {
1315*fcf3ce44SJohn Forte 		GLOBAL_HW_UNLOCK();
1316*fcf3ce44SJohn Forte 	}
1317*fcf3ce44SJohn Forte }
1318*fcf3ce44SJohn Forte 
1319*fcf3ce44SJohn Forte /*
1320*fcf3ce44SJohn Forte  * ql_23_properties
1321*fcf3ce44SJohn Forte  *	Copies driver properties to NVRAM or adapter structure.
1322*fcf3ce44SJohn Forte  *
1323*fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1324*fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1325*fcf3ce44SJohn Forte  *	override the default values using driver.conf
1326*fcf3ce44SJohn Forte  *
1327*fcf3ce44SJohn Forte  * Input:
1328*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1329*fcf3ce44SJohn Forte  *	nv:	NVRAM structure pointer.
1330*fcf3ce44SJohn Forte  *
1331*fcf3ce44SJohn Forte  * Context:
1332*fcf3ce44SJohn Forte  *	Kernel context.
1333*fcf3ce44SJohn Forte  */
1334*fcf3ce44SJohn Forte static void
1335*fcf3ce44SJohn Forte ql_23_properties(ql_adapter_state_t *ha, nvram_t *nv)
1336*fcf3ce44SJohn Forte {
1337*fcf3ce44SJohn Forte 	uint32_t	data, cnt;
1338*fcf3ce44SJohn Forte 
1339*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1340*fcf3ce44SJohn Forte 
1341*fcf3ce44SJohn Forte 	/* Get frame payload size. */
1342*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
1343*fcf3ce44SJohn Forte 		data = 2048;
1344*fcf3ce44SJohn Forte 	}
1345*fcf3ce44SJohn Forte 	if (data == 512 || data == 1024 || data == 2048) {
1346*fcf3ce44SJohn Forte 		nv->max_frame_length[0] = LSB(data);
1347*fcf3ce44SJohn Forte 		nv->max_frame_length[1] = MSB(data);
1348*fcf3ce44SJohn Forte 	} else {
1349*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'max-frame-length': "
1350*fcf3ce44SJohn Forte 		    "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1351*fcf3ce44SJohn Forte 		    nv->max_frame_length[0], nv->max_frame_length[1]));
1352*fcf3ce44SJohn Forte 	}
1353*fcf3ce44SJohn Forte 
1354*fcf3ce44SJohn Forte 	/* Get max IOCB allocation. */
1355*fcf3ce44SJohn Forte 	nv->max_iocb_allocation[0] = 0;
1356*fcf3ce44SJohn Forte 	nv->max_iocb_allocation[1] = 1;
1357*fcf3ce44SJohn Forte 
1358*fcf3ce44SJohn Forte 	/* Get execution throttle. */
1359*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
1360*fcf3ce44SJohn Forte 		data = 32;
1361*fcf3ce44SJohn Forte 	}
1362*fcf3ce44SJohn Forte 	if (data != 0 && data < 65536) {
1363*fcf3ce44SJohn Forte 		nv->execution_throttle[0] = LSB(data);
1364*fcf3ce44SJohn Forte 		nv->execution_throttle[1] = MSB(data);
1365*fcf3ce44SJohn Forte 	} else {
1366*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'execution-throttle': "
1367*fcf3ce44SJohn Forte 		    "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1368*fcf3ce44SJohn Forte 		    nv->execution_throttle[0], nv->execution_throttle[1]));
1369*fcf3ce44SJohn Forte 	}
1370*fcf3ce44SJohn Forte 
1371*fcf3ce44SJohn Forte 	/* Get Login timeout. */
1372*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
1373*fcf3ce44SJohn Forte 		data = 3;
1374*fcf3ce44SJohn Forte 	}
1375*fcf3ce44SJohn Forte 	if (data < 256) {
1376*fcf3ce44SJohn Forte 		nv->login_timeout = (uint8_t)data;
1377*fcf3ce44SJohn Forte 	} else {
1378*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-timeout': "
1379*fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data, nv->login_timeout);
1380*fcf3ce44SJohn Forte 	}
1381*fcf3ce44SJohn Forte 
1382*fcf3ce44SJohn Forte 	/* Get retry count. */
1383*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
1384*fcf3ce44SJohn Forte 		data = 4;
1385*fcf3ce44SJohn Forte 	}
1386*fcf3ce44SJohn Forte 	if (data < 256) {
1387*fcf3ce44SJohn Forte 		nv->login_retry_count = (uint8_t)data;
1388*fcf3ce44SJohn Forte 	} else {
1389*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-retry-count': "
1390*fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data,
1391*fcf3ce44SJohn Forte 		    nv->login_retry_count);
1392*fcf3ce44SJohn Forte 	}
1393*fcf3ce44SJohn Forte 
1394*fcf3ce44SJohn Forte 	/* Get adapter hard loop ID enable. */
1395*fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "enable-adapter-hard-loop-ID");
1396*fcf3ce44SJohn Forte 	if (data == 0) {
1397*fcf3ce44SJohn Forte 		nv->firmware_options[0] =
1398*fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options[0] & ~BIT_0);
1399*fcf3ce44SJohn Forte 	} else if (data == 1) {
1400*fcf3ce44SJohn Forte 		nv->firmware_options[0] =
1401*fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options[0] | BIT_0);
1402*fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1403*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1404*fcf3ce44SJohn Forte 		    "'enable-adapter-hard-loop-ID': %d; using nvram value "
1405*fcf3ce44SJohn Forte 		    "of %d\n", data, nv->firmware_options[0] & BIT_0 ? 1 : 0);
1406*fcf3ce44SJohn Forte 	}
1407*fcf3ce44SJohn Forte 
1408*fcf3ce44SJohn Forte 	/* Get adapter hard loop ID. */
1409*fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "adapter-hard-loop-ID");
1410*fcf3ce44SJohn Forte 	if (data < 126) {
1411*fcf3ce44SJohn Forte 		nv->hard_address[0] = (uint8_t)data;
1412*fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1413*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'adapter-hard-loop-ID': "
1414*fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data, nv->hard_address[0]);
1415*fcf3ce44SJohn Forte 	}
1416*fcf3ce44SJohn Forte 
1417*fcf3ce44SJohn Forte 	/* Get LIP reset. */
1418*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
1419*fcf3ce44SJohn Forte 	    0xffffffff) {
1420*fcf3ce44SJohn Forte 		data = 0;
1421*fcf3ce44SJohn Forte 	}
1422*fcf3ce44SJohn Forte 	if (data == 0) {
1423*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_1);
1424*fcf3ce44SJohn Forte 	} else if (data == 1) {
1425*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_1);
1426*fcf3ce44SJohn Forte 	} else {
1427*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1428*fcf3ce44SJohn Forte 		    "'enable-LIP-reset-on-bus-reset': %d; using nvram value "
1429*fcf3ce44SJohn Forte 		    "of %d\n", data, nv->host_p[1] & BIT_1 ? 1 : 0);
1430*fcf3ce44SJohn Forte 	}
1431*fcf3ce44SJohn Forte 
1432*fcf3ce44SJohn Forte 	/* Get LIP full login. */
1433*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
1434*fcf3ce44SJohn Forte 	    0xffffffff) {
1435*fcf3ce44SJohn Forte 		data = 1;
1436*fcf3ce44SJohn Forte 	}
1437*fcf3ce44SJohn Forte 	if (data == 0) {
1438*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2);
1439*fcf3ce44SJohn Forte 	} else if (data == 1) {
1440*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2);
1441*fcf3ce44SJohn Forte 	} else {
1442*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1443*fcf3ce44SJohn Forte 		    "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
1444*fcf3ce44SJohn Forte 		    "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0);
1445*fcf3ce44SJohn Forte 	}
1446*fcf3ce44SJohn Forte 
1447*fcf3ce44SJohn Forte 	/* Get target reset. */
1448*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
1449*fcf3ce44SJohn Forte 	    0xffffffff) {
1450*fcf3ce44SJohn Forte 		data = 0;
1451*fcf3ce44SJohn Forte 	}
1452*fcf3ce44SJohn Forte 	if (data == 0) {
1453*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3);
1454*fcf3ce44SJohn Forte 	} else if (data == 1) {
1455*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3);
1456*fcf3ce44SJohn Forte 	} else {
1457*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1458*fcf3ce44SJohn Forte 		    "'enable-target-reset-on-bus-reset': %d; using nvram "
1459*fcf3ce44SJohn Forte 		    "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0);
1460*fcf3ce44SJohn Forte 	}
1461*fcf3ce44SJohn Forte 
1462*fcf3ce44SJohn Forte 	/* Get reset delay. */
1463*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
1464*fcf3ce44SJohn Forte 		data = 5;
1465*fcf3ce44SJohn Forte 	}
1466*fcf3ce44SJohn Forte 	if (data != 0 && data < 256) {
1467*fcf3ce44SJohn Forte 		nv->reset_delay = (uint8_t)data;
1468*fcf3ce44SJohn Forte 	} else {
1469*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'reset-delay': %d; "
1470*fcf3ce44SJohn Forte 		    "using nvram value of %d", data, nv->reset_delay);
1471*fcf3ce44SJohn Forte 	}
1472*fcf3ce44SJohn Forte 
1473*fcf3ce44SJohn Forte 	/* Get port down retry count. */
1474*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
1475*fcf3ce44SJohn Forte 		data = 8;
1476*fcf3ce44SJohn Forte 	}
1477*fcf3ce44SJohn Forte 	if (data < 256) {
1478*fcf3ce44SJohn Forte 		nv->port_down_retry_count = (uint8_t)data;
1479*fcf3ce44SJohn Forte 	} else {
1480*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-count':"
1481*fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data,
1482*fcf3ce44SJohn Forte 		    nv->port_down_retry_count);
1483*fcf3ce44SJohn Forte 	}
1484*fcf3ce44SJohn Forte 
1485*fcf3ce44SJohn Forte 	/* Get connection mode setting. */
1486*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) {
1487*fcf3ce44SJohn Forte 		data = 2;
1488*fcf3ce44SJohn Forte 	}
1489*fcf3ce44SJohn Forte 	cnt = CFG_IST(ha, CFG_CTRL_2200) ? 3 : 2;
1490*fcf3ce44SJohn Forte 	if (data <= cnt) {
1491*fcf3ce44SJohn Forte 		nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] &
1492*fcf3ce44SJohn Forte 		    ~(BIT_6 | BIT_5 | BIT_4));
1493*fcf3ce44SJohn Forte 		nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
1494*fcf3ce44SJohn Forte 		    (uint8_t)(data << 4));
1495*fcf3ce44SJohn Forte 	} else {
1496*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'connection-options': "
1497*fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data,
1498*fcf3ce44SJohn Forte 		    (nv->add_fw_opt[0] >> 4) & 0x3);
1499*fcf3ce44SJohn Forte 	}
1500*fcf3ce44SJohn Forte 
1501*fcf3ce44SJohn Forte 	/* Get data rate setting. */
1502*fcf3ce44SJohn Forte 	if ((CFG_IST(ha, CFG_CTRL_2200)) == 0) {
1503*fcf3ce44SJohn Forte 		if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
1504*fcf3ce44SJohn Forte 			data = 2;
1505*fcf3ce44SJohn Forte 		}
1506*fcf3ce44SJohn Forte 		if (data < 3) {
1507*fcf3ce44SJohn Forte 			nv->special_options[1] = (uint8_t)
1508*fcf3ce44SJohn Forte 			    (nv->special_options[1] & 0x3f);
1509*fcf3ce44SJohn Forte 			nv->special_options[1] = (uint8_t)
1510*fcf3ce44SJohn Forte 			    (nv->special_options[1] | (uint8_t)(data << 6));
1511*fcf3ce44SJohn Forte 		} else {
1512*fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for 'fc-data-rate': "
1513*fcf3ce44SJohn Forte 			    "%d; using nvram value of %d\n", data,
1514*fcf3ce44SJohn Forte 			    (nv->special_options[1] >> 6) & 0x3);
1515*fcf3ce44SJohn Forte 		}
1516*fcf3ce44SJohn Forte 	}
1517*fcf3ce44SJohn Forte 
1518*fcf3ce44SJohn Forte 	/* Get adapter id string for Sun branded 23xx only */
1519*fcf3ce44SJohn Forte 	if ((CFG_IST(ha, CFG_CTRL_2300)) && nv->adapInfo[0] != 0) {
1520*fcf3ce44SJohn Forte 		(void) snprintf((int8_t *)ha->adapInfo, 16, "%s",
1521*fcf3ce44SJohn Forte 		    nv->adapInfo);
1522*fcf3ce44SJohn Forte 	}
1523*fcf3ce44SJohn Forte 
1524*fcf3ce44SJohn Forte 	/* Get IP FW container count. */
1525*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.cc[0] = LSB(ql_ip_buffer_count);
1526*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.cc[1] = MSB(ql_ip_buffer_count);
1527*fcf3ce44SJohn Forte 
1528*fcf3ce44SJohn Forte 	/* Get IP low water mark. */
1529*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.low_water_mark[0] = LSB(ql_ip_low_water);
1530*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.low_water_mark[1] = MSB(ql_ip_low_water);
1531*fcf3ce44SJohn Forte 
1532*fcf3ce44SJohn Forte 	/* Get IP fast register post count. */
1533*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb.fast_post_reg_count[0] =
1534*fcf3ce44SJohn Forte 	    ql_ip_fast_post_count;
1535*fcf3ce44SJohn Forte 
1536*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1537*fcf3ce44SJohn Forte 
1538*fcf3ce44SJohn Forte 	ql_common_properties(ha);
1539*fcf3ce44SJohn Forte 
1540*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1541*fcf3ce44SJohn Forte 
1542*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1543*fcf3ce44SJohn Forte }
1544*fcf3ce44SJohn Forte 
1545*fcf3ce44SJohn Forte /*
1546*fcf3ce44SJohn Forte  * ql_common_properties
1547*fcf3ce44SJohn Forte  *	Driver properties adapter structure.
1548*fcf3ce44SJohn Forte  *
1549*fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1550*fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1551*fcf3ce44SJohn Forte  *	override the default values using driver.conf
1552*fcf3ce44SJohn Forte  *
1553*fcf3ce44SJohn Forte  * Input:
1554*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1555*fcf3ce44SJohn Forte  *
1556*fcf3ce44SJohn Forte  * Context:
1557*fcf3ce44SJohn Forte  *	Kernel context.
1558*fcf3ce44SJohn Forte  */
1559*fcf3ce44SJohn Forte void
1560*fcf3ce44SJohn Forte ql_common_properties(ql_adapter_state_t *ha)
1561*fcf3ce44SJohn Forte {
1562*fcf3ce44SJohn Forte 	uint32_t	data;
1563*fcf3ce44SJohn Forte 
1564*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1565*fcf3ce44SJohn Forte 
1566*fcf3ce44SJohn Forte 	/* Get FCP 2 Error Recovery. */
1567*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-FCP-2-error-recovery")) ==
1568*fcf3ce44SJohn Forte 	    0xffffffff || data == 1) {
1569*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
1570*fcf3ce44SJohn Forte 	} else if (data == 0) {
1571*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_FCP_2_SUPPORT;
1572*fcf3ce44SJohn Forte 	} else {
1573*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1574*fcf3ce44SJohn Forte 		    "'enable-FCP-2-error-recovery': %d; using nvram value of "
1575*fcf3ce44SJohn Forte 		    "1\n", data);
1576*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
1577*fcf3ce44SJohn Forte 	}
1578*fcf3ce44SJohn Forte 
1579*fcf3ce44SJohn Forte 	/* Get target mode enable. */
1580*fcf3ce44SJohn Forte 	ha->cfg_flags &= ~CFG_TARGET_MODE_ENABLE;
1581*fcf3ce44SJohn Forte 
1582*fcf3ce44SJohn Forte 	/* Get extended logging enable. */
1583*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "extended-logging")) == 0xffffffff ||
1584*fcf3ce44SJohn Forte 	    data == 0) {
1585*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
1586*fcf3ce44SJohn Forte 	} else if (data == 1) {
1587*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
1588*fcf3ce44SJohn Forte 	} else {
1589*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'extended-logging': %d;"
1590*fcf3ce44SJohn Forte 		    " using default value of 0\n", data);
1591*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
1592*fcf3ce44SJohn Forte 	}
1593*fcf3ce44SJohn Forte 
1594*fcf3ce44SJohn Forte #ifdef QL_DEBUG_LEVEL_2
1595*fcf3ce44SJohn Forte 	ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
1596*fcf3ce44SJohn Forte #endif
1597*fcf3ce44SJohn Forte 
1598*fcf3ce44SJohn Forte 	/* Get port down retry delay. */
1599*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-delay")) == 0xffffffff) {
1600*fcf3ce44SJohn Forte 		ha->port_down_retry_delay = PORT_RETRY_TIME;
1601*fcf3ce44SJohn Forte 	} else if (data < 256) {
1602*fcf3ce44SJohn Forte 		ha->port_down_retry_delay = (uint8_t)data;
1603*fcf3ce44SJohn Forte 	} else {
1604*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-delay':"
1605*fcf3ce44SJohn Forte 		    " %d; using default value of %d", data, PORT_RETRY_TIME);
1606*fcf3ce44SJohn Forte 		ha->port_down_retry_delay = PORT_RETRY_TIME;
1607*fcf3ce44SJohn Forte 	}
1608*fcf3ce44SJohn Forte 
1609*fcf3ce44SJohn Forte 	/* Get queue full retry count. */
1610*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "queue-full-retry-count")) == 0xffffffff) {
1611*fcf3ce44SJohn Forte 		ha->qfull_retry_count = 16;
1612*fcf3ce44SJohn Forte 	} else if (data < 256) {
1613*fcf3ce44SJohn Forte 		ha->qfull_retry_count = (uint8_t)data;
1614*fcf3ce44SJohn Forte 	} else {
1615*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'queue-full-retry-count':"
1616*fcf3ce44SJohn Forte 		    " %d; using default value of 16", data);
1617*fcf3ce44SJohn Forte 		ha->qfull_retry_count = 16;
1618*fcf3ce44SJohn Forte 	}
1619*fcf3ce44SJohn Forte 
1620*fcf3ce44SJohn Forte 	/* Get queue full retry delay. */
1621*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "queue-full-retry-delay")) == 0xffffffff) {
1622*fcf3ce44SJohn Forte 		ha->qfull_retry_delay = PORT_RETRY_TIME;
1623*fcf3ce44SJohn Forte 	} else if (data < 256) {
1624*fcf3ce44SJohn Forte 		ha->qfull_retry_delay = (uint8_t)data;
1625*fcf3ce44SJohn Forte 	} else {
1626*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'queue-full-retry-delay':"
1627*fcf3ce44SJohn Forte 		    " %d; using default value of %d", data, PORT_RETRY_TIME);
1628*fcf3ce44SJohn Forte 		ha->qfull_retry_delay = PORT_RETRY_TIME;
1629*fcf3ce44SJohn Forte 	}
1630*fcf3ce44SJohn Forte 
1631*fcf3ce44SJohn Forte 	/* Get loop down timeout. */
1632*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "link-down-timeout")) == 0xffffffff) {
1633*fcf3ce44SJohn Forte 		data = 0;
1634*fcf3ce44SJohn Forte 	} else if (data > 255) {
1635*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'link-down-timeout': %d;"
1636*fcf3ce44SJohn Forte 		    " using nvram value of 0\n", data);
1637*fcf3ce44SJohn Forte 		data = 0;
1638*fcf3ce44SJohn Forte 	}
1639*fcf3ce44SJohn Forte 	ha->loop_down_abort_time = (uint8_t)(LOOP_DOWN_TIMER_START - data);
1640*fcf3ce44SJohn Forte 	if (ha->loop_down_abort_time == LOOP_DOWN_TIMER_START) {
1641*fcf3ce44SJohn Forte 		ha->loop_down_abort_time--;
1642*fcf3ce44SJohn Forte 	} else if (ha->loop_down_abort_time <= LOOP_DOWN_TIMER_END) {
1643*fcf3ce44SJohn Forte 		ha->loop_down_abort_time = LOOP_DOWN_TIMER_END + 1;
1644*fcf3ce44SJohn Forte 	}
1645*fcf3ce44SJohn Forte 
1646*fcf3ce44SJohn Forte 	/* Get link down error enable. */
1647*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-link-down-error")) == 0xffffffff ||
1648*fcf3ce44SJohn Forte 	    data == 1) {
1649*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_LINK_DOWN_REPORTING;
1650*fcf3ce44SJohn Forte 	} else if (data == 0) {
1651*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_LINK_DOWN_REPORTING;
1652*fcf3ce44SJohn Forte 	} else {
1653*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'link-down-error': %d;"
1654*fcf3ce44SJohn Forte 		    " using default value of 1\n", data);
1655*fcf3ce44SJohn Forte 	}
1656*fcf3ce44SJohn Forte 
1657*fcf3ce44SJohn Forte 	/*
1658*fcf3ce44SJohn Forte 	 * Get firmware dump flags.
1659*fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT		BIT_0
1660*fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR	BIT_1
1661*fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT	BIT_2
1662*fcf3ce44SJohn Forte 	 *	TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT	BIT_3
1663*fcf3ce44SJohn Forte 	 */
1664*fcf3ce44SJohn Forte 	ha->cfg_flags &= ~(CFG_DUMP_MAILBOX_TIMEOUT |
1665*fcf3ce44SJohn Forte 	    CFG_DUMP_ISP_SYSTEM_ERROR | CFG_DUMP_DRIVER_COMMAND_TIMEOUT |
1666*fcf3ce44SJohn Forte 	    CFG_DUMP_LOOP_OFFLINE_TIMEOUT);
1667*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "firmware-dump-flags")) != 0xffffffff) {
1668*fcf3ce44SJohn Forte 		if (data & BIT_0) {
1669*fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_MAILBOX_TIMEOUT;
1670*fcf3ce44SJohn Forte 		}
1671*fcf3ce44SJohn Forte 		if (data & BIT_1) {
1672*fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_ISP_SYSTEM_ERROR;
1673*fcf3ce44SJohn Forte 		}
1674*fcf3ce44SJohn Forte 		if (data & BIT_2) {
1675*fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_DRIVER_COMMAND_TIMEOUT;
1676*fcf3ce44SJohn Forte 		}
1677*fcf3ce44SJohn Forte 		if (data & BIT_3) {
1678*fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_DUMP_LOOP_OFFLINE_TIMEOUT;
1679*fcf3ce44SJohn Forte 		}
1680*fcf3ce44SJohn Forte 	}
1681*fcf3ce44SJohn Forte 
1682*fcf3ce44SJohn Forte 	/* Get the PCI max read request size override. */
1683*fcf3ce44SJohn Forte 	ha->pci_max_read_req = 0;
1684*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "pci-max-read-request")) != 0xffffffff &&
1685*fcf3ce44SJohn Forte 	    data != 0) {
1686*fcf3ce44SJohn Forte 		ha->pci_max_read_req = (uint16_t)(data);
1687*fcf3ce44SJohn Forte 	}
1688*fcf3ce44SJohn Forte 
1689*fcf3ce44SJohn Forte 	/* Get the attach fw_ready override value. */
1690*fcf3ce44SJohn Forte 	ha->fwwait = 10;
1691*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "init-loop-sync-wait")) != 0xffffffff) {
1692*fcf3ce44SJohn Forte 		if (data > 0 && data <= 240) {
1693*fcf3ce44SJohn Forte 			ha->fwwait = (uint8_t)data;
1694*fcf3ce44SJohn Forte 		} else {
1695*fcf3ce44SJohn Forte 			EL(ha, "invalid parameter value for "
1696*fcf3ce44SJohn Forte 			    "'init-loop-sync-wait': %d; using default "
1697*fcf3ce44SJohn Forte 			    "value of %d\n", data, ha->fwwait);
1698*fcf3ce44SJohn Forte 		}
1699*fcf3ce44SJohn Forte 	}
1700*fcf3ce44SJohn Forte 
1701*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1702*fcf3ce44SJohn Forte }
1703*fcf3ce44SJohn Forte 
1704*fcf3ce44SJohn Forte /*
1705*fcf3ce44SJohn Forte  * ql_24xx_properties
1706*fcf3ce44SJohn Forte  *	Copies driver properties to NVRAM or adapter structure.
1707*fcf3ce44SJohn Forte  *
1708*fcf3ce44SJohn Forte  *	Driver properties are by design global variables and hidden
1709*fcf3ce44SJohn Forte  *	completely from administrators. Knowledgeable folks can
1710*fcf3ce44SJohn Forte  *	override the default values using /etc/system.
1711*fcf3ce44SJohn Forte  *
1712*fcf3ce44SJohn Forte  * Input:
1713*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1714*fcf3ce44SJohn Forte  *	nv:	NVRAM structure pointer.
1715*fcf3ce44SJohn Forte  *
1716*fcf3ce44SJohn Forte  * Context:
1717*fcf3ce44SJohn Forte  *	Kernel context.
1718*fcf3ce44SJohn Forte  */
1719*fcf3ce44SJohn Forte static void
1720*fcf3ce44SJohn Forte ql_24xx_properties(ql_adapter_state_t *ha, nvram_24xx_t *nv)
1721*fcf3ce44SJohn Forte {
1722*fcf3ce44SJohn Forte 	uint32_t	data;
1723*fcf3ce44SJohn Forte 
1724*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1725*fcf3ce44SJohn Forte 
1726*fcf3ce44SJohn Forte 	/* Get frame size */
1727*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
1728*fcf3ce44SJohn Forte 		data = 2048;
1729*fcf3ce44SJohn Forte 	}
1730*fcf3ce44SJohn Forte 	if (data == 512 || data == 1024 || data == 2048) {
1731*fcf3ce44SJohn Forte 		nv->max_frame_length[0] = LSB(data);
1732*fcf3ce44SJohn Forte 		nv->max_frame_length[1] = MSB(data);
1733*fcf3ce44SJohn Forte 	} else {
1734*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'max-frame-length': %d;"
1735*fcf3ce44SJohn Forte 		    " using nvram default of %d\n", data, CHAR_TO_SHORT(
1736*fcf3ce44SJohn Forte 		    nv->max_frame_length[0], nv->max_frame_length[1]));
1737*fcf3ce44SJohn Forte 	}
1738*fcf3ce44SJohn Forte 
1739*fcf3ce44SJohn Forte 	/* Get execution throttle. */
1740*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
1741*fcf3ce44SJohn Forte 		data = 32;
1742*fcf3ce44SJohn Forte 	}
1743*fcf3ce44SJohn Forte 	if (data != 0 && data < 65536) {
1744*fcf3ce44SJohn Forte 		nv->execution_throttle[0] = LSB(data);
1745*fcf3ce44SJohn Forte 		nv->execution_throttle[1] = MSB(data);
1746*fcf3ce44SJohn Forte 	} else {
1747*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'execution-throttle':"
1748*fcf3ce44SJohn Forte 		    " %d; using nvram default of %d\n", data, CHAR_TO_SHORT(
1749*fcf3ce44SJohn Forte 		    nv->execution_throttle[0], nv->execution_throttle[1]));
1750*fcf3ce44SJohn Forte 	}
1751*fcf3ce44SJohn Forte 
1752*fcf3ce44SJohn Forte 	/* Get Login timeout. */
1753*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
1754*fcf3ce44SJohn Forte 		data = 3;
1755*fcf3ce44SJohn Forte 	}
1756*fcf3ce44SJohn Forte 	if (data < 65536) {
1757*fcf3ce44SJohn Forte 		nv->login_timeout[0] = LSB(data);
1758*fcf3ce44SJohn Forte 		nv->login_timeout[1] = MSB(data);
1759*fcf3ce44SJohn Forte 	} else {
1760*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-timeout': %d; "
1761*fcf3ce44SJohn Forte 		    "using nvram value of %d\n", data, CHAR_TO_SHORT(
1762*fcf3ce44SJohn Forte 		    nv->login_timeout[0], nv->login_timeout[1]));
1763*fcf3ce44SJohn Forte 	}
1764*fcf3ce44SJohn Forte 
1765*fcf3ce44SJohn Forte 	/* Get retry count. */
1766*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
1767*fcf3ce44SJohn Forte 		data = 4;
1768*fcf3ce44SJohn Forte 	}
1769*fcf3ce44SJohn Forte 	if (data < 65536) {
1770*fcf3ce44SJohn Forte 		nv->login_retry_count[0] = LSB(data);
1771*fcf3ce44SJohn Forte 		nv->login_retry_count[1] = MSB(data);
1772*fcf3ce44SJohn Forte 	} else {
1773*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'login-retry-count': "
1774*fcf3ce44SJohn Forte 		    "%d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1775*fcf3ce44SJohn Forte 		    nv->login_retry_count[0], nv->login_retry_count[1]));
1776*fcf3ce44SJohn Forte 	}
1777*fcf3ce44SJohn Forte 
1778*fcf3ce44SJohn Forte 	/* Get adapter hard loop ID enable. */
1779*fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "enable-adapter-hard-loop-ID");
1780*fcf3ce44SJohn Forte 	if (data == 0) {
1781*fcf3ce44SJohn Forte 		nv->firmware_options_1[0] =
1782*fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options_1[0] & ~BIT_0);
1783*fcf3ce44SJohn Forte 	} else if (data == 1) {
1784*fcf3ce44SJohn Forte 		nv->firmware_options_1[0] =
1785*fcf3ce44SJohn Forte 		    (uint8_t)(nv->firmware_options_1[0] | BIT_0);
1786*fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1787*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1788*fcf3ce44SJohn Forte 		    "'enable-adapter-hard-loop-ID': %d; using nvram value "
1789*fcf3ce44SJohn Forte 		    "of %d\n", data,
1790*fcf3ce44SJohn Forte 		    nv->firmware_options_1[0] & BIT_0 ? 1 : 0);
1791*fcf3ce44SJohn Forte 	}
1792*fcf3ce44SJohn Forte 
1793*fcf3ce44SJohn Forte 	/* Get adapter hard loop ID. */
1794*fcf3ce44SJohn Forte 	data =  ql_get_prop(ha, "adapter-hard-loop-ID");
1795*fcf3ce44SJohn Forte 	if (data < 126) {
1796*fcf3ce44SJohn Forte 		nv->hard_address[0] = LSB(data);
1797*fcf3ce44SJohn Forte 		nv->hard_address[1] = MSB(data);
1798*fcf3ce44SJohn Forte 	} else if (data != 0xffffffff) {
1799*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'adapter-hard-loop-ID':"
1800*fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1801*fcf3ce44SJohn Forte 		    nv->hard_address[0], nv->hard_address[1]));
1802*fcf3ce44SJohn Forte 	}
1803*fcf3ce44SJohn Forte 
1804*fcf3ce44SJohn Forte 	/* Get LIP reset. */
1805*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
1806*fcf3ce44SJohn Forte 	    0xffffffff) {
1807*fcf3ce44SJohn Forte 		data = 0;
1808*fcf3ce44SJohn Forte 	}
1809*fcf3ce44SJohn Forte 	if (data == 0) {
1810*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET;
1811*fcf3ce44SJohn Forte 	} else if (data == 1) {
1812*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_LIP_RESET;
1813*fcf3ce44SJohn Forte 	} else {
1814*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1815*fcf3ce44SJohn Forte 		    "'enable-LIP-reset-on-bus-reset': %d; using value of 0\n",
1816*fcf3ce44SJohn Forte 		    data);
1817*fcf3ce44SJohn Forte 	}
1818*fcf3ce44SJohn Forte 
1819*fcf3ce44SJohn Forte 	/* Get LIP full login. */
1820*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
1821*fcf3ce44SJohn Forte 	    0xffffffff) {
1822*fcf3ce44SJohn Forte 		data = 1;
1823*fcf3ce44SJohn Forte 	}
1824*fcf3ce44SJohn Forte 	if (data == 0) {
1825*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2);
1826*fcf3ce44SJohn Forte 	} else if (data == 1) {
1827*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2);
1828*fcf3ce44SJohn Forte 	} else {
1829*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1830*fcf3ce44SJohn Forte 		    "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
1831*fcf3ce44SJohn Forte 		    "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0);
1832*fcf3ce44SJohn Forte 	}
1833*fcf3ce44SJohn Forte 
1834*fcf3ce44SJohn Forte 	/* Get target reset. */
1835*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
1836*fcf3ce44SJohn Forte 	    0xffffffff) {
1837*fcf3ce44SJohn Forte 		data = 0;
1838*fcf3ce44SJohn Forte 	}
1839*fcf3ce44SJohn Forte 	if (data == 0) {
1840*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3);
1841*fcf3ce44SJohn Forte 	} else if (data == 1) {
1842*fcf3ce44SJohn Forte 		nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3);
1843*fcf3ce44SJohn Forte 	} else {
1844*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for "
1845*fcf3ce44SJohn Forte 		    "'enable-target-reset-on-bus-reset': %d; using nvram "
1846*fcf3ce44SJohn Forte 		    "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0);
1847*fcf3ce44SJohn Forte 	}
1848*fcf3ce44SJohn Forte 
1849*fcf3ce44SJohn Forte 	/* Get reset delay. */
1850*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
1851*fcf3ce44SJohn Forte 		data = 5;
1852*fcf3ce44SJohn Forte 	}
1853*fcf3ce44SJohn Forte 	if (data != 0 && data < 256) {
1854*fcf3ce44SJohn Forte 		nv->reset_delay = (uint8_t)data;
1855*fcf3ce44SJohn Forte 	} else {
1856*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'reset-delay': %d; "
1857*fcf3ce44SJohn Forte 		    "using nvram value of %d", data, nv->reset_delay);
1858*fcf3ce44SJohn Forte 	}
1859*fcf3ce44SJohn Forte 
1860*fcf3ce44SJohn Forte 	/* Get port down retry count. */
1861*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
1862*fcf3ce44SJohn Forte 		data = 8;
1863*fcf3ce44SJohn Forte 	}
1864*fcf3ce44SJohn Forte 	if (data < 256) {
1865*fcf3ce44SJohn Forte 		nv->port_down_retry_count[0] = LSB(data);
1866*fcf3ce44SJohn Forte 		nv->port_down_retry_count[1] = MSB(data);
1867*fcf3ce44SJohn Forte 	} else {
1868*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'port-down-retry-count':"
1869*fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
1870*fcf3ce44SJohn Forte 		    nv->port_down_retry_count[0],
1871*fcf3ce44SJohn Forte 		    nv->port_down_retry_count[1]));
1872*fcf3ce44SJohn Forte 	}
1873*fcf3ce44SJohn Forte 
1874*fcf3ce44SJohn Forte 	/* Get connection mode setting. */
1875*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) {
1876*fcf3ce44SJohn Forte 		data = 2;
1877*fcf3ce44SJohn Forte 	}
1878*fcf3ce44SJohn Forte 	if (data <= 2) {
1879*fcf3ce44SJohn Forte 		nv->firmware_options_2[0] = (uint8_t)
1880*fcf3ce44SJohn Forte 		    (nv->firmware_options_2[0] & ~(BIT_6 | BIT_5 | BIT_4));
1881*fcf3ce44SJohn Forte 		nv->firmware_options_2[0] = (uint8_t)
1882*fcf3ce44SJohn Forte 		    (nv->firmware_options_2[0] | (uint8_t)(data << 4));
1883*fcf3ce44SJohn Forte 	} else {
1884*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'connection-options':"
1885*fcf3ce44SJohn Forte 		    " %d; using nvram value of %d\n", data,
1886*fcf3ce44SJohn Forte 		    (nv->firmware_options_2[0] >> 4) & 0x3);
1887*fcf3ce44SJohn Forte 	}
1888*fcf3ce44SJohn Forte 
1889*fcf3ce44SJohn Forte 	/* Get data rate setting. */
1890*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
1891*fcf3ce44SJohn Forte 		data = 2;
1892*fcf3ce44SJohn Forte 	}
1893*fcf3ce44SJohn Forte 	if ((CFG_IST(ha, CFG_CTRL_2422) && data < 4) ||
1894*fcf3ce44SJohn Forte 	    (CFG_IST(ha, CFG_CTRL_25XX) && data < 5)) {
1895*fcf3ce44SJohn Forte 		nv->firmware_options_3[1] = (uint8_t)
1896*fcf3ce44SJohn Forte 		    (nv->firmware_options_3[1] & 0x1f);
1897*fcf3ce44SJohn Forte 		nv->firmware_options_3[1] = (uint8_t)
1898*fcf3ce44SJohn Forte 		    (nv->firmware_options_3[1] | (uint8_t)(data << 5));
1899*fcf3ce44SJohn Forte 	} else {
1900*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'fc-data-rate': %d; "
1901*fcf3ce44SJohn Forte 		    "using nvram value of %d\n", data,
1902*fcf3ce44SJohn Forte 		    (nv->firmware_options_3[1] >> 5) & 0x7);
1903*fcf3ce44SJohn Forte 	}
1904*fcf3ce44SJohn Forte 
1905*fcf3ce44SJohn Forte 	/* Get IP FW container count. */
1906*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.cc[0] = LSB(ql_ip_buffer_count);
1907*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.cc[1] = MSB(ql_ip_buffer_count);
1908*fcf3ce44SJohn Forte 
1909*fcf3ce44SJohn Forte 	/* Get IP low water mark. */
1910*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.low_water_mark[0] = LSB(ql_ip_low_water);
1911*fcf3ce44SJohn Forte 	ha->ip_init_ctrl_blk.cb24.low_water_mark[1] = MSB(ql_ip_low_water);
1912*fcf3ce44SJohn Forte 
1913*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1914*fcf3ce44SJohn Forte 
1915*fcf3ce44SJohn Forte 	/* Get enable flash load. */
1916*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-flash-load")) == 0xffffffff ||
1917*fcf3ce44SJohn Forte 	    data == 0) {
1918*fcf3ce44SJohn Forte 		ha->cfg_flags &= ~CFG_LOAD_FLASH_FW;
1919*fcf3ce44SJohn Forte 	} else if (data == 1) {
1920*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_LOAD_FLASH_FW;
1921*fcf3ce44SJohn Forte 	} else {
1922*fcf3ce44SJohn Forte 		EL(ha, "invalid parameter value for 'enable-flash-load': "
1923*fcf3ce44SJohn Forte 		    "%d; using default value of 0\n", data);
1924*fcf3ce44SJohn Forte 	}
1925*fcf3ce44SJohn Forte 
1926*fcf3ce44SJohn Forte 	/* Enable firmware extended tracing */
1927*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-fwexttrace")) != 0xffffffff) {
1928*fcf3ce44SJohn Forte 		if (data != 0) {
1929*fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_ENABLE_FWEXTTRACE;
1930*fcf3ce44SJohn Forte 		}
1931*fcf3ce44SJohn Forte 	}
1932*fcf3ce44SJohn Forte 
1933*fcf3ce44SJohn Forte 	/* Enable firmware fc tracing */
1934*fcf3ce44SJohn Forte 	if ((data = ql_get_prop(ha, "enable-fwfcetrace")) != 0xffffffff) {
1935*fcf3ce44SJohn Forte 		ha->cfg_flags |= CFG_ENABLE_FWFCETRACE;
1936*fcf3ce44SJohn Forte 		ha->fwfcetraceopt = data;
1937*fcf3ce44SJohn Forte 	}
1938*fcf3ce44SJohn Forte 
1939*fcf3ce44SJohn Forte 	ql_common_properties(ha);
1940*fcf3ce44SJohn Forte 
1941*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1942*fcf3ce44SJohn Forte 
1943*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1944*fcf3ce44SJohn Forte }
1945*fcf3ce44SJohn Forte 
1946*fcf3ce44SJohn Forte /*
1947*fcf3ce44SJohn Forte  * ql_get_prop
1948*fcf3ce44SJohn Forte  *	Get property value from configuration file.
1949*fcf3ce44SJohn Forte  *
1950*fcf3ce44SJohn Forte  * Input:
1951*fcf3ce44SJohn Forte  *	ha= adapter state pointer.
1952*fcf3ce44SJohn Forte  *	string = property string pointer.
1953*fcf3ce44SJohn Forte  *
1954*fcf3ce44SJohn Forte  * Returns:
1955*fcf3ce44SJohn Forte  *	0xFFFFFFFF = no property else property value.
1956*fcf3ce44SJohn Forte  *
1957*fcf3ce44SJohn Forte  * Context:
1958*fcf3ce44SJohn Forte  *	Kernel context.
1959*fcf3ce44SJohn Forte  */
1960*fcf3ce44SJohn Forte uint32_t
1961*fcf3ce44SJohn Forte ql_get_prop(ql_adapter_state_t *ha, char *string)
1962*fcf3ce44SJohn Forte {
1963*fcf3ce44SJohn Forte 	char		buf[256];
1964*fcf3ce44SJohn Forte 	uint32_t	data;
1965*fcf3ce44SJohn Forte 
1966*fcf3ce44SJohn Forte 	/* Get adapter instance parameter. */
1967*fcf3ce44SJohn Forte 	(void) sprintf(buf, "hba%d-%s", ha->instance, string);
1968*fcf3ce44SJohn Forte 	/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
1969*fcf3ce44SJohn Forte 	data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0, buf,
1970*fcf3ce44SJohn Forte 	    (int)0xffffffff);
1971*fcf3ce44SJohn Forte 
1972*fcf3ce44SJohn Forte 	/* Adapter instance parameter found? */
1973*fcf3ce44SJohn Forte 	if (data == 0xffffffff) {
1974*fcf3ce44SJohn Forte 		/* No, get default parameter. */
1975*fcf3ce44SJohn Forte 		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
1976*fcf3ce44SJohn Forte 		data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
1977*fcf3ce44SJohn Forte 		    string, (int)0xffffffff);
1978*fcf3ce44SJohn Forte 	}
1979*fcf3ce44SJohn Forte 
1980*fcf3ce44SJohn Forte 	return (data);
1981*fcf3ce44SJohn Forte }
1982*fcf3ce44SJohn Forte 
1983*fcf3ce44SJohn Forte /*
1984*fcf3ce44SJohn Forte  * ql_check_isp_firmware
1985*fcf3ce44SJohn Forte  *	Checks if using already loaded RISC code or drivers copy.
1986*fcf3ce44SJohn Forte  *	If using already loaded code, save a copy of it.
1987*fcf3ce44SJohn Forte  *
1988*fcf3ce44SJohn Forte  * Input:
1989*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
1990*fcf3ce44SJohn Forte  *
1991*fcf3ce44SJohn Forte  * Returns:
1992*fcf3ce44SJohn Forte  *	ql local function return status code.
1993*fcf3ce44SJohn Forte  *
1994*fcf3ce44SJohn Forte  * Context:
1995*fcf3ce44SJohn Forte  *	Kernel context.
1996*fcf3ce44SJohn Forte  */
1997*fcf3ce44SJohn Forte static int
1998*fcf3ce44SJohn Forte ql_check_isp_firmware(ql_adapter_state_t *ha)
1999*fcf3ce44SJohn Forte {
2000*fcf3ce44SJohn Forte 	int		rval;
2001*fcf3ce44SJohn Forte 	uint16_t	word_count;
2002*fcf3ce44SJohn Forte 	uint32_t	byte_count;
2003*fcf3ce44SJohn Forte 	uint32_t	fw_size, *lptr;
2004*fcf3ce44SJohn Forte 	caddr_t		bufp;
2005*fcf3ce44SJohn Forte 	uint16_t	risc_address = (uint16_t)ha->risc_fw[0].addr;
2006*fcf3ce44SJohn Forte 
2007*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2008*fcf3ce44SJohn Forte 
2009*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_DISABLE_RISC_CODE_LOAD)) {
2010*fcf3ce44SJohn Forte 		if (ha->risc_code != NULL) {
2011*fcf3ce44SJohn Forte 			kmem_free(ha->risc_code, ha->risc_code_size);
2012*fcf3ce44SJohn Forte 			ha->risc_code = NULL;
2013*fcf3ce44SJohn Forte 			ha->risc_code_size = 0;
2014*fcf3ce44SJohn Forte 		}
2015*fcf3ce44SJohn Forte 
2016*fcf3ce44SJohn Forte 		/* Get RISC code length. */
2017*fcf3ce44SJohn Forte 		rval = ql_rd_risc_ram(ha, risc_address + 3, ha->request_dvma,
2018*fcf3ce44SJohn Forte 		    1);
2019*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2020*fcf3ce44SJohn Forte 			lptr = (uint32_t *)ha->request_ring_bp;
2021*fcf3ce44SJohn Forte 			fw_size = *lptr << 1;
2022*fcf3ce44SJohn Forte 
2023*fcf3ce44SJohn Forte 			if ((bufp = kmem_alloc(fw_size, KM_SLEEP)) != NULL) {
2024*fcf3ce44SJohn Forte 				ha->risc_code_size = fw_size;
2025*fcf3ce44SJohn Forte 				ha->risc_code = bufp;
2026*fcf3ce44SJohn Forte 				ha->fw_transfer_size = 128;
2027*fcf3ce44SJohn Forte 
2028*fcf3ce44SJohn Forte 				/* Dump RISC code. */
2029*fcf3ce44SJohn Forte 				do {
2030*fcf3ce44SJohn Forte 					if (fw_size > ha->fw_transfer_size) {
2031*fcf3ce44SJohn Forte 						byte_count =
2032*fcf3ce44SJohn Forte 						    ha->fw_transfer_size;
2033*fcf3ce44SJohn Forte 					} else {
2034*fcf3ce44SJohn Forte 						byte_count = fw_size;
2035*fcf3ce44SJohn Forte 					}
2036*fcf3ce44SJohn Forte 
2037*fcf3ce44SJohn Forte 					word_count =
2038*fcf3ce44SJohn Forte 					    (uint16_t)(byte_count >> 1);
2039*fcf3ce44SJohn Forte 
2040*fcf3ce44SJohn Forte 					rval = ql_rd_risc_ram(ha, risc_address,
2041*fcf3ce44SJohn Forte 					    ha->request_dvma, word_count);
2042*fcf3ce44SJohn Forte 					if (rval != QL_SUCCESS) {
2043*fcf3ce44SJohn Forte 						kmem_free(ha->risc_code,
2044*fcf3ce44SJohn Forte 						    ha->risc_code_size);
2045*fcf3ce44SJohn Forte 						ha->risc_code = NULL;
2046*fcf3ce44SJohn Forte 						ha->risc_code_size = 0;
2047*fcf3ce44SJohn Forte 						break;
2048*fcf3ce44SJohn Forte 					}
2049*fcf3ce44SJohn Forte 
2050*fcf3ce44SJohn Forte 					(void) ddi_dma_sync(
2051*fcf3ce44SJohn Forte 					    ha->hba_buf.dma_handle,
2052*fcf3ce44SJohn Forte 					    REQUEST_Q_BUFFER_OFFSET,
2053*fcf3ce44SJohn Forte 					    byte_count,
2054*fcf3ce44SJohn Forte 					    DDI_DMA_SYNC_FORKERNEL);
2055*fcf3ce44SJohn Forte 					ddi_rep_get16(ha->hba_buf.acc_handle,
2056*fcf3ce44SJohn Forte 					    (uint16_t *)bufp,
2057*fcf3ce44SJohn Forte 					    (uint16_t *)ha->request_ring_bp,
2058*fcf3ce44SJohn Forte 					    word_count, DDI_DEV_AUTOINCR);
2059*fcf3ce44SJohn Forte 
2060*fcf3ce44SJohn Forte 					risc_address += word_count;
2061*fcf3ce44SJohn Forte 					fw_size -= byte_count;
2062*fcf3ce44SJohn Forte 					bufp	+= byte_count;
2063*fcf3ce44SJohn Forte 				} while (fw_size != 0);
2064*fcf3ce44SJohn Forte 			}
2065*fcf3ce44SJohn Forte 		}
2066*fcf3ce44SJohn Forte 	} else {
2067*fcf3ce44SJohn Forte 		rval = QL_FUNCTION_FAILED;
2068*fcf3ce44SJohn Forte 	}
2069*fcf3ce44SJohn Forte 
2070*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2071*fcf3ce44SJohn Forte 		EL(ha, "Load RISC code\n");
2072*fcf3ce44SJohn Forte 	} else {
2073*fcf3ce44SJohn Forte 		/*EMPTY*/
2074*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2075*fcf3ce44SJohn Forte 	}
2076*fcf3ce44SJohn Forte 	return (rval);
2077*fcf3ce44SJohn Forte }
2078*fcf3ce44SJohn Forte 
2079*fcf3ce44SJohn Forte /*
2080*fcf3ce44SJohn Forte  * Chip diagnostics
2081*fcf3ce44SJohn Forte  *	Test chip for proper operation.
2082*fcf3ce44SJohn Forte  *
2083*fcf3ce44SJohn Forte  * Input:
2084*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2085*fcf3ce44SJohn Forte  *
2086*fcf3ce44SJohn Forte  * Returns:
2087*fcf3ce44SJohn Forte  *	ql local function return status code.
2088*fcf3ce44SJohn Forte  *
2089*fcf3ce44SJohn Forte  * Context:
2090*fcf3ce44SJohn Forte  *	Kernel context.
2091*fcf3ce44SJohn Forte  */
2092*fcf3ce44SJohn Forte static int
2093*fcf3ce44SJohn Forte ql_chip_diag(ql_adapter_state_t *ha)
2094*fcf3ce44SJohn Forte {
2095*fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
2096*fcf3ce44SJohn Forte 	int32_t		rval = QL_FUNCTION_FAILED;
2097*fcf3ce44SJohn Forte 	int32_t		retries = 4;
2098*fcf3ce44SJohn Forte 	uint16_t	id;
2099*fcf3ce44SJohn Forte 
2100*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2101*fcf3ce44SJohn Forte 
2102*fcf3ce44SJohn Forte 	do {
2103*fcf3ce44SJohn Forte 		/* Reset ISP chip. */
2104*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2105*fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
2106*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2107*fcf3ce44SJohn Forte 		ql_reset_chip(ha);
2108*fcf3ce44SJohn Forte 
2109*fcf3ce44SJohn Forte 		/* For ISP2200A reduce firmware load size. */
2110*fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_2200) &&
2111*fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[7]) == 4) {
2112*fcf3ce44SJohn Forte 			ha->fw_transfer_size = 128;
2113*fcf3ce44SJohn Forte 		} else {
2114*fcf3ce44SJohn Forte 			ha->fw_transfer_size = REQUEST_QUEUE_SIZE;
2115*fcf3ce44SJohn Forte 		}
2116*fcf3ce44SJohn Forte 
2117*fcf3ce44SJohn Forte 		/* Check product ID of chip */
2118*fcf3ce44SJohn Forte 		mr.mb[1] = RD16_IO_REG(ha, mailbox[1]);
2119*fcf3ce44SJohn Forte 		mr.mb[2] = RD16_IO_REG(ha, mailbox[2]);
2120*fcf3ce44SJohn Forte 		mr.mb[3] = RD16_IO_REG(ha, mailbox[3]);
2121*fcf3ce44SJohn Forte 
2122*fcf3ce44SJohn Forte 		if (ha->device_id == 0x5432 || ha->device_id == 0x8432) {
2123*fcf3ce44SJohn Forte 			id = 0x2432;
2124*fcf3ce44SJohn Forte 		} else if (ha->device_id == 0x5422 ||
2125*fcf3ce44SJohn Forte 		    ha->device_id == 0x8432) {
2126*fcf3ce44SJohn Forte 			id = 0x2422;
2127*fcf3ce44SJohn Forte 		} else {
2128*fcf3ce44SJohn Forte 			id = ha->device_id;
2129*fcf3ce44SJohn Forte 		}
2130*fcf3ce44SJohn Forte 
2131*fcf3ce44SJohn Forte 		if (mr.mb[1] == PROD_ID_1 &&
2132*fcf3ce44SJohn Forte 		    (mr.mb[2] == PROD_ID_2 || mr.mb[2] == PROD_ID_2a) &&
2133*fcf3ce44SJohn Forte 		    (mr.mb[3] == PROD_ID_3 || mr.mb[3] == id)) {
2134*fcf3ce44SJohn Forte 
2135*fcf3ce44SJohn Forte 			ha->adapter_stats->revlvl.isp2200 = RD16_IO_REG(ha,
2136*fcf3ce44SJohn Forte 			    mailbox[4]);
2137*fcf3ce44SJohn Forte 			ha->adapter_stats->revlvl.risc = RD16_IO_REG(ha,
2138*fcf3ce44SJohn Forte 			    mailbox[5]);
2139*fcf3ce44SJohn Forte 			ha->adapter_stats->revlvl.frmbfr = RD16_IO_REG(ha,
2140*fcf3ce44SJohn Forte 			    mailbox[6]);
2141*fcf3ce44SJohn Forte 			ha->adapter_stats->revlvl.riscrom = RD16_IO_REG(ha,
2142*fcf3ce44SJohn Forte 			    mailbox[7]);
2143*fcf3ce44SJohn Forte 			bcopy(QL_VERSION, ha->adapter_stats->revlvl.qlddv,
2144*fcf3ce44SJohn Forte 			    strlen(QL_VERSION));
2145*fcf3ce44SJohn Forte 
2146*fcf3ce44SJohn Forte 			/* Wrap Incoming Mailboxes Test. */
2147*fcf3ce44SJohn Forte 			mr.mb[1] = 0xAAAA;
2148*fcf3ce44SJohn Forte 			mr.mb[2] = 0x5555;
2149*fcf3ce44SJohn Forte 			mr.mb[3] = 0xAA55;
2150*fcf3ce44SJohn Forte 			mr.mb[4] = 0x55AA;
2151*fcf3ce44SJohn Forte 			mr.mb[5] = 0xA5A5;
2152*fcf3ce44SJohn Forte 			mr.mb[6] = 0x5A5A;
2153*fcf3ce44SJohn Forte 			mr.mb[7] = 0x2525;
2154*fcf3ce44SJohn Forte 			rval = ql_mbx_wrap_test(ha, &mr);
2155*fcf3ce44SJohn Forte 			if (rval == QL_SUCCESS) {
2156*fcf3ce44SJohn Forte 				if (mr.mb[1] != 0xAAAA ||
2157*fcf3ce44SJohn Forte 				    mr.mb[2] != 0x5555 ||
2158*fcf3ce44SJohn Forte 				    mr.mb[3] != 0xAA55 ||
2159*fcf3ce44SJohn Forte 				    mr.mb[4] != 0x55AA ||
2160*fcf3ce44SJohn Forte 				    mr.mb[5] != 0xA5A5 ||
2161*fcf3ce44SJohn Forte 				    mr.mb[6] != 0x5A5A ||
2162*fcf3ce44SJohn Forte 				    mr.mb[7] != 0x2525) {
2163*fcf3ce44SJohn Forte 					rval = QL_FUNCTION_FAILED;
2164*fcf3ce44SJohn Forte 					(void) ql_flash_errlog(ha,
2165*fcf3ce44SJohn Forte 					    FLASH_ERRLOG_ISP_ERR, 0,
2166*fcf3ce44SJohn Forte 					    RD16_IO_REG(ha, hccr),
2167*fcf3ce44SJohn Forte 					    RD16_IO_REG(ha, istatus));
2168*fcf3ce44SJohn Forte 				}
2169*fcf3ce44SJohn Forte 			} else {
2170*fcf3ce44SJohn Forte 				cmn_err(CE_WARN, "%s(%d) - reg test failed="
2171*fcf3ce44SJohn Forte 				    "%xh!", QL_NAME, ha->instance, rval);
2172*fcf3ce44SJohn Forte 			}
2173*fcf3ce44SJohn Forte 		} else {
2174*fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d) - prod id failed!, mb1=%xh, "
2175*fcf3ce44SJohn Forte 			    "mb2=%xh, mb3=%xh", QL_NAME, ha->instance,
2176*fcf3ce44SJohn Forte 			    mr.mb[1], mr.mb[2], mr.mb[3]);
2177*fcf3ce44SJohn Forte 		}
2178*fcf3ce44SJohn Forte 	} while ((retries-- != 0) && (rval != QL_SUCCESS));
2179*fcf3ce44SJohn Forte 
2180*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2181*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2182*fcf3ce44SJohn Forte 	} else {
2183*fcf3ce44SJohn Forte 		/*EMPTY*/
2184*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2185*fcf3ce44SJohn Forte 	}
2186*fcf3ce44SJohn Forte 	return (rval);
2187*fcf3ce44SJohn Forte }
2188*fcf3ce44SJohn Forte 
2189*fcf3ce44SJohn Forte /*
2190*fcf3ce44SJohn Forte  * ql_load_isp_firmware
2191*fcf3ce44SJohn Forte  *	Load and start RISC firmware.
2192*fcf3ce44SJohn Forte  *	Uses request ring for DMA buffer.
2193*fcf3ce44SJohn Forte  *
2194*fcf3ce44SJohn Forte  * Input:
2195*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2196*fcf3ce44SJohn Forte  *
2197*fcf3ce44SJohn Forte  * Returns:
2198*fcf3ce44SJohn Forte  *	ql local function return status code.
2199*fcf3ce44SJohn Forte  *
2200*fcf3ce44SJohn Forte  * Context:
2201*fcf3ce44SJohn Forte  *	Kernel context.
2202*fcf3ce44SJohn Forte  */
2203*fcf3ce44SJohn Forte int
2204*fcf3ce44SJohn Forte ql_load_isp_firmware(ql_adapter_state_t *vha)
2205*fcf3ce44SJohn Forte {
2206*fcf3ce44SJohn Forte 	caddr_t			risc_code_address;
2207*fcf3ce44SJohn Forte 	uint32_t		risc_address, risc_code_size;
2208*fcf3ce44SJohn Forte 	int			rval;
2209*fcf3ce44SJohn Forte 	uint32_t		word_count, cnt;
2210*fcf3ce44SJohn Forte 	size_t			byte_count;
2211*fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
2212*fcf3ce44SJohn Forte 
2213*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) {
2214*fcf3ce44SJohn Forte 		return (ql_load_flash_fw(ha));
2215*fcf3ce44SJohn Forte 	}
2216*fcf3ce44SJohn Forte 
2217*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2218*fcf3ce44SJohn Forte 
2219*fcf3ce44SJohn Forte 	/* Load firmware segments */
2220*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < MAX_RISC_CODE_SEGMENTS &&
2221*fcf3ce44SJohn Forte 	    ha->risc_fw[cnt].code != NULL; cnt++) {
2222*fcf3ce44SJohn Forte 
2223*fcf3ce44SJohn Forte 		risc_code_address = ha->risc_fw[cnt].code;
2224*fcf3ce44SJohn Forte 		risc_address = ha->risc_fw[cnt].addr;
2225*fcf3ce44SJohn Forte 		risc_code_size = ha->risc_fw[cnt].length;
2226*fcf3ce44SJohn Forte 
2227*fcf3ce44SJohn Forte 		while (risc_code_size) {
2228*fcf3ce44SJohn Forte 			if (CFG_IST(ha, CFG_CTRL_2425)) {
2229*fcf3ce44SJohn Forte 				word_count = ha->fw_transfer_size >> 2;
2230*fcf3ce44SJohn Forte 				if (word_count > risc_code_size) {
2231*fcf3ce44SJohn Forte 					word_count = risc_code_size;
2232*fcf3ce44SJohn Forte 				}
2233*fcf3ce44SJohn Forte 				byte_count = word_count << 2;
2234*fcf3ce44SJohn Forte 
2235*fcf3ce44SJohn Forte 				ddi_rep_put32(ha->hba_buf.acc_handle,
2236*fcf3ce44SJohn Forte 				    (uint32_t *)risc_code_address,
2237*fcf3ce44SJohn Forte 				    (uint32_t *)ha->request_ring_bp,
2238*fcf3ce44SJohn Forte 				    word_count, DDI_DEV_AUTOINCR);
2239*fcf3ce44SJohn Forte 			} else {
2240*fcf3ce44SJohn Forte 				word_count = ha->fw_transfer_size >> 1;
2241*fcf3ce44SJohn Forte 				if (word_count > risc_code_size) {
2242*fcf3ce44SJohn Forte 					word_count = risc_code_size;
2243*fcf3ce44SJohn Forte 				}
2244*fcf3ce44SJohn Forte 				byte_count = word_count << 1;
2245*fcf3ce44SJohn Forte 
2246*fcf3ce44SJohn Forte 				ddi_rep_put16(ha->hba_buf.acc_handle,
2247*fcf3ce44SJohn Forte 				    (uint16_t *)risc_code_address,
2248*fcf3ce44SJohn Forte 				    (uint16_t *)ha->request_ring_bp,
2249*fcf3ce44SJohn Forte 				    word_count, DDI_DEV_AUTOINCR);
2250*fcf3ce44SJohn Forte 			}
2251*fcf3ce44SJohn Forte 
2252*fcf3ce44SJohn Forte 			(void) ddi_dma_sync(ha->hba_buf.dma_handle,
2253*fcf3ce44SJohn Forte 			    REQUEST_Q_BUFFER_OFFSET, byte_count,
2254*fcf3ce44SJohn Forte 			    DDI_DMA_SYNC_FORDEV);
2255*fcf3ce44SJohn Forte 
2256*fcf3ce44SJohn Forte 			rval = ql_wrt_risc_ram(ha, risc_address,
2257*fcf3ce44SJohn Forte 			    ha->request_dvma, word_count);
2258*fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2259*fcf3ce44SJohn Forte 				EL(ha, "failed, load=%xh\n", rval);
2260*fcf3ce44SJohn Forte 				cnt = MAX_RISC_CODE_SEGMENTS;
2261*fcf3ce44SJohn Forte 				break;
2262*fcf3ce44SJohn Forte 			}
2263*fcf3ce44SJohn Forte 
2264*fcf3ce44SJohn Forte 			risc_address += word_count;
2265*fcf3ce44SJohn Forte 			risc_code_size -= word_count;
2266*fcf3ce44SJohn Forte 			risc_code_address += byte_count;
2267*fcf3ce44SJohn Forte 		}
2268*fcf3ce44SJohn Forte 	}
2269*fcf3ce44SJohn Forte 
2270*fcf3ce44SJohn Forte 	/* Start firmware. */
2271*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2272*fcf3ce44SJohn Forte 		rval = ql_start_firmware(ha);
2273*fcf3ce44SJohn Forte 	}
2274*fcf3ce44SJohn Forte 
2275*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2276*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2277*fcf3ce44SJohn Forte 	} else {
2278*fcf3ce44SJohn Forte 		/*EMPTY*/
2279*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2280*fcf3ce44SJohn Forte 	}
2281*fcf3ce44SJohn Forte 
2282*fcf3ce44SJohn Forte 	return (rval);
2283*fcf3ce44SJohn Forte }
2284*fcf3ce44SJohn Forte 
2285*fcf3ce44SJohn Forte /*
2286*fcf3ce44SJohn Forte  * ql_load_flash_fw
2287*fcf3ce44SJohn Forte  *	Gets ISP24xx firmware from flash and loads ISP.
2288*fcf3ce44SJohn Forte  *
2289*fcf3ce44SJohn Forte  * Input:
2290*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
2291*fcf3ce44SJohn Forte  *
2292*fcf3ce44SJohn Forte  * Returns:
2293*fcf3ce44SJohn Forte  *	qla local function return status code.
2294*fcf3ce44SJohn Forte  */
2295*fcf3ce44SJohn Forte static int
2296*fcf3ce44SJohn Forte ql_load_flash_fw(ql_adapter_state_t *ha)
2297*fcf3ce44SJohn Forte {
2298*fcf3ce44SJohn Forte 	int		rval;
2299*fcf3ce44SJohn Forte 	uint8_t		seg_cnt;
2300*fcf3ce44SJohn Forte 	uint32_t	risc_address, xfer_size, count,	*bp, faddr;
2301*fcf3ce44SJohn Forte 	uint32_t	flash_addr = FLASH_24XX_FIRMWARE_ADDR;
2302*fcf3ce44SJohn Forte 	uint32_t	risc_code_size = 0;
2303*fcf3ce44SJohn Forte 
2304*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2305*fcf3ce44SJohn Forte 
2306*fcf3ce44SJohn Forte 	/* Adjust addr for 32 bit words */
2307*fcf3ce44SJohn Forte 	flash_addr = flash_addr / 4;
2308*fcf3ce44SJohn Forte 
2309*fcf3ce44SJohn Forte 	for (seg_cnt = 0; seg_cnt < 2; seg_cnt++) {
2310*fcf3ce44SJohn Forte 		xfer_size = ha->fw_transfer_size >> 2;
2311*fcf3ce44SJohn Forte 		do {
2312*fcf3ce44SJohn Forte 			GLOBAL_HW_LOCK();
2313*fcf3ce44SJohn Forte 
2314*fcf3ce44SJohn Forte 			/* Read data from flash. */
2315*fcf3ce44SJohn Forte 			bp = (uint32_t *)ha->request_ring_bp;
2316*fcf3ce44SJohn Forte 			faddr = FLASH_DATA_ADDR | flash_addr;
2317*fcf3ce44SJohn Forte 			for (count = 0; count < xfer_size; count++) {
2318*fcf3ce44SJohn Forte 				rval = ql_24xx_read_flash(ha, faddr++, bp);
2319*fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS) {
2320*fcf3ce44SJohn Forte 					break;
2321*fcf3ce44SJohn Forte 				}
2322*fcf3ce44SJohn Forte 				ql_chg_endian((uint8_t *)bp++, 4);
2323*fcf3ce44SJohn Forte 			}
2324*fcf3ce44SJohn Forte 
2325*fcf3ce44SJohn Forte 			GLOBAL_HW_UNLOCK();
2326*fcf3ce44SJohn Forte 
2327*fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2328*fcf3ce44SJohn Forte 				EL(ha, "24xx_read_flash failed=%xh\n", rval);
2329*fcf3ce44SJohn Forte 				break;
2330*fcf3ce44SJohn Forte 			}
2331*fcf3ce44SJohn Forte 
2332*fcf3ce44SJohn Forte 			if (risc_code_size == 0) {
2333*fcf3ce44SJohn Forte 				bp = (uint32_t *)ha->request_ring_bp;
2334*fcf3ce44SJohn Forte 				risc_address = bp[2];
2335*fcf3ce44SJohn Forte 				risc_code_size = bp[3];
2336*fcf3ce44SJohn Forte 				ha->risc_fw[seg_cnt].addr = risc_address;
2337*fcf3ce44SJohn Forte 				ha->risc_fw[seg_cnt].length = risc_code_size;
2338*fcf3ce44SJohn Forte 			}
2339*fcf3ce44SJohn Forte 
2340*fcf3ce44SJohn Forte 			if (risc_code_size < xfer_size) {
2341*fcf3ce44SJohn Forte 				xfer_size = risc_code_size;
2342*fcf3ce44SJohn Forte 			}
2343*fcf3ce44SJohn Forte 
2344*fcf3ce44SJohn Forte 			(void) ddi_dma_sync(ha->hba_buf.dma_handle,
2345*fcf3ce44SJohn Forte 			    REQUEST_Q_BUFFER_OFFSET, xfer_size << 2,
2346*fcf3ce44SJohn Forte 			    DDI_DMA_SYNC_FORDEV);
2347*fcf3ce44SJohn Forte 
2348*fcf3ce44SJohn Forte 			rval = ql_wrt_risc_ram(ha, risc_address,
2349*fcf3ce44SJohn Forte 			    ha->request_dvma, xfer_size);
2350*fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2351*fcf3ce44SJohn Forte 				EL(ha, "ql_wrt_risc_ram failed=%xh\n", rval);
2352*fcf3ce44SJohn Forte 				break;
2353*fcf3ce44SJohn Forte 			}
2354*fcf3ce44SJohn Forte 
2355*fcf3ce44SJohn Forte 			risc_address += xfer_size;
2356*fcf3ce44SJohn Forte 			risc_code_size -= xfer_size;
2357*fcf3ce44SJohn Forte 			flash_addr += xfer_size;
2358*fcf3ce44SJohn Forte 		} while (risc_code_size);
2359*fcf3ce44SJohn Forte 
2360*fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
2361*fcf3ce44SJohn Forte 			break;
2362*fcf3ce44SJohn Forte 		}
2363*fcf3ce44SJohn Forte 	}
2364*fcf3ce44SJohn Forte 
2365*fcf3ce44SJohn Forte 	/* Start firmware. */
2366*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2367*fcf3ce44SJohn Forte 		rval = ql_start_firmware(ha);
2368*fcf3ce44SJohn Forte 	}
2369*fcf3ce44SJohn Forte 
2370*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2371*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2372*fcf3ce44SJohn Forte 	} else {
2373*fcf3ce44SJohn Forte 		/*EMPTY*/
2374*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2375*fcf3ce44SJohn Forte 	}
2376*fcf3ce44SJohn Forte 	return (rval);
2377*fcf3ce44SJohn Forte }
2378*fcf3ce44SJohn Forte 
2379*fcf3ce44SJohn Forte /*
2380*fcf3ce44SJohn Forte  * ql_start_firmware
2381*fcf3ce44SJohn Forte  *	Starts RISC code.
2382*fcf3ce44SJohn Forte  *
2383*fcf3ce44SJohn Forte  * Input:
2384*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2385*fcf3ce44SJohn Forte  *
2386*fcf3ce44SJohn Forte  * Returns:
2387*fcf3ce44SJohn Forte  *	ql local function return status code.
2388*fcf3ce44SJohn Forte  *
2389*fcf3ce44SJohn Forte  * Context:
2390*fcf3ce44SJohn Forte  *	Kernel context.
2391*fcf3ce44SJohn Forte  */
2392*fcf3ce44SJohn Forte int
2393*fcf3ce44SJohn Forte ql_start_firmware(ql_adapter_state_t *vha)
2394*fcf3ce44SJohn Forte {
2395*fcf3ce44SJohn Forte 	int			rval;
2396*fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
2397*fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
2398*fcf3ce44SJohn Forte 
2399*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2400*fcf3ce44SJohn Forte 
2401*fcf3ce44SJohn Forte 	/* Verify checksum of loaded RISC code. */
2402*fcf3ce44SJohn Forte 	rval = ql_verify_checksum(ha);
2403*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2404*fcf3ce44SJohn Forte 		/* Start firmware execution. */
2405*fcf3ce44SJohn Forte 		(void) ql_execute_fw(ha);
2406*fcf3ce44SJohn Forte 
2407*fcf3ce44SJohn Forte 		/* Save firmware version. */
2408*fcf3ce44SJohn Forte 		(void) ql_get_fw_version(ha, &mr);
2409*fcf3ce44SJohn Forte 		ha->fw_major_version = mr.mb[1];
2410*fcf3ce44SJohn Forte 		ha->fw_minor_version = mr.mb[2];
2411*fcf3ce44SJohn Forte 		ha->fw_subminor_version = mr.mb[3];
2412*fcf3ce44SJohn Forte 		ha->fw_ext_memory_size = ((SHORT_TO_LONG(mr.mb[4], mr.mb[5]) -
2413*fcf3ce44SJohn Forte 		    0x100000) + 1) * 4;
2414*fcf3ce44SJohn Forte 		ha->fw_attributes = mr.mb[6];
2415*fcf3ce44SJohn Forte 
2416*fcf3ce44SJohn Forte 		/* Set Serdes Transmit Parameters. */
2417*fcf3ce44SJohn Forte 		if (ha->serdes_param[0] & BIT_0) {
2418*fcf3ce44SJohn Forte 			mr.mb[1] = ha->serdes_param[0];
2419*fcf3ce44SJohn Forte 			mr.mb[2] = ha->serdes_param[1];
2420*fcf3ce44SJohn Forte 			mr.mb[3] = ha->serdes_param[2];
2421*fcf3ce44SJohn Forte 			mr.mb[4] = ha->serdes_param[3];
2422*fcf3ce44SJohn Forte 			(void) ql_serdes_param(ha, &mr);
2423*fcf3ce44SJohn Forte 		}
2424*fcf3ce44SJohn Forte 	}
2425*fcf3ce44SJohn Forte 
2426*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2427*fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~FIRMWARE_LOADED;
2428*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2429*fcf3ce44SJohn Forte 	} else {
2430*fcf3ce44SJohn Forte 		ha->task_daemon_flags |= FIRMWARE_LOADED;
2431*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2432*fcf3ce44SJohn Forte 	}
2433*fcf3ce44SJohn Forte 	return (rval);
2434*fcf3ce44SJohn Forte }
2435*fcf3ce44SJohn Forte 
2436*fcf3ce44SJohn Forte /*
2437*fcf3ce44SJohn Forte  * ql_set_cache_line
2438*fcf3ce44SJohn Forte  *	Sets PCI cache line parameter.
2439*fcf3ce44SJohn Forte  *
2440*fcf3ce44SJohn Forte  * Input:
2441*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2442*fcf3ce44SJohn Forte  *
2443*fcf3ce44SJohn Forte  * Returns:
2444*fcf3ce44SJohn Forte  *	ql local function return status code.
2445*fcf3ce44SJohn Forte  *
2446*fcf3ce44SJohn Forte  * Context:
2447*fcf3ce44SJohn Forte  *	Kernel context.
2448*fcf3ce44SJohn Forte  */
2449*fcf3ce44SJohn Forte int
2450*fcf3ce44SJohn Forte ql_set_cache_line(ql_adapter_state_t *ha)
2451*fcf3ce44SJohn Forte {
2452*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2453*fcf3ce44SJohn Forte 
2454*fcf3ce44SJohn Forte 	/* Set the cache line. */
2455*fcf3ce44SJohn Forte 	if (CFG_IST(ha->pha, CFG_SET_CACHE_LINE_SIZE_1)) {
2456*fcf3ce44SJohn Forte 		/* Set cache line register. */
2457*fcf3ce44SJohn Forte 		ql_pci_config_put8(ha->pha, PCI_CONF_CACHE_LINESZ, 1);
2458*fcf3ce44SJohn Forte 	}
2459*fcf3ce44SJohn Forte 
2460*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2461*fcf3ce44SJohn Forte 
2462*fcf3ce44SJohn Forte 	return (QL_SUCCESS);
2463*fcf3ce44SJohn Forte }
2464*fcf3ce44SJohn Forte 
2465*fcf3ce44SJohn Forte /*
2466*fcf3ce44SJohn Forte  * ql_init_rings
2467*fcf3ce44SJohn Forte  *	Initializes firmware and ring pointers.
2468*fcf3ce44SJohn Forte  *
2469*fcf3ce44SJohn Forte  *	Beginning of response ring has initialization control block
2470*fcf3ce44SJohn Forte  *	already built by nvram config routine.
2471*fcf3ce44SJohn Forte  *
2472*fcf3ce44SJohn Forte  * Input:
2473*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2474*fcf3ce44SJohn Forte  *	ha->hba_buf = request and response rings
2475*fcf3ce44SJohn Forte  *	ha->init_ctrl_blk = initialization control block
2476*fcf3ce44SJohn Forte  *
2477*fcf3ce44SJohn Forte  * Returns:
2478*fcf3ce44SJohn Forte  *	ql local function return status code.
2479*fcf3ce44SJohn Forte  *
2480*fcf3ce44SJohn Forte  * Context:
2481*fcf3ce44SJohn Forte  *	Kernel context.
2482*fcf3ce44SJohn Forte  */
2483*fcf3ce44SJohn Forte int
2484*fcf3ce44SJohn Forte ql_init_rings(ql_adapter_state_t *vha2)
2485*fcf3ce44SJohn Forte {
2486*fcf3ce44SJohn Forte 	int			rval, rval2;
2487*fcf3ce44SJohn Forte 	uint16_t		index;
2488*fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
2489*fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha2->pha;
2490*fcf3ce44SJohn Forte 
2491*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2492*fcf3ce44SJohn Forte 
2493*fcf3ce44SJohn Forte 	/* Clear outstanding commands array. */
2494*fcf3ce44SJohn Forte 	for (index = 0; index < MAX_OUTSTANDING_COMMANDS; index++) {
2495*fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
2496*fcf3ce44SJohn Forte 	}
2497*fcf3ce44SJohn Forte 	ha->osc_index = 1;
2498*fcf3ce44SJohn Forte 
2499*fcf3ce44SJohn Forte 	ha->pending_cmds.first = NULL;
2500*fcf3ce44SJohn Forte 	ha->pending_cmds.last = NULL;
2501*fcf3ce44SJohn Forte 
2502*fcf3ce44SJohn Forte 	/* Initialize firmware. */
2503*fcf3ce44SJohn Forte 	ha->request_ring_ptr = ha->request_ring_bp;
2504*fcf3ce44SJohn Forte 	ha->req_ring_index = 0;
2505*fcf3ce44SJohn Forte 	ha->req_q_cnt = REQUEST_ENTRY_CNT - 1;
2506*fcf3ce44SJohn Forte 	ha->response_ring_ptr = ha->response_ring_bp;
2507*fcf3ce44SJohn Forte 	ha->rsp_ring_index = 0;
2508*fcf3ce44SJohn Forte 
2509*fcf3ce44SJohn Forte 	if (ha->flags & VP_ENABLED) {
2510*fcf3ce44SJohn Forte 		ql_adapter_state_t	*vha;
2511*fcf3ce44SJohn Forte 		uint16_t		cnt;
2512*fcf3ce44SJohn Forte 		uint32_t		max_vports;
2513*fcf3ce44SJohn Forte 		ql_init_24xx_cb_t	*icb = &ha->init_ctrl_blk.cb24;
2514*fcf3ce44SJohn Forte 
2515*fcf3ce44SJohn Forte 		max_vports = (CFG_IST(ha, CFG_CTRL_2422) ?
2516*fcf3ce44SJohn Forte 		    MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS);
2517*fcf3ce44SJohn Forte 		bzero(icb->vp_count,
2518*fcf3ce44SJohn Forte 		    ((uintptr_t)icb + sizeof (ql_init_24xx_cb_t)) -
2519*fcf3ce44SJohn Forte 		    (uintptr_t)icb->vp_count);
2520*fcf3ce44SJohn Forte 		icb->vp_count[0] = (uint8_t)max_vports;
2521*fcf3ce44SJohn Forte 
2522*fcf3ce44SJohn Forte 		/* Allow connection option 2. */
2523*fcf3ce44SJohn Forte 		icb->global_vp_option[0] = BIT_1;
2524*fcf3ce44SJohn Forte 
2525*fcf3ce44SJohn Forte 		for (cnt = 0, vha = ha->vp_next; cnt < max_vports &&
2526*fcf3ce44SJohn Forte 		    vha != NULL; vha = vha->vp_next, cnt++) {
2527*fcf3ce44SJohn Forte 
2528*fcf3ce44SJohn Forte 			index = (uint8_t)(vha->vp_index - 1);
2529*fcf3ce44SJohn Forte 			bcopy(vha->loginparams.node_ww_name.raw_wwn,
2530*fcf3ce44SJohn Forte 			    icb->vpc[index].node_name, 8);
2531*fcf3ce44SJohn Forte 			bcopy(vha->loginparams.nport_ww_name.raw_wwn,
2532*fcf3ce44SJohn Forte 			    icb->vpc[index].port_name, 8);
2533*fcf3ce44SJohn Forte 
2534*fcf3ce44SJohn Forte 			icb->vpc[index].options = VPO_TARGET_MODE_DISABLED |
2535*fcf3ce44SJohn Forte 			    VPO_INITIATOR_MODE_ENABLED;
2536*fcf3ce44SJohn Forte 			if (vha->flags & VP_ENABLED) {
2537*fcf3ce44SJohn Forte 				icb->vpc[index].options = (uint8_t)
2538*fcf3ce44SJohn Forte 				    (icb->vpc[index].options | VPO_ENABLED);
2539*fcf3ce44SJohn Forte 			}
2540*fcf3ce44SJohn Forte 		}
2541*fcf3ce44SJohn Forte 	}
2542*fcf3ce44SJohn Forte 
2543*fcf3ce44SJohn Forte 	rval = ql_init_firmware(ha);
2544*fcf3ce44SJohn Forte 
2545*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && (CFG_IST(ha, CFG_CTRL_2425)) == 0) {
2546*fcf3ce44SJohn Forte 		/* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */
2547*fcf3ce44SJohn Forte 		rval = ql_get_firmware_option(ha, &mr);
2548*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2549*fcf3ce44SJohn Forte 			mr.mb[1] = (uint16_t)(mr.mb[1] | BIT_9);
2550*fcf3ce44SJohn Forte 			mr.mb[2] = 0;
2551*fcf3ce44SJohn Forte 			mr.mb[3] = BIT_10;
2552*fcf3ce44SJohn Forte 			rval = ql_set_firmware_option(ha, &mr);
2553*fcf3ce44SJohn Forte 		}
2554*fcf3ce44SJohn Forte 	}
2555*fcf3ce44SJohn Forte 
2556*fcf3ce44SJohn Forte 	if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWFCETRACE))) {
2557*fcf3ce44SJohn Forte 		if ((rval2 = ql_get_dma_mem(ha, &ha->fwfcetracebuf,
2558*fcf3ce44SJohn Forte 		    FWFCESIZE, LITTLE_ENDIAN_DMA, MEM_RING_ALIGN))
2559*fcf3ce44SJohn Forte 		    != QL_SUCCESS) {
2560*fcf3ce44SJohn Forte 			EL(ha, "fcetrace buffer alloc failed: %xh\n", rval2);
2561*fcf3ce44SJohn Forte 		} else {
2562*fcf3ce44SJohn Forte 			if ((rval2 = ql_fw_etrace(ha, &ha->fwfcetracebuf,
2563*fcf3ce44SJohn Forte 			    FTO_FCEENABLE)) != QL_SUCCESS) {
2564*fcf3ce44SJohn Forte 				EL(ha, "fcetrace enable failed: %xh\n", rval2);
2565*fcf3ce44SJohn Forte 				ql_free_phys(ha, &ha->fwfcetracebuf);
2566*fcf3ce44SJohn Forte 			}
2567*fcf3ce44SJohn Forte 		}
2568*fcf3ce44SJohn Forte 	}
2569*fcf3ce44SJohn Forte 
2570*fcf3ce44SJohn Forte 	if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE))) {
2571*fcf3ce44SJohn Forte 		if ((rval2 = ql_get_dma_mem(ha, &ha->fwexttracebuf,
2572*fcf3ce44SJohn Forte 		    FWEXTSIZE, LITTLE_ENDIAN_DMA, MEM_RING_ALIGN))
2573*fcf3ce44SJohn Forte 		    != QL_SUCCESS) {
2574*fcf3ce44SJohn Forte 			EL(ha, "exttrace buffer alloc failed: %xh\n", rval2);
2575*fcf3ce44SJohn Forte 		} else {
2576*fcf3ce44SJohn Forte 			if ((rval2 = ql_fw_etrace(ha, &ha->fwexttracebuf,
2577*fcf3ce44SJohn Forte 			    FTO_EXTENABLE)) != QL_SUCCESS) {
2578*fcf3ce44SJohn Forte 				EL(ha, "exttrace enable failed: %xh\n", rval2);
2579*fcf3ce44SJohn Forte 				ql_free_phys(ha, &ha->fwexttracebuf);
2580*fcf3ce44SJohn Forte 			}
2581*fcf3ce44SJohn Forte 		}
2582*fcf3ce44SJohn Forte 	}
2583*fcf3ce44SJohn Forte 
2584*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && CFG_IST(ha, CFG_CTRL_MENLO)) {
2585*fcf3ce44SJohn Forte 		ql_mbx_iocb_t	*pkt;
2586*fcf3ce44SJohn Forte 		clock_t		timer;
2587*fcf3ce44SJohn Forte 
2588*fcf3ce44SJohn Forte 		/* Wait for firmware login of menlo. */
2589*fcf3ce44SJohn Forte 		for (timer = 3000; timer; timer--) {
2590*fcf3ce44SJohn Forte 			if (ha->flags & MENLO_LOGIN_OPERATIONAL) {
2591*fcf3ce44SJohn Forte 				break;
2592*fcf3ce44SJohn Forte 			}
2593*fcf3ce44SJohn Forte 
2594*fcf3ce44SJohn Forte 			if (!(ha->flags & INTERRUPTS_ENABLED) ||
2595*fcf3ce44SJohn Forte 			    ddi_in_panic()) {
2596*fcf3ce44SJohn Forte 				if (RD16_IO_REG(ha, istatus) & RISC_INT) {
2597*fcf3ce44SJohn Forte 					(void) ql_isr((caddr_t)ha);
2598*fcf3ce44SJohn Forte 					INTR_LOCK(ha);
2599*fcf3ce44SJohn Forte 					ha->intr_claimed = B_TRUE;
2600*fcf3ce44SJohn Forte 					INTR_UNLOCK(ha);
2601*fcf3ce44SJohn Forte 				}
2602*fcf3ce44SJohn Forte 			}
2603*fcf3ce44SJohn Forte 
2604*fcf3ce44SJohn Forte 			/* Delay for 1 tick (10 milliseconds). */
2605*fcf3ce44SJohn Forte 			ql_delay(ha, 10000);
2606*fcf3ce44SJohn Forte 		}
2607*fcf3ce44SJohn Forte 
2608*fcf3ce44SJohn Forte 		if (timer == 0) {
2609*fcf3ce44SJohn Forte 			rval = QL_FUNCTION_TIMEOUT;
2610*fcf3ce44SJohn Forte 		} else {
2611*fcf3ce44SJohn Forte 			pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
2612*fcf3ce44SJohn Forte 			if (pkt == NULL) {
2613*fcf3ce44SJohn Forte 				EL(ha, "failed, kmem_zalloc\n");
2614*fcf3ce44SJohn Forte 				rval = QL_MEMORY_ALLOC_FAILED;
2615*fcf3ce44SJohn Forte 			} else {
2616*fcf3ce44SJohn Forte 				pkt->mvfy.entry_type = VERIFY_MENLO_TYPE;
2617*fcf3ce44SJohn Forte 				pkt->mvfy.entry_count = 1;
2618*fcf3ce44SJohn Forte 				pkt->mvfy.options_status =
2619*fcf3ce44SJohn Forte 				    LE_16(VMF_DO_NOT_UPDATE_FW);
2620*fcf3ce44SJohn Forte 
2621*fcf3ce44SJohn Forte 				rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
2622*fcf3ce44SJohn Forte 				    sizeof (ql_mbx_iocb_t));
2623*fcf3ce44SJohn Forte 				LITTLE_ENDIAN_16(&pkt->mvfy.options_status);
2624*fcf3ce44SJohn Forte 				LITTLE_ENDIAN_16(&pkt->mvfy.failure_code);
2625*fcf3ce44SJohn Forte 
2626*fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS ||
2627*fcf3ce44SJohn Forte 				    (pkt->mvfy.entry_status & 0x3c) != 0 ||
2628*fcf3ce44SJohn Forte 				    pkt->mvfy.options_status != CS_COMPLETE) {
2629*fcf3ce44SJohn Forte 					EL(ha, "failed, status=%xh, es=%xh, "
2630*fcf3ce44SJohn Forte 					    "cs=%xh, fc=%xh\n", rval,
2631*fcf3ce44SJohn Forte 					    pkt->mvfy.entry_status & 0x3c,
2632*fcf3ce44SJohn Forte 					    pkt->mvfy.options_status,
2633*fcf3ce44SJohn Forte 					    pkt->mvfy.failure_code);
2634*fcf3ce44SJohn Forte 					if (rval == QL_SUCCESS) {
2635*fcf3ce44SJohn Forte 						rval = QL_FUNCTION_FAILED;
2636*fcf3ce44SJohn Forte 					}
2637*fcf3ce44SJohn Forte 				}
2638*fcf3ce44SJohn Forte 
2639*fcf3ce44SJohn Forte 				kmem_free(pkt, sizeof (ql_mbx_iocb_t));
2640*fcf3ce44SJohn Forte 			}
2641*fcf3ce44SJohn Forte 		}
2642*fcf3ce44SJohn Forte 	}
2643*fcf3ce44SJohn Forte 
2644*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2645*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2646*fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~FIRMWARE_UP;
2647*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2648*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2649*fcf3ce44SJohn Forte 	} else {
2650*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2651*fcf3ce44SJohn Forte 		ha->task_daemon_flags |= FIRMWARE_UP;
2652*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2653*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2654*fcf3ce44SJohn Forte 	}
2655*fcf3ce44SJohn Forte 	return (rval);
2656*fcf3ce44SJohn Forte }
2657*fcf3ce44SJohn Forte 
2658*fcf3ce44SJohn Forte /*
2659*fcf3ce44SJohn Forte  * ql_fw_ready
2660*fcf3ce44SJohn Forte  *	Waits for firmware ready. If firmware becomes ready
2661*fcf3ce44SJohn Forte  *	device queues and RISC code are synchronized.
2662*fcf3ce44SJohn Forte  *
2663*fcf3ce44SJohn Forte  * Input:
2664*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2665*fcf3ce44SJohn Forte  *	secs = max wait time, in seconds (0-255).
2666*fcf3ce44SJohn Forte  *
2667*fcf3ce44SJohn Forte  * Returns:
2668*fcf3ce44SJohn Forte  *	ql local function return status code.
2669*fcf3ce44SJohn Forte  *
2670*fcf3ce44SJohn Forte  * Context:
2671*fcf3ce44SJohn Forte  *	Kernel context.
2672*fcf3ce44SJohn Forte  */
2673*fcf3ce44SJohn Forte int
2674*fcf3ce44SJohn Forte ql_fw_ready(ql_adapter_state_t *ha, uint8_t secs)
2675*fcf3ce44SJohn Forte {
2676*fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
2677*fcf3ce44SJohn Forte 	clock_t		timer;
2678*fcf3ce44SJohn Forte 	clock_t		dly = 250000;
2679*fcf3ce44SJohn Forte 	clock_t		sec_delay = MICROSEC / dly;
2680*fcf3ce44SJohn Forte 	clock_t		wait = secs * sec_delay;
2681*fcf3ce44SJohn Forte 	int		rval = QL_FUNCTION_FAILED;
2682*fcf3ce44SJohn Forte 	uint16_t	state = 0xffff;
2683*fcf3ce44SJohn Forte 
2684*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2685*fcf3ce44SJohn Forte 
2686*fcf3ce44SJohn Forte 	timer = ha->r_a_tov < secs ? secs : ha->r_a_tov;
2687*fcf3ce44SJohn Forte 	timer = (timer + 2) * sec_delay;
2688*fcf3ce44SJohn Forte 
2689*fcf3ce44SJohn Forte 	/* Wait for ISP to finish LIP */
2690*fcf3ce44SJohn Forte 	while (timer != 0 && wait != 0 &&
2691*fcf3ce44SJohn Forte 	    !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
2692*fcf3ce44SJohn Forte 
2693*fcf3ce44SJohn Forte 		rval = ql_get_firmware_state(ha, &mr);
2694*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS) {
2695*fcf3ce44SJohn Forte 			if (ha->task_daemon_flags & (ISP_ABORT_NEEDED |
2696*fcf3ce44SJohn Forte 			    LOOP_DOWN)) {
2697*fcf3ce44SJohn Forte 				wait--;
2698*fcf3ce44SJohn Forte 			} else if (mr.mb[1] != FSTATE_READY) {
2699*fcf3ce44SJohn Forte 				if (mr.mb[1] != FSTATE_WAIT_LOGIN) {
2700*fcf3ce44SJohn Forte 					wait--;
2701*fcf3ce44SJohn Forte 				}
2702*fcf3ce44SJohn Forte 				rval = QL_FUNCTION_FAILED;
2703*fcf3ce44SJohn Forte 			} else {
2704*fcf3ce44SJohn Forte 				/* Firmware is ready. Get 2 * R_A_TOV. */
2705*fcf3ce44SJohn Forte 				rval = ql_get_timeout_parameters(ha,
2706*fcf3ce44SJohn Forte 				    &ha->r_a_tov);
2707*fcf3ce44SJohn Forte 				if (rval != QL_SUCCESS) {
2708*fcf3ce44SJohn Forte 					EL(ha, "failed, get_timeout_param"
2709*fcf3ce44SJohn Forte 					    "=%xh\n", rval);
2710*fcf3ce44SJohn Forte 				}
2711*fcf3ce44SJohn Forte 
2712*fcf3ce44SJohn Forte 				/* Configure loop. */
2713*fcf3ce44SJohn Forte 				rval = ql_configure_loop(ha);
2714*fcf3ce44SJohn Forte 				(void) ql_marker(ha, 0, 0, MK_SYNC_ALL);
2715*fcf3ce44SJohn Forte 
2716*fcf3ce44SJohn Forte 				if (ha->task_daemon_flags &
2717*fcf3ce44SJohn Forte 				    LOOP_RESYNC_NEEDED) {
2718*fcf3ce44SJohn Forte 					wait--;
2719*fcf3ce44SJohn Forte 					EL(ha, "loop trans; tdf=%xh\n",
2720*fcf3ce44SJohn Forte 					    ha->task_daemon_flags);
2721*fcf3ce44SJohn Forte 				} else {
2722*fcf3ce44SJohn Forte 					break;
2723*fcf3ce44SJohn Forte 				}
2724*fcf3ce44SJohn Forte 			}
2725*fcf3ce44SJohn Forte 		} else {
2726*fcf3ce44SJohn Forte 			wait--;
2727*fcf3ce44SJohn Forte 		}
2728*fcf3ce44SJohn Forte 
2729*fcf3ce44SJohn Forte 		if (state != mr.mb[1]) {
2730*fcf3ce44SJohn Forte 			EL(ha, "mailbox_reg[1] = %xh\n", mr.mb[1]);
2731*fcf3ce44SJohn Forte 			state = mr.mb[1];
2732*fcf3ce44SJohn Forte 		}
2733*fcf3ce44SJohn Forte 
2734*fcf3ce44SJohn Forte 		/* Delay for a tick if waiting. */
2735*fcf3ce44SJohn Forte 		if (timer-- != 0 && wait != 0) {
2736*fcf3ce44SJohn Forte 			if (timer % 4 == 0) {
2737*fcf3ce44SJohn Forte 				delay(drv_usectohz(dly));
2738*fcf3ce44SJohn Forte 			} else {
2739*fcf3ce44SJohn Forte 				drv_usecwait(dly);
2740*fcf3ce44SJohn Forte 			}
2741*fcf3ce44SJohn Forte 		} else {
2742*fcf3ce44SJohn Forte 			rval = QL_FUNCTION_TIMEOUT;
2743*fcf3ce44SJohn Forte 		}
2744*fcf3ce44SJohn Forte 	}
2745*fcf3ce44SJohn Forte 
2746*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2747*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2748*fcf3ce44SJohn Forte 	} else {
2749*fcf3ce44SJohn Forte 		/*EMPTY*/
2750*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2751*fcf3ce44SJohn Forte 	}
2752*fcf3ce44SJohn Forte 	return (rval);
2753*fcf3ce44SJohn Forte }
2754*fcf3ce44SJohn Forte 
2755*fcf3ce44SJohn Forte /*
2756*fcf3ce44SJohn Forte  * ql_configure_loop
2757*fcf3ce44SJohn Forte  *	Setup configurations based on loop.
2758*fcf3ce44SJohn Forte  *
2759*fcf3ce44SJohn Forte  * Input:
2760*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2761*fcf3ce44SJohn Forte  *
2762*fcf3ce44SJohn Forte  * Returns:
2763*fcf3ce44SJohn Forte  *	ql local function return status code.
2764*fcf3ce44SJohn Forte  *
2765*fcf3ce44SJohn Forte  * Context:
2766*fcf3ce44SJohn Forte  *	Kernel context.
2767*fcf3ce44SJohn Forte  */
2768*fcf3ce44SJohn Forte static int
2769*fcf3ce44SJohn Forte ql_configure_loop(ql_adapter_state_t *ha)
2770*fcf3ce44SJohn Forte {
2771*fcf3ce44SJohn Forte 	int			rval;
2772*fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
2773*fcf3ce44SJohn Forte 
2774*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2775*fcf3ce44SJohn Forte 
2776*fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
2777*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
2778*fcf3ce44SJohn Forte 		if (!(vha->task_daemon_flags & LOOP_RESYNC_NEEDED) &&
2779*fcf3ce44SJohn Forte 		    vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
2780*fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
2781*fcf3ce44SJohn Forte 			continue;
2782*fcf3ce44SJohn Forte 		}
2783*fcf3ce44SJohn Forte 		vha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED;
2784*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
2785*fcf3ce44SJohn Forte 
2786*fcf3ce44SJohn Forte 		rval = ql_configure_hba(vha);
2787*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
2788*fcf3ce44SJohn Forte 		    (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
2789*fcf3ce44SJohn Forte 			rval = ql_configure_device_d_id(vha);
2790*fcf3ce44SJohn Forte 			if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
2791*fcf3ce44SJohn Forte 			    (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
2792*fcf3ce44SJohn Forte 				(void) ql_configure_fabric(vha);
2793*fcf3ce44SJohn Forte 			}
2794*fcf3ce44SJohn Forte 		}
2795*fcf3ce44SJohn Forte 	}
2796*fcf3ce44SJohn Forte 
2797*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2798*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2799*fcf3ce44SJohn Forte 	} else {
2800*fcf3ce44SJohn Forte 		/*EMPTY*/
2801*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2802*fcf3ce44SJohn Forte 	}
2803*fcf3ce44SJohn Forte 	return (rval);
2804*fcf3ce44SJohn Forte }
2805*fcf3ce44SJohn Forte 
2806*fcf3ce44SJohn Forte /*
2807*fcf3ce44SJohn Forte  * ql_configure_hba
2808*fcf3ce44SJohn Forte  *	Setup adapter context.
2809*fcf3ce44SJohn Forte  *
2810*fcf3ce44SJohn Forte  * Input:
2811*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2812*fcf3ce44SJohn Forte  *
2813*fcf3ce44SJohn Forte  * Returns:
2814*fcf3ce44SJohn Forte  *	ql local function return status code.
2815*fcf3ce44SJohn Forte  *
2816*fcf3ce44SJohn Forte  * Context:
2817*fcf3ce44SJohn Forte  *	Kernel context.
2818*fcf3ce44SJohn Forte  */
2819*fcf3ce44SJohn Forte static int
2820*fcf3ce44SJohn Forte ql_configure_hba(ql_adapter_state_t *ha)
2821*fcf3ce44SJohn Forte {
2822*fcf3ce44SJohn Forte 	uint8_t		*bp;
2823*fcf3ce44SJohn Forte 	int		rval;
2824*fcf3ce44SJohn Forte 	uint32_t	state;
2825*fcf3ce44SJohn Forte 	ql_mbx_data_t	mr;
2826*fcf3ce44SJohn Forte 
2827*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2828*fcf3ce44SJohn Forte 
2829*fcf3ce44SJohn Forte 	/* Get host addresses. */
2830*fcf3ce44SJohn Forte 	rval = ql_get_adapter_id(ha, &mr);
2831*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
2832*fcf3ce44SJohn Forte 		ha->topology = (uint8_t)(ha->topology &
2833*fcf3ce44SJohn Forte 		    ~(QL_N_PORT | QL_NL_PORT | QL_F_PORT | QL_FL_PORT));
2834*fcf3ce44SJohn Forte 
2835*fcf3ce44SJohn Forte 		/* Save Host d_id, alpa, loop ID. */
2836*fcf3ce44SJohn Forte 		ha->loop_id = mr.mb[1];
2837*fcf3ce44SJohn Forte 		ha->d_id.b.al_pa = LSB(mr.mb[2]);
2838*fcf3ce44SJohn Forte 		ha->d_id.b.area = MSB(mr.mb[2]);
2839*fcf3ce44SJohn Forte 		ha->d_id.b.domain = LSB(mr.mb[3]);
2840*fcf3ce44SJohn Forte 
2841*fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
2842*fcf3ce44SJohn Forte 		ha->flags &= ~FDISC_ENABLED;
2843*fcf3ce44SJohn Forte 
2844*fcf3ce44SJohn Forte 		/* Get loop topology. */
2845*fcf3ce44SJohn Forte 		switch (mr.mb[6]) {
2846*fcf3ce44SJohn Forte 		case CNX_LOOP_NO_FABRIC:
2847*fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_NL_PORT);
2848*fcf3ce44SJohn Forte 			break;
2849*fcf3ce44SJohn Forte 		case CNX_FLPORT_IN_LOOP:
2850*fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_FL_PORT);
2851*fcf3ce44SJohn Forte 			break;
2852*fcf3ce44SJohn Forte 		case CNX_NPORT_2_NPORT_P2P:
2853*fcf3ce44SJohn Forte 		case CNX_NPORT_2_NPORT_NO_TGT_RSP:
2854*fcf3ce44SJohn Forte 			ha->flags |= POINT_TO_POINT;
2855*fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_N_PORT);
2856*fcf3ce44SJohn Forte 			break;
2857*fcf3ce44SJohn Forte 		case CNX_FLPORT_P2P:
2858*fcf3ce44SJohn Forte 			ha->flags |= POINT_TO_POINT;
2859*fcf3ce44SJohn Forte 			ha->topology = (uint8_t)(ha->topology | QL_F_PORT);
2860*fcf3ce44SJohn Forte 
2861*fcf3ce44SJohn Forte 			/* Get supported option. */
2862*fcf3ce44SJohn Forte 			if (CFG_IST(ha, CFG_CTRL_2425) &&
2863*fcf3ce44SJohn Forte 			    mr.mb[7] & FLOGI_NPIV_SUPPORT) {
2864*fcf3ce44SJohn Forte 				ha->flags |= FDISC_ENABLED;
2865*fcf3ce44SJohn Forte 			}
2866*fcf3ce44SJohn Forte 			break;
2867*fcf3ce44SJohn Forte 		default:
2868*fcf3ce44SJohn Forte 			QL_PRINT_2(CE_CONT, "(%d,%d): UNKNOWN topology=%xh, "
2869*fcf3ce44SJohn Forte 			    "d_id=%xh\n", ha->instance, ha->vp_index, mr.mb[6],
2870*fcf3ce44SJohn Forte 			    ha->d_id.b24);
2871*fcf3ce44SJohn Forte 			rval = QL_FUNCTION_FAILED;
2872*fcf3ce44SJohn Forte 			break;
2873*fcf3ce44SJohn Forte 		}
2874*fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
2875*fcf3ce44SJohn Forte 
2876*fcf3ce44SJohn Forte 		if (CFG_IST(ha, (CFG_CTRL_2300|CFG_CTRL_6322|
2877*fcf3ce44SJohn Forte 		    CFG_CTRL_2425))) {
2878*fcf3ce44SJohn Forte 			mr.mb[1] = 0;
2879*fcf3ce44SJohn Forte 			mr.mb[2] = 0;
2880*fcf3ce44SJohn Forte 			rval = ql_data_rate(ha, &mr);
2881*fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
2882*fcf3ce44SJohn Forte 				EL(ha, "data_rate status=%xh\n", rval);
2883*fcf3ce44SJohn Forte 				state = FC_STATE_FULL_SPEED;
2884*fcf3ce44SJohn Forte 			} else {
2885*fcf3ce44SJohn Forte 				if (mr.mb[1] == 0) {
2886*fcf3ce44SJohn Forte 					state = FC_STATE_1GBIT_SPEED;
2887*fcf3ce44SJohn Forte 				} else if (mr.mb[1] == 1) {
2888*fcf3ce44SJohn Forte 					state = FC_STATE_2GBIT_SPEED;
2889*fcf3ce44SJohn Forte 				} else if (mr.mb[1] == 3) {
2890*fcf3ce44SJohn Forte 					state = FC_STATE_4GBIT_SPEED;
2891*fcf3ce44SJohn Forte 				} else if (mr.mb[1] == 4) {
2892*fcf3ce44SJohn Forte 					state = FC_STATE_8GBIT_SPEED;
2893*fcf3ce44SJohn Forte 				} else {
2894*fcf3ce44SJohn Forte 					state = 0;
2895*fcf3ce44SJohn Forte 				}
2896*fcf3ce44SJohn Forte 			}
2897*fcf3ce44SJohn Forte 		} else {
2898*fcf3ce44SJohn Forte 			state = FC_STATE_FULL_SPEED;
2899*fcf3ce44SJohn Forte 		}
2900*fcf3ce44SJohn Forte 		ha->state = FC_PORT_STATE_MASK(ha->state) | state;
2901*fcf3ce44SJohn Forte 	}
2902*fcf3ce44SJohn Forte 
2903*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
2904*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2905*fcf3ce44SJohn Forte 	} else {
2906*fcf3ce44SJohn Forte 		bp = ha->loginparams.nport_ww_name.raw_wwn;
2907*fcf3ce44SJohn Forte 		EL(ha, "topology=%xh, d_id=%xh, "
2908*fcf3ce44SJohn Forte 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n",
2909*fcf3ce44SJohn Forte 		    ha->topology, ha->d_id.b24, bp[0], bp[1],
2910*fcf3ce44SJohn Forte 		    bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]);
2911*fcf3ce44SJohn Forte 	}
2912*fcf3ce44SJohn Forte 	return (rval);
2913*fcf3ce44SJohn Forte }
2914*fcf3ce44SJohn Forte 
2915*fcf3ce44SJohn Forte /*
2916*fcf3ce44SJohn Forte  * ql_configure_device_d_id
2917*fcf3ce44SJohn Forte  *	Updates device loop ID.
2918*fcf3ce44SJohn Forte  *	Also adds to device queue any new devices found on private loop.
2919*fcf3ce44SJohn Forte  *
2920*fcf3ce44SJohn Forte  * Input:
2921*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
2922*fcf3ce44SJohn Forte  *
2923*fcf3ce44SJohn Forte  * Returns:
2924*fcf3ce44SJohn Forte  *	ql local function return status code.
2925*fcf3ce44SJohn Forte  *
2926*fcf3ce44SJohn Forte  * Context:
2927*fcf3ce44SJohn Forte  *	Kernel context.
2928*fcf3ce44SJohn Forte  */
2929*fcf3ce44SJohn Forte static int
2930*fcf3ce44SJohn Forte ql_configure_device_d_id(ql_adapter_state_t *ha)
2931*fcf3ce44SJohn Forte {
2932*fcf3ce44SJohn Forte 	port_id_t		d_id;
2933*fcf3ce44SJohn Forte 	ql_link_t		*link;
2934*fcf3ce44SJohn Forte 	int			rval;
2935*fcf3ce44SJohn Forte 	int			loop;
2936*fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
2937*fcf3ce44SJohn Forte 	ql_dev_id_list_t	*list;
2938*fcf3ce44SJohn Forte 	uint32_t		list_size;
2939*fcf3ce44SJohn Forte 	uint16_t		index, loop_id;
2940*fcf3ce44SJohn Forte 	ql_mbx_data_t		mr;
2941*fcf3ce44SJohn Forte 	uint8_t			retries = MAX_DEVICE_LOST_RETRY;
2942*fcf3ce44SJohn Forte 
2943*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2944*fcf3ce44SJohn Forte 
2945*fcf3ce44SJohn Forte 	list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
2946*fcf3ce44SJohn Forte 	list = kmem_zalloc(list_size, KM_SLEEP);
2947*fcf3ce44SJohn Forte 	if (list == NULL) {
2948*fcf3ce44SJohn Forte 		rval = QL_MEMORY_ALLOC_FAILED;
2949*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
2950*fcf3ce44SJohn Forte 		return (rval);
2951*fcf3ce44SJohn Forte 	}
2952*fcf3ce44SJohn Forte 
2953*fcf3ce44SJohn Forte 	do {
2954*fcf3ce44SJohn Forte 		/*
2955*fcf3ce44SJohn Forte 		 * Get data from RISC code d_id list to init each device queue.
2956*fcf3ce44SJohn Forte 		 */
2957*fcf3ce44SJohn Forte 		rval = ql_get_id_list(ha, (caddr_t)list, list_size, &mr);
2958*fcf3ce44SJohn Forte 		if (rval != QL_SUCCESS) {
2959*fcf3ce44SJohn Forte 			kmem_free(list, list_size);
2960*fcf3ce44SJohn Forte 			EL(ha, "failed, rval = %xh\n", rval);
2961*fcf3ce44SJohn Forte 			return (rval);
2962*fcf3ce44SJohn Forte 		}
2963*fcf3ce44SJohn Forte 
2964*fcf3ce44SJohn Forte 		/* Acquire adapter state lock. */
2965*fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
2966*fcf3ce44SJohn Forte 
2967*fcf3ce44SJohn Forte 		/* Mark all queues as unusable. */
2968*fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
2969*fcf3ce44SJohn Forte 			for (link = ha->dev[index].first; link != NULL;
2970*fcf3ce44SJohn Forte 			    link = link->next) {
2971*fcf3ce44SJohn Forte 				tq = link->base_address;
2972*fcf3ce44SJohn Forte 				DEVICE_QUEUE_LOCK(tq);
2973*fcf3ce44SJohn Forte 				if (!(tq->flags & TQF_PLOGI_PROGRS)) {
2974*fcf3ce44SJohn Forte 					tq->loop_id = (uint16_t)
2975*fcf3ce44SJohn Forte 					    (tq->loop_id | PORT_LOST_ID);
2976*fcf3ce44SJohn Forte 				}
2977*fcf3ce44SJohn Forte 				DEVICE_QUEUE_UNLOCK(tq);
2978*fcf3ce44SJohn Forte 			}
2979*fcf3ce44SJohn Forte 		}
2980*fcf3ce44SJohn Forte 
2981*fcf3ce44SJohn Forte 		/* If device not in queues add new queue. */
2982*fcf3ce44SJohn Forte 		for (index = 0; index < mr.mb[1]; index++) {
2983*fcf3ce44SJohn Forte 			ql_dev_list(ha, list, index, &d_id, &loop_id);
2984*fcf3ce44SJohn Forte 
2985*fcf3ce44SJohn Forte 			if (VALID_DEVICE_ID(ha, loop_id)) {
2986*fcf3ce44SJohn Forte 				tq = ql_dev_init(ha, d_id, loop_id);
2987*fcf3ce44SJohn Forte 				if (tq != NULL) {
2988*fcf3ce44SJohn Forte 					tq->loop_id = loop_id;
2989*fcf3ce44SJohn Forte 
2990*fcf3ce44SJohn Forte 					/* Test for fabric device. */
2991*fcf3ce44SJohn Forte 					if (d_id.b.domain !=
2992*fcf3ce44SJohn Forte 					    ha->d_id.b.domain ||
2993*fcf3ce44SJohn Forte 					    d_id.b.area != ha->d_id.b.area) {
2994*fcf3ce44SJohn Forte 						tq->flags |= TQF_FABRIC_DEVICE;
2995*fcf3ce44SJohn Forte 					}
2996*fcf3ce44SJohn Forte 
2997*fcf3ce44SJohn Forte 					ADAPTER_STATE_UNLOCK(ha);
2998*fcf3ce44SJohn Forte 					if (ql_get_port_database(ha, tq,
2999*fcf3ce44SJohn Forte 					    PDF_NONE) == QL_SUCCESS) {
3000*fcf3ce44SJohn Forte 						ADAPTER_STATE_LOCK(ha);
3001*fcf3ce44SJohn Forte 						tq->loop_id = (uint16_t)
3002*fcf3ce44SJohn Forte 						    (tq->loop_id &
3003*fcf3ce44SJohn Forte 						    ~PORT_LOST_ID);
3004*fcf3ce44SJohn Forte 					} else {
3005*fcf3ce44SJohn Forte 						ADAPTER_STATE_LOCK(ha);
3006*fcf3ce44SJohn Forte 					}
3007*fcf3ce44SJohn Forte 				}
3008*fcf3ce44SJohn Forte 			}
3009*fcf3ce44SJohn Forte 		}
3010*fcf3ce44SJohn Forte 
3011*fcf3ce44SJohn Forte 		/* 24xx does not report switch devices in ID list. */
3012*fcf3ce44SJohn Forte 		if ((CFG_IST(ha, CFG_CTRL_2425)) &&
3013*fcf3ce44SJohn Forte 		    ha->topology & (QL_F_PORT | QL_FL_PORT)) {
3014*fcf3ce44SJohn Forte 			d_id.b24 = 0xfffffe;
3015*fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, FL_PORT_24XX_HDL);
3016*fcf3ce44SJohn Forte 			if (tq != NULL) {
3017*fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3018*fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3019*fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3020*fcf3ce44SJohn Forte 			}
3021*fcf3ce44SJohn Forte 			d_id.b24 = 0xfffffc;
3022*fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, SNS_24XX_HDL);
3023*fcf3ce44SJohn Forte 			if (tq != NULL) {
3024*fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3025*fcf3ce44SJohn Forte 				if (ha->vp_index != 0) {
3026*fcf3ce44SJohn Forte 					(void) ql_login_fport(ha, tq,
3027*fcf3ce44SJohn Forte 					    SNS_24XX_HDL, LFF_NONE, NULL);
3028*fcf3ce44SJohn Forte 				}
3029*fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3030*fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3031*fcf3ce44SJohn Forte 			}
3032*fcf3ce44SJohn Forte 		}
3033*fcf3ce44SJohn Forte 
3034*fcf3ce44SJohn Forte 		/* If F_port exists, allocate queue for FL_Port. */
3035*fcf3ce44SJohn Forte 		index = ql_alpa_to_index[0xfe];
3036*fcf3ce44SJohn Forte 		d_id.b24 = 0;
3037*fcf3ce44SJohn Forte 		if (ha->dev[index].first != NULL) {
3038*fcf3ce44SJohn Forte 			tq = ql_dev_init(ha, d_id, (uint16_t)
3039*fcf3ce44SJohn Forte 			    (CFG_IST(ha, CFG_CTRL_2425) ?
3040*fcf3ce44SJohn Forte 			    FL_PORT_24XX_HDL : FL_PORT_LOOP_ID));
3041*fcf3ce44SJohn Forte 			if (tq != NULL) {
3042*fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3043*fcf3ce44SJohn Forte 				(void) ql_get_port_database(ha, tq, PDF_NONE);
3044*fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3045*fcf3ce44SJohn Forte 			}
3046*fcf3ce44SJohn Forte 		}
3047*fcf3ce44SJohn Forte 
3048*fcf3ce44SJohn Forte 		/* Allocate queue for broadcast. */
3049*fcf3ce44SJohn Forte 		d_id.b24 = 0xffffff;
3050*fcf3ce44SJohn Forte 		(void) ql_dev_init(ha, d_id, (uint16_t)
3051*fcf3ce44SJohn Forte 		    (CFG_IST(ha, CFG_CTRL_2425) ? BROADCAST_24XX_HDL :
3052*fcf3ce44SJohn Forte 		    IP_BROADCAST_LOOP_ID));
3053*fcf3ce44SJohn Forte 
3054*fcf3ce44SJohn Forte 		/* Check for any devices lost. */
3055*fcf3ce44SJohn Forte 		loop = FALSE;
3056*fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3057*fcf3ce44SJohn Forte 			for (link = ha->dev[index].first; link != NULL;
3058*fcf3ce44SJohn Forte 			    link = link->next) {
3059*fcf3ce44SJohn Forte 				tq = link->base_address;
3060*fcf3ce44SJohn Forte 
3061*fcf3ce44SJohn Forte 				if ((tq->loop_id & PORT_LOST_ID) &&
3062*fcf3ce44SJohn Forte 				    !(tq->flags & (TQF_INITIATOR_DEVICE |
3063*fcf3ce44SJohn Forte 				    TQF_FABRIC_DEVICE))) {
3064*fcf3ce44SJohn Forte 					loop = TRUE;
3065*fcf3ce44SJohn Forte 				}
3066*fcf3ce44SJohn Forte 			}
3067*fcf3ce44SJohn Forte 		}
3068*fcf3ce44SJohn Forte 
3069*fcf3ce44SJohn Forte 		/* Release adapter state lock. */
3070*fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3071*fcf3ce44SJohn Forte 
3072*fcf3ce44SJohn Forte 		/* Give devices time to recover. */
3073*fcf3ce44SJohn Forte 		if (loop == TRUE) {
3074*fcf3ce44SJohn Forte 			drv_usecwait(1000000);
3075*fcf3ce44SJohn Forte 		}
3076*fcf3ce44SJohn Forte 	} while (retries-- && loop == TRUE &&
3077*fcf3ce44SJohn Forte 	    !(ha->pha->task_daemon_flags & LOOP_RESYNC_NEEDED));
3078*fcf3ce44SJohn Forte 
3079*fcf3ce44SJohn Forte 	kmem_free(list, list_size);
3080*fcf3ce44SJohn Forte 
3081*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3082*fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
3083*fcf3ce44SJohn Forte 	} else {
3084*fcf3ce44SJohn Forte 		/*EMPTY*/
3085*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3086*fcf3ce44SJohn Forte 	}
3087*fcf3ce44SJohn Forte 
3088*fcf3ce44SJohn Forte 	return (rval);
3089*fcf3ce44SJohn Forte }
3090*fcf3ce44SJohn Forte 
3091*fcf3ce44SJohn Forte /*
3092*fcf3ce44SJohn Forte  * ql_dev_list
3093*fcf3ce44SJohn Forte  *	Gets device d_id and loop ID from firmware device list.
3094*fcf3ce44SJohn Forte  *
3095*fcf3ce44SJohn Forte  * Input:
3096*fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
3097*fcf3ce44SJohn Forte  *	list	device list pointer.
3098*fcf3ce44SJohn Forte  *	index:	list index of device data.
3099*fcf3ce44SJohn Forte  *	d_id:	pointer for d_id data.
3100*fcf3ce44SJohn Forte  *	id:	pointer for loop ID.
3101*fcf3ce44SJohn Forte  *
3102*fcf3ce44SJohn Forte  * Context:
3103*fcf3ce44SJohn Forte  *	Kernel context.
3104*fcf3ce44SJohn Forte  */
3105*fcf3ce44SJohn Forte void
3106*fcf3ce44SJohn Forte ql_dev_list(ql_adapter_state_t *ha, union ql_dev_id_list *list,
3107*fcf3ce44SJohn Forte     uint32_t index, port_id_t *d_id, uint16_t *id)
3108*fcf3ce44SJohn Forte {
3109*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_CTRL_2425)) {
3110*fcf3ce44SJohn Forte 		struct ql_24_dev_id	*list24 = (struct ql_24_dev_id *)list;
3111*fcf3ce44SJohn Forte 
3112*fcf3ce44SJohn Forte 		d_id->b.al_pa = list24[index].al_pa;
3113*fcf3ce44SJohn Forte 		d_id->b.area = list24[index].area;
3114*fcf3ce44SJohn Forte 		d_id->b.domain = list24[index].domain;
3115*fcf3ce44SJohn Forte 		*id = CHAR_TO_SHORT(list24[index].n_port_hdl_l,
3116*fcf3ce44SJohn Forte 		    list24[index].n_port_hdl_h);
3117*fcf3ce44SJohn Forte 
3118*fcf3ce44SJohn Forte 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
3119*fcf3ce44SJohn Forte 		struct ql_ex_dev_id	*list23 = (struct ql_ex_dev_id *)list;
3120*fcf3ce44SJohn Forte 
3121*fcf3ce44SJohn Forte 		d_id->b.al_pa = list23[index].al_pa;
3122*fcf3ce44SJohn Forte 		d_id->b.area = list23[index].area;
3123*fcf3ce44SJohn Forte 		d_id->b.domain = list23[index].domain;
3124*fcf3ce44SJohn Forte 		*id = CHAR_TO_SHORT(list23[index].loop_id_l,
3125*fcf3ce44SJohn Forte 		    list23[index].loop_id_h);
3126*fcf3ce44SJohn Forte 
3127*fcf3ce44SJohn Forte 	} else {
3128*fcf3ce44SJohn Forte 		struct ql_dev_id	*list22 = (struct ql_dev_id *)list;
3129*fcf3ce44SJohn Forte 
3130*fcf3ce44SJohn Forte 		d_id->b.al_pa = list22[index].al_pa;
3131*fcf3ce44SJohn Forte 		d_id->b.area = list22[index].area;
3132*fcf3ce44SJohn Forte 		d_id->b.domain = list22[index].domain;
3133*fcf3ce44SJohn Forte 		*id = (uint16_t)list22[index].loop_id;
3134*fcf3ce44SJohn Forte 	}
3135*fcf3ce44SJohn Forte }
3136*fcf3ce44SJohn Forte 
3137*fcf3ce44SJohn Forte /*
3138*fcf3ce44SJohn Forte  * ql_configure_fabric
3139*fcf3ce44SJohn Forte  *	Setup fabric context.
3140*fcf3ce44SJohn Forte  *
3141*fcf3ce44SJohn Forte  * Input:
3142*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3143*fcf3ce44SJohn Forte  *
3144*fcf3ce44SJohn Forte  * Returns:
3145*fcf3ce44SJohn Forte  *	ql local function return status code.
3146*fcf3ce44SJohn Forte  *
3147*fcf3ce44SJohn Forte  * Context:
3148*fcf3ce44SJohn Forte  *	Kernel context.
3149*fcf3ce44SJohn Forte  */
3150*fcf3ce44SJohn Forte static int
3151*fcf3ce44SJohn Forte ql_configure_fabric(ql_adapter_state_t *ha)
3152*fcf3ce44SJohn Forte {
3153*fcf3ce44SJohn Forte 	port_id_t	d_id;
3154*fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3155*fcf3ce44SJohn Forte 	int		rval = QL_FUNCTION_FAILED;
3156*fcf3ce44SJohn Forte 
3157*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3158*fcf3ce44SJohn Forte 
3159*fcf3ce44SJohn Forte 	ha->topology = (uint8_t)(ha->topology & ~QL_SNS_CONNECTION);
3160*fcf3ce44SJohn Forte 
3161*fcf3ce44SJohn Forte 	/* Test switch fabric controller present. */
3162*fcf3ce44SJohn Forte 	d_id.b24 = FS_FABRIC_F_PORT;
3163*fcf3ce44SJohn Forte 	tq = ql_d_id_to_queue(ha, d_id);
3164*fcf3ce44SJohn Forte 	if (tq != NULL) {
3165*fcf3ce44SJohn Forte 		/* Get port/node names of F_Port. */
3166*fcf3ce44SJohn Forte 		(void) ql_get_port_database(ha, tq, PDF_NONE);
3167*fcf3ce44SJohn Forte 
3168*fcf3ce44SJohn Forte 		d_id.b24 = FS_NAME_SERVER;
3169*fcf3ce44SJohn Forte 		tq = ql_d_id_to_queue(ha, d_id);
3170*fcf3ce44SJohn Forte 		if (tq != NULL) {
3171*fcf3ce44SJohn Forte 			(void) ql_get_port_database(ha, tq, PDF_NONE);
3172*fcf3ce44SJohn Forte 			ha->topology = (uint8_t)
3173*fcf3ce44SJohn Forte 			    (ha->topology | QL_SNS_CONNECTION);
3174*fcf3ce44SJohn Forte 			rval = QL_SUCCESS;
3175*fcf3ce44SJohn Forte 		}
3176*fcf3ce44SJohn Forte 	}
3177*fcf3ce44SJohn Forte 
3178*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3179*fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
3180*fcf3ce44SJohn Forte 	} else {
3181*fcf3ce44SJohn Forte 		/*EMPTY*/
3182*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3183*fcf3ce44SJohn Forte 	}
3184*fcf3ce44SJohn Forte 	return (rval);
3185*fcf3ce44SJohn Forte }
3186*fcf3ce44SJohn Forte 
3187*fcf3ce44SJohn Forte /*
3188*fcf3ce44SJohn Forte  * ql_reset_chip
3189*fcf3ce44SJohn Forte  *	Reset ISP chip.
3190*fcf3ce44SJohn Forte  *
3191*fcf3ce44SJohn Forte  * Input:
3192*fcf3ce44SJohn Forte  *	ha = adapter block pointer.
3193*fcf3ce44SJohn Forte  *	All activity on chip must be already stopped.
3194*fcf3ce44SJohn Forte  *	ADAPTER_STATE_LOCK must be released.
3195*fcf3ce44SJohn Forte  *
3196*fcf3ce44SJohn Forte  * Context:
3197*fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3198*fcf3ce44SJohn Forte  */
3199*fcf3ce44SJohn Forte void
3200*fcf3ce44SJohn Forte ql_reset_chip(ql_adapter_state_t *vha)
3201*fcf3ce44SJohn Forte {
3202*fcf3ce44SJohn Forte 	uint32_t		cnt;
3203*fcf3ce44SJohn Forte 	uint16_t		cmd;
3204*fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
3205*fcf3ce44SJohn Forte 
3206*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3207*fcf3ce44SJohn Forte 
3208*fcf3ce44SJohn Forte 	/*
3209*fcf3ce44SJohn Forte 	 * accessing pci space while not powered can cause panic's
3210*fcf3ce44SJohn Forte 	 * on some platforms (i.e. Sunblade 1000's)
3211*fcf3ce44SJohn Forte 	 */
3212*fcf3ce44SJohn Forte 	if (ha->power_level == PM_LEVEL_D3) {
3213*fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "(%d): Low Power exit\n", ha->instance);
3214*fcf3ce44SJohn Forte 		return;
3215*fcf3ce44SJohn Forte 	}
3216*fcf3ce44SJohn Forte 
3217*fcf3ce44SJohn Forte 	/* Reset all outbound mailbox registers */
3218*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < ha->reg_off->mbox_cnt; cnt++) {
3219*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, mailbox[cnt], (uint16_t)0);
3220*fcf3ce44SJohn Forte 	}
3221*fcf3ce44SJohn Forte 
3222*fcf3ce44SJohn Forte 	/* Disable ISP interrupts. */
3223*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ictrl, 0);
3224*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
3225*fcf3ce44SJohn Forte 	ha->flags &= ~INTERRUPTS_ENABLED;
3226*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
3227*fcf3ce44SJohn Forte 
3228*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_CTRL_2425)) {
3229*fcf3ce44SJohn Forte 		RD32_IO_REG(ha, ictrl);
3230*fcf3ce44SJohn Forte 		ql_reset_24xx_chip(ha);
3231*fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): 24xx exit\n", ha->instance);
3232*fcf3ce44SJohn Forte 		return;
3233*fcf3ce44SJohn Forte 	}
3234*fcf3ce44SJohn Forte 
3235*fcf3ce44SJohn Forte 	/*
3236*fcf3ce44SJohn Forte 	 * We are going to reset the chip in case of 2300. That might cause
3237*fcf3ce44SJohn Forte 	 * a PBM ERR if a DMA transaction is in progress. One way of
3238*fcf3ce44SJohn Forte 	 * avoiding it is to disable Bus Master operation before we start
3239*fcf3ce44SJohn Forte 	 * the reset activity.
3240*fcf3ce44SJohn Forte 	 */
3241*fcf3ce44SJohn Forte 	cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
3242*fcf3ce44SJohn Forte 	cmd = (uint16_t)(cmd & ~PCI_COMM_ME);
3243*fcf3ce44SJohn Forte 	ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3244*fcf3ce44SJohn Forte 
3245*fcf3ce44SJohn Forte 	/* Pause RISC. */
3246*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
3247*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 30000; cnt++) {
3248*fcf3ce44SJohn Forte 		if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
3249*fcf3ce44SJohn Forte 			break;
3250*fcf3ce44SJohn Forte 		}
3251*fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3252*fcf3ce44SJohn Forte 	}
3253*fcf3ce44SJohn Forte 
3254*fcf3ce44SJohn Forte 	/*
3255*fcf3ce44SJohn Forte 	 * A call to ql_isr() can still happen through
3256*fcf3ce44SJohn Forte 	 * ql_mailbox_command(). So Mark that we are/(will-be)
3257*fcf3ce44SJohn Forte 	 * running from rom code now.
3258*fcf3ce44SJohn Forte 	 */
3259*fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
3260*fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FIRMWARE_UP | FIRMWARE_LOADED);
3261*fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
3262*fcf3ce44SJohn Forte 
3263*fcf3ce44SJohn Forte 	/* Select FPM registers. */
3264*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0x20);
3265*fcf3ce44SJohn Forte 
3266*fcf3ce44SJohn Forte 	/* FPM Soft Reset. */
3267*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, fpm_diag_config, 0x100);
3268*fcf3ce44SJohn Forte 
3269*fcf3ce44SJohn Forte 	/* Toggle FPM reset for 2300 */
3270*fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
3271*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fpm_diag_config, 0);
3272*fcf3ce44SJohn Forte 	}
3273*fcf3ce44SJohn Forte 
3274*fcf3ce44SJohn Forte 	/* Select frame buffer registers. */
3275*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0x10);
3276*fcf3ce44SJohn Forte 
3277*fcf3ce44SJohn Forte 	/* Reset frame buffer FIFOs. */
3278*fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
3279*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fb_cmd, 0x00fc);
3280*fcf3ce44SJohn Forte 		/* read back fb_cmd until zero or 3 seconds max */
3281*fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 300000; cnt++) {
3282*fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, fb_cmd) & 0xff) == 0) {
3283*fcf3ce44SJohn Forte 				break;
3284*fcf3ce44SJohn Forte 			}
3285*fcf3ce44SJohn Forte 			drv_usecwait(10);
3286*fcf3ce44SJohn Forte 		}
3287*fcf3ce44SJohn Forte 	} else  {
3288*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, fb_cmd, 0xa000);
3289*fcf3ce44SJohn Forte 	}
3290*fcf3ce44SJohn Forte 
3291*fcf3ce44SJohn Forte 	/* Select RISC module registers. */
3292*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ctrl_status, 0);
3293*fcf3ce44SJohn Forte 
3294*fcf3ce44SJohn Forte 	/* Reset RISC module. */
3295*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
3296*fcf3ce44SJohn Forte 
3297*fcf3ce44SJohn Forte 	/* Reset ISP semaphore. */
3298*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, semaphore, 0);
3299*fcf3ce44SJohn Forte 
3300*fcf3ce44SJohn Forte 	/* Release RISC module. */
3301*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3302*fcf3ce44SJohn Forte 
3303*fcf3ce44SJohn Forte 	/* Insure mailbox registers are free. */
3304*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
3305*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_CLR_HOST_INT);
3306*fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
3307*fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
3308*fcf3ce44SJohn Forte 	ha->mcp = NULL;
3309*fcf3ce44SJohn Forte 
3310*fcf3ce44SJohn Forte 	/* Bus Master is disabled so chip reset is safe. */
3311*fcf3ce44SJohn Forte 	if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
3312*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, ISP_RESET);
3313*fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3314*fcf3ce44SJohn Forte 
3315*fcf3ce44SJohn Forte 		/* Wait for reset to finish. */
3316*fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 30000; cnt++) {
3317*fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
3318*fcf3ce44SJohn Forte 				break;
3319*fcf3ce44SJohn Forte 			}
3320*fcf3ce44SJohn Forte 			drv_usecwait(MILLISEC);
3321*fcf3ce44SJohn Forte 		}
3322*fcf3ce44SJohn Forte 	}
3323*fcf3ce44SJohn Forte 
3324*fcf3ce44SJohn Forte 	/* Wait for RISC to recover from reset. */
3325*fcf3ce44SJohn Forte 	for (cnt = 0; cnt < 30000; cnt++) {
3326*fcf3ce44SJohn Forte 		if (RD16_IO_REG(ha, mailbox[0]) != MBS_BUSY) {
3327*fcf3ce44SJohn Forte 			break;
3328*fcf3ce44SJohn Forte 		}
3329*fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
3330*fcf3ce44SJohn Forte 	}
3331*fcf3ce44SJohn Forte 
3332*fcf3ce44SJohn Forte 	/* restore bus master */
3333*fcf3ce44SJohn Forte 	cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
3334*fcf3ce44SJohn Forte 	cmd = (uint16_t)(cmd | PCI_COMM_ME);
3335*fcf3ce44SJohn Forte 	ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3336*fcf3ce44SJohn Forte 
3337*fcf3ce44SJohn Forte 	/* Disable RISC pause on FPM parity error. */
3338*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, hccr, HC_DISABLE_PARITY_PAUSE);
3339*fcf3ce44SJohn Forte 
3340*fcf3ce44SJohn Forte 	/* Initialize probe registers */
3341*fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
3342*fcf3ce44SJohn Forte 		/* Pause RISC. */
3343*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
3344*fcf3ce44SJohn Forte 		for (cnt = 0; cnt < 30000; cnt++) {
3345*fcf3ce44SJohn Forte 			if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
3346*fcf3ce44SJohn Forte 				break;
3347*fcf3ce44SJohn Forte 			} else {
3348*fcf3ce44SJohn Forte 				drv_usecwait(MILLISEC);
3349*fcf3ce44SJohn Forte 			}
3350*fcf3ce44SJohn Forte 		}
3351*fcf3ce44SJohn Forte 
3352*fcf3ce44SJohn Forte 		/* Select FPM registers. */
3353*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, 0x30);
3354*fcf3ce44SJohn Forte 
3355*fcf3ce44SJohn Forte 		/* Set probe register */
3356*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, mailbox[23], 0x204c);
3357*fcf3ce44SJohn Forte 
3358*fcf3ce44SJohn Forte 		/* Select RISC module registers. */
3359*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, ctrl_status, 0);
3360*fcf3ce44SJohn Forte 
3361*fcf3ce44SJohn Forte 		/* Release RISC module. */
3362*fcf3ce44SJohn Forte 		WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3363*fcf3ce44SJohn Forte 	}
3364*fcf3ce44SJohn Forte 
3365*fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3366*fcf3ce44SJohn Forte }
3367*fcf3ce44SJohn Forte 
3368*fcf3ce44SJohn Forte /*
3369*fcf3ce44SJohn Forte  * ql_reset_24xx_chip
3370*fcf3ce44SJohn Forte  *	Reset ISP24xx chip.
3371*fcf3ce44SJohn Forte  *
3372*fcf3ce44SJohn Forte  * Input:
3373*fcf3ce44SJohn Forte  *	ha = adapter block pointer.
3374*fcf3ce44SJohn Forte  *	All activity on chip must be already stopped.
3375*fcf3ce44SJohn Forte  *
3376*fcf3ce44SJohn Forte  * Context:
3377*fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3378*fcf3ce44SJohn Forte  */
3379*fcf3ce44SJohn Forte void
3380*fcf3ce44SJohn Forte ql_reset_24xx_chip(ql_adapter_state_t *ha)
3381*fcf3ce44SJohn Forte {
3382*fcf3ce44SJohn Forte 	uint32_t	timer, stat;
3383*fcf3ce44SJohn Forte 
3384*fcf3ce44SJohn Forte 	/* Shutdown DMA. */
3385*fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN | MWB_4096_BYTES);
3386*fcf3ce44SJohn Forte 
3387*fcf3ce44SJohn Forte 	/* Wait for DMA to stop. */
3388*fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3389*fcf3ce44SJohn Forte 		if ((RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE) == 0) {
3390*fcf3ce44SJohn Forte 			break;
3391*fcf3ce44SJohn Forte 		}
3392*fcf3ce44SJohn Forte 		drv_usecwait(100);
3393*fcf3ce44SJohn Forte 	}
3394*fcf3ce44SJohn Forte 
3395*fcf3ce44SJohn Forte 	/* Stop the firmware. */
3396*fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3397*fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, mailbox[0], MBC_STOP_FIRMWARE);
3398*fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
3399*fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3400*fcf3ce44SJohn Forte 		stat = RD32_IO_REG(ha, intr_info_lo);
3401*fcf3ce44SJohn Forte 		if (stat & BIT_15) {
3402*fcf3ce44SJohn Forte 			if ((stat & 0xff) < 0x12) {
3403*fcf3ce44SJohn Forte 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3404*fcf3ce44SJohn Forte 				break;
3405*fcf3ce44SJohn Forte 			}
3406*fcf3ce44SJohn Forte 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
3407*fcf3ce44SJohn Forte 		}
3408*fcf3ce44SJohn Forte 		drv_usecwait(100);
3409*fcf3ce44SJohn Forte 	}
3410*fcf3ce44SJohn Forte 
3411*fcf3ce44SJohn Forte 	/* Reset the chip. */
3412*fcf3ce44SJohn Forte 	WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN |
3413*fcf3ce44SJohn Forte 	    MWB_4096_BYTES);
3414*fcf3ce44SJohn Forte 	drv_usecwait(100);
3415*fcf3ce44SJohn Forte 
3416*fcf3ce44SJohn Forte 	/* Wait for idle status from ROM firmware. */
3417*fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3418*fcf3ce44SJohn Forte 		if (RD16_IO_REG(ha, mailbox[0]) == 0) {
3419*fcf3ce44SJohn Forte 			break;
3420*fcf3ce44SJohn Forte 		}
3421*fcf3ce44SJohn Forte 		drv_usecwait(100);
3422*fcf3ce44SJohn Forte 	}
3423*fcf3ce44SJohn Forte 
3424*fcf3ce44SJohn Forte 	/* Wait for reset to finish. */
3425*fcf3ce44SJohn Forte 	for (timer = 0; timer < 30000; timer++) {
3426*fcf3ce44SJohn Forte 		if ((RD32_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
3427*fcf3ce44SJohn Forte 			break;
3428*fcf3ce44SJohn Forte 		}
3429*fcf3ce44SJohn Forte 		drv_usecwait(100);
3430*fcf3ce44SJohn Forte 	}
3431*fcf3ce44SJohn Forte 
3432*fcf3ce44SJohn Forte 	/* Insure mailbox registers are free. */
3433*fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
3434*fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
3435*fcf3ce44SJohn Forte 	ha->mcp = NULL;
3436*fcf3ce44SJohn Forte 
3437*fcf3ce44SJohn Forte 	if (ha->fwfcetracebuf.bp != NULL) {
3438*fcf3ce44SJohn Forte 		ql_free_phys(ha, &ha->fwfcetracebuf);
3439*fcf3ce44SJohn Forte 	}
3440*fcf3ce44SJohn Forte 
3441*fcf3ce44SJohn Forte 	if (ha->fwexttracebuf.bp != NULL) {
3442*fcf3ce44SJohn Forte 		ql_free_phys(ha, &ha->fwexttracebuf);
3443*fcf3ce44SJohn Forte 	}
3444*fcf3ce44SJohn Forte 
3445*fcf3ce44SJohn Forte 	/*
3446*fcf3ce44SJohn Forte 	 * Set flash write-protection.
3447*fcf3ce44SJohn Forte 	 */
3448*fcf3ce44SJohn Forte 	if ((ha->flags & ONLINE) == 0) {
3449*fcf3ce44SJohn Forte 		ql_24xx_protect_flash(ha);
3450*fcf3ce44SJohn Forte 	}
3451*fcf3ce44SJohn Forte }
3452*fcf3ce44SJohn Forte 
3453*fcf3ce44SJohn Forte /*
3454*fcf3ce44SJohn Forte  * ql_abort_isp
3455*fcf3ce44SJohn Forte  *	Resets ISP and aborts all outstanding commands.
3456*fcf3ce44SJohn Forte  *
3457*fcf3ce44SJohn Forte  * Input:
3458*fcf3ce44SJohn Forte  *	ha = adapter state pointer.
3459*fcf3ce44SJohn Forte  *	DEVICE_QUEUE_LOCK must be released.
3460*fcf3ce44SJohn Forte  *
3461*fcf3ce44SJohn Forte  * Returns:
3462*fcf3ce44SJohn Forte  *	ql local function return status code.
3463*fcf3ce44SJohn Forte  *
3464*fcf3ce44SJohn Forte  * Context:
3465*fcf3ce44SJohn Forte  *	Kernel context.
3466*fcf3ce44SJohn Forte  */
3467*fcf3ce44SJohn Forte int
3468*fcf3ce44SJohn Forte ql_abort_isp(ql_adapter_state_t *vha)
3469*fcf3ce44SJohn Forte {
3470*fcf3ce44SJohn Forte 	ql_link_t		*link, *link2;
3471*fcf3ce44SJohn Forte 	ddi_devstate_t		state;
3472*fcf3ce44SJohn Forte 	uint16_t		index;
3473*fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
3474*fcf3ce44SJohn Forte 	ql_lun_t		*lq;
3475*fcf3ce44SJohn Forte 	ql_srb_t		*sp;
3476*fcf3ce44SJohn Forte 	int			rval = QL_SUCCESS;
3477*fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
3478*fcf3ce44SJohn Forte 
3479*fcf3ce44SJohn Forte 	QL_PRINT_2(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3480*fcf3ce44SJohn Forte 
3481*fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
3482*fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
3483*fcf3ce44SJohn Forte 	if (ha->task_daemon_flags & ABORT_ISP_ACTIVE ||
3484*fcf3ce44SJohn Forte 	    (ha->flags & ONLINE) == 0 || ha->flags & ADAPTER_SUSPENDED) {
3485*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
3486*fcf3ce44SJohn Forte 		return (rval);
3487*fcf3ce44SJohn Forte 	}
3488*fcf3ce44SJohn Forte 
3489*fcf3ce44SJohn Forte 	ha->task_daemon_flags |= ABORT_ISP_ACTIVE;
3490*fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(RESET_MARKER_NEEDED | FIRMWARE_UP |
3491*fcf3ce44SJohn Forte 	    FIRMWARE_LOADED);
3492*fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
3493*fcf3ce44SJohn Forte 		vha->task_daemon_flags |= LOOP_DOWN;
3494*fcf3ce44SJohn Forte 		vha->task_daemon_flags &= ~(COMMAND_WAIT_NEEDED |
3495*fcf3ce44SJohn Forte 		    LOOP_RESYNC_NEEDED);
3496*fcf3ce44SJohn Forte 	}
3497*fcf3ce44SJohn Forte 
3498*fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
3499*fcf3ce44SJohn Forte 
3500*fcf3ce44SJohn Forte 	if (ha->mailbox_flags & MBX_BUSY_FLG) {
3501*fcf3ce44SJohn Forte 		/* Acquire mailbox register lock. */
3502*fcf3ce44SJohn Forte 		MBX_REGISTER_LOCK(ha);
3503*fcf3ce44SJohn Forte 
3504*fcf3ce44SJohn Forte 		/* Wake up mailbox box routine. */
3505*fcf3ce44SJohn Forte 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_ABORT);
3506*fcf3ce44SJohn Forte 		cv_broadcast(&ha->cv_mbx_intr);
3507*fcf3ce44SJohn Forte 
3508*fcf3ce44SJohn Forte 		/* Release mailbox register lock. */
3509*fcf3ce44SJohn Forte 		MBX_REGISTER_UNLOCK(ha);
3510*fcf3ce44SJohn Forte 
3511*fcf3ce44SJohn Forte 		/* Wait for mailbox. */
3512*fcf3ce44SJohn Forte 		for (index = 100; index &&
3513*fcf3ce44SJohn Forte 		    ha->mailbox_flags & MBX_ABORT; index--) {
3514*fcf3ce44SJohn Forte 			drv_usecwait(50000);
3515*fcf3ce44SJohn Forte 		}
3516*fcf3ce44SJohn Forte 	}
3517*fcf3ce44SJohn Forte 
3518*fcf3ce44SJohn Forte 	/* Wait for commands to end gracefully if not in panic. */
3519*fcf3ce44SJohn Forte 	if (ha->flags & PARITY_ERROR) {
3520*fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3521*fcf3ce44SJohn Forte 		ha->flags &= ~PARITY_ERROR;
3522*fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3523*fcf3ce44SJohn Forte 	} else if (ddi_in_panic() == 0) {
3524*fcf3ce44SJohn Forte 		ql_cmd_wait(ha);
3525*fcf3ce44SJohn Forte 	}
3526*fcf3ce44SJohn Forte 
3527*fcf3ce44SJohn Forte 	/* Shutdown IP. */
3528*fcf3ce44SJohn Forte 	if (ha->flags & IP_INITIALIZED) {
3529*fcf3ce44SJohn Forte 		(void) ql_shutdown_ip(ha);
3530*fcf3ce44SJohn Forte 	}
3531*fcf3ce44SJohn Forte 
3532*fcf3ce44SJohn Forte 	/* Reset the chip. */
3533*fcf3ce44SJohn Forte 	ql_reset_chip(ha);
3534*fcf3ce44SJohn Forte 
3535*fcf3ce44SJohn Forte 	/* Place all commands in outstanding cmd list on device queue. */
3536*fcf3ce44SJohn Forte 	for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
3537*fcf3ce44SJohn Forte 		REQUEST_RING_LOCK(ha);
3538*fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) != NULL) {
3539*fcf3ce44SJohn Forte 			sp = link->base_address;
3540*fcf3ce44SJohn Forte 			ql_remove_link(&ha->pending_cmds, &sp->cmd);
3541*fcf3ce44SJohn Forte 
3542*fcf3ce44SJohn Forte 			REQUEST_RING_UNLOCK(ha);
3543*fcf3ce44SJohn Forte 			index = 0;
3544*fcf3ce44SJohn Forte 		} else {
3545*fcf3ce44SJohn Forte 			REQUEST_RING_UNLOCK(ha);
3546*fcf3ce44SJohn Forte 			if ((sp = ha->outstanding_cmds[index]) == NULL) {
3547*fcf3ce44SJohn Forte 				continue;
3548*fcf3ce44SJohn Forte 			}
3549*fcf3ce44SJohn Forte 		}
3550*fcf3ce44SJohn Forte 
3551*fcf3ce44SJohn Forte 		/* If command timeout. */
3552*fcf3ce44SJohn Forte 		if (sp->flags & SRB_COMMAND_TIMEOUT) {
3553*fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_TIMEOUT;
3554*fcf3ce44SJohn Forte 			sp->flags &= ~SRB_RETRY;
3555*fcf3ce44SJohn Forte 			sp->flags |= SRB_ISP_COMPLETED;
3556*fcf3ce44SJohn Forte 
3557*fcf3ce44SJohn Forte 			/* Call done routine to handle completion. */
3558*fcf3ce44SJohn Forte 			ql_done(&sp->cmd);
3559*fcf3ce44SJohn Forte 			continue;
3560*fcf3ce44SJohn Forte 		}
3561*fcf3ce44SJohn Forte 
3562*fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
3563*fcf3ce44SJohn Forte 		sp->handle = 0;
3564*fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
3565*fcf3ce44SJohn Forte 
3566*fcf3ce44SJohn Forte 		/* Acquire target queue lock. */
3567*fcf3ce44SJohn Forte 		lq = sp->lun_queue;
3568*fcf3ce44SJohn Forte 		tq = lq->target_queue;
3569*fcf3ce44SJohn Forte 		DEVICE_QUEUE_LOCK(tq);
3570*fcf3ce44SJohn Forte 
3571*fcf3ce44SJohn Forte 		/* Reset watchdog time. */
3572*fcf3ce44SJohn Forte 		sp->wdg_q_time = sp->init_wdg_q_time;
3573*fcf3ce44SJohn Forte 
3574*fcf3ce44SJohn Forte 		/* Place request back on top of device queue. */
3575*fcf3ce44SJohn Forte 		sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED |
3576*fcf3ce44SJohn Forte 		    SRB_RETRY);
3577*fcf3ce44SJohn Forte 
3578*fcf3ce44SJohn Forte 		ql_add_link_t(&lq->cmd, &sp->cmd);
3579*fcf3ce44SJohn Forte 		sp->flags |= SRB_IN_DEVICE_QUEUE;
3580*fcf3ce44SJohn Forte 
3581*fcf3ce44SJohn Forte 		/* Release target queue lock. */
3582*fcf3ce44SJohn Forte 		DEVICE_QUEUE_UNLOCK(tq);
3583*fcf3ce44SJohn Forte 	}
3584*fcf3ce44SJohn Forte 
3585*fcf3ce44SJohn Forte 	/*
3586*fcf3ce44SJohn Forte 	 * Clear per LUN active count, because there should not be
3587*fcf3ce44SJohn Forte 	 * any IO outstanding at this time.
3588*fcf3ce44SJohn Forte 	 */
3589*fcf3ce44SJohn Forte 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
3590*fcf3ce44SJohn Forte 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
3591*fcf3ce44SJohn Forte 			link = vha->dev[index].first;
3592*fcf3ce44SJohn Forte 			while (link != NULL) {
3593*fcf3ce44SJohn Forte 				tq = link->base_address;
3594*fcf3ce44SJohn Forte 				link = link->next;
3595*fcf3ce44SJohn Forte 				DEVICE_QUEUE_LOCK(tq);
3596*fcf3ce44SJohn Forte 				tq->outcnt = 0;
3597*fcf3ce44SJohn Forte 				tq->flags &= ~TQF_QUEUE_SUSPENDED;
3598*fcf3ce44SJohn Forte 				for (link2 = tq->lun_queues.first;
3599*fcf3ce44SJohn Forte 				    link2 != NULL; link2 = link2->next) {
3600*fcf3ce44SJohn Forte 					lq = link2->base_address;
3601*fcf3ce44SJohn Forte 					lq->lun_outcnt = 0;
3602*fcf3ce44SJohn Forte 					lq->flags &= ~LQF_UNTAGGED_PENDING;
3603*fcf3ce44SJohn Forte 				}
3604*fcf3ce44SJohn Forte 				DEVICE_QUEUE_UNLOCK(tq);
3605*fcf3ce44SJohn Forte 			}
3606*fcf3ce44SJohn Forte 		}
3607*fcf3ce44SJohn Forte 	}
3608*fcf3ce44SJohn Forte 
3609*fcf3ce44SJohn Forte 	if (ha->flags & TARGET_MODE_INITIALIZED) {
3610*fcf3ce44SJohn Forte 		/* Enable Target Mode */
3611*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.lun_enables[0] = (uint8_t)
3612*fcf3ce44SJohn Forte 		    (ha->init_ctrl_blk.cb.lun_enables[0] | 0x01);
3613*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.immediate_notify_resouce_count =
3614*fcf3ce44SJohn Forte 		    ha->ub_notify_count;
3615*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.command_resouce_count =
3616*fcf3ce44SJohn Forte 		    ha->ub_command_count;
3617*fcf3ce44SJohn Forte 	} else {
3618*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.lun_enables[0] = 0;
3619*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.lun_enables[1] = 0;
3620*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.immediate_notify_resouce_count = 0;
3621*fcf3ce44SJohn Forte 		ha->init_ctrl_blk.cb.command_resouce_count = 0;
3622*fcf3ce44SJohn Forte 	}
3623*fcf3ce44SJohn Forte 
3624*fcf3ce44SJohn Forte 	rval = ql_chip_diag(ha);
3625*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
3626*fcf3ce44SJohn Forte 		(void) ql_load_isp_firmware(ha);
3627*fcf3ce44SJohn Forte 	}
3628*fcf3ce44SJohn Forte 
3629*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
3630*fcf3ce44SJohn Forte 	    QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS &&
3631*fcf3ce44SJohn Forte 	    (rval = ql_fw_ready(ha, 10)) == QL_SUCCESS) {
3632*fcf3ce44SJohn Forte 
3633*fcf3ce44SJohn Forte 		/* If reset abort needed that may have been set. */
3634*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
3635*fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED |
3636*fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE);
3637*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
3638*fcf3ce44SJohn Forte 
3639*fcf3ce44SJohn Forte 		/* Enable ISP interrupts. */
3640*fcf3ce44SJohn Forte 		CFG_IST(ha, CFG_CTRL_2425) ?
3641*fcf3ce44SJohn Forte 		    WRT32_IO_REG(ha, ictrl, ISP_EN_RISC) :
3642*fcf3ce44SJohn Forte 		    WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
3643*fcf3ce44SJohn Forte 
3644*fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3645*fcf3ce44SJohn Forte 		ha->flags |= INTERRUPTS_ENABLED;
3646*fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3647*fcf3ce44SJohn Forte 
3648*fcf3ce44SJohn Forte 		/* Set loop online, if it really is. */
3649*fcf3ce44SJohn Forte 		ql_loop_online(ha);
3650*fcf3ce44SJohn Forte 
3651*fcf3ce44SJohn Forte 		state = ddi_get_devstate(ha->dip);
3652*fcf3ce44SJohn Forte 		if (state != DDI_DEVSTATE_UP) {
3653*fcf3ce44SJohn Forte 			/*EMPTY*/
3654*fcf3ce44SJohn Forte 			ddi_dev_report_fault(ha->dip, DDI_SERVICE_RESTORED,
3655*fcf3ce44SJohn Forte 			    DDI_DEVICE_FAULT, "Device reset succeeded");
3656*fcf3ce44SJohn Forte 		}
3657*fcf3ce44SJohn Forte 	} else {
3658*fcf3ce44SJohn Forte 		/* Enable ISP interrupts. */
3659*fcf3ce44SJohn Forte 		CFG_IST(ha, CFG_CTRL_2425) ?
3660*fcf3ce44SJohn Forte 		    WRT32_IO_REG(ha, ictrl, ISP_EN_RISC) :
3661*fcf3ce44SJohn Forte 		    WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
3662*fcf3ce44SJohn Forte 
3663*fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
3664*fcf3ce44SJohn Forte 		ha->flags |= INTERRUPTS_ENABLED;
3665*fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
3666*fcf3ce44SJohn Forte 
3667*fcf3ce44SJohn Forte 		TASK_DAEMON_LOCK(ha);
3668*fcf3ce44SJohn Forte 		ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE);
3669*fcf3ce44SJohn Forte 		ha->task_daemon_flags |= LOOP_DOWN;
3670*fcf3ce44SJohn Forte 		TASK_DAEMON_UNLOCK(ha);
3671*fcf3ce44SJohn Forte 
3672*fcf3ce44SJohn Forte 		ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
3673*fcf3ce44SJohn Forte 	}
3674*fcf3ce44SJohn Forte 
3675*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3676*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3677*fcf3ce44SJohn Forte 	} else {
3678*fcf3ce44SJohn Forte 		/*EMPTY*/
3679*fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "(%d): done\n", ha->instance);
3680*fcf3ce44SJohn Forte 	}
3681*fcf3ce44SJohn Forte 	return (rval);
3682*fcf3ce44SJohn Forte }
3683*fcf3ce44SJohn Forte 
3684*fcf3ce44SJohn Forte /*
3685*fcf3ce44SJohn Forte  * ql_vport_control
3686*fcf3ce44SJohn Forte  *	Issue Virtual Port Control command.
3687*fcf3ce44SJohn Forte  *
3688*fcf3ce44SJohn Forte  * Input:
3689*fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
3690*fcf3ce44SJohn Forte  *	cmd = control command.
3691*fcf3ce44SJohn Forte  *
3692*fcf3ce44SJohn Forte  * Returns:
3693*fcf3ce44SJohn Forte  *	ql local function return status code.
3694*fcf3ce44SJohn Forte  *
3695*fcf3ce44SJohn Forte  * Context:
3696*fcf3ce44SJohn Forte  *	Kernel context.
3697*fcf3ce44SJohn Forte  */
3698*fcf3ce44SJohn Forte int
3699*fcf3ce44SJohn Forte ql_vport_control(ql_adapter_state_t *ha, uint8_t cmd)
3700*fcf3ce44SJohn Forte {
3701*fcf3ce44SJohn Forte 	ql_mbx_iocb_t	*pkt;
3702*fcf3ce44SJohn Forte 	uint8_t		bit;
3703*fcf3ce44SJohn Forte 	int		rval;
3704*fcf3ce44SJohn Forte 	uint32_t	pkt_size;
3705*fcf3ce44SJohn Forte 
3706*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3707*fcf3ce44SJohn Forte 
3708*fcf3ce44SJohn Forte 	if (ha->vp_index != 0) {
3709*fcf3ce44SJohn Forte 		pkt_size = sizeof (ql_mbx_iocb_t);
3710*fcf3ce44SJohn Forte 		pkt = kmem_zalloc(pkt_size, KM_SLEEP);
3711*fcf3ce44SJohn Forte 		if (pkt == NULL) {
3712*fcf3ce44SJohn Forte 			EL(ha, "failed, kmem_zalloc\n");
3713*fcf3ce44SJohn Forte 			return (QL_MEMORY_ALLOC_FAILED);
3714*fcf3ce44SJohn Forte 		}
3715*fcf3ce44SJohn Forte 
3716*fcf3ce44SJohn Forte 		pkt->vpc.entry_type = VP_CONTROL_TYPE;
3717*fcf3ce44SJohn Forte 		pkt->vpc.entry_count = 1;
3718*fcf3ce44SJohn Forte 		pkt->vpc.command = cmd;
3719*fcf3ce44SJohn Forte 		pkt->vpc.vp_count = 1;
3720*fcf3ce44SJohn Forte 		bit = (uint8_t)(ha->vp_index - 1);
3721*fcf3ce44SJohn Forte 		pkt->vpc.vp_index[bit / 8] = (uint8_t)
3722*fcf3ce44SJohn Forte 		    (pkt->vpc.vp_index[bit / 8] | BIT_0 << bit % 8);
3723*fcf3ce44SJohn Forte 
3724*fcf3ce44SJohn Forte 		rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
3725*fcf3ce44SJohn Forte 		if (rval == QL_SUCCESS && pkt->vpc.status != 0) {
3726*fcf3ce44SJohn Forte 			rval = QL_COMMAND_ERROR;
3727*fcf3ce44SJohn Forte 		}
3728*fcf3ce44SJohn Forte 
3729*fcf3ce44SJohn Forte 		kmem_free(pkt, pkt_size);
3730*fcf3ce44SJohn Forte 	} else {
3731*fcf3ce44SJohn Forte 		rval = QL_SUCCESS;
3732*fcf3ce44SJohn Forte 	}
3733*fcf3ce44SJohn Forte 
3734*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3735*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3736*fcf3ce44SJohn Forte 	} else {
3737*fcf3ce44SJohn Forte 		/*EMPTY*/
3738*fcf3ce44SJohn Forte 		QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
3739*fcf3ce44SJohn Forte 		    ha->vp_index);
3740*fcf3ce44SJohn Forte 	}
3741*fcf3ce44SJohn Forte 	return (rval);
3742*fcf3ce44SJohn Forte }
3743*fcf3ce44SJohn Forte 
3744*fcf3ce44SJohn Forte /*
3745*fcf3ce44SJohn Forte  * ql_vport_modify
3746*fcf3ce44SJohn Forte  *	Issue of Modify Virtual Port command.
3747*fcf3ce44SJohn Forte  *
3748*fcf3ce44SJohn Forte  * Input:
3749*fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
3750*fcf3ce44SJohn Forte  *	cmd = command.
3751*fcf3ce44SJohn Forte  *	opt = option.
3752*fcf3ce44SJohn Forte  *
3753*fcf3ce44SJohn Forte  * Context:
3754*fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3755*fcf3ce44SJohn Forte  */
3756*fcf3ce44SJohn Forte int
3757*fcf3ce44SJohn Forte ql_vport_modify(ql_adapter_state_t *ha, uint8_t cmd, uint8_t opt)
3758*fcf3ce44SJohn Forte {
3759*fcf3ce44SJohn Forte 	ql_mbx_iocb_t	*pkt;
3760*fcf3ce44SJohn Forte 	int		rval;
3761*fcf3ce44SJohn Forte 	uint32_t	pkt_size;
3762*fcf3ce44SJohn Forte 
3763*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3764*fcf3ce44SJohn Forte 
3765*fcf3ce44SJohn Forte 	pkt_size = sizeof (ql_mbx_iocb_t);
3766*fcf3ce44SJohn Forte 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
3767*fcf3ce44SJohn Forte 	if (pkt == NULL) {
3768*fcf3ce44SJohn Forte 		EL(ha, "failed, kmem_zalloc\n");
3769*fcf3ce44SJohn Forte 		return (QL_MEMORY_ALLOC_FAILED);
3770*fcf3ce44SJohn Forte 	}
3771*fcf3ce44SJohn Forte 
3772*fcf3ce44SJohn Forte 	pkt->vpm.entry_type = VP_MODIFY_TYPE;
3773*fcf3ce44SJohn Forte 	pkt->vpm.entry_count = 1;
3774*fcf3ce44SJohn Forte 	pkt->vpm.command = cmd;
3775*fcf3ce44SJohn Forte 	pkt->vpm.vp_count = 1;
3776*fcf3ce44SJohn Forte 	pkt->vpm.first_vp_index = ha->vp_index;
3777*fcf3ce44SJohn Forte 	pkt->vpm.first_options = opt;
3778*fcf3ce44SJohn Forte 	bcopy(ha->loginparams.nport_ww_name.raw_wwn, pkt->vpm.first_port_name,
3779*fcf3ce44SJohn Forte 	    8);
3780*fcf3ce44SJohn Forte 	bcopy(ha->loginparams.node_ww_name.raw_wwn, pkt->vpm.first_node_name,
3781*fcf3ce44SJohn Forte 	    8);
3782*fcf3ce44SJohn Forte 
3783*fcf3ce44SJohn Forte 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
3784*fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS && pkt->vpm.status != 0) {
3785*fcf3ce44SJohn Forte 		EL(ha, "failed, ql_issue_mbx_iocb=%xh, status=%xh\n", rval,
3786*fcf3ce44SJohn Forte 		    pkt->vpm.status);
3787*fcf3ce44SJohn Forte 		rval = QL_COMMAND_ERROR;
3788*fcf3ce44SJohn Forte 	}
3789*fcf3ce44SJohn Forte 
3790*fcf3ce44SJohn Forte 	kmem_free(pkt, pkt_size);
3791*fcf3ce44SJohn Forte 
3792*fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
3793*fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
3794*fcf3ce44SJohn Forte 	} else {
3795*fcf3ce44SJohn Forte 		/*EMPTY*/
3796*fcf3ce44SJohn Forte 		QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
3797*fcf3ce44SJohn Forte 		    ha->vp_index);
3798*fcf3ce44SJohn Forte 	}
3799*fcf3ce44SJohn Forte 	return (rval);
3800*fcf3ce44SJohn Forte }
3801*fcf3ce44SJohn Forte 
3802*fcf3ce44SJohn Forte /*
3803*fcf3ce44SJohn Forte  * ql_vport_enable
3804*fcf3ce44SJohn Forte  *	Enable virtual port.
3805*fcf3ce44SJohn Forte  *
3806*fcf3ce44SJohn Forte  * Input:
3807*fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
3808*fcf3ce44SJohn Forte  *
3809*fcf3ce44SJohn Forte  * Context:
3810*fcf3ce44SJohn Forte  *	Kernel context.
3811*fcf3ce44SJohn Forte  */
3812*fcf3ce44SJohn Forte int
3813*fcf3ce44SJohn Forte ql_vport_enable(ql_adapter_state_t *ha)
3814*fcf3ce44SJohn Forte {
3815*fcf3ce44SJohn Forte 	int	timer;
3816*fcf3ce44SJohn Forte 
3817*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3818*fcf3ce44SJohn Forte 
3819*fcf3ce44SJohn Forte 	ha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
3820*fcf3ce44SJohn Forte 	TASK_DAEMON_LOCK(ha);
3821*fcf3ce44SJohn Forte 	ha->task_daemon_flags |= LOOP_DOWN;
3822*fcf3ce44SJohn Forte 	ha->task_daemon_flags &= ~(FC_STATE_CHANGE | STATE_ONLINE);
3823*fcf3ce44SJohn Forte 	TASK_DAEMON_UNLOCK(ha);
3824*fcf3ce44SJohn Forte 
3825*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
3826*fcf3ce44SJohn Forte 	ha->flags |= VP_ENABLED;
3827*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
3828*fcf3ce44SJohn Forte 
3829*fcf3ce44SJohn Forte 	if (ql_vport_modify(ha, VPM_MODIFY_ENABLE, VPO_TARGET_MODE_DISABLED |
3830*fcf3ce44SJohn Forte 	    VPO_INITIATOR_MODE_ENABLED | VPO_ENABLED) != QL_SUCCESS) {
3831*fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "(%d): failed to enable virtual port=%d\n",
3832*fcf3ce44SJohn Forte 		    ha->instance, ha->vp_index);
3833*fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
3834*fcf3ce44SJohn Forte 	}
3835*fcf3ce44SJohn Forte 	if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) {
3836*fcf3ce44SJohn Forte 		/* Wait for loop to come up. */
3837*fcf3ce44SJohn Forte 		for (timer = 0; timer < 3000 &&
3838*fcf3ce44SJohn Forte 		    !(ha->task_daemon_flags & STATE_ONLINE);
3839*fcf3ce44SJohn Forte 		    timer++) {
3840*fcf3ce44SJohn Forte 			delay(1);
3841*fcf3ce44SJohn Forte 		}
3842*fcf3ce44SJohn Forte 	}
3843*fcf3ce44SJohn Forte 
3844*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
3845*fcf3ce44SJohn Forte 
3846*fcf3ce44SJohn Forte 	return (QL_SUCCESS);
3847*fcf3ce44SJohn Forte }
3848*fcf3ce44SJohn Forte 
3849*fcf3ce44SJohn Forte /*
3850*fcf3ce44SJohn Forte  * ql_vport_create
3851*fcf3ce44SJohn Forte  *	Create virtual port context.
3852*fcf3ce44SJohn Forte  *
3853*fcf3ce44SJohn Forte  * Input:
3854*fcf3ce44SJohn Forte  *	ha:	parent adapter state pointer.
3855*fcf3ce44SJohn Forte  *	index:	virtual port index number.
3856*fcf3ce44SJohn Forte  *
3857*fcf3ce44SJohn Forte  * Context:
3858*fcf3ce44SJohn Forte  *	Kernel context.
3859*fcf3ce44SJohn Forte  */
3860*fcf3ce44SJohn Forte ql_adapter_state_t *
3861*fcf3ce44SJohn Forte ql_vport_create(ql_adapter_state_t *ha, uint8_t index)
3862*fcf3ce44SJohn Forte {
3863*fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
3864*fcf3ce44SJohn Forte 
3865*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3866*fcf3ce44SJohn Forte 
3867*fcf3ce44SJohn Forte 	/* Inherit the parents data. */
3868*fcf3ce44SJohn Forte 	vha = kmem_alloc(sizeof (ql_adapter_state_t), KM_SLEEP);
3869*fcf3ce44SJohn Forte 
3870*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
3871*fcf3ce44SJohn Forte 	bcopy(ha, vha, sizeof (ql_adapter_state_t));
3872*fcf3ce44SJohn Forte 	vha->pi_attrs = NULL;
3873*fcf3ce44SJohn Forte 	vha->ub_outcnt = 0;
3874*fcf3ce44SJohn Forte 	vha->ub_allocated = 0;
3875*fcf3ce44SJohn Forte 	vha->flags = 0;
3876*fcf3ce44SJohn Forte 	vha->task_daemon_flags = 0;
3877*fcf3ce44SJohn Forte 	ha->vp_next = vha;
3878*fcf3ce44SJohn Forte 	vha->pha = ha;
3879*fcf3ce44SJohn Forte 	vha->vp_index = index;
3880*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
3881*fcf3ce44SJohn Forte 
3882*fcf3ce44SJohn Forte 	vha->hba.next = NULL;
3883*fcf3ce44SJohn Forte 	vha->hba.prev = NULL;
3884*fcf3ce44SJohn Forte 	vha->hba.base_address = vha;
3885*fcf3ce44SJohn Forte 	vha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
3886*fcf3ce44SJohn Forte 	vha->dev = kmem_zalloc(sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE,
3887*fcf3ce44SJohn Forte 	    KM_SLEEP);
3888*fcf3ce44SJohn Forte 	vha->ub_array = kmem_zalloc(sizeof (*vha->ub_array) * QL_UB_LIMIT,
3889*fcf3ce44SJohn Forte 	    KM_SLEEP);
3890*fcf3ce44SJohn Forte 
3891*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
3892*fcf3ce44SJohn Forte 
3893*fcf3ce44SJohn Forte 	return (vha);
3894*fcf3ce44SJohn Forte }
3895*fcf3ce44SJohn Forte 
3896*fcf3ce44SJohn Forte /*
3897*fcf3ce44SJohn Forte  * ql_vport_destroy
3898*fcf3ce44SJohn Forte  *	Destroys virtual port context.
3899*fcf3ce44SJohn Forte  *
3900*fcf3ce44SJohn Forte  * Input:
3901*fcf3ce44SJohn Forte  *	ha = virtual adapter state pointer.
3902*fcf3ce44SJohn Forte  *
3903*fcf3ce44SJohn Forte  * Context:
3904*fcf3ce44SJohn Forte  *	Kernel context.
3905*fcf3ce44SJohn Forte  */
3906*fcf3ce44SJohn Forte void
3907*fcf3ce44SJohn Forte ql_vport_destroy(ql_adapter_state_t *ha)
3908*fcf3ce44SJohn Forte {
3909*fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
3910*fcf3ce44SJohn Forte 
3911*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3912*fcf3ce44SJohn Forte 
3913*fcf3ce44SJohn Forte 	/* Remove port from list. */
3914*fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
3915*fcf3ce44SJohn Forte 	for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
3916*fcf3ce44SJohn Forte 		if (vha->vp_next == ha) {
3917*fcf3ce44SJohn Forte 			vha->vp_next = ha->vp_next;
3918*fcf3ce44SJohn Forte 			break;
3919*fcf3ce44SJohn Forte 		}
3920*fcf3ce44SJohn Forte 	}
3921*fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
3922*fcf3ce44SJohn Forte 
3923*fcf3ce44SJohn Forte 	if (ha->ub_array != NULL) {
3924*fcf3ce44SJohn Forte 		kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
3925*fcf3ce44SJohn Forte 	}
3926*fcf3ce44SJohn Forte 	if (ha->dev != NULL) {
3927*fcf3ce44SJohn Forte 		kmem_free(ha->dev, sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE);
3928*fcf3ce44SJohn Forte 	}
3929*fcf3ce44SJohn Forte 	kmem_free(ha, sizeof (ql_adapter_state_t));
3930*fcf3ce44SJohn Forte 
3931*fcf3ce44SJohn Forte 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
3932*fcf3ce44SJohn Forte }
3933