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