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