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