1eb82ff87SDaniel Beauregard /*
2eb82ff87SDaniel Beauregard  * CDDL HEADER START
3eb82ff87SDaniel Beauregard  *
4eb82ff87SDaniel Beauregard  * The contents of this file are subject to the terms of the
5eb82ff87SDaniel Beauregard  * Common Development and Distribution License (the "License").
6eb82ff87SDaniel Beauregard  * You may not use this file except in compliance with the License.
7eb82ff87SDaniel Beauregard  *
8eb82ff87SDaniel Beauregard  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9eb82ff87SDaniel Beauregard  * or http://www.opensolaris.org/os/licensing.
10eb82ff87SDaniel Beauregard  * See the License for the specific language governing permissions
11eb82ff87SDaniel Beauregard  * and limitations under the License.
12eb82ff87SDaniel Beauregard  *
13eb82ff87SDaniel Beauregard  * When distributing Covered Code, include this CDDL HEADER in each
14eb82ff87SDaniel Beauregard  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eb82ff87SDaniel Beauregard  * If applicable, add the following below this CDDL HEADER, with the
16eb82ff87SDaniel Beauregard  * fields enclosed by brackets "[]" replaced with your own identifying
17eb82ff87SDaniel Beauregard  * information: Portions Copyright [yyyy] [name of copyright owner]
18eb82ff87SDaniel Beauregard  *
19eb82ff87SDaniel Beauregard  * CDDL HEADER END
20eb82ff87SDaniel Beauregard  */
21eb82ff87SDaniel Beauregard 
22eb82ff87SDaniel Beauregard /*
23*4c3888b8SHans Rosenfeld  * Copyright 2015 QLogic Corporation.  All rights reserved.
24eb82ff87SDaniel Beauregard  * Use is subject to license terms.
25eb82ff87SDaniel Beauregard  */
26eb82ff87SDaniel Beauregard 
27eb82ff87SDaniel Beauregard /*
28eb82ff87SDaniel Beauregard  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
29eb82ff87SDaniel Beauregard  *
30eb82ff87SDaniel Beauregard  * ***********************************************************************
31eb82ff87SDaniel Beauregard  * *									**
32eb82ff87SDaniel Beauregard  * *				NOTICE					**
33*4c3888b8SHans Rosenfeld  * *		COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION		**
34eb82ff87SDaniel Beauregard  * *			ALL RIGHTS RESERVED				**
35eb82ff87SDaniel Beauregard  * *									**
36eb82ff87SDaniel Beauregard  * ***********************************************************************
37eb82ff87SDaniel Beauregard  *
38eb82ff87SDaniel Beauregard  */
39eb82ff87SDaniel Beauregard 
40eb82ff87SDaniel Beauregard #include <ql_apps.h>
41eb82ff87SDaniel Beauregard #include <ql_api.h>
42eb82ff87SDaniel Beauregard #include <ql_debug.h>
43*4c3888b8SHans Rosenfeld #include <ql_init.h>
44eb82ff87SDaniel Beauregard #include <ql_mbx.h>
45eb82ff87SDaniel Beauregard #include <ql_nx.h>
46eb82ff87SDaniel Beauregard 
47eb82ff87SDaniel Beauregard /*
48eb82ff87SDaniel Beauregard  *  Local Function Prototypes.
49eb82ff87SDaniel Beauregard  */
50eb82ff87SDaniel Beauregard static void ql_crb_addr_transform_setup(ql_adapter_state_t *);
51eb82ff87SDaniel Beauregard static void ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *, uint64_t *);
52eb82ff87SDaniel Beauregard static int ql_8021_crb_win_lock(ql_adapter_state_t *);
53eb82ff87SDaniel Beauregard static void ql_8021_crb_win_unlock(ql_adapter_state_t *);
54eb82ff87SDaniel Beauregard static int ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *, uint64_t *);
55eb82ff87SDaniel Beauregard static uint32_t ql_8021_pci_mem_bound_check(ql_adapter_state_t *, uint64_t,
56eb82ff87SDaniel Beauregard     uint32_t);
57eb82ff87SDaniel Beauregard static uint64_t ql_8021_pci_set_window(ql_adapter_state_t *, uint64_t);
58eb82ff87SDaniel Beauregard static int ql_8021_pci_is_same_window(ql_adapter_state_t *, uint64_t);
59eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_read_direct(ql_adapter_state_t *, uint64_t, void *,
60eb82ff87SDaniel Beauregard     uint32_t);
61eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_write_direct(ql_adapter_state_t *, uint64_t, void *,
62eb82ff87SDaniel Beauregard     uint32_t);
63eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_read_2M(ql_adapter_state_t *, uint64_t, void *,
64eb82ff87SDaniel Beauregard     uint32_t);
65eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_write_2M(ql_adapter_state_t *, uint64_t, void *,
66eb82ff87SDaniel Beauregard     uint32_t);
67eb82ff87SDaniel Beauregard static uint32_t ql_8021_decode_crb_addr(ql_adapter_state_t *, uint32_t);
68eb82ff87SDaniel Beauregard static int ql_8021_rom_lock(ql_adapter_state_t *);
69eb82ff87SDaniel Beauregard static void ql_8021_rom_unlock(ql_adapter_state_t *);
70eb82ff87SDaniel Beauregard static int ql_8021_wait_rom_done(ql_adapter_state_t *);
71eb82ff87SDaniel Beauregard static int ql_8021_wait_flash_done(ql_adapter_state_t *);
72eb82ff87SDaniel Beauregard static int ql_8021_do_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *);
73eb82ff87SDaniel Beauregard static int ql_8021_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *);
74eb82ff87SDaniel Beauregard static int ql_8021_do_rom_write(ql_adapter_state_t *, uint32_t, uint32_t);
75eb82ff87SDaniel Beauregard static int ql_8021_do_rom_erase(ql_adapter_state_t *, uint32_t);
76eb82ff87SDaniel Beauregard static int ql_8021_phantom_init(ql_adapter_state_t *);
77eb82ff87SDaniel Beauregard static int ql_8021_pinit_from_rom(ql_adapter_state_t *);
78eb82ff87SDaniel Beauregard static int ql_8021_load_from_flash(ql_adapter_state_t *);
79eb82ff87SDaniel Beauregard static int ql_8021_load_firmware(ql_adapter_state_t *);
80eb82ff87SDaniel Beauregard static int ql_8021_reset_hw(ql_adapter_state_t *, int);
81eb82ff87SDaniel Beauregard static int ql_8021_init_p3p(ql_adapter_state_t *);
82eb82ff87SDaniel Beauregard static int ql_8021_hw_lock(ql_adapter_state_t *, uint32_t);
83eb82ff87SDaniel Beauregard static void ql_8021_hw_unlock(ql_adapter_state_t *);
84eb82ff87SDaniel Beauregard static void ql_8021_need_reset_handler(ql_adapter_state_t *);
85*4c3888b8SHans Rosenfeld static int ql_8021_load_fw(ql_adapter_state_t *);
86*4c3888b8SHans Rosenfeld static uint32_t ql_8021_check_fw_alive(ql_adapter_state_t *);
87*4c3888b8SHans Rosenfeld static int ql_8021_get_fw_dump(ql_adapter_state_t *);
88*4c3888b8SHans Rosenfeld static void ql_8021_md_parse_template(ql_adapter_state_t *, caddr_t, caddr_t,
89*4c3888b8SHans Rosenfeld     uint32_t, uint32_t);
90*4c3888b8SHans Rosenfeld static int ql_8021_md_rdcrb(ql_adapter_state_t *, md_entry_rdcrb_t *,
91*4c3888b8SHans Rosenfeld     uint32_t *);
92*4c3888b8SHans Rosenfeld static int ql_8021_md_L2Cache(ql_adapter_state_t *, md_entry_cache_t *,
93*4c3888b8SHans Rosenfeld     uint32_t *);
94*4c3888b8SHans Rosenfeld static int ql_8021_md_L1Cache(ql_adapter_state_t *, md_entry_cache_t *,
95*4c3888b8SHans Rosenfeld     uint32_t *);
96*4c3888b8SHans Rosenfeld static int ql_8021_md_rdocm(ql_adapter_state_t *, md_entry_rdocm_t *,
97*4c3888b8SHans Rosenfeld     uint32_t *);
98*4c3888b8SHans Rosenfeld static int ql_8021_md_rdmem(ql_adapter_state_t *, md_entry_rdmem_t *,
99*4c3888b8SHans Rosenfeld     uint32_t *);
100*4c3888b8SHans Rosenfeld static int ql_8021_md_rdrom(ql_adapter_state_t *, md_entry_rdrom_t *,
101*4c3888b8SHans Rosenfeld     uint32_t *);
102*4c3888b8SHans Rosenfeld static int ql_8021_md_rdmux(ql_adapter_state_t *, md_entry_mux_t *,
103*4c3888b8SHans Rosenfeld     uint32_t *);
104*4c3888b8SHans Rosenfeld static int ql_8021_md_rdqueue(ql_adapter_state_t *, md_entry_queue_t *,
105*4c3888b8SHans Rosenfeld     uint32_t *);
106*4c3888b8SHans Rosenfeld static int ql_8021_md_cntrl(ql_adapter_state_t *, md_template_hdr_t *,
107*4c3888b8SHans Rosenfeld     md_entry_cntrl_t *);
108*4c3888b8SHans Rosenfeld static void ql_8021_md_entry_err_chk(ql_adapter_state_t *, md_entry_t *,
109*4c3888b8SHans Rosenfeld     uint32_t, int);
110*4c3888b8SHans Rosenfeld static uint32_t ql_8021_md_template_checksum(ql_adapter_state_t *);
111*4c3888b8SHans Rosenfeld static uint32_t ql_8021_read_reg(ql_adapter_state_t *, uint32_t);
112*4c3888b8SHans Rosenfeld static void ql_8021_write_reg(ql_adapter_state_t *, uint32_t, uint32_t);
113*4c3888b8SHans Rosenfeld static uint32_t ql_8021_read_ocm(ql_adapter_state_t *, uint32_t);
114eb82ff87SDaniel Beauregard 
115eb82ff87SDaniel Beauregard /*
116eb82ff87SDaniel Beauregard  * Local Data.
117eb82ff87SDaniel Beauregard  */
118eb82ff87SDaniel Beauregard static uint32_t	crb_addr_xform[MAX_CRB_XFORM];
119eb82ff87SDaniel Beauregard static int	crb_table_initialized = 0;
120eb82ff87SDaniel Beauregard static int	pci_set_window_warning_count = 0;
121eb82ff87SDaniel Beauregard 
122eb82ff87SDaniel Beauregard static struct legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
123eb82ff87SDaniel Beauregard 
124eb82ff87SDaniel Beauregard static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
125eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 0: PCI */
126eb82ff87SDaniel Beauregard 	{{{1, 0x0100000, 0x0102000, 0x120000},		/* 1: PCIE */
127eb82ff87SDaniel Beauregard 	    {1, 0x0110000, 0x0120000, 0x130000},
128eb82ff87SDaniel Beauregard 	    {1, 0x0120000, 0x0122000, 0x124000},
129eb82ff87SDaniel Beauregard 	    {1, 0x0130000, 0x0132000, 0x126000},
130eb82ff87SDaniel Beauregard 	    {1, 0x0140000, 0x0142000, 0x128000},
131eb82ff87SDaniel Beauregard 	    {1, 0x0150000, 0x0152000, 0x12a000},
132eb82ff87SDaniel Beauregard 	    {1, 0x0160000, 0x0170000, 0x110000},
133eb82ff87SDaniel Beauregard 	    {1, 0x0170000, 0x0172000, 0x12e000},
134eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
135eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
136eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
137eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
138eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
139eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
140eb82ff87SDaniel Beauregard 	    {1, 0x01e0000, 0x01e0800, 0x122000},
141eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000}}},
142eb82ff87SDaniel Beauregard 	{{{1, 0x0200000, 0x0210000, 0x180000}}},	/* 2: MN */
143eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 3: */
144eb82ff87SDaniel Beauregard 	{{{1, 0x0400000, 0x0401000, 0x169000}}},	/* 4: P2NR1 */
145eb82ff87SDaniel Beauregard 	{{{1, 0x0500000, 0x0510000, 0x140000}}},	/* 5: SRE   */
146eb82ff87SDaniel Beauregard 	{{{1, 0x0600000, 0x0610000, 0x1c0000}}},	/* 6: NIU   */
147eb82ff87SDaniel Beauregard 	{{{1, 0x0700000, 0x0704000, 0x1b8000}}},	/* 7: QM    */
148*4c3888b8SHans Rosenfeld 	{{{1, 0x0800000, 0x0802000, 0x170000},		/* 8: SQM0  */
149eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
150eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
151eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
152eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
153eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
154eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
155eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
156eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
157eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
158eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
159eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
160eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
161eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
162eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
163eb82ff87SDaniel Beauregard 	    {1, 0x08f0000, 0x08f2000, 0x172000}}},
164eb82ff87SDaniel Beauregard 	{{{1, 0x0900000, 0x0902000, 0x174000},		/* 9: SQM1 */
165eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
166eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
167eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
168eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
169eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
170eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
171eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
172eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
173eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
174eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
175eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
176eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
177eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
178eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
179eb82ff87SDaniel Beauregard 	    {1, 0x09f0000, 0x09f2000, 0x176000}}},
180eb82ff87SDaniel Beauregard 	{{{0, 0x0a00000, 0x0a02000, 0x178000},		/* 10: SQM2 */
181eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
182eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
183eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
184eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
185eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
186eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
187eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
188eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
189eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
190eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
191eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
192eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
193eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
194eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
195eb82ff87SDaniel Beauregard 	    {1, 0x0af0000, 0x0af2000, 0x17a000}}},
196eb82ff87SDaniel Beauregard 	{{{0, 0x0b00000, 0x0b02000, 0x17c000},		/* 11: SQM3 */
197eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
198eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
199eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
200eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
201eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
202eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
203eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
204eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
205eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
206eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
207eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
208eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
209eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
210eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
211eb82ff87SDaniel Beauregard 	    {1, 0x0bf0000, 0x0bf2000, 0x17e000}}},
212eb82ff87SDaniel Beauregard 	{{{1, 0x0c00000, 0x0c04000, 0x1d4000}}},	/* 12: I2Q */
213eb82ff87SDaniel Beauregard 	{{{1, 0x0d00000, 0x0d04000, 0x1a4000}}},	/* 13: TMR */
214eb82ff87SDaniel Beauregard 	{{{1, 0x0e00000, 0x0e04000, 0x1a0000}}},	/* 14: ROMUSB */
215eb82ff87SDaniel Beauregard 	{{{1, 0x0f00000, 0x0f01000, 0x164000}}},	/* 15: PEG4 */
216eb82ff87SDaniel Beauregard 	{{{0, 0x1000000, 0x1004000, 0x1a8000}}},	/* 16: XDMA */
217eb82ff87SDaniel Beauregard 	{{{1, 0x1100000, 0x1101000, 0x160000}}},	/* 17: PEG0 */
218eb82ff87SDaniel Beauregard 	{{{1, 0x1200000, 0x1201000, 0x161000}}},	/* 18: PEG1 */
219eb82ff87SDaniel Beauregard 	{{{1, 0x1300000, 0x1301000, 0x162000}}},	/* 19: PEG2 */
220eb82ff87SDaniel Beauregard 	{{{1, 0x1400000, 0x1401000, 0x163000}}},	/* 20: PEG3 */
221eb82ff87SDaniel Beauregard 	{{{1, 0x1500000, 0x1501000, 0x165000}}},	/* 21: P2ND */
222eb82ff87SDaniel Beauregard 	{{{1, 0x1600000, 0x1601000, 0x166000}}},	/* 22: P2NI */
223eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 23: */
224eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 24: */
225eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 25: */
226eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 26: */
227eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 27: */
228eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 28: */
229eb82ff87SDaniel Beauregard 	{{{1, 0x1d00000, 0x1d10000, 0x190000}}},	/* 29: MS */
230eb82ff87SDaniel Beauregard 	{{{1, 0x1e00000, 0x1e01000, 0x16a000}}},	/* 30: P2NR2 */
231eb82ff87SDaniel Beauregard 	{{{1, 0x1f00000, 0x1f10000, 0x150000}}},	/* 31: EPG */
232eb82ff87SDaniel Beauregard 	{{{0}}},					/* 32: PCI */
233eb82ff87SDaniel Beauregard 	{{{1, 0x2100000, 0x2102000, 0x120000},		/* 33: PCIE */
234eb82ff87SDaniel Beauregard 	    {1, 0x2110000, 0x2120000, 0x130000},
235eb82ff87SDaniel Beauregard 	    {1, 0x2120000, 0x2122000, 0x124000},
236eb82ff87SDaniel Beauregard 	    {1, 0x2130000, 0x2132000, 0x126000},
237eb82ff87SDaniel Beauregard 	    {1, 0x2140000, 0x2142000, 0x128000},
238eb82ff87SDaniel Beauregard 	    {1, 0x2150000, 0x2152000, 0x12a000},
239eb82ff87SDaniel Beauregard 	    {1, 0x2160000, 0x2170000, 0x110000},
240eb82ff87SDaniel Beauregard 	    {1, 0x2170000, 0x2172000, 0x12e000},
241eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
242eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
243eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
244eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
245eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
246eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
247eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
248eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000}}},
249eb82ff87SDaniel Beauregard 	{{{1, 0x2200000, 0x2204000, 0x1b0000}}},	/* 34: CAM */
250eb82ff87SDaniel Beauregard 	{{{0}}},					/* 35: */
251eb82ff87SDaniel Beauregard 	{{{0}}},					/* 36: */
252eb82ff87SDaniel Beauregard 	{{{0}}},					/* 37: */
253eb82ff87SDaniel Beauregard 	{{{0}}},					/* 38: */
254eb82ff87SDaniel Beauregard 	{{{0}}},					/* 39: */
255eb82ff87SDaniel Beauregard 	{{{1, 0x2800000, 0x2804000, 0x1a4000}}},	/* 40: TMR */
256eb82ff87SDaniel Beauregard 	{{{1, 0x2900000, 0x2901000, 0x16b000}}},	/* 41: P2NR3 */
257eb82ff87SDaniel Beauregard 	{{{1, 0x2a00000, 0x2a00400, 0x1ac400}}},	/* 42: RPMX1 */
258eb82ff87SDaniel Beauregard 	{{{1, 0x2b00000, 0x2b00400, 0x1ac800}}},	/* 43: RPMX2 */
259eb82ff87SDaniel Beauregard 	{{{1, 0x2c00000, 0x2c00400, 0x1acc00}}},	/* 44: RPMX3 */
260eb82ff87SDaniel Beauregard 	{{{1, 0x2d00000, 0x2d00400, 0x1ad000}}},	/* 45: RPMX4 */
261eb82ff87SDaniel Beauregard 	{{{1, 0x2e00000, 0x2e00400, 0x1ad400}}},	/* 46: RPMX5 */
262eb82ff87SDaniel Beauregard 	{{{1, 0x2f00000, 0x2f00400, 0x1ad800}}},	/* 47: RPMX6 */
263eb82ff87SDaniel Beauregard 	{{{1, 0x3000000, 0x3000400, 0x1adc00}}},	/* 48: RPMX7 */
264eb82ff87SDaniel Beauregard 	{{{0, 0x3100000, 0x3104000, 0x1a8000}}},	/* 49: XDMA */
265eb82ff87SDaniel Beauregard 	{{{1, 0x3200000, 0x3204000, 0x1d4000}}},	/* 50: I2Q */
266eb82ff87SDaniel Beauregard 	{{{1, 0x3300000, 0x3304000, 0x1a0000}}},	/* 51: ROMUSB */
267eb82ff87SDaniel Beauregard 	{{{0}}},					/* 52: */
268eb82ff87SDaniel Beauregard 	{{{1, 0x3500000, 0x3500400, 0x1ac000}}},	/* 53: RPMX0 */
269eb82ff87SDaniel Beauregard 	{{{1, 0x3600000, 0x3600400, 0x1ae000}}},	/* 54: RPMX8 */
270eb82ff87SDaniel Beauregard 	{{{1, 0x3700000, 0x3700400, 0x1ae400}}},	/* 55: RPMX9 */
271eb82ff87SDaniel Beauregard 	{{{1, 0x3800000, 0x3804000, 0x1d0000}}},	/* 56: OCM0 */
272eb82ff87SDaniel Beauregard 	{{{1, 0x3900000, 0x3904000, 0x1b4000}}},	/* 57: CRYPTO */
273eb82ff87SDaniel Beauregard 	{{{1, 0x3a00000, 0x3a04000, 0x1d8000}}},	/* 58: SMB */
274eb82ff87SDaniel Beauregard 	{{{0}}},					/* 59: I2C0 */
275eb82ff87SDaniel Beauregard 	{{{0}}},					/* 60: I2C1 */
276eb82ff87SDaniel Beauregard 	{{{1, 0x3d00000, 0x3d04000, 0x1dc000}}},	/* 61: LPC */
277eb82ff87SDaniel Beauregard 	{{{1, 0x3e00000, 0x3e01000, 0x167000}}},	/* 62: P2NC */
278eb82ff87SDaniel Beauregard 	{{{1, 0x3f00000, 0x3f01000, 0x168000}}}		/* 63: P2NR0 */
279eb82ff87SDaniel Beauregard };
280eb82ff87SDaniel Beauregard 
281eb82ff87SDaniel Beauregard /*
282eb82ff87SDaniel Beauregard  * top 12 bits of crb internal address (hub, agent)
283eb82ff87SDaniel Beauregard  */
284eb82ff87SDaniel Beauregard static uint32_t crb_hub_agt[64] = {
285eb82ff87SDaniel Beauregard 	0,
286eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PS,
287eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_MN,
288eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_MS,
289eb82ff87SDaniel Beauregard 	0,
290eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SRE,
291eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_NIU,
292eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_QMN,
293eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN0,
294eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN1,
295eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN2,
296eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN3,
297eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
298eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
299eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
300eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN4,
301eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
302eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN0,
303eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN1,
304eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN2,
305eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN3,
306eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGND,
307eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGNI,
308eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS0,
309eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS1,
310eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS2,
311eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS3,
312eb82ff87SDaniel Beauregard 	0,
313eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGSI,
314eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SN,
315eb82ff87SDaniel Beauregard 	0,
316eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_EG,
317eb82ff87SDaniel Beauregard 	0,
318eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PS,
319eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_CAM,
320eb82ff87SDaniel Beauregard 	0,
321eb82ff87SDaniel Beauregard 	0,
322eb82ff87SDaniel Beauregard 	0,
323eb82ff87SDaniel Beauregard 	0,
324eb82ff87SDaniel Beauregard 	0,
325eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
326eb82ff87SDaniel Beauregard 	0,
327eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX1,
328eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX2,
329eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX3,
330eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX4,
331eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX5,
332eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX6,
333eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX7,
334eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
335eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
336eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
337eb82ff87SDaniel Beauregard 	0,
338eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX0,
339eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX8,
340eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX9,
341eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_OCM0,
342eb82ff87SDaniel Beauregard 	0,
343eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SMB,
344eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2C0,
345eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2C1,
346eb82ff87SDaniel Beauregard 	0,
347eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGNC,
348eb82ff87SDaniel Beauregard 	0,
349eb82ff87SDaniel Beauregard };
350eb82ff87SDaniel Beauregard 
351eb82ff87SDaniel Beauregard /* ARGSUSED */
352eb82ff87SDaniel Beauregard static void
ql_crb_addr_transform_setup(ql_adapter_state_t * ha)353eb82ff87SDaniel Beauregard ql_crb_addr_transform_setup(ql_adapter_state_t *ha)
354eb82ff87SDaniel Beauregard {
355eb82ff87SDaniel Beauregard 	crb_addr_transform(XDMA);
356eb82ff87SDaniel Beauregard 	crb_addr_transform(TIMR);
357eb82ff87SDaniel Beauregard 	crb_addr_transform(SRE);
358eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN3);
359eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN2);
360eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN1);
361eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN0);
362eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS3);
363eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS2);
364eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS1);
365eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS0);
366eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX7);
367eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX6);
368eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX5);
369eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX4);
370eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX3);
371eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX2);
372eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX1);
373eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX0);
374eb82ff87SDaniel Beauregard 	crb_addr_transform(ROMUSB);
375eb82ff87SDaniel Beauregard 	crb_addr_transform(SN);
376eb82ff87SDaniel Beauregard 	crb_addr_transform(QMN);
377eb82ff87SDaniel Beauregard 	crb_addr_transform(QMS);
378eb82ff87SDaniel Beauregard 	crb_addr_transform(PGNI);
379eb82ff87SDaniel Beauregard 	crb_addr_transform(PGND);
380eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN3);
381eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN2);
382eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN1);
383eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN0);
384eb82ff87SDaniel Beauregard 	crb_addr_transform(PGSI);
385eb82ff87SDaniel Beauregard 	crb_addr_transform(PGSD);
386eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS3);
387eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS2);
388eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS1);
389eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS0);
390eb82ff87SDaniel Beauregard 	crb_addr_transform(PS);
391eb82ff87SDaniel Beauregard 	crb_addr_transform(PH);
392eb82ff87SDaniel Beauregard 	crb_addr_transform(NIU);
393eb82ff87SDaniel Beauregard 	crb_addr_transform(I2Q);
394eb82ff87SDaniel Beauregard 	crb_addr_transform(EG);
395eb82ff87SDaniel Beauregard 	crb_addr_transform(MN);
396eb82ff87SDaniel Beauregard 	crb_addr_transform(MS);
397eb82ff87SDaniel Beauregard 	crb_addr_transform(CAS2);
398eb82ff87SDaniel Beauregard 	crb_addr_transform(CAS1);
399eb82ff87SDaniel Beauregard 	crb_addr_transform(CAS0);
400eb82ff87SDaniel Beauregard 	crb_addr_transform(CAM);
401eb82ff87SDaniel Beauregard 	crb_addr_transform(C2C1);
402eb82ff87SDaniel Beauregard 	crb_addr_transform(C2C0);
403eb82ff87SDaniel Beauregard 	crb_addr_transform(SMB);
404eb82ff87SDaniel Beauregard 	crb_addr_transform(OCM0);
405eb82ff87SDaniel Beauregard 	/*
406eb82ff87SDaniel Beauregard 	 * Used only in P3 just define it for P2 also.
407eb82ff87SDaniel Beauregard 	 */
408eb82ff87SDaniel Beauregard 	crb_addr_transform(I2C0);
409eb82ff87SDaniel Beauregard 
410eb82ff87SDaniel Beauregard 	crb_table_initialized = 1;
411eb82ff87SDaniel Beauregard }
412eb82ff87SDaniel Beauregard 
413eb82ff87SDaniel Beauregard /*
414eb82ff87SDaniel Beauregard  * In: 'off' is offset from CRB space in 128M pci map
415eb82ff87SDaniel Beauregard  * Out: 'off' is 2M pci map addr
416eb82ff87SDaniel Beauregard  * side effect: lock crb window
417eb82ff87SDaniel Beauregard  */
418eb82ff87SDaniel Beauregard static void
ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t * ha,uint64_t * off)419eb82ff87SDaniel Beauregard ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *ha, uint64_t *off)
420eb82ff87SDaniel Beauregard {
421*4c3888b8SHans Rosenfeld 	uint32_t	win_read, crb_win;
422eb82ff87SDaniel Beauregard 
423*4c3888b8SHans Rosenfeld 	crb_win = (uint32_t)CRB_HI(*off);
424*4c3888b8SHans Rosenfeld 	WRT_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase, crb_win);
425eb82ff87SDaniel Beauregard 
426eb82ff87SDaniel Beauregard 	/*
427eb82ff87SDaniel Beauregard 	 * Read back value to make sure write has gone through before trying
428eb82ff87SDaniel Beauregard 	 * to use it.
429eb82ff87SDaniel Beauregard 	 */
430eb82ff87SDaniel Beauregard 	win_read = RD_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase);
431*4c3888b8SHans Rosenfeld 	if (win_read != crb_win) {
432eb82ff87SDaniel Beauregard 		EL(ha, "Written crbwin (0x%x) != Read crbwin (0x%x), "
433*4c3888b8SHans Rosenfeld 		    "off=0x%llx\n", crb_win, win_read, *off);
434eb82ff87SDaniel Beauregard 	}
435eb82ff87SDaniel Beauregard 	*off = (*off & MASK(16)) + CRB_INDIRECT_2M + (uintptr_t)ha->nx_pcibase;
436eb82ff87SDaniel Beauregard }
437eb82ff87SDaniel Beauregard 
438*4c3888b8SHans Rosenfeld void
ql_8021_wr_32(ql_adapter_state_t * ha,uint64_t off,uint32_t data)439eb82ff87SDaniel Beauregard ql_8021_wr_32(ql_adapter_state_t *ha, uint64_t off, uint32_t data)
440eb82ff87SDaniel Beauregard {
441eb82ff87SDaniel Beauregard 	int	rv;
442eb82ff87SDaniel Beauregard 
443eb82ff87SDaniel Beauregard 	rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
444eb82ff87SDaniel Beauregard 	if (rv == -1) {
445eb82ff87SDaniel Beauregard 		cmn_err(CE_PANIC, "ql_8021_wr_32, ql_8021_pci_get_crb_addr_"
446eb82ff87SDaniel Beauregard 		    "2M=-1\n");
447eb82ff87SDaniel Beauregard 	}
448eb82ff87SDaniel Beauregard 	if (rv == 1) {
449eb82ff87SDaniel Beauregard 		(void) ql_8021_crb_win_lock(ha);
450eb82ff87SDaniel Beauregard 		ql_8021_pci_set_crbwindow_2M(ha, &off);
451eb82ff87SDaniel Beauregard 	}
452eb82ff87SDaniel Beauregard 
453eb82ff87SDaniel Beauregard 	WRT_REG_DWORD(ha, (uintptr_t)off, data);
454eb82ff87SDaniel Beauregard 
455eb82ff87SDaniel Beauregard 	if (rv == 1) {
456eb82ff87SDaniel Beauregard 		ql_8021_crb_win_unlock(ha);
457eb82ff87SDaniel Beauregard 	}
458eb82ff87SDaniel Beauregard }
459eb82ff87SDaniel Beauregard 
460*4c3888b8SHans Rosenfeld void
ql_8021_rd_32(ql_adapter_state_t * ha,uint64_t off,uint32_t * data)461eb82ff87SDaniel Beauregard ql_8021_rd_32(ql_adapter_state_t *ha, uint64_t off, uint32_t *data)
462eb82ff87SDaniel Beauregard {
463eb82ff87SDaniel Beauregard 	int		rv;
464eb82ff87SDaniel Beauregard 	uint32_t	n;
465eb82ff87SDaniel Beauregard 
466eb82ff87SDaniel Beauregard 	rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
467eb82ff87SDaniel Beauregard 	if (rv == -1) {
468eb82ff87SDaniel Beauregard 		cmn_err(CE_PANIC, "ql_8021_rd_32, ql_8021_pci_get_crb_addr_"
469eb82ff87SDaniel Beauregard 		    "2M=-1\n");
470eb82ff87SDaniel Beauregard 	}
471eb82ff87SDaniel Beauregard 
472eb82ff87SDaniel Beauregard 	if (rv == 1) {
473eb82ff87SDaniel Beauregard 		(void) ql_8021_crb_win_lock(ha);
474eb82ff87SDaniel Beauregard 		ql_8021_pci_set_crbwindow_2M(ha, &off);
475eb82ff87SDaniel Beauregard 	}
476eb82ff87SDaniel Beauregard 	n = RD_REG_DWORD(ha, (uintptr_t)off);
477eb82ff87SDaniel Beauregard 
478eb82ff87SDaniel Beauregard 	if (data != NULL) {
479eb82ff87SDaniel Beauregard 		*data = n;
480eb82ff87SDaniel Beauregard 	}
481eb82ff87SDaniel Beauregard 
482eb82ff87SDaniel Beauregard 	if (rv == 1) {
483eb82ff87SDaniel Beauregard 		ql_8021_crb_win_unlock(ha);
484eb82ff87SDaniel Beauregard 	}
485eb82ff87SDaniel Beauregard }
486eb82ff87SDaniel Beauregard 
487eb82ff87SDaniel Beauregard static int
ql_8021_crb_win_lock(ql_adapter_state_t * ha)488eb82ff87SDaniel Beauregard ql_8021_crb_win_lock(ql_adapter_state_t *ha)
489eb82ff87SDaniel Beauregard {
490eb82ff87SDaniel Beauregard 	uint32_t	done = 0, timeout = 0;
491eb82ff87SDaniel Beauregard 
492eb82ff87SDaniel Beauregard 	while (!done) {
493eb82ff87SDaniel Beauregard 		/* acquire semaphore3 from PCI HW block */
494eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_LOCK), &done);
495eb82ff87SDaniel Beauregard 		if (done == 1) {
496eb82ff87SDaniel Beauregard 			break;
497eb82ff87SDaniel Beauregard 		}
498eb82ff87SDaniel Beauregard 		if (timeout >= CRB_WIN_LOCK_TIMEOUT) {
499eb82ff87SDaniel Beauregard 			EL(ha, "timeout\n");
500eb82ff87SDaniel Beauregard 			return (-1);
501eb82ff87SDaniel Beauregard 		}
502eb82ff87SDaniel Beauregard 		timeout++;
503eb82ff87SDaniel Beauregard 
504eb82ff87SDaniel Beauregard 		/* Yield CPU */
505eb82ff87SDaniel Beauregard 		delay(1);
506eb82ff87SDaniel Beauregard 	}
507*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_WIN_LOCK_ID, ha->pci_function_number);
508eb82ff87SDaniel Beauregard 
509eb82ff87SDaniel Beauregard 	return (0);
510eb82ff87SDaniel Beauregard }
511eb82ff87SDaniel Beauregard 
512eb82ff87SDaniel Beauregard static void
ql_8021_crb_win_unlock(ql_adapter_state_t * ha)513eb82ff87SDaniel Beauregard ql_8021_crb_win_unlock(ql_adapter_state_t *ha)
514eb82ff87SDaniel Beauregard {
515eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_UNLOCK), NULL);
516eb82ff87SDaniel Beauregard }
517eb82ff87SDaniel Beauregard 
518eb82ff87SDaniel Beauregard static int
ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t * ha,uint64_t * off)519eb82ff87SDaniel Beauregard ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *ha, uint64_t *off)
520eb82ff87SDaniel Beauregard {
521eb82ff87SDaniel Beauregard 	crb_128M_2M_sub_block_map_t	*m;
522eb82ff87SDaniel Beauregard 
523eb82ff87SDaniel Beauregard 	if (*off >= UNM_CRB_MAX) {
524eb82ff87SDaniel Beauregard 		EL(ha, "%llx >= %llx\n", *off, UNM_CRB_MAX);
525eb82ff87SDaniel Beauregard 		return (-1);
526eb82ff87SDaniel Beauregard 	}
527eb82ff87SDaniel Beauregard 
528eb82ff87SDaniel Beauregard 	if (*off >= UNM_PCI_CAMQM && (*off < UNM_PCI_CAMQM_2M_END)) {
529eb82ff87SDaniel Beauregard 		*off = (*off - UNM_PCI_CAMQM) + UNM_PCI_CAMQM_2M_BASE +
530eb82ff87SDaniel Beauregard 		    (uintptr_t)ha->nx_pcibase;
531eb82ff87SDaniel Beauregard 		return (0);
532eb82ff87SDaniel Beauregard 	}
533eb82ff87SDaniel Beauregard 
534eb82ff87SDaniel Beauregard 	if (*off < UNM_PCI_CRBSPACE) {
535eb82ff87SDaniel Beauregard 		EL(ha, "%llx < %llx\n", *off, UNM_PCI_CRBSPACE);
536eb82ff87SDaniel Beauregard 		return (-1);
537eb82ff87SDaniel Beauregard 	}
538eb82ff87SDaniel Beauregard 
539eb82ff87SDaniel Beauregard 	*off -= UNM_PCI_CRBSPACE;
540eb82ff87SDaniel Beauregard 	/*
541eb82ff87SDaniel Beauregard 	 * Try direct map
542eb82ff87SDaniel Beauregard 	 */
543eb82ff87SDaniel Beauregard 
544eb82ff87SDaniel Beauregard 	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
545eb82ff87SDaniel Beauregard 
546eb82ff87SDaniel Beauregard 	if (m->valid && ((uint64_t)m->start_128M <= *off) &&
547eb82ff87SDaniel Beauregard 	    ((uint64_t)m->end_128M > *off)) {
548eb82ff87SDaniel Beauregard 		*off = (uint64_t)(*off + m->start_2M - m->start_128M +
549eb82ff87SDaniel Beauregard 		    (uintptr_t)ha->nx_pcibase);
550eb82ff87SDaniel Beauregard 		return (0);
551eb82ff87SDaniel Beauregard 	}
552eb82ff87SDaniel Beauregard 
553eb82ff87SDaniel Beauregard 	/*
554eb82ff87SDaniel Beauregard 	 * Not in direct map, use crb window
555eb82ff87SDaniel Beauregard 	 */
556eb82ff87SDaniel Beauregard 	return (1);
557eb82ff87SDaniel Beauregard }
558eb82ff87SDaniel Beauregard 
559eb82ff87SDaniel Beauregard /*
560eb82ff87SDaniel Beauregard  * check memory access boundary.
561eb82ff87SDaniel Beauregard  * used by test agent. support ddr access only for now
562eb82ff87SDaniel Beauregard  */
563eb82ff87SDaniel Beauregard /* ARGSUSED */
564eb82ff87SDaniel Beauregard static uint32_t
ql_8021_pci_mem_bound_check(ql_adapter_state_t * ha,uint64_t addr,uint32_t size)565eb82ff87SDaniel Beauregard ql_8021_pci_mem_bound_check(ql_adapter_state_t *ha, uint64_t addr,
566eb82ff87SDaniel Beauregard     uint32_t size)
567eb82ff87SDaniel Beauregard {
568eb82ff87SDaniel Beauregard 	/*LINTED suspicious 0 comparison*/
569eb82ff87SDaniel Beauregard 	if (!QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
570eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX) ||
571eb82ff87SDaniel Beauregard 	    /*LINTED suspicious 0 comparison*/
572eb82ff87SDaniel Beauregard 	    !QL_8021_ADDR_IN_RANGE(addr + size - 1, UNM_ADDR_DDR_NET,
573eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX) ||
574eb82ff87SDaniel Beauregard 	    ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
575eb82ff87SDaniel Beauregard 		return (0);
576eb82ff87SDaniel Beauregard 	}
577eb82ff87SDaniel Beauregard 
578eb82ff87SDaniel Beauregard 	return (1);
579eb82ff87SDaniel Beauregard }
580eb82ff87SDaniel Beauregard 
581eb82ff87SDaniel Beauregard static uint64_t
ql_8021_pci_set_window(ql_adapter_state_t * ha,uint64_t addr)582eb82ff87SDaniel Beauregard ql_8021_pci_set_window(ql_adapter_state_t *ha, uint64_t addr)
583eb82ff87SDaniel Beauregard {
584eb82ff87SDaniel Beauregard 	uint32_t	window, win_read;
585eb82ff87SDaniel Beauregard 
586eb82ff87SDaniel Beauregard 	/*LINTED suspicious 0 comparison*/
587eb82ff87SDaniel Beauregard 	if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
588eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX)) {
589eb82ff87SDaniel Beauregard 		/* DDR network side */
590eb82ff87SDaniel Beauregard 		window = (uint32_t)MN_WIN(addr);
591*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, UNM_PCI_CRBSPACE, window);
592*4c3888b8SHans Rosenfeld 		ql_8021_rd_32(ha, UNM_PCI_CRBSPACE, &win_read);
593eb82ff87SDaniel Beauregard 		if ((win_read << 17) != window) {
594eb82ff87SDaniel Beauregard 			EL(ha, "Warning, Written MNwin (0x%x) != Read MNwin "
595eb82ff87SDaniel Beauregard 			    "(0x%x)\n", window, win_read);
596eb82ff87SDaniel Beauregard 		}
597eb82ff87SDaniel Beauregard 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
598eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
599eb82ff87SDaniel Beauregard 	    UNM_ADDR_OCM0_MAX)) {
600eb82ff87SDaniel Beauregard 		uint32_t	temp1;
601eb82ff87SDaniel Beauregard 
602eb82ff87SDaniel Beauregard 		if ((addr & 0x00ff800) == 0xff800) {
603eb82ff87SDaniel Beauregard 			/* if bits 19:18&17:11 are on */
604eb82ff87SDaniel Beauregard 			EL(ha, "QM access not handled\n");
605eb82ff87SDaniel Beauregard 			addr = -1UL;
606eb82ff87SDaniel Beauregard 		}
607eb82ff87SDaniel Beauregard 
608eb82ff87SDaniel Beauregard 		window = (uint32_t)OCM_WIN(addr);
609*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, UNM_PCI_CRBSPACE, window);
610*4c3888b8SHans Rosenfeld 		ql_8021_rd_32(ha, UNM_PCI_CRBSPACE, &win_read);
611eb82ff87SDaniel Beauregard 		temp1 = ((window & 0x1FF) << 7) |
612eb82ff87SDaniel Beauregard 		    ((window & 0x0FFFE0000) >> 17);
613eb82ff87SDaniel Beauregard 		if (win_read != temp1) {
614eb82ff87SDaniel Beauregard 			EL(ha, "Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
615eb82ff87SDaniel Beauregard 			    temp1, win_read);
616eb82ff87SDaniel Beauregard 		}
617eb82ff87SDaniel Beauregard 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
618eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
619eb82ff87SDaniel Beauregard 	    NX_P3_ADDR_QDR_NET_MAX)) {
620eb82ff87SDaniel Beauregard 		/* QDR network side */
621eb82ff87SDaniel Beauregard 		window = (uint32_t)MS_WIN(addr);
622eb82ff87SDaniel Beauregard 		ha->qdr_sn_window = window;
623*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, UNM_PCI_CRBSPACE, window);
624*4c3888b8SHans Rosenfeld 		ql_8021_rd_32(ha, UNM_PCI_CRBSPACE, &win_read);
625eb82ff87SDaniel Beauregard 		if (win_read != window) {
626eb82ff87SDaniel Beauregard 			EL(ha, "Written MSwin (0x%x) != Read MSwin (0x%x)\n",
627eb82ff87SDaniel Beauregard 			    window, win_read);
628eb82ff87SDaniel Beauregard 		}
629eb82ff87SDaniel Beauregard 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
630eb82ff87SDaniel Beauregard 	} else {
631eb82ff87SDaniel Beauregard 		/*
632eb82ff87SDaniel Beauregard 		 * peg gdb frequently accesses memory that doesn't exist,
633eb82ff87SDaniel Beauregard 		 * this limits the chit chat so debugging isn't slowed down.
634eb82ff87SDaniel Beauregard 		 */
635eb82ff87SDaniel Beauregard 		if ((pci_set_window_warning_count++ < 8) ||
636eb82ff87SDaniel Beauregard 		    (pci_set_window_warning_count % 64 == 0)) {
637eb82ff87SDaniel Beauregard 			EL(ha, "Unknown address range\n");
638eb82ff87SDaniel Beauregard 		}
639eb82ff87SDaniel Beauregard 		addr = -1UL;
640eb82ff87SDaniel Beauregard 	}
641eb82ff87SDaniel Beauregard 
642eb82ff87SDaniel Beauregard 	return (addr);
643eb82ff87SDaniel Beauregard }
644eb82ff87SDaniel Beauregard 
645eb82ff87SDaniel Beauregard /* check if address is in the same windows as the previous access */
646eb82ff87SDaniel Beauregard static int
ql_8021_pci_is_same_window(ql_adapter_state_t * ha,uint64_t addr)647eb82ff87SDaniel Beauregard ql_8021_pci_is_same_window(ql_adapter_state_t *ha, uint64_t addr)
648eb82ff87SDaniel Beauregard {
649eb82ff87SDaniel Beauregard 	uint32_t	window;
650eb82ff87SDaniel Beauregard 	uint64_t	qdr_max;
651eb82ff87SDaniel Beauregard 
652eb82ff87SDaniel Beauregard 	qdr_max = NX_P3_ADDR_QDR_NET_MAX;
653eb82ff87SDaniel Beauregard 
654eb82ff87SDaniel Beauregard 	/*LINTED suspicious 0 comparison*/
655eb82ff87SDaniel Beauregard 	if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
656eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX)) {
657eb82ff87SDaniel Beauregard 		/* DDR network side */
658eb82ff87SDaniel Beauregard 		EL(ha, "DDR network side\n");
659eb82ff87SDaniel Beauregard 		return (0);	/* MN access can not come here */
660eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
661eb82ff87SDaniel Beauregard 	    UNM_ADDR_OCM0_MAX)) {
662eb82ff87SDaniel Beauregard 		return (1);
663eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM1,
664eb82ff87SDaniel Beauregard 	    UNM_ADDR_OCM1_MAX)) {
665eb82ff87SDaniel Beauregard 		return (1);
666eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
667eb82ff87SDaniel Beauregard 		/* QDR network side */
668eb82ff87SDaniel Beauregard 		window = (uint32_t)(((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f);
669eb82ff87SDaniel Beauregard 		if (ha->qdr_sn_window == window) {
670eb82ff87SDaniel Beauregard 			return (1);
671eb82ff87SDaniel Beauregard 		}
672eb82ff87SDaniel Beauregard 	}
673eb82ff87SDaniel Beauregard 
674eb82ff87SDaniel Beauregard 	return (0);
675eb82ff87SDaniel Beauregard }
676eb82ff87SDaniel Beauregard 
677eb82ff87SDaniel Beauregard static int
ql_8021_pci_mem_read_direct(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)678eb82ff87SDaniel Beauregard ql_8021_pci_mem_read_direct(ql_adapter_state_t *ha, uint64_t off, void *data,
679eb82ff87SDaniel Beauregard     uint32_t size)
680eb82ff87SDaniel Beauregard {
681eb82ff87SDaniel Beauregard 	void		*addr;
682eb82ff87SDaniel Beauregard 	int		ret = 0;
683eb82ff87SDaniel Beauregard 	uint64_t	start;
684eb82ff87SDaniel Beauregard 
685eb82ff87SDaniel Beauregard 	/*
686eb82ff87SDaniel Beauregard 	 * If attempting to access unknown address or straddle hw windows,
687eb82ff87SDaniel Beauregard 	 * do not access.
688eb82ff87SDaniel Beauregard 	 */
689eb82ff87SDaniel Beauregard 	if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
690eb82ff87SDaniel Beauregard 	    (ql_8021_pci_is_same_window(ha, off + size - 1) == 0)) {
691eb82ff87SDaniel Beauregard 		EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
692eb82ff87SDaniel Beauregard 		    off);
693eb82ff87SDaniel Beauregard 		return (-1);
694eb82ff87SDaniel Beauregard 	}
695eb82ff87SDaniel Beauregard 
696*4c3888b8SHans Rosenfeld 	addr = (void *)((uint8_t *)ha->nx_pcibase + start);
697eb82ff87SDaniel Beauregard 
698eb82ff87SDaniel Beauregard 	switch (size) {
699eb82ff87SDaniel Beauregard 	case 1:
700*4c3888b8SHans Rosenfeld 		*(uint8_t *)data = RD_REG_BYTE(ha, addr);
701eb82ff87SDaniel Beauregard 		break;
702eb82ff87SDaniel Beauregard 	case 2:
703*4c3888b8SHans Rosenfeld 		*(uint16_t *)data = RD_REG_WORD(ha, addr);
704eb82ff87SDaniel Beauregard 		break;
705eb82ff87SDaniel Beauregard 	case 4:
706*4c3888b8SHans Rosenfeld 		*(uint32_t *)data = RD_REG_DWORD(ha, addr);
707eb82ff87SDaniel Beauregard 		break;
708eb82ff87SDaniel Beauregard 	case 8:
709*4c3888b8SHans Rosenfeld 		*(uint64_t *)data = RD_REG_DDWORD(ha, addr);
710eb82ff87SDaniel Beauregard 		break;
711eb82ff87SDaniel Beauregard 	default:
712eb82ff87SDaniel Beauregard 		EL(ha, "invalid size=%x\n", size);
713eb82ff87SDaniel Beauregard 		ret = -1;
714eb82ff87SDaniel Beauregard 		break;
715eb82ff87SDaniel Beauregard 	}
716eb82ff87SDaniel Beauregard 
717eb82ff87SDaniel Beauregard 	return (ret);
718eb82ff87SDaniel Beauregard }
719eb82ff87SDaniel Beauregard 
720eb82ff87SDaniel Beauregard static int
ql_8021_pci_mem_write_direct(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)721eb82ff87SDaniel Beauregard ql_8021_pci_mem_write_direct(ql_adapter_state_t *ha, uint64_t off, void *data,
722eb82ff87SDaniel Beauregard     uint32_t size)
723eb82ff87SDaniel Beauregard {
724eb82ff87SDaniel Beauregard 	void		*addr;
725eb82ff87SDaniel Beauregard 	int		ret = 0;
726eb82ff87SDaniel Beauregard 	uint64_t	start;
727eb82ff87SDaniel Beauregard 
728eb82ff87SDaniel Beauregard 	/*
729eb82ff87SDaniel Beauregard 	 * If attempting to access unknown address or straddle hw windows,
730eb82ff87SDaniel Beauregard 	 * do not access.
731eb82ff87SDaniel Beauregard 	 */
732eb82ff87SDaniel Beauregard 	if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
733eb82ff87SDaniel Beauregard 	    (ql_8021_pci_is_same_window(ha, off + size -1) == 0)) {
734eb82ff87SDaniel Beauregard 		EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
735eb82ff87SDaniel Beauregard 		    off);
736eb82ff87SDaniel Beauregard 		return (-1);
737eb82ff87SDaniel Beauregard 	}
738eb82ff87SDaniel Beauregard 
739*4c3888b8SHans Rosenfeld 	addr = (void *)((uint8_t *)ha->nx_pcibase + start);
740eb82ff87SDaniel Beauregard 
741eb82ff87SDaniel Beauregard 	switch (size) {
742eb82ff87SDaniel Beauregard 	case 1:
743eb82ff87SDaniel Beauregard 		WRT_REG_BYTE(ha, addr, *(uint8_t *)data);
744eb82ff87SDaniel Beauregard 		break;
745eb82ff87SDaniel Beauregard 	case 2:
746eb82ff87SDaniel Beauregard 		WRT_REG_WORD(ha, addr, *(uint16_t *)data);
747eb82ff87SDaniel Beauregard 		break;
748eb82ff87SDaniel Beauregard 	case 4:
749eb82ff87SDaniel Beauregard 		WRT_REG_DWORD(ha, addr, *(uint32_t *)data);
750eb82ff87SDaniel Beauregard 		break;
751eb82ff87SDaniel Beauregard 	case 8:
752eb82ff87SDaniel Beauregard 		WRT_REG_DDWORD(ha, addr, *(uint64_t *)data);
753eb82ff87SDaniel Beauregard 		break;
754eb82ff87SDaniel Beauregard 	default:
755eb82ff87SDaniel Beauregard 		EL(ha, "invalid size=%x\n", size);
756eb82ff87SDaniel Beauregard 		ret = -1;
757eb82ff87SDaniel Beauregard 		break;
758eb82ff87SDaniel Beauregard 	}
759eb82ff87SDaniel Beauregard 
760eb82ff87SDaniel Beauregard 	return (ret);
761eb82ff87SDaniel Beauregard }
762eb82ff87SDaniel Beauregard 
763eb82ff87SDaniel Beauregard static int
ql_8021_pci_mem_read_2M(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)764eb82ff87SDaniel Beauregard ql_8021_pci_mem_read_2M(ql_adapter_state_t *ha, uint64_t off, void *data,
765eb82ff87SDaniel Beauregard     uint32_t size)
766eb82ff87SDaniel Beauregard {
767eb82ff87SDaniel Beauregard 	int		j = 0;
768eb82ff87SDaniel Beauregard 	uint32_t	i, temp, sz[2], loop, shift_amount;
769eb82ff87SDaniel Beauregard 	uint64_t	start, end, k;
770eb82ff87SDaniel Beauregard 	uint64_t	off8, off0[2], val, mem_crb, word[2] = {0, 0};
771eb82ff87SDaniel Beauregard 
772eb82ff87SDaniel Beauregard 	/*
773eb82ff87SDaniel Beauregard 	 * If not MN, go check for MS or invalid.
774eb82ff87SDaniel Beauregard 	 */
775eb82ff87SDaniel Beauregard 
776eb82ff87SDaniel Beauregard 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
777eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_QDR_NET;
778eb82ff87SDaniel Beauregard 	} else {
779eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_DDR_NET;
780eb82ff87SDaniel Beauregard 		if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) {
781eb82ff87SDaniel Beauregard 			return (ql_8021_pci_mem_read_direct(ha, off, data,
782eb82ff87SDaniel Beauregard 			    size));
783eb82ff87SDaniel Beauregard 		}
784eb82ff87SDaniel Beauregard 	}
785eb82ff87SDaniel Beauregard 
786eb82ff87SDaniel Beauregard 	if (NX_IS_REVISION_P3PLUS(ha->rev_id)) {
787eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff0;
788eb82ff87SDaniel Beauregard 		off0[0] = off & 0xf;
789eb82ff87SDaniel Beauregard 		sz[0] = (uint32_t)(((uint64_t)size < (16 - off0[0])) ? size :
790eb82ff87SDaniel Beauregard 		    (16 - off0[0]));
791eb82ff87SDaniel Beauregard 		shift_amount = 4;
792eb82ff87SDaniel Beauregard 	} else {
793eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff8;
794eb82ff87SDaniel Beauregard 		off0[0] = off & 0x7;
795eb82ff87SDaniel Beauregard 		sz[0] = (uint32_t)(((uint64_t)size < (8 - off0[0])) ? size :
796eb82ff87SDaniel Beauregard 		    (8 - off0[0]));
797eb82ff87SDaniel Beauregard 		shift_amount = 3;
798eb82ff87SDaniel Beauregard 	}
799eb82ff87SDaniel Beauregard 	loop = (uint32_t)(((off0[0] + size - 1) >> shift_amount) + 1);
800eb82ff87SDaniel Beauregard 	off0[1] = 0;
801eb82ff87SDaniel Beauregard 	sz[1] = size - sz[0];
802eb82ff87SDaniel Beauregard 
803eb82ff87SDaniel Beauregard 	/*
804eb82ff87SDaniel Beauregard 	 * don't lock here - write_wx gets the lock if each time
805eb82ff87SDaniel Beauregard 	 * write_lock_irqsave(&adapter->adapter_lock, flags);
806eb82ff87SDaniel Beauregard 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
807eb82ff87SDaniel Beauregard 	 */
808eb82ff87SDaniel Beauregard 
809eb82ff87SDaniel Beauregard 	for (i = 0; i < loop; i++) {
810eb82ff87SDaniel Beauregard 		temp = (uint32_t)(off8 + (i << shift_amount));
811eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
812eb82ff87SDaniel Beauregard 		temp = 0;
813eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
814eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_ENABLE;
815eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
816eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
817eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
818eb82ff87SDaniel Beauregard 
819eb82ff87SDaniel Beauregard 		for (j = 0; j < MAX_CTL_CHECK; j++) {
820eb82ff87SDaniel Beauregard 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp);
821eb82ff87SDaniel Beauregard 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
822eb82ff87SDaniel Beauregard 				break;
823eb82ff87SDaniel Beauregard 			}
824eb82ff87SDaniel Beauregard 		}
825eb82ff87SDaniel Beauregard 
826eb82ff87SDaniel Beauregard 		if (j >= MAX_CTL_CHECK) {
827eb82ff87SDaniel Beauregard 			EL(ha, "failed to read through agent\n");
828eb82ff87SDaniel Beauregard 			break;
829eb82ff87SDaniel Beauregard 		}
830eb82ff87SDaniel Beauregard 
831eb82ff87SDaniel Beauregard 		start = off0[i] >> 2;
832eb82ff87SDaniel Beauregard 		end = (off0[i] + sz[i] - 1) >> 2;
833eb82ff87SDaniel Beauregard 		for (k = start; k <= end; k++) {
834eb82ff87SDaniel Beauregard 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_RDDATA(k),
835eb82ff87SDaniel Beauregard 			    &temp);
836eb82ff87SDaniel Beauregard 			word[i] |= ((uint64_t)temp << (32 * (k & 1)));
837eb82ff87SDaniel Beauregard 		}
838eb82ff87SDaniel Beauregard 	}
839eb82ff87SDaniel Beauregard 
840eb82ff87SDaniel Beauregard 	/*
841eb82ff87SDaniel Beauregard 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
842eb82ff87SDaniel Beauregard 	 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
843eb82ff87SDaniel Beauregard 	 */
844eb82ff87SDaniel Beauregard 
845eb82ff87SDaniel Beauregard 	if (j >= MAX_CTL_CHECK) {
846eb82ff87SDaniel Beauregard 		return (-1);
847eb82ff87SDaniel Beauregard 	}
848eb82ff87SDaniel Beauregard 
849eb82ff87SDaniel Beauregard 	if ((off0[0] & 7) == 0) {
850eb82ff87SDaniel Beauregard 		val = word[0];
851eb82ff87SDaniel Beauregard 	} else {
852eb82ff87SDaniel Beauregard 		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
853eb82ff87SDaniel Beauregard 		    ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
854eb82ff87SDaniel Beauregard 	}
855eb82ff87SDaniel Beauregard 
856eb82ff87SDaniel Beauregard 	switch (size) {
857eb82ff87SDaniel Beauregard 	case 1:
858eb82ff87SDaniel Beauregard 		*(uint8_t *)data = (uint8_t)val;
859eb82ff87SDaniel Beauregard 		break;
860eb82ff87SDaniel Beauregard 	case 2:
861eb82ff87SDaniel Beauregard 		*(uint16_t *)data = (uint16_t)val;
862eb82ff87SDaniel Beauregard 		break;
863eb82ff87SDaniel Beauregard 	case 4:
864eb82ff87SDaniel Beauregard 		*(uint32_t *)data = (uint32_t)val;
865eb82ff87SDaniel Beauregard 		break;
866eb82ff87SDaniel Beauregard 	case 8:
867eb82ff87SDaniel Beauregard 		*(uint64_t *)data = val;
868eb82ff87SDaniel Beauregard 		break;
869eb82ff87SDaniel Beauregard 	}
870eb82ff87SDaniel Beauregard 
871eb82ff87SDaniel Beauregard 	return (0);
872eb82ff87SDaniel Beauregard }
873eb82ff87SDaniel Beauregard 
874eb82ff87SDaniel Beauregard static int
ql_8021_pci_mem_write_2M(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)875eb82ff87SDaniel Beauregard ql_8021_pci_mem_write_2M(ql_adapter_state_t *ha, uint64_t off, void *data,
876eb82ff87SDaniel Beauregard     uint32_t size)
877eb82ff87SDaniel Beauregard {
878eb82ff87SDaniel Beauregard 	int		j, ret = 0;
879eb82ff87SDaniel Beauregard 	uint32_t	i, temp, loop, sz[2];
880eb82ff87SDaniel Beauregard 	uint32_t	scale, shift_amount, p3p, startword;
881eb82ff87SDaniel Beauregard 	uint64_t	off8, off0, mem_crb, tmpw, word[2] = {0, 0};
882eb82ff87SDaniel Beauregard 
883eb82ff87SDaniel Beauregard 	/*
884eb82ff87SDaniel Beauregard 	 * If not MN, go check for MS or invalid.
885eb82ff87SDaniel Beauregard 	 */
886eb82ff87SDaniel Beauregard 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
887eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_QDR_NET;
888eb82ff87SDaniel Beauregard 	} else {
889eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_DDR_NET;
890eb82ff87SDaniel Beauregard 		if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) {
891eb82ff87SDaniel Beauregard 			return (ql_8021_pci_mem_write_direct(ha, off, data,
892eb82ff87SDaniel Beauregard 			    size));
893eb82ff87SDaniel Beauregard 		}
894eb82ff87SDaniel Beauregard 	}
895eb82ff87SDaniel Beauregard 
896eb82ff87SDaniel Beauregard 	off0 = off & 0x7;
897eb82ff87SDaniel Beauregard 	sz[0] = (uint32_t)(((uint64_t)size < (8 - off0)) ? size : (8 - off0));
898eb82ff87SDaniel Beauregard 	sz[1] = size - sz[0];
899eb82ff87SDaniel Beauregard 
900eb82ff87SDaniel Beauregard 	if (NX_IS_REVISION_P3PLUS(ha->rev_id)) {
901eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff0;
902eb82ff87SDaniel Beauregard 		loop = (uint32_t)((((off & 0xf) + size - 1) >> 4) + 1);
903eb82ff87SDaniel Beauregard 		shift_amount = 4;
904eb82ff87SDaniel Beauregard 		scale = 2;
905eb82ff87SDaniel Beauregard 		p3p = 1;
906eb82ff87SDaniel Beauregard 		startword = (uint32_t)((off & 0xf) / 8);
907eb82ff87SDaniel Beauregard 	} else {
908eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff8;
909eb82ff87SDaniel Beauregard 		loop = (uint32_t)(((off0 + size - 1) >> 3) + 1);
910eb82ff87SDaniel Beauregard 		shift_amount = 3;
911eb82ff87SDaniel Beauregard 		scale = 1;
912eb82ff87SDaniel Beauregard 		p3p = 0;
913eb82ff87SDaniel Beauregard 		startword = 0;
914eb82ff87SDaniel Beauregard 	}
915eb82ff87SDaniel Beauregard 
916eb82ff87SDaniel Beauregard 	if (p3p || (size != 8) || (off0 != 0)) {
917eb82ff87SDaniel Beauregard 		for (i = 0; i < loop; i++) {
918eb82ff87SDaniel Beauregard 			if (ql_8021_pci_mem_read_2M(ha, off8 +
919eb82ff87SDaniel Beauregard 			    (i << shift_amount), &word[i * scale], 8)) {
920eb82ff87SDaniel Beauregard 				EL(ha, "8021_pci_mem_read_2M != 0\n");
921eb82ff87SDaniel Beauregard 				return (-1);
922eb82ff87SDaniel Beauregard 			}
923eb82ff87SDaniel Beauregard 		}
924eb82ff87SDaniel Beauregard 	}
925eb82ff87SDaniel Beauregard 
926eb82ff87SDaniel Beauregard 	switch (size) {
927eb82ff87SDaniel Beauregard 	case 1:
928eb82ff87SDaniel Beauregard 		tmpw = (uint64_t)(*((uint8_t *)data));
929eb82ff87SDaniel Beauregard 		break;
930eb82ff87SDaniel Beauregard 	case 2:
931eb82ff87SDaniel Beauregard 		tmpw = (uint64_t)(*((uint16_t *)data));
932eb82ff87SDaniel Beauregard 		break;
933eb82ff87SDaniel Beauregard 	case 4:
934eb82ff87SDaniel Beauregard 		tmpw = (uint64_t)(*((uint32_t *)data));
935eb82ff87SDaniel Beauregard 		break;
936eb82ff87SDaniel Beauregard 	case 8:
937eb82ff87SDaniel Beauregard 	default:
938eb82ff87SDaniel Beauregard 		tmpw = *((uint64_t *)data);
939eb82ff87SDaniel Beauregard 		break;
940eb82ff87SDaniel Beauregard 	}
941eb82ff87SDaniel Beauregard 
942eb82ff87SDaniel Beauregard 	if (p3p) {
943eb82ff87SDaniel Beauregard 		if (sz[0] == 8) {
944eb82ff87SDaniel Beauregard 			word[startword] = tmpw;
945eb82ff87SDaniel Beauregard 		} else {
946eb82ff87SDaniel Beauregard 			word[startword] &= ~((~(~0ULL << (sz[0] * 8))) <<
947eb82ff87SDaniel Beauregard 			    (off0 * 8));
948eb82ff87SDaniel Beauregard 			word[startword] |= tmpw << (off0 * 8);
949eb82ff87SDaniel Beauregard 		}
950eb82ff87SDaniel Beauregard 		if (sz[1] != 0) {
951*4c3888b8SHans Rosenfeld 			word[startword + 1] &= ~(~0ULL << (sz[1] * 8));
952*4c3888b8SHans Rosenfeld 			word[startword + 1] |= tmpw >> (sz[0] * 8);
953eb82ff87SDaniel Beauregard 		}
954eb82ff87SDaniel Beauregard 	} else {
955eb82ff87SDaniel Beauregard 		word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
956eb82ff87SDaniel Beauregard 		word[startword] |= tmpw << (off0 * 8);
957eb82ff87SDaniel Beauregard 
958eb82ff87SDaniel Beauregard 		if (loop == 2) {
959eb82ff87SDaniel Beauregard 			word[1] &= ~(~0ULL << (sz[1] * 8));
960eb82ff87SDaniel Beauregard 			word[1] |= tmpw >> (sz[0] * 8);
961eb82ff87SDaniel Beauregard 		}
962eb82ff87SDaniel Beauregard 	}
963eb82ff87SDaniel Beauregard 
964eb82ff87SDaniel Beauregard 	/*
965eb82ff87SDaniel Beauregard 	 * don't lock here - write_wx gets the lock if each time
966eb82ff87SDaniel Beauregard 	 * write_lock_irqsave(&adapter->adapter_lock, flags);
967eb82ff87SDaniel Beauregard 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
968eb82ff87SDaniel Beauregard 	 */
969eb82ff87SDaniel Beauregard 
970eb82ff87SDaniel Beauregard 	for (i = 0; i < loop; i++) {
971eb82ff87SDaniel Beauregard 		temp = (uint32_t)(off8 + (i << shift_amount));
972eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
973eb82ff87SDaniel Beauregard 		temp = 0;
974eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
975eb82ff87SDaniel Beauregard 		temp = (uint32_t)(word[i * scale] & 0xffffffff);
976eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_LO, temp);
977eb82ff87SDaniel Beauregard 		temp = (uint32_t)((word[i * scale] >> 32) & 0xffffffff);
978eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_HI, temp);
979eb82ff87SDaniel Beauregard 		if (p3p) {
980eb82ff87SDaniel Beauregard 			temp = (uint32_t)(word[i * scale + 1] & 0xffffffff);
981eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha,
982eb82ff87SDaniel Beauregard 			    mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
983eb82ff87SDaniel Beauregard 			temp = (uint32_t)((word[i * scale + 1] >> 32) &
984eb82ff87SDaniel Beauregard 			    0xffffffff);
985eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha,
986eb82ff87SDaniel Beauregard 			    mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
987eb82ff87SDaniel Beauregard 		}
988eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
989eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
990eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
991eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
992eb82ff87SDaniel Beauregard 
993eb82ff87SDaniel Beauregard 		for (j = 0; j < MAX_CTL_CHECK; j++) {
994eb82ff87SDaniel Beauregard 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp);
995eb82ff87SDaniel Beauregard 			if ((temp & MIU_TA_CTL_BUSY) == 0)
996eb82ff87SDaniel Beauregard 				break;
997eb82ff87SDaniel Beauregard 		}
998eb82ff87SDaniel Beauregard 
999eb82ff87SDaniel Beauregard 		if (j >= MAX_CTL_CHECK) {
1000eb82ff87SDaniel Beauregard 			EL(ha, "failed to write through agent\n");
1001eb82ff87SDaniel Beauregard 			ret = -1;
1002eb82ff87SDaniel Beauregard 			break;
1003eb82ff87SDaniel Beauregard 		}
1004eb82ff87SDaniel Beauregard 	}
1005eb82ff87SDaniel Beauregard 
1006eb82ff87SDaniel Beauregard 	return (ret);
1007eb82ff87SDaniel Beauregard }
1008eb82ff87SDaniel Beauregard 
1009eb82ff87SDaniel Beauregard static uint32_t
ql_8021_decode_crb_addr(ql_adapter_state_t * ha,uint32_t addr)1010eb82ff87SDaniel Beauregard ql_8021_decode_crb_addr(ql_adapter_state_t *ha, uint32_t addr)
1011eb82ff87SDaniel Beauregard {
1012eb82ff87SDaniel Beauregard 	int		i;
1013eb82ff87SDaniel Beauregard 	uint32_t	base_addr, offset, pci_base;
1014eb82ff87SDaniel Beauregard 
1015eb82ff87SDaniel Beauregard 	if (!crb_table_initialized) {
1016eb82ff87SDaniel Beauregard 		ql_crb_addr_transform_setup(ha);
1017eb82ff87SDaniel Beauregard 	}
1018eb82ff87SDaniel Beauregard 
1019eb82ff87SDaniel Beauregard 	pci_base = ADDR_ERROR;
1020eb82ff87SDaniel Beauregard 	base_addr = addr & 0xfff00000;
1021eb82ff87SDaniel Beauregard 	offset = addr & 0x000fffff;
1022eb82ff87SDaniel Beauregard 
1023eb82ff87SDaniel Beauregard 	for (i = 0; i < MAX_CRB_XFORM; i++) {
1024eb82ff87SDaniel Beauregard 		if (crb_addr_xform[i] == base_addr) {
1025eb82ff87SDaniel Beauregard 			pci_base = i << 20;
1026eb82ff87SDaniel Beauregard 			break;
1027eb82ff87SDaniel Beauregard 		}
1028eb82ff87SDaniel Beauregard 	}
1029eb82ff87SDaniel Beauregard 	if (pci_base == ADDR_ERROR) {
1030eb82ff87SDaniel Beauregard 		return (pci_base);
1031eb82ff87SDaniel Beauregard 	} else {
1032eb82ff87SDaniel Beauregard 		return (pci_base + offset);
1033eb82ff87SDaniel Beauregard 	}
1034eb82ff87SDaniel Beauregard }
1035eb82ff87SDaniel Beauregard 
1036eb82ff87SDaniel Beauregard static int
ql_8021_hw_lock(ql_adapter_state_t * ha,uint32_t timer)1037eb82ff87SDaniel Beauregard ql_8021_hw_lock(ql_adapter_state_t *ha, uint32_t timer)
1038eb82ff87SDaniel Beauregard {
1039eb82ff87SDaniel Beauregard 	uint32_t	done = 0, timeout = 0;
1040eb82ff87SDaniel Beauregard 
1041eb82ff87SDaniel Beauregard 	while (!done) {
1042eb82ff87SDaniel Beauregard 		/* acquire semaphore5 from PCI HW block */
1043eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_LOCK), &done);
1044eb82ff87SDaniel Beauregard 		if (done == 1) {
1045eb82ff87SDaniel Beauregard 			break;
1046eb82ff87SDaniel Beauregard 		}
1047eb82ff87SDaniel Beauregard 		if (timeout >= timer) {
1048eb82ff87SDaniel Beauregard 			EL(ha, "timeout\n");
1049eb82ff87SDaniel Beauregard 			return (-1);
1050eb82ff87SDaniel Beauregard 		}
1051eb82ff87SDaniel Beauregard 		timeout++;
1052eb82ff87SDaniel Beauregard 
1053eb82ff87SDaniel Beauregard 		/*
1054eb82ff87SDaniel Beauregard 		 * Yield CPU
1055eb82ff87SDaniel Beauregard 		 */
1056eb82ff87SDaniel Beauregard 		delay(1);
1057eb82ff87SDaniel Beauregard 	}
1058eb82ff87SDaniel Beauregard 
1059eb82ff87SDaniel Beauregard 	return (0);
1060eb82ff87SDaniel Beauregard }
1061eb82ff87SDaniel Beauregard 
1062eb82ff87SDaniel Beauregard static void
ql_8021_hw_unlock(ql_adapter_state_t * ha)1063eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ql_adapter_state_t *ha)
1064eb82ff87SDaniel Beauregard {
1065eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_UNLOCK), NULL);
1066eb82ff87SDaniel Beauregard }
1067eb82ff87SDaniel Beauregard 
1068eb82ff87SDaniel Beauregard static int
ql_8021_rom_lock(ql_adapter_state_t * ha)1069eb82ff87SDaniel Beauregard ql_8021_rom_lock(ql_adapter_state_t *ha)
1070eb82ff87SDaniel Beauregard {
1071eb82ff87SDaniel Beauregard 	uint32_t	done = 0, timeout = 0;
1072eb82ff87SDaniel Beauregard 
1073eb82ff87SDaniel Beauregard 	while (!done) {
1074eb82ff87SDaniel Beauregard 		/* acquire semaphore2 from PCI HW block */
1075eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done);
1076eb82ff87SDaniel Beauregard 		if (done == 1) {
1077eb82ff87SDaniel Beauregard 			break;
1078eb82ff87SDaniel Beauregard 		}
1079eb82ff87SDaniel Beauregard 		if (timeout >= ROM_LOCK_TIMEOUT) {
1080eb82ff87SDaniel Beauregard 			EL(ha, "timeout\n");
1081eb82ff87SDaniel Beauregard 			return (-1);
1082eb82ff87SDaniel Beauregard 		}
1083eb82ff87SDaniel Beauregard 		timeout++;
1084eb82ff87SDaniel Beauregard 
1085eb82ff87SDaniel Beauregard 		/*
1086eb82ff87SDaniel Beauregard 		 * Yield CPU
1087eb82ff87SDaniel Beauregard 		 */
1088eb82ff87SDaniel Beauregard 		delay(1);
1089eb82ff87SDaniel Beauregard 	}
1090eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER);
1091eb82ff87SDaniel Beauregard 
1092eb82ff87SDaniel Beauregard 	return (0);
1093eb82ff87SDaniel Beauregard }
1094eb82ff87SDaniel Beauregard 
1095eb82ff87SDaniel Beauregard static void
ql_8021_rom_unlock(ql_adapter_state_t * ha)1096eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ql_adapter_state_t *ha)
1097eb82ff87SDaniel Beauregard {
1098eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), NULL);
1099eb82ff87SDaniel Beauregard }
1100eb82ff87SDaniel Beauregard 
1101eb82ff87SDaniel Beauregard static int
ql_8021_wait_rom_done(ql_adapter_state_t * ha)1102eb82ff87SDaniel Beauregard ql_8021_wait_rom_done(ql_adapter_state_t *ha)
1103eb82ff87SDaniel Beauregard {
1104eb82ff87SDaniel Beauregard 	uint32_t	timeout = 0, done = 0;
1105eb82ff87SDaniel Beauregard 
1106eb82ff87SDaniel Beauregard 	while (done == 0) {
1107eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_ROMUSB_GLB_STATUS, &done);
1108eb82ff87SDaniel Beauregard 		done &= 2;
1109eb82ff87SDaniel Beauregard 		timeout++;
1110eb82ff87SDaniel Beauregard 		if (timeout >= ROM_MAX_TIMEOUT) {
1111eb82ff87SDaniel Beauregard 			EL(ha, "Timeout reached waiting for rom done\n");
1112eb82ff87SDaniel Beauregard 			return (-1);
1113eb82ff87SDaniel Beauregard 		}
1114eb82ff87SDaniel Beauregard 	}
1115eb82ff87SDaniel Beauregard 
1116eb82ff87SDaniel Beauregard 	return (0);
1117eb82ff87SDaniel Beauregard }
1118eb82ff87SDaniel Beauregard 
1119eb82ff87SDaniel Beauregard static int
ql_8021_wait_flash_done(ql_adapter_state_t * ha)1120eb82ff87SDaniel Beauregard ql_8021_wait_flash_done(ql_adapter_state_t *ha)
1121eb82ff87SDaniel Beauregard {
1122eb82ff87SDaniel Beauregard 	clock_t		timer;
1123eb82ff87SDaniel Beauregard 	uint32_t	status;
1124eb82ff87SDaniel Beauregard 
1125*4c3888b8SHans Rosenfeld 	for (timer = 500000; timer; timer--) {
1126eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1127eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1128eb82ff87SDaniel Beauregard 		    UNM_ROMUSB_ROM_RDSR_INSTR);
1129eb82ff87SDaniel Beauregard 		if (ql_8021_wait_rom_done(ha)) {
1130eb82ff87SDaniel Beauregard 			EL(ha, "Error waiting for rom done2\n");
1131eb82ff87SDaniel Beauregard 			return (-1);
1132eb82ff87SDaniel Beauregard 		}
1133eb82ff87SDaniel Beauregard 
1134eb82ff87SDaniel Beauregard 		/* Get status. */
1135eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, &status);
1136eb82ff87SDaniel Beauregard 		if (!(status & BIT_0)) {
1137eb82ff87SDaniel Beauregard 			return (0);
1138eb82ff87SDaniel Beauregard 		}
1139*4c3888b8SHans Rosenfeld 		drv_usecwait(10);
1140eb82ff87SDaniel Beauregard 	}
1141eb82ff87SDaniel Beauregard 
1142eb82ff87SDaniel Beauregard 	EL(ha, "timeout status=%x\n", status);
1143eb82ff87SDaniel Beauregard 	return (-1);
1144eb82ff87SDaniel Beauregard }
1145eb82ff87SDaniel Beauregard 
1146eb82ff87SDaniel Beauregard static int
ql_8021_do_rom_fast_read(ql_adapter_state_t * ha,uint32_t addr,uint32_t * valp)1147eb82ff87SDaniel Beauregard ql_8021_do_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
1148eb82ff87SDaniel Beauregard {
1149eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
1150eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
1151eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
1152eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1153eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_FAST_RD_INSTR);
1154eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1155eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done\n");
1156eb82ff87SDaniel Beauregard 		return (-1);
1157eb82ff87SDaniel Beauregard 	}
1158eb82ff87SDaniel Beauregard 	/* reset abyte_cnt and dummy_byte_cnt */
1159eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
1160eb82ff87SDaniel Beauregard 	drv_usecwait(10);
1161eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1162eb82ff87SDaniel Beauregard 
1163eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, valp);
1164eb82ff87SDaniel Beauregard 
1165eb82ff87SDaniel Beauregard 	return (0);
1166eb82ff87SDaniel Beauregard }
1167eb82ff87SDaniel Beauregard 
1168eb82ff87SDaniel Beauregard int
ql_8021_rom_fast_read(ql_adapter_state_t * ha,uint32_t addr,uint32_t * valp)1169eb82ff87SDaniel Beauregard ql_8021_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
1170eb82ff87SDaniel Beauregard {
1171eb82ff87SDaniel Beauregard 	int	ret, loops = 0;
1172eb82ff87SDaniel Beauregard 
1173*4c3888b8SHans Rosenfeld 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
1174*4c3888b8SHans Rosenfeld 		drv_usecwait(10);
1175eb82ff87SDaniel Beauregard 		loops++;
1176eb82ff87SDaniel Beauregard 	}
1177eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1178eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1179eb82ff87SDaniel Beauregard 		return (-1);
1180eb82ff87SDaniel Beauregard 	}
1181eb82ff87SDaniel Beauregard 	ret = ql_8021_do_rom_fast_read(ha, addr, valp);
1182eb82ff87SDaniel Beauregard 	ql_8021_rom_unlock(ha);
1183eb82ff87SDaniel Beauregard 
1184eb82ff87SDaniel Beauregard 	return (ret);
1185eb82ff87SDaniel Beauregard }
1186eb82ff87SDaniel Beauregard 
1187eb82ff87SDaniel Beauregard static int
ql_8021_do_rom_write(ql_adapter_state_t * ha,uint32_t addr,uint32_t data)1188eb82ff87SDaniel Beauregard ql_8021_do_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
1189eb82ff87SDaniel Beauregard {
1190eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1191eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1192eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_WREN_INSTR);
1193eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1194eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done\n");
1195eb82ff87SDaniel Beauregard 		return (-1);
1196eb82ff87SDaniel Beauregard 	}
1197eb82ff87SDaniel Beauregard 
1198eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data);
1199eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
1200eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
1201eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1202eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_PP_INSTR);
1203eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1204eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done1\n");
1205eb82ff87SDaniel Beauregard 		return (-1);
1206eb82ff87SDaniel Beauregard 	}
1207eb82ff87SDaniel Beauregard 
1208eb82ff87SDaniel Beauregard 	if (ql_8021_wait_flash_done(ha)) {
1209eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for flash done\n");
1210eb82ff87SDaniel Beauregard 		return (-1);
1211eb82ff87SDaniel Beauregard 	}
1212eb82ff87SDaniel Beauregard 
1213eb82ff87SDaniel Beauregard 	return (0);
1214eb82ff87SDaniel Beauregard }
1215eb82ff87SDaniel Beauregard 
1216eb82ff87SDaniel Beauregard static int
ql_8021_do_rom_erase(ql_adapter_state_t * ha,uint32_t addr)1217eb82ff87SDaniel Beauregard ql_8021_do_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
1218eb82ff87SDaniel Beauregard {
1219eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1220eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1221eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_WREN_INSTR);
1222eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1223eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done\n");
1224eb82ff87SDaniel Beauregard 		return (-1);
1225eb82ff87SDaniel Beauregard 	}
1226eb82ff87SDaniel Beauregard 
1227eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
1228eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
1229eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1230eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_SE_INSTR);
1231eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1232eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done1\n");
1233eb82ff87SDaniel Beauregard 		return (-1);
1234eb82ff87SDaniel Beauregard 	}
1235eb82ff87SDaniel Beauregard 
1236eb82ff87SDaniel Beauregard 	if (ql_8021_wait_flash_done(ha)) {
1237eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for flash done\n");
1238eb82ff87SDaniel Beauregard 		return (-1);
1239eb82ff87SDaniel Beauregard 	}
1240eb82ff87SDaniel Beauregard 
1241eb82ff87SDaniel Beauregard 	return (0);
1242eb82ff87SDaniel Beauregard }
1243eb82ff87SDaniel Beauregard 
1244eb82ff87SDaniel Beauregard int
ql_8021_rom_read(ql_adapter_state_t * ha,uint32_t addr,uint32_t * bp)1245eb82ff87SDaniel Beauregard ql_8021_rom_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *bp)
1246eb82ff87SDaniel Beauregard {
1247eb82ff87SDaniel Beauregard 	int	ret;
1248eb82ff87SDaniel Beauregard 
1249eb82ff87SDaniel Beauregard 	ret = ql_8021_rom_fast_read(ha, addr << 2, bp) == 0 ? QL_SUCCESS :
1250eb82ff87SDaniel Beauregard 	    QL_FUNCTION_FAILED;
1251eb82ff87SDaniel Beauregard 
1252eb82ff87SDaniel Beauregard 	return (ret);
1253eb82ff87SDaniel Beauregard }
1254eb82ff87SDaniel Beauregard 
1255eb82ff87SDaniel Beauregard int
ql_8021_rom_write(ql_adapter_state_t * ha,uint32_t addr,uint32_t data)1256eb82ff87SDaniel Beauregard ql_8021_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
1257eb82ff87SDaniel Beauregard {
1258eb82ff87SDaniel Beauregard 	int	ret, loops = 0;
1259eb82ff87SDaniel Beauregard 
1260*4c3888b8SHans Rosenfeld 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
1261*4c3888b8SHans Rosenfeld 		drv_usecwait(10);
1262eb82ff87SDaniel Beauregard 		loops++;
1263eb82ff87SDaniel Beauregard 	}
1264eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1265eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1266eb82ff87SDaniel Beauregard 		ret = QL_FUNCTION_TIMEOUT;
1267eb82ff87SDaniel Beauregard 	} else {
1268eb82ff87SDaniel Beauregard 		ret = ql_8021_do_rom_write(ha, addr << 2, data) == 0 ?
1269eb82ff87SDaniel Beauregard 		    QL_SUCCESS : QL_FUNCTION_FAILED;
1270eb82ff87SDaniel Beauregard 		ql_8021_rom_unlock(ha);
1271eb82ff87SDaniel Beauregard 	}
1272eb82ff87SDaniel Beauregard 
1273eb82ff87SDaniel Beauregard 	return (ret);
1274eb82ff87SDaniel Beauregard }
1275eb82ff87SDaniel Beauregard 
1276eb82ff87SDaniel Beauregard int
ql_8021_rom_erase(ql_adapter_state_t * ha,uint32_t addr)1277eb82ff87SDaniel Beauregard ql_8021_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
1278eb82ff87SDaniel Beauregard {
1279eb82ff87SDaniel Beauregard 	int	ret, loops = 0;
1280eb82ff87SDaniel Beauregard 
1281*4c3888b8SHans Rosenfeld 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
1282*4c3888b8SHans Rosenfeld 		drv_usecwait(10);
1283eb82ff87SDaniel Beauregard 		loops++;
1284eb82ff87SDaniel Beauregard 	}
1285eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1286eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1287eb82ff87SDaniel Beauregard 		ret = QL_FUNCTION_TIMEOUT;
1288eb82ff87SDaniel Beauregard 	} else {
1289eb82ff87SDaniel Beauregard 		ret = ql_8021_do_rom_erase(ha, addr << 2) == 0 ? QL_SUCCESS :
1290eb82ff87SDaniel Beauregard 		    QL_FUNCTION_FAILED;
1291eb82ff87SDaniel Beauregard 		ql_8021_rom_unlock(ha);
1292eb82ff87SDaniel Beauregard 	}
1293eb82ff87SDaniel Beauregard 
1294eb82ff87SDaniel Beauregard 	return (ret);
1295eb82ff87SDaniel Beauregard }
1296eb82ff87SDaniel Beauregard 
1297eb82ff87SDaniel Beauregard int
ql_8021_rom_wrsr(ql_adapter_state_t * ha,uint32_t data)1298eb82ff87SDaniel Beauregard ql_8021_rom_wrsr(ql_adapter_state_t *ha, uint32_t data)
1299eb82ff87SDaniel Beauregard {
1300eb82ff87SDaniel Beauregard 	int	ret = QL_SUCCESS, loops = 0;
1301eb82ff87SDaniel Beauregard 
1302*4c3888b8SHans Rosenfeld 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
1303*4c3888b8SHans Rosenfeld 		drv_usecwait(10);
1304eb82ff87SDaniel Beauregard 		loops++;
1305eb82ff87SDaniel Beauregard 	}
1306eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1307eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1308eb82ff87SDaniel Beauregard 		ret = QL_FUNCTION_TIMEOUT;
1309eb82ff87SDaniel Beauregard 	} else {
1310eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1311eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1312eb82ff87SDaniel Beauregard 		    UNM_ROMUSB_ROM_WREN_INSTR);
1313eb82ff87SDaniel Beauregard 		if (ql_8021_wait_rom_done(ha)) {
1314eb82ff87SDaniel Beauregard 			EL(ha, "Error waiting for rom done\n");
1315eb82ff87SDaniel Beauregard 			ret = QL_FUNCTION_FAILED;
1316eb82ff87SDaniel Beauregard 		} else {
1317eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data);
1318eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1319eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1320eb82ff87SDaniel Beauregard 			    UNM_ROMUSB_ROM_WRSR_INSTR);
1321eb82ff87SDaniel Beauregard 			if (ql_8021_wait_rom_done(ha)) {
1322eb82ff87SDaniel Beauregard 				EL(ha, "Error waiting for rom done1\n");
1323eb82ff87SDaniel Beauregard 				ret = QL_FUNCTION_FAILED;
1324eb82ff87SDaniel Beauregard 			} else if (ql_8021_wait_flash_done(ha)) {
1325eb82ff87SDaniel Beauregard 				EL(ha, "Error waiting for flash done\n");
1326eb82ff87SDaniel Beauregard 				ret = QL_FUNCTION_FAILED;
1327eb82ff87SDaniel Beauregard 			}
1328eb82ff87SDaniel Beauregard 		}
1329eb82ff87SDaniel Beauregard 		ql_8021_rom_unlock(ha);
1330eb82ff87SDaniel Beauregard 	}
1331eb82ff87SDaniel Beauregard 
1332eb82ff87SDaniel Beauregard 	return (ret);
1333eb82ff87SDaniel Beauregard }
1334eb82ff87SDaniel Beauregard 
1335eb82ff87SDaniel Beauregard static int
ql_8021_phantom_init(ql_adapter_state_t * ha)1336eb82ff87SDaniel Beauregard ql_8021_phantom_init(ql_adapter_state_t *ha)
1337eb82ff87SDaniel Beauregard {
1338eb82ff87SDaniel Beauregard 	uint32_t	val = 0, err = 0;
1339eb82ff87SDaniel Beauregard 	int		retries = 60;
1340eb82ff87SDaniel Beauregard 
1341eb82ff87SDaniel Beauregard 	do {
1342eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_CMDPEG_STATE, &val);
1343eb82ff87SDaniel Beauregard 
1344eb82ff87SDaniel Beauregard 		switch (val) {
1345eb82ff87SDaniel Beauregard 		case PHAN_INITIALIZE_COMPLETE:
1346eb82ff87SDaniel Beauregard 		case PHAN_INITIALIZE_ACK:
1347eb82ff87SDaniel Beauregard 			EL(ha, "success=%xh\n", val);
1348eb82ff87SDaniel Beauregard 			return (0);
1349eb82ff87SDaniel Beauregard 		case PHAN_INITIALIZE_FAILED:
1350eb82ff87SDaniel Beauregard 			EL(ha, "PHAN_INITIALIZE_FAILED\n");
1351eb82ff87SDaniel Beauregard 			err = 1;
1352eb82ff87SDaniel Beauregard 			break;
1353eb82ff87SDaniel Beauregard 		default:
1354eb82ff87SDaniel Beauregard 			break;
1355eb82ff87SDaniel Beauregard 		}
1356eb82ff87SDaniel Beauregard 
1357eb82ff87SDaniel Beauregard 		if (err) {
1358eb82ff87SDaniel Beauregard 			break;
1359eb82ff87SDaniel Beauregard 		}
1360eb82ff87SDaniel Beauregard 		/* 500 msec wait */
1361eb82ff87SDaniel Beauregard 		delay(50);
1362eb82ff87SDaniel Beauregard 
1363eb82ff87SDaniel Beauregard 	} while (--retries);
1364eb82ff87SDaniel Beauregard 
1365eb82ff87SDaniel Beauregard 	if (!err) {
1366eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
1367eb82ff87SDaniel Beauregard 	}
1368eb82ff87SDaniel Beauregard 
1369eb82ff87SDaniel Beauregard 	EL(ha, "firmware init failed=%x\n", val);
1370eb82ff87SDaniel Beauregard 	return (-1);
1371eb82ff87SDaniel Beauregard }
1372eb82ff87SDaniel Beauregard 
1373eb82ff87SDaniel Beauregard static int
ql_8021_pinit_from_rom(ql_adapter_state_t * ha)1374eb82ff87SDaniel Beauregard ql_8021_pinit_from_rom(ql_adapter_state_t *ha)
1375eb82ff87SDaniel Beauregard {
1376eb82ff87SDaniel Beauregard 	int			init_delay = 0;
1377eb82ff87SDaniel Beauregard 	struct crb_addr_pair	*buf;
1378eb82ff87SDaniel Beauregard 	uint32_t		offset, off, i, n, addr, val;
1379eb82ff87SDaniel Beauregard 
1380eb82ff87SDaniel Beauregard 	/* Grab the lock so that no one can read flash when we reset the chip */
1381eb82ff87SDaniel Beauregard 	(void) ql_8021_rom_lock(ha);
1382eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0xffffffff);
1383eb82ff87SDaniel Beauregard 	/* Just in case it was held when we reset the chip */
1384eb82ff87SDaniel Beauregard 	ql_8021_rom_unlock(ha);
1385*4c3888b8SHans Rosenfeld 	delay(100);
1386eb82ff87SDaniel Beauregard 
1387eb82ff87SDaniel Beauregard 	if (ql_8021_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafe ||
1388eb82ff87SDaniel Beauregard 	    ql_8021_rom_fast_read(ha, 4, &n) != 0) {
1389eb82ff87SDaniel Beauregard 		EL(ha, "ERROR Reading crb_init area: n: %08x\n", n);
1390eb82ff87SDaniel Beauregard 		return (-1);
1391eb82ff87SDaniel Beauregard 	}
1392eb82ff87SDaniel Beauregard 	offset = n & 0xffff;
1393eb82ff87SDaniel Beauregard 	n = (n >> 16) & 0xffff;
1394eb82ff87SDaniel Beauregard 	if (n >= 1024) {
1395eb82ff87SDaniel Beauregard 		EL(ha, "n=0x%x Error! NetXen card flash not initialized\n", n);
1396eb82ff87SDaniel Beauregard 		return (-1);
1397eb82ff87SDaniel Beauregard 	}
1398eb82ff87SDaniel Beauregard 
1399eb82ff87SDaniel Beauregard 	buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP);
1400eb82ff87SDaniel Beauregard 	if (buf == NULL) {
1401eb82ff87SDaniel Beauregard 		EL(ha, "Unable to zalloc memory\n");
1402eb82ff87SDaniel Beauregard 		return (-1);
1403eb82ff87SDaniel Beauregard 	}
1404eb82ff87SDaniel Beauregard 
1405eb82ff87SDaniel Beauregard 	for (i = 0; i < n; i++) {
1406eb82ff87SDaniel Beauregard 		if (ql_8021_rom_fast_read(ha, 8 * i + 4 * offset, &val) != 0 ||
1407eb82ff87SDaniel Beauregard 		    ql_8021_rom_fast_read(ha, 8 * i + 4 * offset + 4, &addr) !=
1408eb82ff87SDaniel Beauregard 		    0) {
1409eb82ff87SDaniel Beauregard 			kmem_free(buf, n * sizeof (struct crb_addr_pair));
1410eb82ff87SDaniel Beauregard 			EL(ha, "ql_8021_rom_fast_read != 0 to zalloc memory\n");
1411eb82ff87SDaniel Beauregard 			return (-1);
1412eb82ff87SDaniel Beauregard 		}
1413eb82ff87SDaniel Beauregard 
1414eb82ff87SDaniel Beauregard 		buf[i].addr = addr;
1415eb82ff87SDaniel Beauregard 		buf[i].data = val;
1416eb82ff87SDaniel Beauregard 	}
1417eb82ff87SDaniel Beauregard 
1418eb82ff87SDaniel Beauregard 	for (i = 0; i < n; i++) {
1419eb82ff87SDaniel Beauregard 		off = ql_8021_decode_crb_addr(ha, buf[i].addr);
1420eb82ff87SDaniel Beauregard 		if (off == ADDR_ERROR) {
1421eb82ff87SDaniel Beauregard 			EL(ha, "Err: Unknown addr: 0x%lx\n", buf[i].addr);
1422eb82ff87SDaniel Beauregard 			continue;
1423eb82ff87SDaniel Beauregard 		}
1424eb82ff87SDaniel Beauregard 		off += UNM_PCI_CRBSPACE;
1425eb82ff87SDaniel Beauregard 
1426eb82ff87SDaniel Beauregard 		if (off & 1) {
1427eb82ff87SDaniel Beauregard 			continue;
1428eb82ff87SDaniel Beauregard 		}
1429eb82ff87SDaniel Beauregard 
1430eb82ff87SDaniel Beauregard 		/* skipping cold reboot MAGIC */
1431eb82ff87SDaniel Beauregard 		if (off == UNM_RAM_COLD_BOOT) {
1432eb82ff87SDaniel Beauregard 			continue;
1433eb82ff87SDaniel Beauregard 		}
1434eb82ff87SDaniel Beauregard 		if (off == (UNM_CRB_I2C0 + 0x1c)) {
1435eb82ff87SDaniel Beauregard 			continue;
1436eb82ff87SDaniel Beauregard 		}
1437eb82ff87SDaniel Beauregard 		/* do not reset PCI */
1438eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0xbc)) {
1439eb82ff87SDaniel Beauregard 			continue;
1440eb82ff87SDaniel Beauregard 		}
1441eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0xa8)) {
1442eb82ff87SDaniel Beauregard 			continue;
1443eb82ff87SDaniel Beauregard 		}
1444eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0xc8)) {	/* core clock */
1445eb82ff87SDaniel Beauregard 			continue;
1446eb82ff87SDaniel Beauregard 		}
1447eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0x24)) {	/* MN clock */
1448eb82ff87SDaniel Beauregard 			continue;
1449eb82ff87SDaniel Beauregard 		}
1450eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0x1c)) {	/* MS clock */
1451eb82ff87SDaniel Beauregard 			continue;
1452eb82ff87SDaniel Beauregard 		}
1453eb82ff87SDaniel Beauregard 		if ((off & 0x0ff00000) == UNM_CRB_DDR_NET) {
1454eb82ff87SDaniel Beauregard 			continue;
1455eb82ff87SDaniel Beauregard 		}
1456eb82ff87SDaniel Beauregard 		if (off == (UNM_CRB_PEG_NET_1 + 0x18) &&
1457eb82ff87SDaniel Beauregard 		    !NX_IS_REVISION_P3PLUS(ha->rev_id)) {
1458eb82ff87SDaniel Beauregard 			buf[i].data = 0x1020;
1459eb82ff87SDaniel Beauregard 		}
1460eb82ff87SDaniel Beauregard 		/* skip the function enable register */
1461eb82ff87SDaniel Beauregard 		if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) {
1462eb82ff87SDaniel Beauregard 			continue;
1463eb82ff87SDaniel Beauregard 		}
1464eb82ff87SDaniel Beauregard 		if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) {
1465eb82ff87SDaniel Beauregard 			continue;
1466eb82ff87SDaniel Beauregard 		}
1467eb82ff87SDaniel Beauregard 		if ((off & 0x0ff00000) == UNM_CRB_SMB) {
1468eb82ff87SDaniel Beauregard 			continue;
1469eb82ff87SDaniel Beauregard 		}
1470eb82ff87SDaniel Beauregard 
1471eb82ff87SDaniel Beauregard 		/* After writing this register, HW needs time for CRB */
1472eb82ff87SDaniel Beauregard 		/* to quiet down (else crb_window returns 0xffffffff) */
1473eb82ff87SDaniel Beauregard 		init_delay = 1;
1474eb82ff87SDaniel Beauregard 		if (off == UNM_ROMUSB_GLB_SW_RESET) {
1475eb82ff87SDaniel Beauregard 			init_delay = 100;	/* Sleep 1000 msecs */
1476eb82ff87SDaniel Beauregard 		}
1477eb82ff87SDaniel Beauregard 
1478eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, off, buf[i].data);
1479eb82ff87SDaniel Beauregard 
1480eb82ff87SDaniel Beauregard 		delay(init_delay);
1481eb82ff87SDaniel Beauregard 	}
1482eb82ff87SDaniel Beauregard 	kmem_free(buf, n * sizeof (struct crb_addr_pair));
1483eb82ff87SDaniel Beauregard 
1484eb82ff87SDaniel Beauregard 	/* disable_peg_cache_all */
1485eb82ff87SDaniel Beauregard 
1486eb82ff87SDaniel Beauregard 	/* p2dn replyCount */
1487eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0xec, 0x1e);
1488eb82ff87SDaniel Beauregard 	/* disable_peg_cache 0 */
1489eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0x4c, 8);
1490eb82ff87SDaniel Beauregard 	/* disable_peg_cache 1 */
1491eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_I + 0x4c, 8);
1492eb82ff87SDaniel Beauregard 
1493eb82ff87SDaniel Beauregard 	/* peg_clr_all */
1494eb82ff87SDaniel Beauregard 	/* peg_clr 0 */
1495eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x8, 0);
1496eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0xc, 0);
1497eb82ff87SDaniel Beauregard 	/* peg_clr 1 */
1498eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0x8, 0);
1499eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0xc, 0);
1500eb82ff87SDaniel Beauregard 	/* peg_clr 2 */
1501eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0x8, 0);
1502eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0xc, 0);
1503eb82ff87SDaniel Beauregard 	/* peg_clr 3 */
1504eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0x8, 0);
1505eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0xc, 0);
1506eb82ff87SDaniel Beauregard 
1507eb82ff87SDaniel Beauregard 	return (0);
1508eb82ff87SDaniel Beauregard }
1509eb82ff87SDaniel Beauregard 
1510eb82ff87SDaniel Beauregard static int
ql_8021_load_from_flash(ql_adapter_state_t * ha)1511eb82ff87SDaniel Beauregard ql_8021_load_from_flash(ql_adapter_state_t *ha)
1512eb82ff87SDaniel Beauregard {
1513eb82ff87SDaniel Beauregard 	int		i;
1514eb82ff87SDaniel Beauregard 	uint32_t	flashaddr, memaddr;
1515eb82ff87SDaniel Beauregard 	uint32_t	high, low, size;
1516eb82ff87SDaniel Beauregard 	uint64_t	data;
1517eb82ff87SDaniel Beauregard 
1518eb82ff87SDaniel Beauregard 	size = ha->bootloader_size / 2;
1519*4c3888b8SHans Rosenfeld 	memaddr = flashaddr = ha->bootloader_addr << 2;
1520eb82ff87SDaniel Beauregard 
1521eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1522eb82ff87SDaniel Beauregard 		if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
1523eb82ff87SDaniel Beauregard 		    (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
1524eb82ff87SDaniel Beauregard 			EL(ha, "ql_8021_rom_fast_read != 0\n");
1525eb82ff87SDaniel Beauregard 			return (-1);
1526eb82ff87SDaniel Beauregard 		}
1527eb82ff87SDaniel Beauregard 		data = ((uint64_t)high << 32) | low;
1528*4c3888b8SHans Rosenfeld 		if (ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8)) {
1529*4c3888b8SHans Rosenfeld 			EL(ha, "qla_fc_8021_pci_mem_write_2M != 0\n");
1530*4c3888b8SHans Rosenfeld 			return (-1);
1531*4c3888b8SHans Rosenfeld 		}
1532eb82ff87SDaniel Beauregard 		flashaddr += 8;
1533eb82ff87SDaniel Beauregard 		memaddr += 8;
1534*4c3888b8SHans Rosenfeld 
1535*4c3888b8SHans Rosenfeld 		/* Allow other system activity. */
1536*4c3888b8SHans Rosenfeld 		if (i % 0x1000 == 0) {
1537*4c3888b8SHans Rosenfeld 			/* Delay for 1 tick (10ms). */
1538*4c3888b8SHans Rosenfeld 			delay(1);
1539*4c3888b8SHans Rosenfeld 		}
1540eb82ff87SDaniel Beauregard 	}
1541eb82ff87SDaniel Beauregard 
1542*4c3888b8SHans Rosenfeld #if 0
1543*4c3888b8SHans Rosenfeld 	/* Allow other system activity, delay for 1 tick (10ms). */
1544*4c3888b8SHans Rosenfeld 	delay(1);
1545*4c3888b8SHans Rosenfeld 
1546eb82ff87SDaniel Beauregard 	size = ha->flash_fw_size / 2;
1547*4c3888b8SHans Rosenfeld 	memaddr = flashaddr = ha->flash_fw_addr << 2;
1548eb82ff87SDaniel Beauregard 
1549eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1550eb82ff87SDaniel Beauregard 		if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
1551eb82ff87SDaniel Beauregard 		    (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
1552eb82ff87SDaniel Beauregard 			EL(ha, "ql_8021_rom_fast_read3 != 0\n");
1553eb82ff87SDaniel Beauregard 			return (-1);
1554eb82ff87SDaniel Beauregard 		}
1555eb82ff87SDaniel Beauregard 		data = ((uint64_t)high << 32) | low;
1556eb82ff87SDaniel Beauregard 		(void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
1557eb82ff87SDaniel Beauregard 		flashaddr += 8;
1558eb82ff87SDaniel Beauregard 		memaddr += 8;
1559eb82ff87SDaniel Beauregard 
1560*4c3888b8SHans Rosenfeld 		/* Allow other system activity. */
1561*4c3888b8SHans Rosenfeld 		if (i % 0x1000 == 0) {
1562*4c3888b8SHans Rosenfeld 			/* Delay for 1 tick (10ms). */
1563*4c3888b8SHans Rosenfeld 			delay(1);
1564*4c3888b8SHans Rosenfeld 		}
1565*4c3888b8SHans Rosenfeld 	}
1566*4c3888b8SHans Rosenfeld #endif
1567eb82ff87SDaniel Beauregard 	return (0);
1568eb82ff87SDaniel Beauregard }
1569eb82ff87SDaniel Beauregard 
1570eb82ff87SDaniel Beauregard static int
ql_8021_load_firmware(ql_adapter_state_t * ha)1571eb82ff87SDaniel Beauregard ql_8021_load_firmware(ql_adapter_state_t *ha)
1572eb82ff87SDaniel Beauregard {
1573eb82ff87SDaniel Beauregard 	uint64_t	data;
1574eb82ff87SDaniel Beauregard 	uint32_t	i, flashaddr, size;
1575eb82ff87SDaniel Beauregard 	uint8_t		*bp, n, *dp;
1576eb82ff87SDaniel Beauregard 
1577eb82ff87SDaniel Beauregard 	bp = (uint8_t *)(ha->risc_fw[0].code);
1578eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&size;
1579eb82ff87SDaniel Beauregard 	for (n = 0; n < 4; n++) {
1580eb82ff87SDaniel Beauregard 		dp[n] = *bp++;
1581eb82ff87SDaniel Beauregard 	}
1582eb82ff87SDaniel Beauregard 	LITTLE_ENDIAN_32(&size);
1583eb82ff87SDaniel Beauregard 	EL(ha, "signature=%x\n", size);
1584eb82ff87SDaniel Beauregard 
1585*4c3888b8SHans Rosenfeld 	size = ha->bootloader_size / 2;
1586*4c3888b8SHans Rosenfeld 	flashaddr = ha->bootloader_addr << 2;
1587eb82ff87SDaniel Beauregard 
1588*4c3888b8SHans Rosenfeld 	bp = (uint8_t *)(ha->risc_fw[0].code + flashaddr);
1589eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&data;
1590eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1591eb82ff87SDaniel Beauregard 		for (n = 0; n < 8; n++) {
1592eb82ff87SDaniel Beauregard 			dp[n] = *bp++;
1593eb82ff87SDaniel Beauregard 		}
1594eb82ff87SDaniel Beauregard 		LITTLE_ENDIAN_64(&data);
1595*4c3888b8SHans Rosenfeld 		if (ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8)) {
1596*4c3888b8SHans Rosenfeld 			EL(ha, "qla_fc_8021_pci_mem_write_2M != 0\n");
1597*4c3888b8SHans Rosenfeld 			return (-1);
1598*4c3888b8SHans Rosenfeld 		}
1599eb82ff87SDaniel Beauregard 		flashaddr += 8;
1600eb82ff87SDaniel Beauregard 	}
1601eb82ff87SDaniel Beauregard 
1602eb82ff87SDaniel Beauregard 	bp = (uint8_t *)(ha->risc_fw[0].code + FW_SIZE_OFFSET);
1603eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&size;
1604eb82ff87SDaniel Beauregard 	for (n = 0; n < 4; n++) {
1605eb82ff87SDaniel Beauregard 		dp[n] = *bp++;
1606eb82ff87SDaniel Beauregard 	}
1607eb82ff87SDaniel Beauregard 	LITTLE_ENDIAN_32(&size);
1608eb82ff87SDaniel Beauregard 	EL(ha, "IMAGE_START size=%llx\n", size);
1609eb82ff87SDaniel Beauregard 	size = (size + 7) / 8;
1610eb82ff87SDaniel Beauregard 
1611*4c3888b8SHans Rosenfeld 	flashaddr = ha->flash_fw_addr << 2;
1612*4c3888b8SHans Rosenfeld 	bp = (uint8_t *)(ha->risc_fw[0].code + flashaddr);
1613eb82ff87SDaniel Beauregard 
1614eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&data;
1615eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1616eb82ff87SDaniel Beauregard 		for (n = 0; n < 8; n++) {
1617eb82ff87SDaniel Beauregard 			dp[n] = *bp++;
1618eb82ff87SDaniel Beauregard 		}
1619eb82ff87SDaniel Beauregard 		LITTLE_ENDIAN_64(&data);
1620*4c3888b8SHans Rosenfeld 		if (ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8)) {
1621*4c3888b8SHans Rosenfeld 			EL(ha, "qla_fc_8021_pci_mem_write_2M != 0\n");
1622*4c3888b8SHans Rosenfeld 			return (-1);
1623*4c3888b8SHans Rosenfeld 		}
1624eb82ff87SDaniel Beauregard 		flashaddr += 8;
1625eb82ff87SDaniel Beauregard 	}
1626eb82ff87SDaniel Beauregard 
1627eb82ff87SDaniel Beauregard 	return (0);
1628eb82ff87SDaniel Beauregard }
1629eb82ff87SDaniel Beauregard 
1630eb82ff87SDaniel Beauregard static int
ql_8021_init_p3p(ql_adapter_state_t * ha)1631eb82ff87SDaniel Beauregard ql_8021_init_p3p(ql_adapter_state_t *ha)
1632eb82ff87SDaniel Beauregard {
1633eb82ff87SDaniel Beauregard 	uint32_t	data;
1634eb82ff87SDaniel Beauregard 
1635eb82ff87SDaniel Beauregard 	/* ??? */
1636eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_PORT_MODE_ADDR, UNM_PORT_MODE_AUTO_NEG);
1637eb82ff87SDaniel Beauregard 	delay(drv_usectohz(1000000));
1638eb82ff87SDaniel Beauregard 
1639eb82ff87SDaniel Beauregard 	/* CAM RAM Cold Boot Register */
1640eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_RAM_COLD_BOOT, &data);
1641eb82ff87SDaniel Beauregard 	if (data == 0x55555555) {
1642eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &data);
1643eb82ff87SDaniel Beauregard 		if (data != 0x80000f) {
1644eb82ff87SDaniel Beauregard 			EL(ha, "CRB_UNM_GLB_SW_RST=%x exit\n", data);
1645eb82ff87SDaniel Beauregard 			return (-1);
1646eb82ff87SDaniel Beauregard 		}
1647eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_RAM_COLD_BOOT, 0);
1648eb82ff87SDaniel Beauregard 	}
1649eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, &data);
1650eb82ff87SDaniel Beauregard 	data |= 1;
1651eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, data);
1652eb82ff87SDaniel Beauregard 
1653eb82ff87SDaniel Beauregard 	/*
1654eb82ff87SDaniel Beauregard 	 * ???
1655eb82ff87SDaniel Beauregard 	 * data = ha->pci_bus_addr | BIT_31;
1656eb82ff87SDaniel Beauregard 	 * ql_8021_wr_32(ha, UNM_BUS_DEV_NO, data);
1657eb82ff87SDaniel Beauregard 	 */
1658eb82ff87SDaniel Beauregard 
1659eb82ff87SDaniel Beauregard 	return (0);
1660eb82ff87SDaniel Beauregard }
1661eb82ff87SDaniel Beauregard 
1662eb82ff87SDaniel Beauregard /* ARGSUSED */
1663eb82ff87SDaniel Beauregard void
ql_8021_reset_chip(ql_adapter_state_t * ha)1664eb82ff87SDaniel Beauregard ql_8021_reset_chip(ql_adapter_state_t *ha)
1665eb82ff87SDaniel Beauregard {
1666f885d00fSDaniel Beauregard 	/*
1667f885d00fSDaniel Beauregard 	 * Disable interrupts does not work on a per function bases
1668f885d00fSDaniel Beauregard 	 * leave them enabled
1669f885d00fSDaniel Beauregard 	 */
1670eb82ff87SDaniel Beauregard 	ql_8021_enable_intrs(ha);
1671eb82ff87SDaniel Beauregard 
1672eb82ff87SDaniel Beauregard 	ADAPTER_STATE_LOCK(ha);
1673eb82ff87SDaniel Beauregard 	ha->flags |= INTERRUPTS_ENABLED;
1674eb82ff87SDaniel Beauregard 	ADAPTER_STATE_UNLOCK(ha);
1675*4c3888b8SHans Rosenfeld 	if (!(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
1676*4c3888b8SHans Rosenfeld 		(void) ql_stop_firmware(ha);
1677*4c3888b8SHans Rosenfeld 	}
1678eb82ff87SDaniel Beauregard }
1679eb82ff87SDaniel Beauregard 
1680eb82ff87SDaniel Beauregard static int
ql_8021_reset_hw(ql_adapter_state_t * ha,int type)1681eb82ff87SDaniel Beauregard ql_8021_reset_hw(ql_adapter_state_t *ha, int type)
1682eb82ff87SDaniel Beauregard {
1683eb82ff87SDaniel Beauregard 	int		ret;
1684eb82ff87SDaniel Beauregard 	uint32_t	rst;
1685eb82ff87SDaniel Beauregard 
1686eb82ff87SDaniel Beauregard 	/* scrub dma mask expansion register */
1687eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
1688eb82ff87SDaniel Beauregard 
1689eb82ff87SDaniel Beauregard 	/* Overwrite stale initialization register values */
1690eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_CMDPEG_STATE, 0);
1691eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_RCVPEG_STATE, 0);
1692eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0);
1693eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0);
1694eb82ff87SDaniel Beauregard 
1695*4c3888b8SHans Rosenfeld 	/*
1696*4c3888b8SHans Rosenfeld 	 * This reset sequence is to provide a graceful shutdown of the
1697*4c3888b8SHans Rosenfeld 	 * different hardware blocks prior to performing an ASIC Reset,
1698*4c3888b8SHans Rosenfeld 	 * has to be done before writing 0xffffffff to ASIC_RESET.
1699*4c3888b8SHans Rosenfeld 	 */
1700*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x10, 0);
1701*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x14, 0);
1702*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x18, 0);
1703*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x1c, 0);
1704*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x20, 0);
1705*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x24, 0);
1706*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_NIU + 0x40, 0xff);
1707*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_NIU + 0x70000, 0x0);
1708*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_NIU + 0x80000, 0x0);
1709*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_NIU + 0x90000, 0x0);
1710*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_NIU + 0xa0000, 0x0);
1711*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_NIU + 0xb0000, 0x0);
1712*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_SRE + 0x1000, 0x28ff000c);
1713*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_EPG + 0x1300, 0x1);
1714*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x0, 0x0);
1715*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x8, 0x0);
1716*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x10, 0x0);
1717*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x18, 0x0);
1718*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x100, 0x0);
1719*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x200, 0x0);
1720*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x3C, 0x1);
1721*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0x3C, 0x1);
1722*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0x3C, 0x1);
1723*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0x3C, 0x1);
1724*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_4 + 0x3C, 0x1);
1725*4c3888b8SHans Rosenfeld 	delay(1);
1726*4c3888b8SHans Rosenfeld 
1727*4c3888b8SHans Rosenfeld 	ret = ql_8021_pinit_from_rom(ha);
1728*4c3888b8SHans Rosenfeld 	if (ret) {
1729*4c3888b8SHans Rosenfeld 		EL(ha, "pinit_from_rom ret=%d\n", ret);
1730*4c3888b8SHans Rosenfeld 		return (ret);
1731*4c3888b8SHans Rosenfeld 	}
1732eb82ff87SDaniel Beauregard 	delay(1);
1733eb82ff87SDaniel Beauregard 
1734eb82ff87SDaniel Beauregard 	/* Bring QM and CAMRAM out of reset */
1735eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &rst);
1736eb82ff87SDaniel Beauregard 	rst &= ~((1 << 28) | (1 << 24));
1737eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, rst);
1738eb82ff87SDaniel Beauregard 
1739eb82ff87SDaniel Beauregard 	switch (type) {
1740eb82ff87SDaniel Beauregard 	case 0:
1741eb82ff87SDaniel Beauregard 		ret = ql_8021_init_p3p(ha);
1742eb82ff87SDaniel Beauregard 		break;
1743eb82ff87SDaniel Beauregard 	case 1:
1744eb82ff87SDaniel Beauregard 		ret = ql_8021_load_from_flash(ha);
1745eb82ff87SDaniel Beauregard 		break;
1746eb82ff87SDaniel Beauregard 	case 2:
1747eb82ff87SDaniel Beauregard 		ret = ql_8021_load_firmware(ha);
1748eb82ff87SDaniel Beauregard 		break;
1749eb82ff87SDaniel Beauregard 	}
1750eb82ff87SDaniel Beauregard 	delay(1);
1751eb82ff87SDaniel Beauregard 
1752eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x18, 0x1020);
1753eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0x80001e);
1754eb82ff87SDaniel Beauregard 
1755eb82ff87SDaniel Beauregard 	if (ret) {
1756eb82ff87SDaniel Beauregard 		EL(ha, "type=%d, ret=%d\n", type, ret);
1757eb82ff87SDaniel Beauregard 	} else {
1758eb82ff87SDaniel Beauregard 		ret = ql_8021_phantom_init(ha);
1759eb82ff87SDaniel Beauregard 	}
1760eb82ff87SDaniel Beauregard 	return (ret);
1761eb82ff87SDaniel Beauregard }
1762eb82ff87SDaniel Beauregard 
1763*4c3888b8SHans Rosenfeld static int
ql_8021_load_fw(ql_adapter_state_t * ha)1764*4c3888b8SHans Rosenfeld ql_8021_load_fw(ql_adapter_state_t *ha)
1765eb82ff87SDaniel Beauregard {
1766*4c3888b8SHans Rosenfeld 	int	rv = 0;
1767eb82ff87SDaniel Beauregard 
1768eb82ff87SDaniel Beauregard 	GLOBAL_HW_LOCK();
1769*4c3888b8SHans Rosenfeld 	if (ha->risc_fw[0].code) {
1770*4c3888b8SHans Rosenfeld 		EL(ha, "from driver\n");
1771*4c3888b8SHans Rosenfeld 		rv = ql_8021_reset_hw(ha, 2);
1772*4c3888b8SHans Rosenfeld 	} else {
1773*4c3888b8SHans Rosenfeld 		/*
1774*4c3888b8SHans Rosenfeld 		 * BIOS method
1775*4c3888b8SHans Rosenfeld 		 * ql_8021_reset_hw(ha, 0)
1776*4c3888b8SHans Rosenfeld 		 */
1777*4c3888b8SHans Rosenfeld 		EL(ha, "from flash\n");
1778*4c3888b8SHans Rosenfeld 		rv = ql_8021_reset_hw(ha, 1);
1779*4c3888b8SHans Rosenfeld 	}
1780*4c3888b8SHans Rosenfeld 	if (rv == 0) {
1781*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
1782*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0x0);
1783*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0x0);
1784eb82ff87SDaniel Beauregard 
1785*4c3888b8SHans Rosenfeld 		GLOBAL_HW_UNLOCK();
1786eb82ff87SDaniel Beauregard 
1787*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_LOCK(ha);
1788*4c3888b8SHans Rosenfeld 		ha->flags &= ~INTERRUPTS_ENABLED;
1789*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_UNLOCK(ha);
1790eb82ff87SDaniel Beauregard 
1791*4c3888b8SHans Rosenfeld 		/* clear the mailbox command pointer. */
1792*4c3888b8SHans Rosenfeld 		INTR_LOCK(ha);
1793*4c3888b8SHans Rosenfeld 		ha->mcp = NULL;
1794*4c3888b8SHans Rosenfeld 		INTR_UNLOCK(ha);
1795eb82ff87SDaniel Beauregard 
1796*4c3888b8SHans Rosenfeld 		MBX_REGISTER_LOCK(ha);
1797*4c3888b8SHans Rosenfeld 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
1798*4c3888b8SHans Rosenfeld 		    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
1799*4c3888b8SHans Rosenfeld 		MBX_REGISTER_UNLOCK(ha);
1800eb82ff87SDaniel Beauregard 
1801*4c3888b8SHans Rosenfeld 		(void) ql_8021_enable_intrs(ha);
1802*4c3888b8SHans Rosenfeld 
1803*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_LOCK(ha);
1804*4c3888b8SHans Rosenfeld 		ha->flags |= INTERRUPTS_ENABLED;
1805*4c3888b8SHans Rosenfeld 		ADAPTER_STATE_UNLOCK(ha);
1806eb82ff87SDaniel Beauregard 	} else {
1807eb82ff87SDaniel Beauregard 		GLOBAL_HW_UNLOCK();
1808eb82ff87SDaniel Beauregard 	}
1809eb82ff87SDaniel Beauregard 
1810eb82ff87SDaniel Beauregard 	if (rv == 0) {
1811eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR, &ha->fw_major_version);
1812eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR, &ha->fw_minor_version);
1813eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_FW_VERSION_SUB, &ha->fw_subminor_version);
1814eb82ff87SDaniel Beauregard 		EL(ha, "fw v%d.%02d.%02d\n", ha->fw_major_version,
1815eb82ff87SDaniel Beauregard 		    ha->fw_minor_version, ha->fw_subminor_version);
1816eb82ff87SDaniel Beauregard 	} else {
1817eb82ff87SDaniel Beauregard 		EL(ha, "status = -1\n");
1818eb82ff87SDaniel Beauregard 	}
1819eb82ff87SDaniel Beauregard 
1820*4c3888b8SHans Rosenfeld 	return (rv);
1821eb82ff87SDaniel Beauregard }
1822eb82ff87SDaniel Beauregard 
1823eb82ff87SDaniel Beauregard void
ql_8021_clr_hw_intr(ql_adapter_state_t * ha)1824eb82ff87SDaniel Beauregard ql_8021_clr_hw_intr(ql_adapter_state_t *ha)
1825eb82ff87SDaniel Beauregard {
1826eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
1827eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
1828eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
1829eb82ff87SDaniel Beauregard }
1830eb82ff87SDaniel Beauregard 
1831eb82ff87SDaniel Beauregard void
ql_8021_clr_fw_intr(ql_adapter_state_t * ha)1832eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ql_adapter_state_t *ha)
1833eb82ff87SDaniel Beauregard {
1834eb82ff87SDaniel Beauregard 	WRT32_IO_REG(ha, nx_risc_int, 0);
1835eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xfbff);
1836eb82ff87SDaniel Beauregard }
1837eb82ff87SDaniel Beauregard 
1838eb82ff87SDaniel Beauregard void
ql_8021_enable_intrs(ql_adapter_state_t * ha)1839eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ql_adapter_state_t *ha)
1840eb82ff87SDaniel Beauregard {
1841eb82ff87SDaniel Beauregard 	GLOBAL_HW_LOCK();
1842eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
1843eb82ff87SDaniel Beauregard 	GLOBAL_HW_UNLOCK();
1844*4c3888b8SHans Rosenfeld 	if (!(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
1845*4c3888b8SHans Rosenfeld 		(void) ql_toggle_interrupt(ha, 1);
1846*4c3888b8SHans Rosenfeld 	}
1847eb82ff87SDaniel Beauregard }
1848eb82ff87SDaniel Beauregard 
1849eb82ff87SDaniel Beauregard void
ql_8021_disable_intrs(ql_adapter_state_t * ha)1850eb82ff87SDaniel Beauregard ql_8021_disable_intrs(ql_adapter_state_t *ha)
1851eb82ff87SDaniel Beauregard {
1852eb82ff87SDaniel Beauregard 	(void) ql_toggle_interrupt(ha, 0);
1853eb82ff87SDaniel Beauregard 	GLOBAL_HW_LOCK();
1854eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
1855eb82ff87SDaniel Beauregard 	GLOBAL_HW_UNLOCK();
1856eb82ff87SDaniel Beauregard }
1857eb82ff87SDaniel Beauregard 
1858eb82ff87SDaniel Beauregard void
ql_8021_update_crb_int_ptr(ql_adapter_state_t * ha)1859eb82ff87SDaniel Beauregard ql_8021_update_crb_int_ptr(ql_adapter_state_t *ha)
1860eb82ff87SDaniel Beauregard {
1861eb82ff87SDaniel Beauregard 	struct legacy_intr_set	*nx_legacy_intr;
1862eb82ff87SDaniel Beauregard 
1863eb82ff87SDaniel Beauregard 	ha->qdr_sn_window = (uint32_t)-1;
1864*4c3888b8SHans Rosenfeld 	nx_legacy_intr = &legacy_intr[ha->pci_function_number];
1865eb82ff87SDaniel Beauregard 
1866eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
1867eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg;
1868eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
1869eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
1870eb82ff87SDaniel Beauregard }
1871eb82ff87SDaniel Beauregard 
1872eb82ff87SDaniel Beauregard void
ql_8021_set_drv_active(ql_adapter_state_t * ha)1873eb82ff87SDaniel Beauregard ql_8021_set_drv_active(ql_adapter_state_t *ha)
1874eb82ff87SDaniel Beauregard {
1875eb82ff87SDaniel Beauregard 	uint32_t	val;
1876eb82ff87SDaniel Beauregard 
1877eb82ff87SDaniel Beauregard 	if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
1878eb82ff87SDaniel Beauregard 		return;
1879eb82ff87SDaniel Beauregard 	}
1880eb82ff87SDaniel Beauregard 
1881eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
1882eb82ff87SDaniel Beauregard 	if (val == 0xffffffff) {
1883*4c3888b8SHans Rosenfeld 		val = (1 << (ha->pci_function_number * 4));
1884eb82ff87SDaniel Beauregard 	} else {
1885*4c3888b8SHans Rosenfeld 		val |= (1 << (ha->pci_function_number * 4));
1886eb82ff87SDaniel Beauregard 	}
1887eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
1888eb82ff87SDaniel Beauregard 
1889eb82ff87SDaniel Beauregard 	ql_8021_hw_unlock(ha);
1890eb82ff87SDaniel Beauregard }
1891eb82ff87SDaniel Beauregard 
1892eb82ff87SDaniel Beauregard void
ql_8021_clr_drv_active(ql_adapter_state_t * ha)1893eb82ff87SDaniel Beauregard ql_8021_clr_drv_active(ql_adapter_state_t *ha)
1894eb82ff87SDaniel Beauregard {
1895eb82ff87SDaniel Beauregard 	uint32_t	val;
1896eb82ff87SDaniel Beauregard 
1897eb82ff87SDaniel Beauregard 	if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
1898eb82ff87SDaniel Beauregard 		return;
1899eb82ff87SDaniel Beauregard 	}
1900eb82ff87SDaniel Beauregard 
1901eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
1902*4c3888b8SHans Rosenfeld 	val &= ~(1 << (ha->pci_function_number * 4));
1903eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
1904eb82ff87SDaniel Beauregard 
1905eb82ff87SDaniel Beauregard 	ql_8021_hw_unlock(ha);
1906eb82ff87SDaniel Beauregard }
1907eb82ff87SDaniel Beauregard 
1908eb82ff87SDaniel Beauregard static void
ql_8021_need_reset_handler(ql_adapter_state_t * ha)1909eb82ff87SDaniel Beauregard ql_8021_need_reset_handler(ql_adapter_state_t *ha)
1910eb82ff87SDaniel Beauregard {
1911*4c3888b8SHans Rosenfeld 	uint32_t	drv_state, drv_active, cnt;
1912eb82ff87SDaniel Beauregard 
1913eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1914*4c3888b8SHans Rosenfeld 	if (drv_state == 0xffffffff) {
1915*4c3888b8SHans Rosenfeld 		drv_state = 0;
1916*4c3888b8SHans Rosenfeld 	}
1917*4c3888b8SHans Rosenfeld 	if (!(ha->ql_dump_state & QL_DUMPING)) {
1918*4c3888b8SHans Rosenfeld 		drv_state |= (1 << (ha->pci_function_number * 4));
1919*4c3888b8SHans Rosenfeld 	}
1920eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
1921eb82ff87SDaniel Beauregard 
1922*4c3888b8SHans Rosenfeld 	for (cnt = 60; cnt; cnt--) {
1923*4c3888b8SHans Rosenfeld 		ql_8021_hw_unlock(ha);
1924eb82ff87SDaniel Beauregard 		delay(100);
1925eb82ff87SDaniel Beauregard 		(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1926*4c3888b8SHans Rosenfeld 
1927eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1928eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
1929*4c3888b8SHans Rosenfeld 		if (ha->ql_dump_state & QL_DUMPING) {
1930*4c3888b8SHans Rosenfeld 			drv_state |= (1 << (ha->pci_function_number * 4));
1931*4c3888b8SHans Rosenfeld 		}
1932*4c3888b8SHans Rosenfeld 		if (drv_state == drv_active) {
1933*4c3888b8SHans Rosenfeld 			if (ha->ql_dump_state & QL_DUMPING) {
1934*4c3888b8SHans Rosenfeld 				ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
1935*4c3888b8SHans Rosenfeld 			}
1936*4c3888b8SHans Rosenfeld 			break;
1937*4c3888b8SHans Rosenfeld 		}
1938eb82ff87SDaniel Beauregard 	}
1939eb82ff87SDaniel Beauregard }
1940eb82ff87SDaniel Beauregard 
1941*4c3888b8SHans Rosenfeld int
ql_8021_fw_reload(ql_adapter_state_t * ha)1942*4c3888b8SHans Rosenfeld ql_8021_fw_reload(ql_adapter_state_t *ha)
1943eb82ff87SDaniel Beauregard {
1944*4c3888b8SHans Rosenfeld 	int	rval;
1945*4c3888b8SHans Rosenfeld 
1946*4c3888b8SHans Rosenfeld 	(void) ql_stall_driver(ha, BIT_0);
1947*4c3888b8SHans Rosenfeld 
1948*4c3888b8SHans Rosenfeld 	(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1949*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING);
1950*4c3888b8SHans Rosenfeld 	ql_8021_hw_unlock(ha);
1951*4c3888b8SHans Rosenfeld 
1952*4c3888b8SHans Rosenfeld 	rval = ql_8021_load_fw(ha) == 0 ? NX_DEV_READY : NX_DEV_FAILED;
1953*4c3888b8SHans Rosenfeld 
1954*4c3888b8SHans Rosenfeld 	(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1955*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, CRB_DEV_STATE, rval);
1956*4c3888b8SHans Rosenfeld 	ql_8021_hw_unlock(ha);
1957*4c3888b8SHans Rosenfeld 
1958*4c3888b8SHans Rosenfeld 	TASK_DAEMON_LOCK(ha);
1959*4c3888b8SHans Rosenfeld 	ha->task_daemon_flags &= ~(TASK_DAEMON_STALLED_FLG | DRIVER_STALL);
1960*4c3888b8SHans Rosenfeld 	TASK_DAEMON_UNLOCK(ha);
1961*4c3888b8SHans Rosenfeld 
1962*4c3888b8SHans Rosenfeld 	if (rval != NX_DEV_READY) {
1963*4c3888b8SHans Rosenfeld 		EL(ha, "status=%xh\n", QL_FUNCTION_FAILED);
1964*4c3888b8SHans Rosenfeld 		return (QL_FUNCTION_FAILED);
1965*4c3888b8SHans Rosenfeld 	}
1966*4c3888b8SHans Rosenfeld 	return (QL_SUCCESS);
1967*4c3888b8SHans Rosenfeld }
1968*4c3888b8SHans Rosenfeld 
1969*4c3888b8SHans Rosenfeld void
ql_8021_idc_poll(ql_adapter_state_t * ha)1970*4c3888b8SHans Rosenfeld ql_8021_idc_poll(ql_adapter_state_t *ha)
1971*4c3888b8SHans Rosenfeld {
1972*4c3888b8SHans Rosenfeld 	uint32_t	new_state;
1973*4c3888b8SHans Rosenfeld 
1974*4c3888b8SHans Rosenfeld 	if (ha->ql_dump_state & QL_DUMPING) {
1975*4c3888b8SHans Rosenfeld 		return;
1976*4c3888b8SHans Rosenfeld 	}
1977*4c3888b8SHans Rosenfeld 	new_state = ql_8021_check_fw_alive(ha);
1978*4c3888b8SHans Rosenfeld 
1979*4c3888b8SHans Rosenfeld 	if (new_state == NX_DEV_NEED_RESET &&
1980*4c3888b8SHans Rosenfeld 	    !(ha->ql_dump_state & QL_DUMPING ||
1981*4c3888b8SHans Rosenfeld 	    (ha->ql_dump_state & QL_DUMP_VALID &&
1982*4c3888b8SHans Rosenfeld 	    !(ha->ql_dump_state & QL_DUMP_UPLOADED)))) {
1983*4c3888b8SHans Rosenfeld 		(void) ql_dump_firmware(ha);
1984*4c3888b8SHans Rosenfeld 	} else {
1985*4c3888b8SHans Rosenfeld 		(void) ql_8021_idc_handler(ha, new_state);
1986*4c3888b8SHans Rosenfeld 	}
1987*4c3888b8SHans Rosenfeld }
1988*4c3888b8SHans Rosenfeld 
1989*4c3888b8SHans Rosenfeld int
ql_8021_idc_handler(ql_adapter_state_t * ha,uint32_t new_state)1990*4c3888b8SHans Rosenfeld ql_8021_idc_handler(ql_adapter_state_t *ha, uint32_t new_state)
1991*4c3888b8SHans Rosenfeld {
1992*4c3888b8SHans Rosenfeld 	int		rval;
1993*4c3888b8SHans Rosenfeld 	uint32_t	dev_state, drv_state, loop;
1994eb82ff87SDaniel Beauregard 	ql_mbx_data_t	mr;
1995*4c3888b8SHans Rosenfeld 	boolean_t	stalled = B_FALSE, reset_needed = B_FALSE;
1996*4c3888b8SHans Rosenfeld 	boolean_t	force_load = B_FALSE;
1997eb82ff87SDaniel Beauregard 
1998*4c3888b8SHans Rosenfeld 	(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1999*4c3888b8SHans Rosenfeld 
2000*4c3888b8SHans Rosenfeld 	/* wait for 180 seconds for device to go ready */
2001*4c3888b8SHans Rosenfeld 	for (loop = 180; loop; loop--) {
2002*4c3888b8SHans Rosenfeld 		if (new_state != NX_DEV_POLL) {
2003*4c3888b8SHans Rosenfeld 			ql_8021_wr_32(ha, CRB_DEV_STATE, new_state);
2004*4c3888b8SHans Rosenfeld 			dev_state = new_state;
2005*4c3888b8SHans Rosenfeld 			new_state = NX_DEV_POLL;
2006*4c3888b8SHans Rosenfeld 		} else {
2007*4c3888b8SHans Rosenfeld 			ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
2008eb82ff87SDaniel Beauregard 		}
2009eb82ff87SDaniel Beauregard 
2010eb82ff87SDaniel Beauregard 		switch (dev_state) {
2011eb82ff87SDaniel Beauregard 		case 0xffffffff:
2012eb82ff87SDaniel Beauregard 		case NX_DEV_COLD:
2013*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2014*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_COLD\n");
2015*4c3888b8SHans Rosenfeld 			}
2016eb82ff87SDaniel Beauregard 			rval = NX_DEV_COLD;
2017eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING);
2018eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DRV_IDC_VERSION, NX_IDC_VERSION);
2019*4c3888b8SHans Rosenfeld 			ql_8021_hw_unlock(ha);
2020*4c3888b8SHans Rosenfeld 			if (!force_load &&
2021*4c3888b8SHans Rosenfeld 			    ql_get_fw_version(ha, &mr, 2) == QL_SUCCESS &&
2022eb82ff87SDaniel Beauregard 			    (mr.mb[1] | mr.mb[2] | mr.mb[3])) {
2023eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR,
2024eb82ff87SDaniel Beauregard 				    &ha->fw_major_version);
2025eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR,
2026eb82ff87SDaniel Beauregard 				    &ha->fw_minor_version);
2027eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, UNM_FW_VERSION_SUB,
2028eb82ff87SDaniel Beauregard 				    &ha->fw_subminor_version);
2029eb82ff87SDaniel Beauregard 				rval = NX_DEV_READY;
2030*4c3888b8SHans Rosenfeld 			} else {
2031*4c3888b8SHans Rosenfeld 				if (!stalled) {
2032*4c3888b8SHans Rosenfeld 					TASK_DAEMON_LOCK(ha);
2033*4c3888b8SHans Rosenfeld 					ha->task_daemon_flags |=
2034*4c3888b8SHans Rosenfeld 					    TASK_DAEMON_STALLED_FLG;
2035*4c3888b8SHans Rosenfeld 					TASK_DAEMON_UNLOCK(ha);
2036*4c3888b8SHans Rosenfeld 					ql_abort_queues(ha);
2037*4c3888b8SHans Rosenfeld 					stalled = B_TRUE;
2038*4c3888b8SHans Rosenfeld 				}
2039*4c3888b8SHans Rosenfeld 				if (ha->ql_dump_state & QL_DUMPING) {
2040*4c3888b8SHans Rosenfeld 					(void) ql_8021_get_fw_dump(ha);
2041*4c3888b8SHans Rosenfeld 				}
2042*4c3888b8SHans Rosenfeld 				rval = ql_8021_load_fw(ha) == 0 ?
2043*4c3888b8SHans Rosenfeld 				    NX_DEV_READY : NX_DEV_FAILED;
2044eb82ff87SDaniel Beauregard 			}
2045eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
2046eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DEV_STATE, rval);
2047eb82ff87SDaniel Beauregard 			break;
2048eb82ff87SDaniel Beauregard 		case NX_DEV_READY:
2049*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2050*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_READY\n");
2051*4c3888b8SHans Rosenfeld 			}
2052eb82ff87SDaniel Beauregard 			rval = NX_DEV_READY;
2053*4c3888b8SHans Rosenfeld 			loop = 1;
2054eb82ff87SDaniel Beauregard 			break;
2055eb82ff87SDaniel Beauregard 		case NX_DEV_FAILED:
2056*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2057*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_FAILED\n");
2058*4c3888b8SHans Rosenfeld 			}
2059eb82ff87SDaniel Beauregard 			rval = NX_DEV_FAILED;
2060*4c3888b8SHans Rosenfeld 			loop = 1;
2061eb82ff87SDaniel Beauregard 			break;
2062eb82ff87SDaniel Beauregard 		case NX_DEV_NEED_RESET:
2063*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2064*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_NEED_RESET\n");
2065*4c3888b8SHans Rosenfeld 			}
2066eb82ff87SDaniel Beauregard 			rval = NX_DEV_NEED_RESET;
2067*4c3888b8SHans Rosenfeld 			ql_8021_need_reset_handler(ha);
2068*4c3888b8SHans Rosenfeld 			/*
2069*4c3888b8SHans Rosenfeld 			 * Force to DEV_COLD unless someone else is starting
2070*4c3888b8SHans Rosenfeld 			 * a reset
2071*4c3888b8SHans Rosenfeld 			 */
2072*4c3888b8SHans Rosenfeld 			ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
2073*4c3888b8SHans Rosenfeld 			if (dev_state == NX_DEV_NEED_RESET) {
2074*4c3888b8SHans Rosenfeld 				EL(ha, "HW State: COLD/RE-INIT\n");
2075*4c3888b8SHans Rosenfeld 				ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_COLD);
2076*4c3888b8SHans Rosenfeld 				force_load = B_TRUE;
2077eb82ff87SDaniel Beauregard 			}
2078*4c3888b8SHans Rosenfeld 			reset_needed = B_TRUE;
2079eb82ff87SDaniel Beauregard 			break;
2080eb82ff87SDaniel Beauregard 		case NX_DEV_NEED_QUIESCENT:
2081*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2082*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_NEED_QUIESCENT\n");
2083*4c3888b8SHans Rosenfeld 			}
2084*4c3888b8SHans Rosenfeld 			ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
2085*4c3888b8SHans Rosenfeld 			drv_state |= (2 << (ha->pci_function_number * 4));
2086*4c3888b8SHans Rosenfeld 			ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
2087*4c3888b8SHans Rosenfeld 			ql_8021_hw_unlock(ha);
2088*4c3888b8SHans Rosenfeld 			if (!stalled) {
2089*4c3888b8SHans Rosenfeld 				TASK_DAEMON_LOCK(ha);
2090*4c3888b8SHans Rosenfeld 				ha->task_daemon_flags |=
2091*4c3888b8SHans Rosenfeld 				    TASK_DAEMON_STALLED_FLG;
2092*4c3888b8SHans Rosenfeld 				TASK_DAEMON_UNLOCK(ha);
2093*4c3888b8SHans Rosenfeld 				(void) ql_stall_driver(ha, BIT_0);
2094eb82ff87SDaniel Beauregard 				stalled = B_TRUE;
2095eb82ff87SDaniel Beauregard 			}
2096*4c3888b8SHans Rosenfeld 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
2097eb82ff87SDaniel Beauregard 			break;
2098eb82ff87SDaniel Beauregard 		case NX_DEV_INITIALIZING:
2099*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2100*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_INITIALIZING\n");
2101*4c3888b8SHans Rosenfeld 			}
2102*4c3888b8SHans Rosenfeld 			ql_8021_hw_unlock(ha);
2103*4c3888b8SHans Rosenfeld 			if (!stalled) {
2104*4c3888b8SHans Rosenfeld 				TASK_DAEMON_LOCK(ha);
2105*4c3888b8SHans Rosenfeld 				ha->task_daemon_flags |=
2106*4c3888b8SHans Rosenfeld 				    TASK_DAEMON_STALLED_FLG;
2107*4c3888b8SHans Rosenfeld 				TASK_DAEMON_UNLOCK(ha);
2108*4c3888b8SHans Rosenfeld 				ql_awaken_task_daemon(ha, NULL,
2109*4c3888b8SHans Rosenfeld 				    DRIVER_STALL, 0);
2110*4c3888b8SHans Rosenfeld 				stalled = B_TRUE;
2111*4c3888b8SHans Rosenfeld 				ql_requeue_all_cmds(ha);
2112*4c3888b8SHans Rosenfeld 				ADAPTER_STATE_LOCK(ha);
2113*4c3888b8SHans Rosenfeld 				ha->flags &= ~INTERRUPTS_ENABLED;
2114*4c3888b8SHans Rosenfeld 				ADAPTER_STATE_UNLOCK(ha);
2115*4c3888b8SHans Rosenfeld 			}
2116*4c3888b8SHans Rosenfeld 			delay(100);
2117*4c3888b8SHans Rosenfeld 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
2118*4c3888b8SHans Rosenfeld 			reset_needed = B_TRUE;
2119eb82ff87SDaniel Beauregard 			break;
2120eb82ff87SDaniel Beauregard 		case NX_DEV_QUIESCENT:
2121*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2122*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=NX_DEV_QUIESCENT\n");
2123*4c3888b8SHans Rosenfeld 			}
2124*4c3888b8SHans Rosenfeld 			ql_8021_hw_unlock(ha);
2125*4c3888b8SHans Rosenfeld 			delay(100);
2126*4c3888b8SHans Rosenfeld 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
2127eb82ff87SDaniel Beauregard 			break;
2128eb82ff87SDaniel Beauregard 		default:
2129*4c3888b8SHans Rosenfeld 			if (ha->dev_state != dev_state) {
2130*4c3888b8SHans Rosenfeld 				EL(ha, "dev_state=%x, default\n", dev_state);
2131*4c3888b8SHans Rosenfeld 			}
2132*4c3888b8SHans Rosenfeld 			ql_8021_hw_unlock(ha);
2133*4c3888b8SHans Rosenfeld 			delay(100);
2134*4c3888b8SHans Rosenfeld 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
2135eb82ff87SDaniel Beauregard 			break;
2136eb82ff87SDaniel Beauregard 		}
2137*4c3888b8SHans Rosenfeld 		ha->dev_state = dev_state;
2138*4c3888b8SHans Rosenfeld 	}
2139*4c3888b8SHans Rosenfeld 
2140*4c3888b8SHans Rosenfeld 	/* Clear reset ready and quiescent flags. */
2141*4c3888b8SHans Rosenfeld 	ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
2142*4c3888b8SHans Rosenfeld 	drv_state &= ~(1 << (ha->pci_function_number * 4));
2143*4c3888b8SHans Rosenfeld 	drv_state &= ~(2 << (ha->pci_function_number * 4));
2144*4c3888b8SHans Rosenfeld 	ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
2145*4c3888b8SHans Rosenfeld 
2146*4c3888b8SHans Rosenfeld 	ql_8021_hw_unlock(ha);
2147*4c3888b8SHans Rosenfeld 	if (reset_needed && ha->flags & ONLINE &&
2148*4c3888b8SHans Rosenfeld 	    !(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
2149*4c3888b8SHans Rosenfeld 		delay(100);
2150*4c3888b8SHans Rosenfeld 		ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
2151*4c3888b8SHans Rosenfeld 	}
2152*4c3888b8SHans Rosenfeld 	if (stalled) {
2153*4c3888b8SHans Rosenfeld 		TASK_DAEMON_LOCK(ha);
2154*4c3888b8SHans Rosenfeld 		ha->task_daemon_flags &= ~TASK_DAEMON_STALLED_FLG;
2155*4c3888b8SHans Rosenfeld 		TASK_DAEMON_UNLOCK(ha);
2156*4c3888b8SHans Rosenfeld 		ql_restart_driver(ha);
2157*4c3888b8SHans Rosenfeld 	}
2158*4c3888b8SHans Rosenfeld 	return (rval);
2159*4c3888b8SHans Rosenfeld }
2160*4c3888b8SHans Rosenfeld 
2161*4c3888b8SHans Rosenfeld void
ql_8021_wr_req_in(ql_adapter_state_t * ha,uint32_t index)2162*4c3888b8SHans Rosenfeld ql_8021_wr_req_in(ql_adapter_state_t *ha, uint32_t index)
2163*4c3888b8SHans Rosenfeld {
2164*4c3888b8SHans Rosenfeld 	index = index << 16 | ha->pci_function_number << 5 | 4;
2165*4c3888b8SHans Rosenfeld 
2166*4c3888b8SHans Rosenfeld 	if (NX_IS_REVISION_P3PLUS_B0(ha->rev_id)) {
2167*4c3888b8SHans Rosenfeld 		uint64_t	addr;
2168*4c3888b8SHans Rosenfeld 
2169*4c3888b8SHans Rosenfeld 		addr = ha->function_number ? (uint64_t)CRB_PORT_1_REQIN :
2170*4c3888b8SHans Rosenfeld 		    (uint64_t)CRB_PORT_0_REQIN;
2171*4c3888b8SHans Rosenfeld 		ql_8021_wr_32(ha, addr, index);
2172*4c3888b8SHans Rosenfeld 	} else {
2173*4c3888b8SHans Rosenfeld 		do {
2174*4c3888b8SHans Rosenfeld 			ddi_put32(ha->db_dev_handle, ha->nx_req_in, index);
2175*4c3888b8SHans Rosenfeld 		} while (RD_REG_DWORD(ha, ha->db_read) != index);
2176*4c3888b8SHans Rosenfeld 	}
2177*4c3888b8SHans Rosenfeld }
2178*4c3888b8SHans Rosenfeld 
2179*4c3888b8SHans Rosenfeld /* Called every 2 seconds */
2180*4c3888b8SHans Rosenfeld static uint32_t
ql_8021_check_fw_alive(ql_adapter_state_t * ha)2181*4c3888b8SHans Rosenfeld ql_8021_check_fw_alive(ql_adapter_state_t *ha)
2182*4c3888b8SHans Rosenfeld {
2183*4c3888b8SHans Rosenfeld 	uint32_t	dev_state, fw_heartbeat_counter, cnt, data[7];
2184*4c3888b8SHans Rosenfeld 	uint32_t	new_state = NX_DEV_POLL;
2185*4c3888b8SHans Rosenfeld 
2186*4c3888b8SHans Rosenfeld 	ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
2187*4c3888b8SHans Rosenfeld 	if (dev_state != NX_DEV_READY) {
2188*4c3888b8SHans Rosenfeld 		return (new_state);
2189*4c3888b8SHans Rosenfeld 	}
2190*4c3888b8SHans Rosenfeld 
2191*4c3888b8SHans Rosenfeld 	ql_8021_rd_32(ha, UNM_PEG_ALIVE_COUNTER, &fw_heartbeat_counter);
2192*4c3888b8SHans Rosenfeld 
2193*4c3888b8SHans Rosenfeld 	if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
2194*4c3888b8SHans Rosenfeld 		ha->seconds_since_last_heartbeat++;
2195*4c3888b8SHans Rosenfeld 		/* FW not alive after 6 seconds */
2196*4c3888b8SHans Rosenfeld 		if (ha->seconds_since_last_heartbeat == 3) {
2197*4c3888b8SHans Rosenfeld 			ha->seconds_since_last_heartbeat = 0;
2198*4c3888b8SHans Rosenfeld 			/* FW not alive after 5 milliseconds */
2199*4c3888b8SHans Rosenfeld 			for (cnt = 5; cnt; cnt--) {
2200*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_PEG_ALIVE_COUNTER,
2201*4c3888b8SHans Rosenfeld 				    &fw_heartbeat_counter);
2202*4c3888b8SHans Rosenfeld 				if (ha->fw_heartbeat_counter !=
2203*4c3888b8SHans Rosenfeld 				    fw_heartbeat_counter) {
2204*4c3888b8SHans Rosenfeld 					break;
2205*4c3888b8SHans Rosenfeld 				}
2206*4c3888b8SHans Rosenfeld 				drv_usecwait(1000);
2207*4c3888b8SHans Rosenfeld 			}
2208*4c3888b8SHans Rosenfeld 			if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
2209*4c3888b8SHans Rosenfeld 				EL(ha, "nx_dev_need_reset\n");
2210*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_PEG_HALT_STATUS1,
2211*4c3888b8SHans Rosenfeld 				    &data[0]);
2212*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_PEG_HALT_STATUS2,
2213*4c3888b8SHans Rosenfeld 				    &data[1]);
2214*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_CRB_PEG_NET_0 + 0x3C,
2215*4c3888b8SHans Rosenfeld 				    &data[2]);
2216*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_CRB_PEG_NET_1 + 0x3C,
2217*4c3888b8SHans Rosenfeld 				    &data[3]);
2218*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_CRB_PEG_NET_2 + 0x3C,
2219*4c3888b8SHans Rosenfeld 				    &data[4]);
2220*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_CRB_PEG_NET_3 + 0x3C,
2221*4c3888b8SHans Rosenfeld 				    &data[5]);
2222*4c3888b8SHans Rosenfeld 				ql_8021_rd_32(ha, UNM_CRB_PEG_NET_4 + 0x3C,
2223*4c3888b8SHans Rosenfeld 				    &data[6]);
2224*4c3888b8SHans Rosenfeld 				EL(ha, "halt_status1=%xh, halt_status2=%xh,\n"
2225*4c3888b8SHans Rosenfeld 				    "peg_pc0=%xh, peg_pc1=%xh, peg_pc2=%xh, "
2226*4c3888b8SHans Rosenfeld 				    "peg_pc3=%xh, peg_pc4=%xh\n", data[0],
2227*4c3888b8SHans Rosenfeld 				    data[1], data[2], data[3], data[4],
2228*4c3888b8SHans Rosenfeld 				    data[5], data[6]);
2229*4c3888b8SHans Rosenfeld 				new_state = NX_DEV_NEED_RESET;
2230*4c3888b8SHans Rosenfeld 			}
2231eb82ff87SDaniel Beauregard 		}
2232*4c3888b8SHans Rosenfeld 	} else {
2233*4c3888b8SHans Rosenfeld 		ha->seconds_since_last_heartbeat = 0;
2234*4c3888b8SHans Rosenfeld 	}
2235eb82ff87SDaniel Beauregard 
2236*4c3888b8SHans Rosenfeld 	ha->fw_heartbeat_counter = fw_heartbeat_counter;
2237*4c3888b8SHans Rosenfeld 	return (new_state);
2238*4c3888b8SHans Rosenfeld }
2239*4c3888b8SHans Rosenfeld 
2240*4c3888b8SHans Rosenfeld int
ql_8021_reset_fw(ql_adapter_state_t * ha)2241*4c3888b8SHans Rosenfeld ql_8021_reset_fw(ql_adapter_state_t *ha)
2242*4c3888b8SHans Rosenfeld {
2243*4c3888b8SHans Rosenfeld 	return (ql_8021_idc_handler(ha, NX_DEV_NEED_RESET));
2244*4c3888b8SHans Rosenfeld }
2245*4c3888b8SHans Rosenfeld 
2246*4c3888b8SHans Rosenfeld int
ql_8021_fw_chk(ql_adapter_state_t * ha)2247*4c3888b8SHans Rosenfeld ql_8021_fw_chk(ql_adapter_state_t *ha)
2248*4c3888b8SHans Rosenfeld {
2249*4c3888b8SHans Rosenfeld 	uint32_t	dev_state, new_state = NX_DEV_POLL;
2250*4c3888b8SHans Rosenfeld 	int		rval;
2251*4c3888b8SHans Rosenfeld 	ql_mbx_data_t	mr;
2252*4c3888b8SHans Rosenfeld 
2253*4c3888b8SHans Rosenfeld 	ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
2254*4c3888b8SHans Rosenfeld 	switch (dev_state) {
2255*4c3888b8SHans Rosenfeld 	case 0xffffffff:
2256*4c3888b8SHans Rosenfeld 	case NX_DEV_COLD:
2257*4c3888b8SHans Rosenfeld 	case NX_DEV_NEED_RESET:
2258*4c3888b8SHans Rosenfeld 	case NX_DEV_NEED_QUIESCENT:
2259*4c3888b8SHans Rosenfeld 	case NX_DEV_INITIALIZING:
2260*4c3888b8SHans Rosenfeld 	case NX_DEV_QUIESCENT:
2261*4c3888b8SHans Rosenfeld 	case NX_DEV_BADOBADO:
2262*4c3888b8SHans Rosenfeld 		break;
2263*4c3888b8SHans Rosenfeld 	case NX_DEV_READY:
2264*4c3888b8SHans Rosenfeld 		if (ql_get_fw_version(ha, &mr, 2) != QL_SUCCESS ||
2265*4c3888b8SHans Rosenfeld 		    (mr.mb[1] | mr.mb[2] | mr.mb[3]) == 0) {
2266*4c3888b8SHans Rosenfeld 			EL(ha, "version check needs reset\n", dev_state);
2267*4c3888b8SHans Rosenfeld 			new_state = NX_DEV_NEED_RESET;
2268eb82ff87SDaniel Beauregard 		}
2269*4c3888b8SHans Rosenfeld 		break;
2270*4c3888b8SHans Rosenfeld 	case NX_DEV_FAILED:
2271*4c3888b8SHans Rosenfeld 		EL(ha, "device needs reset\n");
2272*4c3888b8SHans Rosenfeld 		new_state = NX_DEV_NEED_RESET;
2273*4c3888b8SHans Rosenfeld 		break;
2274*4c3888b8SHans Rosenfeld 	default:
2275*4c3888b8SHans Rosenfeld 		EL(ha, "state=%xh needs reset\n", dev_state);
2276*4c3888b8SHans Rosenfeld 		new_state = NX_DEV_COLD;
2277*4c3888b8SHans Rosenfeld 		break;
2278eb82ff87SDaniel Beauregard 	}
2279eb82ff87SDaniel Beauregard 
2280*4c3888b8SHans Rosenfeld 	/* Test for firmware running. */
2281*4c3888b8SHans Rosenfeld 	rval = ql_8021_idc_handler(ha, new_state) == NX_DEV_READY ?
2282*4c3888b8SHans Rosenfeld 	    QL_SUCCESS : QL_FUNCTION_FAILED;
2283*4c3888b8SHans Rosenfeld 
2284*4c3888b8SHans Rosenfeld 	return (rval);
2285*4c3888b8SHans Rosenfeld }
2286*4c3888b8SHans Rosenfeld 
2287*4c3888b8SHans Rosenfeld /* ****************************************************************** */
2288*4c3888b8SHans Rosenfeld /* ***************** NetXen MiniDump Functions ********************** */
2289*4c3888b8SHans Rosenfeld /* ****************************************************************** */
2290*4c3888b8SHans Rosenfeld 
2291*4c3888b8SHans Rosenfeld /*
2292*4c3888b8SHans Rosenfeld  * ql_8021_get_fw_dump
2293*4c3888b8SHans Rosenfeld  *
2294*4c3888b8SHans Rosenfeld  * Input:
2295*4c3888b8SHans Rosenfeld  *	pi:	FC port info pointer.
2296*4c3888b8SHans Rosenfeld  *
2297*4c3888b8SHans Rosenfeld  * Returns:
2298*4c3888b8SHans Rosenfeld  *	qla driver local function return status codes
2299*4c3888b8SHans Rosenfeld  *
2300*4c3888b8SHans Rosenfeld  * Context:
2301*4c3888b8SHans Rosenfeld  *	Interrupt or Kernel context, no mailbox commands allowed.
2302*4c3888b8SHans Rosenfeld  */
2303*4c3888b8SHans Rosenfeld static int
ql_8021_get_fw_dump(ql_adapter_state_t * ha)2304*4c3888b8SHans Rosenfeld ql_8021_get_fw_dump(ql_adapter_state_t *ha)
2305*4c3888b8SHans Rosenfeld {
2306*4c3888b8SHans Rosenfeld 	uint32_t	tsize, cnt, *dp, *bp;
2307*4c3888b8SHans Rosenfeld 
2308*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "started\n");
2309*4c3888b8SHans Rosenfeld 
2310*4c3888b8SHans Rosenfeld 	tsize = ha->dmp_template.size;
2311*4c3888b8SHans Rosenfeld 	cnt = (uint32_t)(tsize / sizeof (uint32_t));
2312*4c3888b8SHans Rosenfeld 	dp = (uint32_t *)ha->ql_dump_ptr;
2313*4c3888b8SHans Rosenfeld 	bp = (uint32_t *)ha->dmp_template.bp;
2314*4c3888b8SHans Rosenfeld 	while (cnt--) {
2315*4c3888b8SHans Rosenfeld 		*dp++ = ddi_get32(ha->dmp_template.acc_handle, bp++);
2316eb82ff87SDaniel Beauregard 	}
2317*4c3888b8SHans Rosenfeld 	ql_8021_md_parse_template(ha, ha->ql_dump_ptr, (caddr_t)dp,
2318*4c3888b8SHans Rosenfeld 	    ha->md_capture_size - tsize, ha->md_capture_mask);
2319*4c3888b8SHans Rosenfeld 
2320*4c3888b8SHans Rosenfeld #ifdef _BIG_ENDIAN
2321*4c3888b8SHans Rosenfeld 	cnt = (uint32_t)(ha->ql_dump_size / sizeof (uint32_t));
2322*4c3888b8SHans Rosenfeld 	dp = (uint32_t *)ha->ql_dump_ptr;
2323*4c3888b8SHans Rosenfeld 	while (cnt--) {
2324*4c3888b8SHans Rosenfeld 		ql_chg_endian((uint8_t *)dp, 4);
2325*4c3888b8SHans Rosenfeld 		dp++;
2326*4c3888b8SHans Rosenfeld 	}
2327*4c3888b8SHans Rosenfeld #endif
2328*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "done\n");
2329*4c3888b8SHans Rosenfeld 	return (QL_SUCCESS);
2330*4c3888b8SHans Rosenfeld }
2331*4c3888b8SHans Rosenfeld 
2332*4c3888b8SHans Rosenfeld /*
2333*4c3888b8SHans Rosenfeld  * ql_8021_get_md_template
2334*4c3888b8SHans Rosenfeld  *	Get mini-dump template
2335*4c3888b8SHans Rosenfeld  *
2336*4c3888b8SHans Rosenfeld  * Input:
2337*4c3888b8SHans Rosenfeld  *	ha:	adapter state pointer.
2338*4c3888b8SHans Rosenfeld  *
2339*4c3888b8SHans Rosenfeld  * Returns:
2340*4c3888b8SHans Rosenfeld  *	ql local function return status code.
2341*4c3888b8SHans Rosenfeld  *
2342*4c3888b8SHans Rosenfeld  * Context:
2343*4c3888b8SHans Rosenfeld  *	Kernel context.
2344*4c3888b8SHans Rosenfeld  */
2345*4c3888b8SHans Rosenfeld int
ql_8021_get_md_template(ql_adapter_state_t * ha)2346*4c3888b8SHans Rosenfeld ql_8021_get_md_template(ql_adapter_state_t *ha)
2347*4c3888b8SHans Rosenfeld {
2348*4c3888b8SHans Rosenfeld 	ql_mbx_data_t	mr;
2349*4c3888b8SHans Rosenfeld 	uint32_t	tsize, chksum;
2350*4c3888b8SHans Rosenfeld 	int		rval;
2351*4c3888b8SHans Rosenfeld 
2352*4c3888b8SHans Rosenfeld 	rval = ql_get_md_template(ha, NULL, &mr, 0, GTO_TEMPLATE_SIZE);
2353*4c3888b8SHans Rosenfeld 	if (rval != QL_SUCCESS ||
2354*4c3888b8SHans Rosenfeld 	    (tsize = SHORT_TO_LONG(mr.mb[2], mr.mb[3])) == 0) {
2355*4c3888b8SHans Rosenfeld 		EL(ha, "size=%xh status=%xh\n", tsize, rval);
2356*4c3888b8SHans Rosenfeld 		ha->md_capture_size = 0;
2357*4c3888b8SHans Rosenfeld 		ql_free_phys(ha, &ha->dmp_template);
2358*4c3888b8SHans Rosenfeld 		return (rval);
2359*4c3888b8SHans Rosenfeld 	}
2360*4c3888b8SHans Rosenfeld 	if (ha->dmp_template.dma_handle && ha->dmp_template.size != tsize) {
2361*4c3888b8SHans Rosenfeld 		ql_free_phys(ha, &ha->dmp_template);
2362*4c3888b8SHans Rosenfeld 	}
2363*4c3888b8SHans Rosenfeld 	ha->md_capture_mask = 0x1f;
2364*4c3888b8SHans Rosenfeld 	ha->md_capture_size = SHORT_TO_LONG(mr.mb[4], mr.mb[5]) +
2365*4c3888b8SHans Rosenfeld 	    SHORT_TO_LONG(mr.mb[6], mr.mb[7]) +
2366*4c3888b8SHans Rosenfeld 	    SHORT_TO_LONG(mr.mb[8], mr.mb[9]) +
2367*4c3888b8SHans Rosenfeld 	    SHORT_TO_LONG(mr.mb[10], mr.mb[11]) + tsize;
2368*4c3888b8SHans Rosenfeld 	/*
2369*4c3888b8SHans Rosenfeld 	 * Determine ascii dump file size
2370*4c3888b8SHans Rosenfeld 	 * 2 ascii bytes per binary byte + a space and
2371*4c3888b8SHans Rosenfeld 	 * a newline every 16 binary bytes
2372*4c3888b8SHans Rosenfeld 	 */
2373*4c3888b8SHans Rosenfeld 	ha->risc_dump_size = ha->md_capture_size << 1;
2374*4c3888b8SHans Rosenfeld 	ha->risc_dump_size += ha->md_capture_size;
2375*4c3888b8SHans Rosenfeld 	ha->risc_dump_size += ha->md_capture_size / 16 + 1;
2376*4c3888b8SHans Rosenfeld 
2377*4c3888b8SHans Rosenfeld 	/* Allocate template buffer. */
2378*4c3888b8SHans Rosenfeld 	if (ha->dmp_template.dma_handle == NULL) {
2379*4c3888b8SHans Rosenfeld 		rval = ql_get_dma_mem(ha, &ha->dmp_template, tsize,
2380*4c3888b8SHans Rosenfeld 		    LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN);
2381*4c3888b8SHans Rosenfeld 		if (rval != QL_SUCCESS) {
2382*4c3888b8SHans Rosenfeld 			EL(ha, "unable to allocate template buffer, "
2383*4c3888b8SHans Rosenfeld 			    "status=%xh\n", rval);
2384*4c3888b8SHans Rosenfeld 			ha->md_capture_size = 0;
2385*4c3888b8SHans Rosenfeld 			ql_free_phys(ha, &ha->dmp_template);
2386*4c3888b8SHans Rosenfeld 			return (rval);
2387*4c3888b8SHans Rosenfeld 		}
2388*4c3888b8SHans Rosenfeld 	}
2389*4c3888b8SHans Rosenfeld 	rval = ql_get_md_template(ha, &ha->dmp_template, &mr, 0, GTO_TEMPLATE);
2390*4c3888b8SHans Rosenfeld 	if (rval != QL_SUCCESS ||
2391*4c3888b8SHans Rosenfeld 	    (chksum = ql_8021_md_template_checksum(ha))) {
2392*4c3888b8SHans Rosenfeld 		EL(ha, "status=%xh, chksum=%xh\n", rval, chksum);
2393*4c3888b8SHans Rosenfeld 		if (rval == QL_SUCCESS) {
2394*4c3888b8SHans Rosenfeld 			rval = QL_FUNCTION_FAILED;
2395*4c3888b8SHans Rosenfeld 		}
2396*4c3888b8SHans Rosenfeld 		ql_free_phys(ha, &ha->dmp_template);
2397*4c3888b8SHans Rosenfeld 		ha->md_capture_size = 0;
2398*4c3888b8SHans Rosenfeld 	}
2399*4c3888b8SHans Rosenfeld 
2400eb82ff87SDaniel Beauregard 	return (rval);
2401eb82ff87SDaniel Beauregard }
2402*4c3888b8SHans Rosenfeld 
2403*4c3888b8SHans Rosenfeld static void
ql_8021_md_parse_template(ql_adapter_state_t * ha,caddr_t template_buff,caddr_t dump_buff,uint32_t buff_size,uint32_t capture_mask)2404*4c3888b8SHans Rosenfeld ql_8021_md_parse_template(ql_adapter_state_t *ha, caddr_t template_buff,
2405*4c3888b8SHans Rosenfeld     caddr_t dump_buff, uint32_t buff_size, uint32_t capture_mask)
2406*4c3888b8SHans Rosenfeld {
2407*4c3888b8SHans Rosenfeld 	int			e_cnt, buff_level, esize;
2408*4c3888b8SHans Rosenfeld 	uint32_t		num_of_entries;
2409*4c3888b8SHans Rosenfeld 	time_t			time;
2410*4c3888b8SHans Rosenfeld 	caddr_t			dbuff;
2411*4c3888b8SHans Rosenfeld 	int			sane_start = 0, sane_end = 0;
2412*4c3888b8SHans Rosenfeld 	md_template_hdr_t	*template_hdr;
2413*4c3888b8SHans Rosenfeld 	md_entry_t		*entry;
2414*4c3888b8SHans Rosenfeld 
2415*4c3888b8SHans Rosenfeld 	if ((capture_mask & 0x3) != 0x3) {
2416*4c3888b8SHans Rosenfeld 		EL(ha, "capture mask %02xh below minimum needed for valid "
2417*4c3888b8SHans Rosenfeld 		    "dump\n", capture_mask);
2418*4c3888b8SHans Rosenfeld 		return;
2419*4c3888b8SHans Rosenfeld 	}
2420*4c3888b8SHans Rosenfeld 	/* Setup parameters */
2421*4c3888b8SHans Rosenfeld 	template_hdr = (md_template_hdr_t *)template_buff;
2422*4c3888b8SHans Rosenfeld 	if (template_hdr->entry_type == TLHDR) {
2423*4c3888b8SHans Rosenfeld 		sane_start = 1;
2424*4c3888b8SHans Rosenfeld 	}
2425*4c3888b8SHans Rosenfeld 	(void) drv_getparm(TIME, &time);
2426*4c3888b8SHans Rosenfeld 	template_hdr->driver_timestamp = LSD(time);
2427*4c3888b8SHans Rosenfeld 	template_hdr->driver_capture_mask = capture_mask;
2428*4c3888b8SHans Rosenfeld 	num_of_entries = template_hdr->num_of_entries;
2429*4c3888b8SHans Rosenfeld 	entry = (md_entry_t *)((caddr_t)template_buff +
2430*4c3888b8SHans Rosenfeld 	    template_hdr->first_entry_offset);
2431*4c3888b8SHans Rosenfeld 	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
2432*4c3888b8SHans Rosenfeld 		/*
2433*4c3888b8SHans Rosenfeld 		 * If the capture_mask of the entry does not match capture mask
2434*4c3888b8SHans Rosenfeld 		 * skip the entry after marking the driver_flags indicator.
2435*4c3888b8SHans Rosenfeld 		 */
2436*4c3888b8SHans Rosenfeld 		if (!(entry->h.a.ecw.entry_capture_mask & capture_mask)) {
2437*4c3888b8SHans Rosenfeld 			entry->h.a.ecw.driver_flags = (uint8_t)
2438*4c3888b8SHans Rosenfeld 			    (entry->h.a.ecw.driver_flags |
2439*4c3888b8SHans Rosenfeld 			    QL_DBG_SKIPPED_FLAG);
2440*4c3888b8SHans Rosenfeld 			entry = (md_entry_t *)((char *)entry +
2441*4c3888b8SHans Rosenfeld 			    entry->h.entry_size);
2442*4c3888b8SHans Rosenfeld 			continue;
2443*4c3888b8SHans Rosenfeld 		}
2444*4c3888b8SHans Rosenfeld 		/*
2445*4c3888b8SHans Rosenfeld 		 * This is ONLY needed in implementations where
2446*4c3888b8SHans Rosenfeld 		 * the capture buffer allocated is too small to capture
2447*4c3888b8SHans Rosenfeld 		 * all of the required entries for a given capture mask.
2448*4c3888b8SHans Rosenfeld 		 * We need to empty the buffer contents to a file
2449*4c3888b8SHans Rosenfeld 		 * if possible, before processing the next entry
2450*4c3888b8SHans Rosenfeld 		 * If the buff_full_flag is set, no further capture will
2451*4c3888b8SHans Rosenfeld 		 * happen and all remaining non-control entries will be
2452*4c3888b8SHans Rosenfeld 		 * skipped.
2453*4c3888b8SHans Rosenfeld 		 */
2454*4c3888b8SHans Rosenfeld 		if (entry->h.entry_capture_size != 0) {
2455*4c3888b8SHans Rosenfeld 			if ((buff_level + entry->h.entry_capture_size) >
2456*4c3888b8SHans Rosenfeld 			    buff_size) {
2457*4c3888b8SHans Rosenfeld 				entry = (md_entry_t *)((char *)entry +
2458*4c3888b8SHans Rosenfeld 				    entry->h.entry_size);
2459*4c3888b8SHans Rosenfeld 				continue;
2460*4c3888b8SHans Rosenfeld 			}
2461*4c3888b8SHans Rosenfeld 		}
2462*4c3888b8SHans Rosenfeld 		/*
2463*4c3888b8SHans Rosenfeld 		 * Decode the entry type and process it accordingly
2464*4c3888b8SHans Rosenfeld 		 */
2465*4c3888b8SHans Rosenfeld 		switch (entry->h.entry_type) {
2466*4c3888b8SHans Rosenfeld 		case RDNOP:
2467*4c3888b8SHans Rosenfeld 			break;
2468*4c3888b8SHans Rosenfeld 		case RDEND:
2469*4c3888b8SHans Rosenfeld 			sane_end += 1;
2470*4c3888b8SHans Rosenfeld 			break;
2471*4c3888b8SHans Rosenfeld 		case RDCRB:
2472*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2473*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_rdcrb(ha, (void *)entry,
2474*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2475*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2476*4c3888b8SHans Rosenfeld 			buff_level += esize;
2477*4c3888b8SHans Rosenfeld 			break;
2478*4c3888b8SHans Rosenfeld 		case L2ITG:
2479*4c3888b8SHans Rosenfeld 		case L2DTG:
2480*4c3888b8SHans Rosenfeld 		case L2DAT:
2481*4c3888b8SHans Rosenfeld 		case L2INS:
2482*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2483*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_L2Cache(ha, (void *)entry,
2484*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2485*4c3888b8SHans Rosenfeld 			if (esize == -1) {
2486*4c3888b8SHans Rosenfeld 				entry->h.a.ecw.driver_flags = (uint8_t)
2487*4c3888b8SHans Rosenfeld 				    (entry->h.a.ecw.driver_flags |
2488*4c3888b8SHans Rosenfeld 				    QL_DBG_SKIPPED_FLAG);
2489*4c3888b8SHans Rosenfeld 			} else {
2490*4c3888b8SHans Rosenfeld 				ql_8021_md_entry_err_chk(ha, entry, esize,
2491*4c3888b8SHans Rosenfeld 				    e_cnt);
2492*4c3888b8SHans Rosenfeld 				buff_level += esize;
2493*4c3888b8SHans Rosenfeld 			}
2494*4c3888b8SHans Rosenfeld 			break;
2495*4c3888b8SHans Rosenfeld 		case L1DAT:
2496*4c3888b8SHans Rosenfeld 		case L1INS:
2497*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2498*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_L1Cache(ha, (void *)entry,
2499*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2500*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2501*4c3888b8SHans Rosenfeld 			buff_level += esize;
2502*4c3888b8SHans Rosenfeld 			break;
2503*4c3888b8SHans Rosenfeld 		case RDOCM:
2504*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2505*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_rdocm(ha, (void *)entry,
2506*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2507*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2508*4c3888b8SHans Rosenfeld 			buff_level += esize;
2509*4c3888b8SHans Rosenfeld 			break;
2510*4c3888b8SHans Rosenfeld 		case RDMEM:
2511*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2512*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_rdmem(ha, (void *)entry,
2513*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2514*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2515*4c3888b8SHans Rosenfeld 			buff_level += esize;
2516*4c3888b8SHans Rosenfeld 			break;
2517*4c3888b8SHans Rosenfeld 		case BOARD:
2518*4c3888b8SHans Rosenfeld 		case RDROM:
2519*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2520*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_rdrom(ha, (void *)entry,
2521*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2522*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2523*4c3888b8SHans Rosenfeld 			buff_level += esize;
2524*4c3888b8SHans Rosenfeld 			break;
2525*4c3888b8SHans Rosenfeld 		case RDMUX:
2526*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2527*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_rdmux(ha, (void *)entry,
2528*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2529*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2530*4c3888b8SHans Rosenfeld 			buff_level += esize;
2531*4c3888b8SHans Rosenfeld 			break;
2532*4c3888b8SHans Rosenfeld 		case QUEUE:
2533*4c3888b8SHans Rosenfeld 			dbuff = dump_buff + buff_level;
2534*4c3888b8SHans Rosenfeld 			esize = ql_8021_md_rdqueue(ha, (void *)entry,
2535*4c3888b8SHans Rosenfeld 			    (void *)dbuff);
2536*4c3888b8SHans Rosenfeld 			ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
2537*4c3888b8SHans Rosenfeld 			buff_level += esize;
2538*4c3888b8SHans Rosenfeld 			break;
2539*4c3888b8SHans Rosenfeld 		case CNTRL:
2540*4c3888b8SHans Rosenfeld 			if (ql_8021_md_cntrl(ha, template_hdr,
2541*4c3888b8SHans Rosenfeld 			    (void *)entry)) {
2542*4c3888b8SHans Rosenfeld 				entry->h.a.ecw.driver_flags = (uint8_t)
2543*4c3888b8SHans Rosenfeld 				    (entry->h.a.ecw.driver_flags |
2544*4c3888b8SHans Rosenfeld 				    QL_DBG_SKIPPED_FLAG);
2545*4c3888b8SHans Rosenfeld 				EL(ha, "Entry ID=%d, entry_type=%d non zero "
2546*4c3888b8SHans Rosenfeld 				    "status\n", e_cnt, entry->h.entry_type);
2547*4c3888b8SHans Rosenfeld 			}
2548*4c3888b8SHans Rosenfeld 			break;
2549*4c3888b8SHans Rosenfeld 		default:
2550*4c3888b8SHans Rosenfeld 			entry->h.a.ecw.driver_flags = (uint8_t)
2551*4c3888b8SHans Rosenfeld 			    (entry->h.a.ecw.driver_flags |
2552*4c3888b8SHans Rosenfeld 			    QL_DBG_SKIPPED_FLAG);
2553*4c3888b8SHans Rosenfeld 			EL(ha, "Entry ID=%d, entry_type=%d unknown\n", e_cnt,
2554*4c3888b8SHans Rosenfeld 			    entry->h.entry_type);
2555*4c3888b8SHans Rosenfeld 			break;
2556*4c3888b8SHans Rosenfeld 		}
2557*4c3888b8SHans Rosenfeld 		/* next entry in the template */
2558*4c3888b8SHans Rosenfeld 		entry = (md_entry_t *)((caddr_t)entry + entry->h.entry_size);
2559*4c3888b8SHans Rosenfeld 	}
2560*4c3888b8SHans Rosenfeld 	if (!sane_start || (sane_end > 1)) {
2561*4c3888b8SHans Rosenfeld 		EL(ha, "Template configuration error. Check Template\n");
2562*4c3888b8SHans Rosenfeld 	}
2563*4c3888b8SHans Rosenfeld 	QL_PRINT_10(ha, "Minidump num of entries=%d\n",
2564*4c3888b8SHans Rosenfeld 	    template_hdr->num_of_entries);
2565*4c3888b8SHans Rosenfeld }
2566*4c3888b8SHans Rosenfeld 
2567*4c3888b8SHans Rosenfeld /*
2568*4c3888b8SHans Rosenfeld  * Read CRB operation.
2569*4c3888b8SHans Rosenfeld  */
2570*4c3888b8SHans Rosenfeld static int
ql_8021_md_rdcrb(ql_adapter_state_t * ha,md_entry_rdcrb_t * crbEntry,uint32_t * data_buff)2571*4c3888b8SHans Rosenfeld ql_8021_md_rdcrb(ql_adapter_state_t *ha, md_entry_rdcrb_t *crbEntry,
2572*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2573*4c3888b8SHans Rosenfeld {
2574*4c3888b8SHans Rosenfeld 	uint32_t	loop_cnt, op_count, addr, stride, value;
2575*4c3888b8SHans Rosenfeld 	int		i;
2576*4c3888b8SHans Rosenfeld 
2577*4c3888b8SHans Rosenfeld 	addr = crbEntry->addr;
2578*4c3888b8SHans Rosenfeld 	op_count = crbEntry->op_count;
2579*4c3888b8SHans Rosenfeld 	stride = crbEntry->a.ac.addr_stride;
2580*4c3888b8SHans Rosenfeld 
2581*4c3888b8SHans Rosenfeld 	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
2582*4c3888b8SHans Rosenfeld 		value = ql_8021_read_reg(ha, addr);
2583*4c3888b8SHans Rosenfeld 		*data_buff++ = addr;
2584*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2585*4c3888b8SHans Rosenfeld 		addr = addr + stride;
2586*4c3888b8SHans Rosenfeld 	}
2587*4c3888b8SHans Rosenfeld 
2588*4c3888b8SHans Rosenfeld 	/*
2589*4c3888b8SHans Rosenfeld 	 * for testing purpose we return amount of data written
2590*4c3888b8SHans Rosenfeld 	 */
2591*4c3888b8SHans Rosenfeld 	i = (int)(loop_cnt * (2 * sizeof (uint32_t)));
2592*4c3888b8SHans Rosenfeld 
2593*4c3888b8SHans Rosenfeld 	return (i);
2594*4c3888b8SHans Rosenfeld }
2595*4c3888b8SHans Rosenfeld 
2596*4c3888b8SHans Rosenfeld /*
2597*4c3888b8SHans Rosenfeld  * Handle L2 Cache.
2598*4c3888b8SHans Rosenfeld  */
2599*4c3888b8SHans Rosenfeld static int
ql_8021_md_L2Cache(ql_adapter_state_t * ha,md_entry_cache_t * cacheEntry,uint32_t * data_buff)2600*4c3888b8SHans Rosenfeld ql_8021_md_L2Cache(ql_adapter_state_t *ha, md_entry_cache_t *cacheEntry,
2601*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2602*4c3888b8SHans Rosenfeld {
2603*4c3888b8SHans Rosenfeld 	int			i, k, tflag;
2604*4c3888b8SHans Rosenfeld 	uint32_t		read_value, loop_cnt, read_cnt;
2605*4c3888b8SHans Rosenfeld 	uint32_t		addr, read_addr, cntrl_addr, tag_reg_addr;
2606*4c3888b8SHans Rosenfeld 	uint32_t		cntl_value_w, tag_value, tag_value_stride;
2607*4c3888b8SHans Rosenfeld 	volatile uint8_t	cntl_value_r;
2608*4c3888b8SHans Rosenfeld 	clock_t			timeout, elapsed;
2609*4c3888b8SHans Rosenfeld 
2610*4c3888b8SHans Rosenfeld 	read_addr = cacheEntry->read_addr;
2611*4c3888b8SHans Rosenfeld 	loop_cnt = cacheEntry->op_count;
2612*4c3888b8SHans Rosenfeld 	cntrl_addr = cacheEntry->control_addr;
2613*4c3888b8SHans Rosenfeld 	cntl_value_w = CHAR_TO_SHORT(cacheEntry->b.cv.write_value[0],
2614*4c3888b8SHans Rosenfeld 	    cacheEntry->b.cv.write_value[1]);
2615*4c3888b8SHans Rosenfeld 	tag_reg_addr = cacheEntry->tag_reg_addr;
2616*4c3888b8SHans Rosenfeld 	tag_value = CHAR_TO_SHORT(cacheEntry->a.sac.init_tag_value[0],
2617*4c3888b8SHans Rosenfeld 	    cacheEntry->a.sac.init_tag_value[1]);
2618*4c3888b8SHans Rosenfeld 	tag_value_stride = CHAR_TO_SHORT(cacheEntry->a.sac.tag_value_stride[0],
2619*4c3888b8SHans Rosenfeld 	    cacheEntry->a.sac.tag_value_stride[1]);
2620*4c3888b8SHans Rosenfeld 	read_cnt = cacheEntry->c.rac.read_addr_cnt;
2621*4c3888b8SHans Rosenfeld 
2622*4c3888b8SHans Rosenfeld 	for (i = 0; i < loop_cnt; i++) {
2623*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, tag_value, tag_reg_addr);
2624*4c3888b8SHans Rosenfeld 		if (cntl_value_w) {
2625*4c3888b8SHans Rosenfeld 			ql_8021_write_reg(ha, cntl_value_w, cntrl_addr);
2626*4c3888b8SHans Rosenfeld 		}
2627*4c3888b8SHans Rosenfeld 		if (cacheEntry->b.cv.poll_wait) {
2628*4c3888b8SHans Rosenfeld 			(void) drv_getparm(LBOLT, &timeout);
2629*4c3888b8SHans Rosenfeld 			timeout += drv_usectohz(cacheEntry->b.cv.poll_wait *
2630*4c3888b8SHans Rosenfeld 			    1000) + 1;
2631*4c3888b8SHans Rosenfeld 			cntl_value_r = (uint8_t)ql_8021_read_reg(ha,
2632*4c3888b8SHans Rosenfeld 			    cntrl_addr);
2633*4c3888b8SHans Rosenfeld 			tflag = 0;
2634*4c3888b8SHans Rosenfeld 			while (!tflag && ((cntl_value_r &
2635*4c3888b8SHans Rosenfeld 			    cacheEntry->b.cv.poll_mask) != 0)) {
2636*4c3888b8SHans Rosenfeld 				(void) drv_getparm(LBOLT, &elapsed);
2637*4c3888b8SHans Rosenfeld 				if (elapsed > timeout) {
2638*4c3888b8SHans Rosenfeld 					tflag = 1;
2639*4c3888b8SHans Rosenfeld 				}
2640*4c3888b8SHans Rosenfeld 				cntl_value_r = (uint8_t)ql_8021_read_reg(ha,
2641*4c3888b8SHans Rosenfeld 				    cntrl_addr);
2642*4c3888b8SHans Rosenfeld 			}
2643*4c3888b8SHans Rosenfeld 			if (tflag) {
2644*4c3888b8SHans Rosenfeld 				/*
2645*4c3888b8SHans Rosenfeld 				 *  Report timeout error.  core dump capture
2646*4c3888b8SHans Rosenfeld 				 *  failed
2647*4c3888b8SHans Rosenfeld 				 *  Skip remaining entries. Write buffer out
2648*4c3888b8SHans Rosenfeld 				 *  to file
2649*4c3888b8SHans Rosenfeld 				 *  Use driver specific fields in template
2650*4c3888b8SHans Rosenfeld 				 *  header
2651*4c3888b8SHans Rosenfeld 				 *  to report this error.
2652*4c3888b8SHans Rosenfeld 				 */
2653*4c3888b8SHans Rosenfeld 				EL(ha, "timeout\n");
2654*4c3888b8SHans Rosenfeld 				return (-1);
2655*4c3888b8SHans Rosenfeld 			}
2656*4c3888b8SHans Rosenfeld 		}
2657*4c3888b8SHans Rosenfeld 		addr = read_addr;
2658*4c3888b8SHans Rosenfeld 		for (k = 0; k < read_cnt; k++) {
2659*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, addr);
2660*4c3888b8SHans Rosenfeld 			*data_buff++ = read_value;
2661*4c3888b8SHans Rosenfeld 			addr += cacheEntry->c.rac.read_addr_stride;
2662*4c3888b8SHans Rosenfeld 		}
2663*4c3888b8SHans Rosenfeld 		tag_value += tag_value_stride;
2664*4c3888b8SHans Rosenfeld 	}
2665*4c3888b8SHans Rosenfeld 	i = (int)(read_cnt * loop_cnt * sizeof (uint32_t));
2666*4c3888b8SHans Rosenfeld 
2667*4c3888b8SHans Rosenfeld 	return (i);
2668*4c3888b8SHans Rosenfeld }
2669*4c3888b8SHans Rosenfeld 
2670*4c3888b8SHans Rosenfeld /*
2671*4c3888b8SHans Rosenfeld  * Handle L1 Cache.
2672*4c3888b8SHans Rosenfeld  */
2673*4c3888b8SHans Rosenfeld static int
ql_8021_md_L1Cache(ql_adapter_state_t * ha,md_entry_cache_t * cacheEntry,uint32_t * data_buff)2674*4c3888b8SHans Rosenfeld ql_8021_md_L1Cache(ql_adapter_state_t *ha, md_entry_cache_t *cacheEntry,
2675*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2676*4c3888b8SHans Rosenfeld {
2677*4c3888b8SHans Rosenfeld 	int			i, k;
2678*4c3888b8SHans Rosenfeld 	uint32_t		read_value, tag_value, tag_value_stride;
2679*4c3888b8SHans Rosenfeld 	uint32_t		read_cnt, loop_cnt;
2680*4c3888b8SHans Rosenfeld 	uint32_t		addr, read_addr, cntrl_addr, tag_reg_addr;
2681*4c3888b8SHans Rosenfeld 	volatile uint32_t	cntl_value_w;
2682*4c3888b8SHans Rosenfeld 
2683*4c3888b8SHans Rosenfeld 	read_addr = cacheEntry->read_addr;
2684*4c3888b8SHans Rosenfeld 	loop_cnt = cacheEntry->op_count;
2685*4c3888b8SHans Rosenfeld 	cntrl_addr = cacheEntry->control_addr;
2686*4c3888b8SHans Rosenfeld 	cntl_value_w = CHAR_TO_SHORT(cacheEntry->b.cv.write_value[0],
2687*4c3888b8SHans Rosenfeld 	    cacheEntry->b.cv.write_value[1]);
2688*4c3888b8SHans Rosenfeld 	tag_reg_addr = cacheEntry->tag_reg_addr;
2689*4c3888b8SHans Rosenfeld 	tag_value = CHAR_TO_SHORT(cacheEntry->a.sac.init_tag_value[0],
2690*4c3888b8SHans Rosenfeld 	    cacheEntry->a.sac.init_tag_value[1]);
2691*4c3888b8SHans Rosenfeld 	tag_value_stride = CHAR_TO_SHORT(cacheEntry->a.sac.tag_value_stride[0],
2692*4c3888b8SHans Rosenfeld 	    cacheEntry->a.sac.tag_value_stride[1]);
2693*4c3888b8SHans Rosenfeld 	read_cnt = cacheEntry->c.rac.read_addr_cnt;
2694*4c3888b8SHans Rosenfeld 
2695*4c3888b8SHans Rosenfeld 	for (i = 0; i < loop_cnt; i++) {
2696*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, tag_value, tag_reg_addr);
2697*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, cntl_value_w, cntrl_addr);
2698*4c3888b8SHans Rosenfeld 		addr = read_addr;
2699*4c3888b8SHans Rosenfeld 		for (k = 0; k < read_cnt; k++) {
2700*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, addr);
2701*4c3888b8SHans Rosenfeld 			*data_buff++ = read_value;
2702*4c3888b8SHans Rosenfeld 			addr += cacheEntry->c.rac.read_addr_stride;
2703*4c3888b8SHans Rosenfeld 		}
2704*4c3888b8SHans Rosenfeld 		tag_value += tag_value_stride;
2705*4c3888b8SHans Rosenfeld 	}
2706*4c3888b8SHans Rosenfeld 	i = (int)(read_cnt * loop_cnt * sizeof (uint32_t));
2707*4c3888b8SHans Rosenfeld 
2708*4c3888b8SHans Rosenfeld 	return (i);
2709*4c3888b8SHans Rosenfeld }
2710*4c3888b8SHans Rosenfeld 
2711*4c3888b8SHans Rosenfeld /*
2712*4c3888b8SHans Rosenfeld  * Reading OCM memory
2713*4c3888b8SHans Rosenfeld  */
2714*4c3888b8SHans Rosenfeld static int
ql_8021_md_rdocm(ql_adapter_state_t * ha,md_entry_rdocm_t * ocmEntry,uint32_t * data_buff)2715*4c3888b8SHans Rosenfeld ql_8021_md_rdocm(ql_adapter_state_t *ha, md_entry_rdocm_t *ocmEntry,
2716*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2717*4c3888b8SHans Rosenfeld {
2718*4c3888b8SHans Rosenfeld 	int		i;
2719*4c3888b8SHans Rosenfeld 	uint32_t	addr, value, loop_cnt;
2720*4c3888b8SHans Rosenfeld 
2721*4c3888b8SHans Rosenfeld 	addr = ocmEntry->read_addr;
2722*4c3888b8SHans Rosenfeld 	loop_cnt = ocmEntry->op_count;
2723*4c3888b8SHans Rosenfeld 
2724*4c3888b8SHans Rosenfeld 	for (i = 0; i < loop_cnt; i++) {
2725*4c3888b8SHans Rosenfeld 		value = ql_8021_read_ocm(ha, addr);
2726*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2727*4c3888b8SHans Rosenfeld 		addr += ocmEntry->read_addr_stride;
2728*4c3888b8SHans Rosenfeld 	}
2729*4c3888b8SHans Rosenfeld 	i = (int)(loop_cnt * sizeof (value));
2730*4c3888b8SHans Rosenfeld 
2731*4c3888b8SHans Rosenfeld 	return (i);
2732*4c3888b8SHans Rosenfeld }
2733*4c3888b8SHans Rosenfeld 
2734*4c3888b8SHans Rosenfeld /*
2735*4c3888b8SHans Rosenfeld  * Read memory
2736*4c3888b8SHans Rosenfeld  */
2737*4c3888b8SHans Rosenfeld static int
ql_8021_md_rdmem(ql_adapter_state_t * ha,md_entry_rdmem_t * memEntry,uint32_t * data_buff)2738*4c3888b8SHans Rosenfeld ql_8021_md_rdmem(ql_adapter_state_t *ha, md_entry_rdmem_t *memEntry,
2739*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2740*4c3888b8SHans Rosenfeld {
2741*4c3888b8SHans Rosenfeld 	int		i, k;
2742*4c3888b8SHans Rosenfeld 	uint32_t	addr, value, loop_cnt;
2743*4c3888b8SHans Rosenfeld 
2744*4c3888b8SHans Rosenfeld 	addr = memEntry->read_addr;
2745*4c3888b8SHans Rosenfeld 	loop_cnt = (uint32_t)(memEntry->read_data_size /
2746*4c3888b8SHans Rosenfeld 	    (sizeof (uint32_t) * 4));		/* size in bytes / 16 */
2747*4c3888b8SHans Rosenfeld 
2748*4c3888b8SHans Rosenfeld 	ql_8021_write_reg(ha, 0, MD_MIU_TEST_AGT_ADDR_HI);
2749*4c3888b8SHans Rosenfeld 	for (i = 0; i < loop_cnt; i++) {
2750*4c3888b8SHans Rosenfeld 		/*
2751*4c3888b8SHans Rosenfeld 		 * Write address
2752*4c3888b8SHans Rosenfeld 		 */
2753*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, addr, MD_MIU_TEST_AGT_ADDR_LO);
2754*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, MD_TA_CTL_ENABLE,
2755*4c3888b8SHans Rosenfeld 		    MD_MIU_TEST_AGT_CTRL);
2756*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, (MD_TA_CTL_START | MD_TA_CTL_ENABLE),
2757*4c3888b8SHans Rosenfeld 		    MD_MIU_TEST_AGT_CTRL);
2758*4c3888b8SHans Rosenfeld 		/*
2759*4c3888b8SHans Rosenfeld 		 * Check busy bit.
2760*4c3888b8SHans Rosenfeld 		 */
2761*4c3888b8SHans Rosenfeld 		for (k = 0; k < MD_TA_CTL_CHECK; k++) {
2762*4c3888b8SHans Rosenfeld 			value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_CTRL);
2763*4c3888b8SHans Rosenfeld 			if ((value & MD_TA_CTL_BUSY) == 0) {
2764*4c3888b8SHans Rosenfeld 				break;
2765*4c3888b8SHans Rosenfeld 			}
2766*4c3888b8SHans Rosenfeld 		}
2767*4c3888b8SHans Rosenfeld 		if (k == MD_TA_CTL_CHECK) {
2768*4c3888b8SHans Rosenfeld 			i = (int)((uint_t)i * (sizeof (uint32_t) * 4));
2769*4c3888b8SHans Rosenfeld 			EL(ha, "failed to read=xh\n", i);
2770*4c3888b8SHans Rosenfeld 			return (i);
2771*4c3888b8SHans Rosenfeld 		}
2772*4c3888b8SHans Rosenfeld 		/*
2773*4c3888b8SHans Rosenfeld 		 * Read data
2774*4c3888b8SHans Rosenfeld 		 */
2775*4c3888b8SHans Rosenfeld 		value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_0_31);
2776*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2777*4c3888b8SHans Rosenfeld 		value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_32_63);
2778*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2779*4c3888b8SHans Rosenfeld 		value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_64_95);
2780*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2781*4c3888b8SHans Rosenfeld 		value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_96_127);
2782*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2783*4c3888b8SHans Rosenfeld 		/*
2784*4c3888b8SHans Rosenfeld 		 *  next address to read
2785*4c3888b8SHans Rosenfeld 		 */
2786*4c3888b8SHans Rosenfeld 		addr = (uint32_t)(addr + (sizeof (uint32_t) * 4));
2787*4c3888b8SHans Rosenfeld 	}
2788*4c3888b8SHans Rosenfeld 	i = (int)(loop_cnt * (sizeof (uint32_t) * 4));
2789*4c3888b8SHans Rosenfeld 
2790*4c3888b8SHans Rosenfeld 	return (i);
2791*4c3888b8SHans Rosenfeld }
2792*4c3888b8SHans Rosenfeld 
2793*4c3888b8SHans Rosenfeld /*
2794*4c3888b8SHans Rosenfeld  * Read Rom
2795*4c3888b8SHans Rosenfeld  */
2796*4c3888b8SHans Rosenfeld static int
ql_8021_md_rdrom(ql_adapter_state_t * ha,md_entry_rdrom_t * romEntry,uint32_t * data_buff)2797*4c3888b8SHans Rosenfeld ql_8021_md_rdrom(ql_adapter_state_t *ha, md_entry_rdrom_t *romEntry,
2798*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2799*4c3888b8SHans Rosenfeld {
2800*4c3888b8SHans Rosenfeld 	int		i;
2801*4c3888b8SHans Rosenfeld 	uint32_t	addr, waddr, raddr, value, loop_cnt;
2802*4c3888b8SHans Rosenfeld 
2803*4c3888b8SHans Rosenfeld 	addr = romEntry->read_addr;
2804*4c3888b8SHans Rosenfeld 	loop_cnt = romEntry->read_data_size;	/* This is size in bytes */
2805*4c3888b8SHans Rosenfeld 	loop_cnt = (uint32_t)(loop_cnt / sizeof (value));
2806*4c3888b8SHans Rosenfeld 
2807*4c3888b8SHans Rosenfeld 	for (i = 0; i < loop_cnt; i++) {
2808*4c3888b8SHans Rosenfeld 		waddr = addr & 0xFFFF0000;
2809*4c3888b8SHans Rosenfeld 		(void) ql_8021_rom_lock(ha);
2810*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, waddr, MD_DIRECT_ROM_WINDOW);
2811*4c3888b8SHans Rosenfeld 		raddr = MD_DIRECT_ROM_READ_BASE + (addr & 0x0000FFFF);
2812*4c3888b8SHans Rosenfeld 		value = ql_8021_read_reg(ha, raddr);
2813*4c3888b8SHans Rosenfeld 		ql_8021_rom_unlock(ha);
2814*4c3888b8SHans Rosenfeld 		*data_buff++ = value;
2815*4c3888b8SHans Rosenfeld 		addr = (uint32_t)(addr + sizeof (value));
2816*4c3888b8SHans Rosenfeld 	}
2817*4c3888b8SHans Rosenfeld 	i = (int)(loop_cnt * sizeof (value));
2818*4c3888b8SHans Rosenfeld 
2819*4c3888b8SHans Rosenfeld 	return (i);
2820*4c3888b8SHans Rosenfeld }
2821*4c3888b8SHans Rosenfeld 
2822*4c3888b8SHans Rosenfeld /*
2823*4c3888b8SHans Rosenfeld  * Read MUX data
2824*4c3888b8SHans Rosenfeld  */
2825*4c3888b8SHans Rosenfeld static int
ql_8021_md_rdmux(ql_adapter_state_t * ha,md_entry_mux_t * muxEntry,uint32_t * data_buff)2826*4c3888b8SHans Rosenfeld ql_8021_md_rdmux(ql_adapter_state_t *ha, md_entry_mux_t *muxEntry,
2827*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2828*4c3888b8SHans Rosenfeld {
2829*4c3888b8SHans Rosenfeld 	uint32_t	read_value, sel_value, loop_cnt;
2830*4c3888b8SHans Rosenfeld 	uint32_t	read_addr, select_addr;
2831*4c3888b8SHans Rosenfeld 	int		i;
2832*4c3888b8SHans Rosenfeld 
2833*4c3888b8SHans Rosenfeld 	select_addr = muxEntry->select_addr;
2834*4c3888b8SHans Rosenfeld 	sel_value = muxEntry->select_value;
2835*4c3888b8SHans Rosenfeld 	read_addr = muxEntry->read_addr;
2836*4c3888b8SHans Rosenfeld 
2837*4c3888b8SHans Rosenfeld 	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
2838*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, sel_value, select_addr);
2839*4c3888b8SHans Rosenfeld 		read_value = ql_8021_read_reg(ha, read_addr);
2840*4c3888b8SHans Rosenfeld 		*data_buff++ = sel_value;
2841*4c3888b8SHans Rosenfeld 		*data_buff++ = read_value;
2842*4c3888b8SHans Rosenfeld 		sel_value += muxEntry->select_value_stride;
2843*4c3888b8SHans Rosenfeld 	}
2844*4c3888b8SHans Rosenfeld 	i = (int)(loop_cnt * (2 * sizeof (uint32_t)));
2845*4c3888b8SHans Rosenfeld 
2846*4c3888b8SHans Rosenfeld 	return (i);
2847*4c3888b8SHans Rosenfeld }
2848*4c3888b8SHans Rosenfeld 
2849*4c3888b8SHans Rosenfeld /*
2850*4c3888b8SHans Rosenfeld  * Handling Queue State Reads.
2851*4c3888b8SHans Rosenfeld  */
2852*4c3888b8SHans Rosenfeld static int
ql_8021_md_rdqueue(ql_adapter_state_t * ha,md_entry_queue_t * queueEntry,uint32_t * data_buff)2853*4c3888b8SHans Rosenfeld ql_8021_md_rdqueue(ql_adapter_state_t *ha, md_entry_queue_t *queueEntry,
2854*4c3888b8SHans Rosenfeld     uint32_t *data_buff)
2855*4c3888b8SHans Rosenfeld {
2856*4c3888b8SHans Rosenfeld 	int		k;
2857*4c3888b8SHans Rosenfeld 	uint32_t	read_value, read_addr, read_stride, select_addr;
2858*4c3888b8SHans Rosenfeld 	uint32_t	queue_id, loop_cnt, read_cnt;
2859*4c3888b8SHans Rosenfeld 
2860*4c3888b8SHans Rosenfeld 	read_cnt = queueEntry->b.rac.read_addr_cnt;
2861*4c3888b8SHans Rosenfeld 	read_stride = queueEntry->b.rac.read_addr_stride;
2862*4c3888b8SHans Rosenfeld 	select_addr = queueEntry->select_addr;
2863*4c3888b8SHans Rosenfeld 
2864*4c3888b8SHans Rosenfeld 	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
2865*4c3888b8SHans Rosenfeld 	    loop_cnt++) {
2866*4c3888b8SHans Rosenfeld 		ql_8021_write_reg(ha, queue_id, select_addr);
2867*4c3888b8SHans Rosenfeld 		read_addr = queueEntry->read_addr;
2868*4c3888b8SHans Rosenfeld 		for (k = 0; k < read_cnt; k++) {
2869*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, read_addr);
2870*4c3888b8SHans Rosenfeld 			*data_buff++ = read_value;
2871*4c3888b8SHans Rosenfeld 			read_addr += read_stride;
2872*4c3888b8SHans Rosenfeld 		}
2873*4c3888b8SHans Rosenfeld 		queue_id += CHAR_TO_SHORT(queueEntry->a.sac.queue_id_stride[0],
2874*4c3888b8SHans Rosenfeld 		    queueEntry->a.sac.queue_id_stride[1]);
2875*4c3888b8SHans Rosenfeld 	}
2876*4c3888b8SHans Rosenfeld 	k = (int)(loop_cnt * (read_cnt * sizeof (uint32_t)));
2877*4c3888b8SHans Rosenfeld 
2878*4c3888b8SHans Rosenfeld 	return (k);
2879*4c3888b8SHans Rosenfeld }
2880*4c3888b8SHans Rosenfeld 
2881*4c3888b8SHans Rosenfeld /*
2882*4c3888b8SHans Rosenfeld  * Handling control entries.
2883*4c3888b8SHans Rosenfeld  */
2884*4c3888b8SHans Rosenfeld static int
ql_8021_md_cntrl(ql_adapter_state_t * ha,md_template_hdr_t * template_hdr,md_entry_cntrl_t * crbEntry)2885*4c3888b8SHans Rosenfeld ql_8021_md_cntrl(ql_adapter_state_t *ha, md_template_hdr_t *template_hdr,
2886*4c3888b8SHans Rosenfeld     md_entry_cntrl_t *crbEntry)
2887*4c3888b8SHans Rosenfeld {
2888*4c3888b8SHans Rosenfeld 	int		tflag;
2889*4c3888b8SHans Rosenfeld 	uint32_t	opcode, read_value, addr, entry_addr, loop_cnt;
2890*4c3888b8SHans Rosenfeld 	clock_t		timeout, elapsed;
2891*4c3888b8SHans Rosenfeld 
2892*4c3888b8SHans Rosenfeld 	entry_addr = crbEntry->addr;
2893*4c3888b8SHans Rosenfeld 
2894*4c3888b8SHans Rosenfeld 	for (loop_cnt = 0; loop_cnt < crbEntry->op_count; loop_cnt++) {
2895*4c3888b8SHans Rosenfeld 		opcode = crbEntry->b.cv.opcode;
2896*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_WR) {
2897*4c3888b8SHans Rosenfeld 			ql_8021_write_reg(ha, crbEntry->value_1, entry_addr);
2898*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_WR;
2899*4c3888b8SHans Rosenfeld 		}
2900*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_RW) {
2901*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, entry_addr);
2902*4c3888b8SHans Rosenfeld 			ql_8021_write_reg(ha, read_value, entry_addr);
2903*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_RW;
2904*4c3888b8SHans Rosenfeld 		}
2905*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_AND) {
2906*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, entry_addr);
2907*4c3888b8SHans Rosenfeld 			read_value &= crbEntry->value_2;
2908*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_AND;
2909*4c3888b8SHans Rosenfeld 
2910*4c3888b8SHans Rosenfeld 			/* Checking for OR here to avoid extra register write */
2911*4c3888b8SHans Rosenfeld 			if (opcode & QL_DBG_OPCODE_OR) {
2912*4c3888b8SHans Rosenfeld 				read_value |= crbEntry->value_3;
2913*4c3888b8SHans Rosenfeld 				opcode &= ~QL_DBG_OPCODE_OR;
2914*4c3888b8SHans Rosenfeld 			}
2915*4c3888b8SHans Rosenfeld 			ql_8021_write_reg(ha, read_value, entry_addr);
2916*4c3888b8SHans Rosenfeld 		}
2917*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_OR) {
2918*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, entry_addr);
2919*4c3888b8SHans Rosenfeld 			read_value |= crbEntry->value_3;
2920*4c3888b8SHans Rosenfeld 			ql_8021_write_reg(ha, read_value, entry_addr);
2921*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_OR;
2922*4c3888b8SHans Rosenfeld 		}
2923*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_POLL) {
2924*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_POLL;
2925*4c3888b8SHans Rosenfeld 			(void) drv_getparm(LBOLT, &timeout);
2926*4c3888b8SHans Rosenfeld 			timeout += drv_usectohz(
2927*4c3888b8SHans Rosenfeld 			    CHAR_TO_SHORT(crbEntry->a.ac.poll_timeout[0],
2928*4c3888b8SHans Rosenfeld 			    crbEntry->a.ac.poll_timeout[1]) * 1000) + 1;
2929*4c3888b8SHans Rosenfeld 			addr = entry_addr;
2930*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, addr);
2931*4c3888b8SHans Rosenfeld 			tflag = 0;
2932*4c3888b8SHans Rosenfeld 			while (!tflag && ((read_value & crbEntry->value_2) !=
2933*4c3888b8SHans Rosenfeld 			    crbEntry->value_1)) {
2934*4c3888b8SHans Rosenfeld 				(void) drv_getparm(LBOLT, &elapsed);
2935*4c3888b8SHans Rosenfeld 				if (elapsed > timeout) {
2936*4c3888b8SHans Rosenfeld 					tflag = 1;
2937*4c3888b8SHans Rosenfeld 				}
2938*4c3888b8SHans Rosenfeld 				read_value = ql_8021_read_reg(ha, addr);
2939*4c3888b8SHans Rosenfeld 			}
2940*4c3888b8SHans Rosenfeld 			if (tflag) {
2941*4c3888b8SHans Rosenfeld 				/*
2942*4c3888b8SHans Rosenfeld 				 *  Report timeout error.  core dump capture
2943*4c3888b8SHans Rosenfeld 				 *  failed Skip remaining entries. Write buffer
2944*4c3888b8SHans Rosenfeld 				 *  out to file Use driver specific fields in
2945*4c3888b8SHans Rosenfeld 				 *  template header to report this error.
2946*4c3888b8SHans Rosenfeld 				 */
2947*4c3888b8SHans Rosenfeld 				EL(ha, "timeout\n");
2948*4c3888b8SHans Rosenfeld 				return (-1);
2949*4c3888b8SHans Rosenfeld 			}
2950*4c3888b8SHans Rosenfeld 		}
2951*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_RDSTATE) {
2952*4c3888b8SHans Rosenfeld 			/*
2953*4c3888b8SHans Rosenfeld 			 * decide which address to use.
2954*4c3888b8SHans Rosenfeld 			 */
2955*4c3888b8SHans Rosenfeld 			if (crbEntry->a.ac.state_index_a) {
2956*4c3888b8SHans Rosenfeld 				addr = template_hdr->saved_state_array[
2957*4c3888b8SHans Rosenfeld 				    crbEntry->a.ac.state_index_a];
2958*4c3888b8SHans Rosenfeld 			} else {
2959*4c3888b8SHans Rosenfeld 				addr = entry_addr;
2960*4c3888b8SHans Rosenfeld 			}
2961*4c3888b8SHans Rosenfeld 			read_value = ql_8021_read_reg(ha, addr);
2962*4c3888b8SHans Rosenfeld 			template_hdr->saved_state_array[
2963*4c3888b8SHans Rosenfeld 			    crbEntry->b.cv.state_index_v] = read_value;
2964*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_RDSTATE;
2965*4c3888b8SHans Rosenfeld 		}
2966*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_WRSTATE) {
2967*4c3888b8SHans Rosenfeld 			/*
2968*4c3888b8SHans Rosenfeld 			 * decide which value to use.
2969*4c3888b8SHans Rosenfeld 			 */
2970*4c3888b8SHans Rosenfeld 			if (crbEntry->b.cv.state_index_v) {
2971*4c3888b8SHans Rosenfeld 				read_value = template_hdr->saved_state_array[
2972*4c3888b8SHans Rosenfeld 				    crbEntry->b.cv.state_index_v];
2973*4c3888b8SHans Rosenfeld 			} else {
2974*4c3888b8SHans Rosenfeld 				read_value = crbEntry->value_1;
2975*4c3888b8SHans Rosenfeld 			}
2976*4c3888b8SHans Rosenfeld 			/*
2977*4c3888b8SHans Rosenfeld 			 * decide which address to use.
2978*4c3888b8SHans Rosenfeld 			 */
2979*4c3888b8SHans Rosenfeld 			if (crbEntry->a.ac.state_index_a) {
2980*4c3888b8SHans Rosenfeld 				addr = template_hdr->saved_state_array[
2981*4c3888b8SHans Rosenfeld 				    crbEntry->a.ac.state_index_a];
2982*4c3888b8SHans Rosenfeld 			} else {
2983*4c3888b8SHans Rosenfeld 				addr = entry_addr;
2984*4c3888b8SHans Rosenfeld 			}
2985*4c3888b8SHans Rosenfeld 			ql_8021_write_reg(ha, read_value, addr);
2986*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_WRSTATE;
2987*4c3888b8SHans Rosenfeld 		}
2988*4c3888b8SHans Rosenfeld 		if (opcode & QL_DBG_OPCODE_MDSTATE) {
2989*4c3888b8SHans Rosenfeld 			/* Read value from saved state using index */
2990*4c3888b8SHans Rosenfeld 			read_value = template_hdr->saved_state_array[
2991*4c3888b8SHans Rosenfeld 			    crbEntry->b.cv.state_index_v];
2992*4c3888b8SHans Rosenfeld 			/* Shift left operation */
2993*4c3888b8SHans Rosenfeld 			read_value <<= crbEntry->b.cv.shl;
2994*4c3888b8SHans Rosenfeld 			/* Shift right operation */
2995*4c3888b8SHans Rosenfeld 			read_value >>= crbEntry->b.cv.shr;
2996*4c3888b8SHans Rosenfeld 			/* check if AND mask is provided */
2997*4c3888b8SHans Rosenfeld 			if (crbEntry->value_2) {
2998*4c3888b8SHans Rosenfeld 				read_value &= crbEntry->value_2;
2999*4c3888b8SHans Rosenfeld 			}
3000*4c3888b8SHans Rosenfeld 			read_value |= crbEntry->value_3; /* OR operation */
3001*4c3888b8SHans Rosenfeld 			read_value += crbEntry->value_1; /* inc operation */
3002*4c3888b8SHans Rosenfeld 			/* Write value back to state area. */
3003*4c3888b8SHans Rosenfeld 			template_hdr->saved_state_array[
3004*4c3888b8SHans Rosenfeld 			    crbEntry->b.cv.state_index_v] = read_value;
3005*4c3888b8SHans Rosenfeld 			opcode &= ~QL_DBG_OPCODE_MDSTATE;
3006*4c3888b8SHans Rosenfeld 		}
3007*4c3888b8SHans Rosenfeld 		entry_addr += crbEntry->a.ac.addr_stride;
3008*4c3888b8SHans Rosenfeld 	}
3009*4c3888b8SHans Rosenfeld 
3010*4c3888b8SHans Rosenfeld 	return (0);
3011*4c3888b8SHans Rosenfeld }
3012*4c3888b8SHans Rosenfeld 
3013*4c3888b8SHans Rosenfeld /*
3014*4c3888b8SHans Rosenfeld  * Error Checking routines for template consistency.
3015*4c3888b8SHans Rosenfeld  *
3016*4c3888b8SHans Rosenfeld  * We catch an error where driver does not read
3017*4c3888b8SHans Rosenfeld  * as much data as we expect from the entry.
3018*4c3888b8SHans Rosenfeld  */
3019*4c3888b8SHans Rosenfeld static void
ql_8021_md_entry_err_chk(ql_adapter_state_t * ha,md_entry_t * entry,uint32_t esize,int e_cnt)3020*4c3888b8SHans Rosenfeld ql_8021_md_entry_err_chk(ql_adapter_state_t *ha, md_entry_t *entry,
3021*4c3888b8SHans Rosenfeld     uint32_t esize, int e_cnt)
3022*4c3888b8SHans Rosenfeld {
3023*4c3888b8SHans Rosenfeld 	if (esize != entry->h.entry_capture_size) {
3024*4c3888b8SHans Rosenfeld 		EL(ha, "%d %04x Dump write count = %d did not match entry "
3025*4c3888b8SHans Rosenfeld 		    "capture size = %d entry_count = %d\n", entry->h.entry_type,
3026*4c3888b8SHans Rosenfeld 		    entry->h.a.ecw.entry_capture_mask, esize,
3027*4c3888b8SHans Rosenfeld 		    entry->h.entry_capture_size, e_cnt);
3028*4c3888b8SHans Rosenfeld 		entry->h.entry_capture_size = esize;
3029*4c3888b8SHans Rosenfeld 		entry->h.a.ecw.driver_flags = (uint8_t)
3030*4c3888b8SHans Rosenfeld 		    (entry->h.a.ecw.driver_flags | QL_DBG_SKIPPED_FLAG);
3031*4c3888b8SHans Rosenfeld 	}
3032*4c3888b8SHans Rosenfeld }
3033*4c3888b8SHans Rosenfeld 
3034*4c3888b8SHans Rosenfeld static uint32_t
ql_8021_md_template_checksum(ql_adapter_state_t * ha)3035*4c3888b8SHans Rosenfeld ql_8021_md_template_checksum(ql_adapter_state_t *ha)
3036*4c3888b8SHans Rosenfeld {
3037*4c3888b8SHans Rosenfeld 	uint64_t	sum = 0;
3038*4c3888b8SHans Rosenfeld 	uint32_t	cnt, *bp;
3039*4c3888b8SHans Rosenfeld 
3040*4c3888b8SHans Rosenfeld 	cnt = (uint32_t)(ha->dmp_template.size / sizeof (uint32_t));
3041*4c3888b8SHans Rosenfeld 	bp = ha->dmp_template.bp;
3042*4c3888b8SHans Rosenfeld 	while (cnt-- > 0) {
3043*4c3888b8SHans Rosenfeld 		sum += ddi_get32(ha->dmp_template.acc_handle, bp++);
3044*4c3888b8SHans Rosenfeld 	}
3045*4c3888b8SHans Rosenfeld 	while (sum >> 32) {
3046*4c3888b8SHans Rosenfeld 		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
3047*4c3888b8SHans Rosenfeld 	}
3048*4c3888b8SHans Rosenfeld 	cnt = (uint32_t)~sum;
3049*4c3888b8SHans Rosenfeld 
3050*4c3888b8SHans Rosenfeld 	return (cnt);
3051*4c3888b8SHans Rosenfeld }
3052*4c3888b8SHans Rosenfeld 
3053*4c3888b8SHans Rosenfeld static uint32_t
ql_8021_read_reg(ql_adapter_state_t * ha,uint32_t addr)3054*4c3888b8SHans Rosenfeld ql_8021_read_reg(ql_adapter_state_t *ha, uint32_t addr)
3055*4c3888b8SHans Rosenfeld {
3056*4c3888b8SHans Rosenfeld 	uint32_t	addr0, addr1, value;
3057*4c3888b8SHans Rosenfeld 
3058*4c3888b8SHans Rosenfeld 	(void) ql_8021_crb_win_lock(ha);
3059*4c3888b8SHans Rosenfeld 
3060*4c3888b8SHans Rosenfeld 	addr0 = addr & 0xFFFF0000;
3061*4c3888b8SHans Rosenfeld 	WRT_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060), addr0);
3062*4c3888b8SHans Rosenfeld 	/* PCI posting read */
3063*4c3888b8SHans Rosenfeld 	(void) RD_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060));
3064*4c3888b8SHans Rosenfeld 	addr1 = addr & 0x0000FFFF;
3065*4c3888b8SHans Rosenfeld 	value = RD_REG_DWORD(ha, (ha->nx_pcibase + 0x001E0000 + addr1));
3066*4c3888b8SHans Rosenfeld 
3067*4c3888b8SHans Rosenfeld 	ql_8021_crb_win_unlock(ha);
3068*4c3888b8SHans Rosenfeld 
3069*4c3888b8SHans Rosenfeld 	return (value);
3070*4c3888b8SHans Rosenfeld }
3071*4c3888b8SHans Rosenfeld 
3072*4c3888b8SHans Rosenfeld static void
ql_8021_write_reg(ql_adapter_state_t * ha,uint32_t value,uint32_t addr)3073*4c3888b8SHans Rosenfeld ql_8021_write_reg(ql_adapter_state_t *ha, uint32_t value, uint32_t addr)
3074*4c3888b8SHans Rosenfeld {
3075*4c3888b8SHans Rosenfeld 	uint32_t	addr0, addr1;
3076*4c3888b8SHans Rosenfeld 
3077*4c3888b8SHans Rosenfeld 	(void) ql_8021_crb_win_lock(ha);
3078*4c3888b8SHans Rosenfeld 
3079*4c3888b8SHans Rosenfeld 	addr0 = addr & 0xFFFF0000;
3080*4c3888b8SHans Rosenfeld 	WRT_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060), addr0);
3081*4c3888b8SHans Rosenfeld 	/* PCI posting read */
3082*4c3888b8SHans Rosenfeld 	(void) RD_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060));
3083*4c3888b8SHans Rosenfeld 	addr1 = addr & 0x0000FFFF;
3084*4c3888b8SHans Rosenfeld 	WRT_REG_DWORD(ha, (ha->nx_pcibase + 0x001E0000 + addr1), value);
3085*4c3888b8SHans Rosenfeld 	/* PCI posting read */
3086*4c3888b8SHans Rosenfeld 	(void) RD_REG_DWORD(ha, (ha->nx_pcibase + 0x001E0000 + addr1));
3087*4c3888b8SHans Rosenfeld 
3088*4c3888b8SHans Rosenfeld 	ql_8021_crb_win_unlock(ha);
3089*4c3888b8SHans Rosenfeld }
3090*4c3888b8SHans Rosenfeld 
3091*4c3888b8SHans Rosenfeld static uint32_t
ql_8021_read_ocm(ql_adapter_state_t * ha,uint32_t addr)3092*4c3888b8SHans Rosenfeld ql_8021_read_ocm(ql_adapter_state_t *ha, uint32_t addr)
3093*4c3888b8SHans Rosenfeld {
3094*4c3888b8SHans Rosenfeld 	uint32_t	value;
3095*4c3888b8SHans Rosenfeld 
3096*4c3888b8SHans Rosenfeld 	value = RD_REG_DWORD(ha, (ha->nx_pcibase + addr));
3097*4c3888b8SHans Rosenfeld 
3098*4c3888b8SHans Rosenfeld 	return (value);
3099*4c3888b8SHans Rosenfeld }
3100