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 /*
23eb82ff87SDaniel Beauregard  * Copyright 2010 QLogic Corporation.  All rights reserved.
24eb82ff87SDaniel Beauregard  * Use is subject to license terms.
25eb82ff87SDaniel Beauregard  */
26eb82ff87SDaniel Beauregard 
27eb82ff87SDaniel Beauregard #pragma ident	"Copyright 2010 QLogic Corporation; ql_nx.c"
28eb82ff87SDaniel Beauregard 
29eb82ff87SDaniel Beauregard /*
30eb82ff87SDaniel Beauregard  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
31eb82ff87SDaniel Beauregard  *
32eb82ff87SDaniel Beauregard  * ***********************************************************************
33eb82ff87SDaniel Beauregard  * *									**
34eb82ff87SDaniel Beauregard  * *				NOTICE					**
35eb82ff87SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
36eb82ff87SDaniel Beauregard  * *			ALL RIGHTS RESERVED				**
37eb82ff87SDaniel Beauregard  * *									**
38eb82ff87SDaniel Beauregard  * ***********************************************************************
39eb82ff87SDaniel Beauregard  *
40eb82ff87SDaniel Beauregard  */
41eb82ff87SDaniel Beauregard 
42eb82ff87SDaniel Beauregard #include <ql_apps.h>
43eb82ff87SDaniel Beauregard #include <ql_api.h>
44eb82ff87SDaniel Beauregard #include <ql_debug.h>
45eb82ff87SDaniel Beauregard #include <ql_mbx.h>
46eb82ff87SDaniel Beauregard #include <ql_nx.h>
47eb82ff87SDaniel Beauregard 
48eb82ff87SDaniel Beauregard /*
49eb82ff87SDaniel Beauregard  *  Local Function Prototypes.
50eb82ff87SDaniel Beauregard  */
51eb82ff87SDaniel Beauregard static void *ql_8021_pci_base_offsetfset(ql_adapter_state_t *, uint64_t);
52eb82ff87SDaniel Beauregard static void ql_crb_addr_transform_setup(ql_adapter_state_t *);
53eb82ff87SDaniel Beauregard static void ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *, uint64_t *);
54eb82ff87SDaniel Beauregard static void ql_8021_wr_32(ql_adapter_state_t *, uint64_t, uint32_t);
55eb82ff87SDaniel Beauregard static void ql_8021_rd_32(ql_adapter_state_t *, uint64_t, uint32_t *);
56eb82ff87SDaniel Beauregard static int ql_8021_crb_win_lock(ql_adapter_state_t *);
57eb82ff87SDaniel Beauregard static void ql_8021_crb_win_unlock(ql_adapter_state_t *);
58eb82ff87SDaniel Beauregard static int ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *, uint64_t *);
59eb82ff87SDaniel Beauregard static uint32_t ql_8021_pci_mem_bound_check(ql_adapter_state_t *, uint64_t,
60eb82ff87SDaniel Beauregard     uint32_t);
61eb82ff87SDaniel Beauregard static uint64_t ql_8021_pci_set_window(ql_adapter_state_t *, uint64_t);
62eb82ff87SDaniel Beauregard static int ql_8021_pci_is_same_window(ql_adapter_state_t *, uint64_t);
63eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_read_direct(ql_adapter_state_t *, uint64_t, void *,
64eb82ff87SDaniel Beauregard     uint32_t);
65eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_write_direct(ql_adapter_state_t *, uint64_t, void *,
66eb82ff87SDaniel Beauregard     uint32_t);
67eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_read_2M(ql_adapter_state_t *, uint64_t, void *,
68eb82ff87SDaniel Beauregard     uint32_t);
69eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_write_2M(ql_adapter_state_t *, uint64_t, void *,
70eb82ff87SDaniel Beauregard     uint32_t);
71eb82ff87SDaniel Beauregard static uint32_t ql_8021_decode_crb_addr(ql_adapter_state_t *, uint32_t);
72eb82ff87SDaniel Beauregard static int ql_8021_rom_lock(ql_adapter_state_t *);
73eb82ff87SDaniel Beauregard static void ql_8021_rom_unlock(ql_adapter_state_t *);
74eb82ff87SDaniel Beauregard static int ql_8021_wait_rom_done(ql_adapter_state_t *);
75eb82ff87SDaniel Beauregard static int ql_8021_wait_flash_done(ql_adapter_state_t *);
76eb82ff87SDaniel Beauregard static int ql_8021_do_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *);
77eb82ff87SDaniel Beauregard static int ql_8021_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *);
78eb82ff87SDaniel Beauregard static int ql_8021_do_rom_write(ql_adapter_state_t *, uint32_t, uint32_t);
79eb82ff87SDaniel Beauregard static int ql_8021_do_rom_erase(ql_adapter_state_t *, uint32_t);
80eb82ff87SDaniel Beauregard static int ql_8021_phantom_init(ql_adapter_state_t *);
81eb82ff87SDaniel Beauregard static int ql_8021_pinit_from_rom(ql_adapter_state_t *);
82eb82ff87SDaniel Beauregard static int ql_8021_load_from_flash(ql_adapter_state_t *);
83eb82ff87SDaniel Beauregard static int ql_8021_load_firmware(ql_adapter_state_t *);
84eb82ff87SDaniel Beauregard static int ql_8021_reset_hw(ql_adapter_state_t *, int);
85eb82ff87SDaniel Beauregard static int ql_8021_init_p3p(ql_adapter_state_t *);
86eb82ff87SDaniel Beauregard static int ql_8021_hw_lock(ql_adapter_state_t *, uint32_t);
87eb82ff87SDaniel Beauregard static void ql_8021_hw_unlock(ql_adapter_state_t *);
88eb82ff87SDaniel Beauregard static void ql_8021_need_reset_handler(ql_adapter_state_t *);
89eb82ff87SDaniel Beauregard 
90eb82ff87SDaniel Beauregard /*
91eb82ff87SDaniel Beauregard  * Local Data.
92eb82ff87SDaniel Beauregard  */
93eb82ff87SDaniel Beauregard static uint32_t	crb_addr_xform[MAX_CRB_XFORM];
94eb82ff87SDaniel Beauregard static int	crb_table_initialized = 0;
95eb82ff87SDaniel Beauregard static int	pci_set_window_warning_count = 0;
96eb82ff87SDaniel Beauregard 
97eb82ff87SDaniel Beauregard static struct legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
98eb82ff87SDaniel Beauregard 
99eb82ff87SDaniel Beauregard static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
100eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 0: PCI */
101eb82ff87SDaniel Beauregard 	{{{1, 0x0100000, 0x0102000, 0x120000},		/* 1: PCIE */
102eb82ff87SDaniel Beauregard 	    {1, 0x0110000, 0x0120000, 0x130000},
103eb82ff87SDaniel Beauregard 	    {1, 0x0120000, 0x0122000, 0x124000},
104eb82ff87SDaniel Beauregard 	    {1, 0x0130000, 0x0132000, 0x126000},
105eb82ff87SDaniel Beauregard 	    {1, 0x0140000, 0x0142000, 0x128000},
106eb82ff87SDaniel Beauregard 	    {1, 0x0150000, 0x0152000, 0x12a000},
107eb82ff87SDaniel Beauregard 	    {1, 0x0160000, 0x0170000, 0x110000},
108eb82ff87SDaniel Beauregard 	    {1, 0x0170000, 0x0172000, 0x12e000},
109eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
110eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
111eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
112eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
113eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
114eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
115eb82ff87SDaniel Beauregard 	    {1, 0x01e0000, 0x01e0800, 0x122000},
116eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000}}},
117eb82ff87SDaniel Beauregard 	{{{1, 0x0200000, 0x0210000, 0x180000}}},	/* 2: MN */
118eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 3: */
119eb82ff87SDaniel Beauregard 	{{{1, 0x0400000, 0x0401000, 0x169000}}},	/* 4: P2NR1 */
120eb82ff87SDaniel Beauregard 	{{{1, 0x0500000, 0x0510000, 0x140000}}},	/* 5: SRE   */
121eb82ff87SDaniel Beauregard 	{{{1, 0x0600000, 0x0610000, 0x1c0000}}},	/* 6: NIU   */
122eb82ff87SDaniel Beauregard 	{{{1, 0x0700000, 0x0704000, 0x1b8000}}},	/* 7: QM    */
123eb82ff87SDaniel Beauregard 	{{{1, 0x0800000, 0x0802000, 0x170000},  	/* 8: SQM0  */
124eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
125eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
126eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
127eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
128eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
129eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
130eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
131eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
132eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
133eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
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 	    {1, 0x08f0000, 0x08f2000, 0x172000}}},
139eb82ff87SDaniel Beauregard 	{{{1, 0x0900000, 0x0902000, 0x174000},		/* 9: SQM1 */
140eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
141eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
142eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
143eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
144eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
145eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
146eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
147eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
148eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
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 	    {1, 0x09f0000, 0x09f2000, 0x176000}}},
155eb82ff87SDaniel Beauregard 	{{{0, 0x0a00000, 0x0a02000, 0x178000},		/* 10: SQM2 */
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 	    {0, 0x0000000, 0x0000000, 0x000000},
164eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
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 	    {1, 0x0af0000, 0x0af2000, 0x17a000}}},
171eb82ff87SDaniel Beauregard 	{{{0, 0x0b00000, 0x0b02000, 0x17c000},		/* 11: SQM3 */
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 	    {0, 0x0000000, 0x0000000, 0x000000},
180eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
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 	    {1, 0x0bf0000, 0x0bf2000, 0x17e000}}},
187eb82ff87SDaniel Beauregard 	{{{1, 0x0c00000, 0x0c04000, 0x1d4000}}},	/* 12: I2Q */
188eb82ff87SDaniel Beauregard 	{{{1, 0x0d00000, 0x0d04000, 0x1a4000}}},	/* 13: TMR */
189eb82ff87SDaniel Beauregard 	{{{1, 0x0e00000, 0x0e04000, 0x1a0000}}},	/* 14: ROMUSB */
190eb82ff87SDaniel Beauregard 	{{{1, 0x0f00000, 0x0f01000, 0x164000}}},	/* 15: PEG4 */
191eb82ff87SDaniel Beauregard 	{{{0, 0x1000000, 0x1004000, 0x1a8000}}},	/* 16: XDMA */
192eb82ff87SDaniel Beauregard 	{{{1, 0x1100000, 0x1101000, 0x160000}}},	/* 17: PEG0 */
193eb82ff87SDaniel Beauregard 	{{{1, 0x1200000, 0x1201000, 0x161000}}},	/* 18: PEG1 */
194eb82ff87SDaniel Beauregard 	{{{1, 0x1300000, 0x1301000, 0x162000}}},	/* 19: PEG2 */
195eb82ff87SDaniel Beauregard 	{{{1, 0x1400000, 0x1401000, 0x163000}}},	/* 20: PEG3 */
196eb82ff87SDaniel Beauregard 	{{{1, 0x1500000, 0x1501000, 0x165000}}},	/* 21: P2ND */
197eb82ff87SDaniel Beauregard 	{{{1, 0x1600000, 0x1601000, 0x166000}}},	/* 22: P2NI */
198eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 23: */
199eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 24: */
200eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 25: */
201eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 26: */
202eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 27: */
203eb82ff87SDaniel Beauregard 	{{{0, 0,	 0,	 0}}},			/* 28: */
204eb82ff87SDaniel Beauregard 	{{{1, 0x1d00000, 0x1d10000, 0x190000}}},	/* 29: MS */
205eb82ff87SDaniel Beauregard 	{{{1, 0x1e00000, 0x1e01000, 0x16a000}}},	/* 30: P2NR2 */
206eb82ff87SDaniel Beauregard 	{{{1, 0x1f00000, 0x1f10000, 0x150000}}},	/* 31: EPG */
207eb82ff87SDaniel Beauregard 	{{{0}}},					/* 32: PCI */
208eb82ff87SDaniel Beauregard 	{{{1, 0x2100000, 0x2102000, 0x120000},		/* 33: PCIE */
209eb82ff87SDaniel Beauregard 	    {1, 0x2110000, 0x2120000, 0x130000},
210eb82ff87SDaniel Beauregard 	    {1, 0x2120000, 0x2122000, 0x124000},
211eb82ff87SDaniel Beauregard 	    {1, 0x2130000, 0x2132000, 0x126000},
212eb82ff87SDaniel Beauregard 	    {1, 0x2140000, 0x2142000, 0x128000},
213eb82ff87SDaniel Beauregard 	    {1, 0x2150000, 0x2152000, 0x12a000},
214eb82ff87SDaniel Beauregard 	    {1, 0x2160000, 0x2170000, 0x110000},
215eb82ff87SDaniel Beauregard 	    {1, 0x2170000, 0x2172000, 0x12e000},
216eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
217eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
218eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
219eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
220eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
221eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
222eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000},
223eb82ff87SDaniel Beauregard 	    {0, 0x0000000, 0x0000000, 0x000000}}},
224eb82ff87SDaniel Beauregard 	{{{1, 0x2200000, 0x2204000, 0x1b0000}}},	/* 34: CAM */
225eb82ff87SDaniel Beauregard 	{{{0}}},					/* 35: */
226eb82ff87SDaniel Beauregard 	{{{0}}},					/* 36: */
227eb82ff87SDaniel Beauregard 	{{{0}}},					/* 37: */
228eb82ff87SDaniel Beauregard 	{{{0}}},					/* 38: */
229eb82ff87SDaniel Beauregard 	{{{0}}},					/* 39: */
230eb82ff87SDaniel Beauregard 	{{{1, 0x2800000, 0x2804000, 0x1a4000}}},	/* 40: TMR */
231eb82ff87SDaniel Beauregard 	{{{1, 0x2900000, 0x2901000, 0x16b000}}},	/* 41: P2NR3 */
232eb82ff87SDaniel Beauregard 	{{{1, 0x2a00000, 0x2a00400, 0x1ac400}}},	/* 42: RPMX1 */
233eb82ff87SDaniel Beauregard 	{{{1, 0x2b00000, 0x2b00400, 0x1ac800}}},	/* 43: RPMX2 */
234eb82ff87SDaniel Beauregard 	{{{1, 0x2c00000, 0x2c00400, 0x1acc00}}},	/* 44: RPMX3 */
235eb82ff87SDaniel Beauregard 	{{{1, 0x2d00000, 0x2d00400, 0x1ad000}}},	/* 45: RPMX4 */
236eb82ff87SDaniel Beauregard 	{{{1, 0x2e00000, 0x2e00400, 0x1ad400}}},	/* 46: RPMX5 */
237eb82ff87SDaniel Beauregard 	{{{1, 0x2f00000, 0x2f00400, 0x1ad800}}},	/* 47: RPMX6 */
238eb82ff87SDaniel Beauregard 	{{{1, 0x3000000, 0x3000400, 0x1adc00}}},	/* 48: RPMX7 */
239eb82ff87SDaniel Beauregard 	{{{0, 0x3100000, 0x3104000, 0x1a8000}}},	/* 49: XDMA */
240eb82ff87SDaniel Beauregard 	{{{1, 0x3200000, 0x3204000, 0x1d4000}}},	/* 50: I2Q */
241eb82ff87SDaniel Beauregard 	{{{1, 0x3300000, 0x3304000, 0x1a0000}}},	/* 51: ROMUSB */
242eb82ff87SDaniel Beauregard 	{{{0}}},					/* 52: */
243eb82ff87SDaniel Beauregard 	{{{1, 0x3500000, 0x3500400, 0x1ac000}}},	/* 53: RPMX0 */
244eb82ff87SDaniel Beauregard 	{{{1, 0x3600000, 0x3600400, 0x1ae000}}},	/* 54: RPMX8 */
245eb82ff87SDaniel Beauregard 	{{{1, 0x3700000, 0x3700400, 0x1ae400}}},	/* 55: RPMX9 */
246eb82ff87SDaniel Beauregard 	{{{1, 0x3800000, 0x3804000, 0x1d0000}}},	/* 56: OCM0 */
247eb82ff87SDaniel Beauregard 	{{{1, 0x3900000, 0x3904000, 0x1b4000}}},	/* 57: CRYPTO */
248eb82ff87SDaniel Beauregard 	{{{1, 0x3a00000, 0x3a04000, 0x1d8000}}},	/* 58: SMB */
249eb82ff87SDaniel Beauregard 	{{{0}}},					/* 59: I2C0 */
250eb82ff87SDaniel Beauregard 	{{{0}}},					/* 60: I2C1 */
251eb82ff87SDaniel Beauregard 	{{{1, 0x3d00000, 0x3d04000, 0x1dc000}}},	/* 61: LPC */
252eb82ff87SDaniel Beauregard 	{{{1, 0x3e00000, 0x3e01000, 0x167000}}},	/* 62: P2NC */
253eb82ff87SDaniel Beauregard 	{{{1, 0x3f00000, 0x3f01000, 0x168000}}}		/* 63: P2NR0 */
254eb82ff87SDaniel Beauregard };
255eb82ff87SDaniel Beauregard 
256eb82ff87SDaniel Beauregard /*
257eb82ff87SDaniel Beauregard  * top 12 bits of crb internal address (hub, agent)
258eb82ff87SDaniel Beauregard  */
259eb82ff87SDaniel Beauregard static uint32_t crb_hub_agt[64] = {
260eb82ff87SDaniel Beauregard 	0,
261eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PS,
262eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_MN,
263eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_MS,
264eb82ff87SDaniel Beauregard 	0,
265eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SRE,
266eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_NIU,
267eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_QMN,
268eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN0,
269eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN1,
270eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN2,
271eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SQN3,
272eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
273eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
274eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
275eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN4,
276eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
277eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN0,
278eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN1,
279eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN2,
280eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGN3,
281eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGND,
282eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGNI,
283eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS0,
284eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS1,
285eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS2,
286eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGS3,
287eb82ff87SDaniel Beauregard 	0,
288eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGSI,
289eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SN,
290eb82ff87SDaniel Beauregard 	0,
291eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_EG,
292eb82ff87SDaniel Beauregard 	0,
293eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PS,
294eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_CAM,
295eb82ff87SDaniel Beauregard 	0,
296eb82ff87SDaniel Beauregard 	0,
297eb82ff87SDaniel Beauregard 	0,
298eb82ff87SDaniel Beauregard 	0,
299eb82ff87SDaniel Beauregard 	0,
300eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
301eb82ff87SDaniel Beauregard 	0,
302eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX1,
303eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX2,
304eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX3,
305eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX4,
306eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX5,
307eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX6,
308eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX7,
309eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
310eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
311eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
312eb82ff87SDaniel Beauregard 	0,
313eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX0,
314eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX8,
315eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_RPMX9,
316eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_OCM0,
317eb82ff87SDaniel Beauregard 	0,
318eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_SMB,
319eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2C0,
320eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_I2C1,
321eb82ff87SDaniel Beauregard 	0,
322eb82ff87SDaniel Beauregard 	UNM_HW_CRB_HUB_AGT_ADR_PGNC,
323eb82ff87SDaniel Beauregard 	0,
324eb82ff87SDaniel Beauregard };
325eb82ff87SDaniel Beauregard 
326eb82ff87SDaniel Beauregard static void *
327eb82ff87SDaniel Beauregard ql_8021_pci_base_offsetfset(ql_adapter_state_t *ha, uint64_t off)
328eb82ff87SDaniel Beauregard {
329eb82ff87SDaniel Beauregard 	if ((off < ha->first_page_group_end) &&
330eb82ff87SDaniel Beauregard 	    (off >= ha->first_page_group_start)) {
331eb82ff87SDaniel Beauregard 		return ((void *)(ha->nx_pcibase + off));
332eb82ff87SDaniel Beauregard 	}
333eb82ff87SDaniel Beauregard 
334eb82ff87SDaniel Beauregard 	return (NULL);
335eb82ff87SDaniel Beauregard }
336eb82ff87SDaniel Beauregard 
337eb82ff87SDaniel Beauregard /* ARGSUSED */
338eb82ff87SDaniel Beauregard static void
339eb82ff87SDaniel Beauregard ql_crb_addr_transform_setup(ql_adapter_state_t *ha)
340eb82ff87SDaniel Beauregard {
341eb82ff87SDaniel Beauregard 	crb_addr_transform(XDMA);
342eb82ff87SDaniel Beauregard 	crb_addr_transform(TIMR);
343eb82ff87SDaniel Beauregard 	crb_addr_transform(SRE);
344eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN3);
345eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN2);
346eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN1);
347eb82ff87SDaniel Beauregard 	crb_addr_transform(SQN0);
348eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS3);
349eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS2);
350eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS1);
351eb82ff87SDaniel Beauregard 	crb_addr_transform(SQS0);
352eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX7);
353eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX6);
354eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX5);
355eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX4);
356eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX3);
357eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX2);
358eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX1);
359eb82ff87SDaniel Beauregard 	crb_addr_transform(RPMX0);
360eb82ff87SDaniel Beauregard 	crb_addr_transform(ROMUSB);
361eb82ff87SDaniel Beauregard 	crb_addr_transform(SN);
362eb82ff87SDaniel Beauregard 	crb_addr_transform(QMN);
363eb82ff87SDaniel Beauregard 	crb_addr_transform(QMS);
364eb82ff87SDaniel Beauregard 	crb_addr_transform(PGNI);
365eb82ff87SDaniel Beauregard 	crb_addr_transform(PGND);
366eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN3);
367eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN2);
368eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN1);
369eb82ff87SDaniel Beauregard 	crb_addr_transform(PGN0);
370eb82ff87SDaniel Beauregard 	crb_addr_transform(PGSI);
371eb82ff87SDaniel Beauregard 	crb_addr_transform(PGSD);
372eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS3);
373eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS2);
374eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS1);
375eb82ff87SDaniel Beauregard 	crb_addr_transform(PGS0);
376eb82ff87SDaniel Beauregard 	crb_addr_transform(PS);
377eb82ff87SDaniel Beauregard 	crb_addr_transform(PH);
378eb82ff87SDaniel Beauregard 	crb_addr_transform(NIU);
379eb82ff87SDaniel Beauregard 	crb_addr_transform(I2Q);
380eb82ff87SDaniel Beauregard 	crb_addr_transform(EG);
381eb82ff87SDaniel Beauregard 	crb_addr_transform(MN);
382eb82ff87SDaniel Beauregard 	crb_addr_transform(MS);
383eb82ff87SDaniel Beauregard 	crb_addr_transform(CAS2);
384eb82ff87SDaniel Beauregard 	crb_addr_transform(CAS1);
385eb82ff87SDaniel Beauregard 	crb_addr_transform(CAS0);
386eb82ff87SDaniel Beauregard 	crb_addr_transform(CAM);
387eb82ff87SDaniel Beauregard 	crb_addr_transform(C2C1);
388eb82ff87SDaniel Beauregard 	crb_addr_transform(C2C0);
389eb82ff87SDaniel Beauregard 	crb_addr_transform(SMB);
390eb82ff87SDaniel Beauregard 	crb_addr_transform(OCM0);
391eb82ff87SDaniel Beauregard 	/*
392eb82ff87SDaniel Beauregard 	 * Used only in P3 just define it for P2 also.
393eb82ff87SDaniel Beauregard 	 */
394eb82ff87SDaniel Beauregard 	crb_addr_transform(I2C0);
395eb82ff87SDaniel Beauregard 
396eb82ff87SDaniel Beauregard 	crb_table_initialized = 1;
397eb82ff87SDaniel Beauregard }
398eb82ff87SDaniel Beauregard 
399eb82ff87SDaniel Beauregard /*
400eb82ff87SDaniel Beauregard  * In: 'off' is offset from CRB space in 128M pci map
401eb82ff87SDaniel Beauregard  * Out: 'off' is 2M pci map addr
402eb82ff87SDaniel Beauregard  * side effect: lock crb window
403eb82ff87SDaniel Beauregard  */
404eb82ff87SDaniel Beauregard static void
405eb82ff87SDaniel Beauregard ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *ha, uint64_t *off)
406eb82ff87SDaniel Beauregard {
407eb82ff87SDaniel Beauregard 	uint32_t	win_read;
408eb82ff87SDaniel Beauregard 
409eb82ff87SDaniel Beauregard 	ha->crb_win = (uint32_t)CRB_HI(*off);
410eb82ff87SDaniel Beauregard 	WRT_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase, ha->crb_win);
411eb82ff87SDaniel Beauregard 
412eb82ff87SDaniel Beauregard 	/*
413eb82ff87SDaniel Beauregard 	 * Read back value to make sure write has gone through before trying
414eb82ff87SDaniel Beauregard 	 * to use it.
415eb82ff87SDaniel Beauregard 	 */
416eb82ff87SDaniel Beauregard 	win_read = RD_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase);
417eb82ff87SDaniel Beauregard 	if (win_read != ha->crb_win) {
418eb82ff87SDaniel Beauregard 		EL(ha, "Written crbwin (0x%x) != Read crbwin (0x%x), "
419eb82ff87SDaniel Beauregard 		    "off=0x%llx\n", ha->crb_win, win_read, *off);
420eb82ff87SDaniel Beauregard 	}
421eb82ff87SDaniel Beauregard 	*off = (*off & MASK(16)) + CRB_INDIRECT_2M + (uintptr_t)ha->nx_pcibase;
422eb82ff87SDaniel Beauregard }
423eb82ff87SDaniel Beauregard 
424eb82ff87SDaniel Beauregard static void
425eb82ff87SDaniel Beauregard ql_8021_wr_32(ql_adapter_state_t *ha, uint64_t off, uint32_t data)
426eb82ff87SDaniel Beauregard {
427eb82ff87SDaniel Beauregard 	int	rv;
428eb82ff87SDaniel Beauregard 
429eb82ff87SDaniel Beauregard 	rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
430eb82ff87SDaniel Beauregard 	if (rv == -1) {
431eb82ff87SDaniel Beauregard 		cmn_err(CE_PANIC, "ql_8021_wr_32, ql_8021_pci_get_crb_addr_"
432eb82ff87SDaniel Beauregard 		    "2M=-1\n");
433eb82ff87SDaniel Beauregard 	}
434eb82ff87SDaniel Beauregard 	if (rv == 1) {
435eb82ff87SDaniel Beauregard 		(void) ql_8021_crb_win_lock(ha);
436eb82ff87SDaniel Beauregard 		ql_8021_pci_set_crbwindow_2M(ha, &off);
437eb82ff87SDaniel Beauregard 	}
438eb82ff87SDaniel Beauregard 
439eb82ff87SDaniel Beauregard 	WRT_REG_DWORD(ha, (uintptr_t)off, data);
440eb82ff87SDaniel Beauregard 
441eb82ff87SDaniel Beauregard 	if (rv == 1) {
442eb82ff87SDaniel Beauregard 		ql_8021_crb_win_unlock(ha);
443eb82ff87SDaniel Beauregard 	}
444eb82ff87SDaniel Beauregard }
445eb82ff87SDaniel Beauregard 
446eb82ff87SDaniel Beauregard static void
447eb82ff87SDaniel Beauregard ql_8021_rd_32(ql_adapter_state_t *ha, uint64_t off, uint32_t *data)
448eb82ff87SDaniel Beauregard {
449eb82ff87SDaniel Beauregard 	int		rv;
450eb82ff87SDaniel Beauregard 	uint32_t	n;
451eb82ff87SDaniel Beauregard 
452eb82ff87SDaniel Beauregard 	rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
453eb82ff87SDaniel Beauregard 	if (rv == -1) {
454eb82ff87SDaniel Beauregard 		cmn_err(CE_PANIC, "ql_8021_rd_32, ql_8021_pci_get_crb_addr_"
455eb82ff87SDaniel Beauregard 		    "2M=-1\n");
456eb82ff87SDaniel Beauregard 	}
457eb82ff87SDaniel Beauregard 
458eb82ff87SDaniel Beauregard 	if (rv == 1) {
459eb82ff87SDaniel Beauregard 		(void) ql_8021_crb_win_lock(ha);
460eb82ff87SDaniel Beauregard 		ql_8021_pci_set_crbwindow_2M(ha, &off);
461eb82ff87SDaniel Beauregard 	}
462eb82ff87SDaniel Beauregard 	n = RD_REG_DWORD(ha, (uintptr_t)off);
463eb82ff87SDaniel Beauregard 
464eb82ff87SDaniel Beauregard 	if (data != NULL) {
465eb82ff87SDaniel Beauregard 		*data = n;
466eb82ff87SDaniel Beauregard 	}
467eb82ff87SDaniel Beauregard 
468eb82ff87SDaniel Beauregard 	if (rv == 1) {
469eb82ff87SDaniel Beauregard 		ql_8021_crb_win_unlock(ha);
470eb82ff87SDaniel Beauregard 	}
471eb82ff87SDaniel Beauregard }
472eb82ff87SDaniel Beauregard 
473eb82ff87SDaniel Beauregard static int
474eb82ff87SDaniel Beauregard ql_8021_crb_win_lock(ql_adapter_state_t *ha)
475eb82ff87SDaniel Beauregard {
476eb82ff87SDaniel Beauregard 	uint32_t	done = 0, timeout = 0;
477eb82ff87SDaniel Beauregard 
478eb82ff87SDaniel Beauregard 	while (!done) {
479eb82ff87SDaniel Beauregard 		/* acquire semaphore3 from PCI HW block */
480eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_LOCK), &done);
481eb82ff87SDaniel Beauregard 		if (done == 1) {
482eb82ff87SDaniel Beauregard 			break;
483eb82ff87SDaniel Beauregard 		}
484eb82ff87SDaniel Beauregard 		if (timeout >= CRB_WIN_LOCK_TIMEOUT) {
485eb82ff87SDaniel Beauregard 			EL(ha, "timeout\n");
486eb82ff87SDaniel Beauregard 			return (-1);
487eb82ff87SDaniel Beauregard 		}
488eb82ff87SDaniel Beauregard 		timeout++;
489eb82ff87SDaniel Beauregard 
490eb82ff87SDaniel Beauregard 		/* Yield CPU */
491eb82ff87SDaniel Beauregard 		delay(1);
492eb82ff87SDaniel Beauregard 	}
493eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_WIN_LOCK_ID, ha->function_number);
494eb82ff87SDaniel Beauregard 
495eb82ff87SDaniel Beauregard 	return (0);
496eb82ff87SDaniel Beauregard }
497eb82ff87SDaniel Beauregard 
498eb82ff87SDaniel Beauregard static void
499eb82ff87SDaniel Beauregard ql_8021_crb_win_unlock(ql_adapter_state_t *ha)
500eb82ff87SDaniel Beauregard {
501eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_UNLOCK), NULL);
502eb82ff87SDaniel Beauregard }
503eb82ff87SDaniel Beauregard 
504eb82ff87SDaniel Beauregard static int
505eb82ff87SDaniel Beauregard ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *ha, uint64_t *off)
506eb82ff87SDaniel Beauregard {
507eb82ff87SDaniel Beauregard 	crb_128M_2M_sub_block_map_t	*m;
508eb82ff87SDaniel Beauregard 
509eb82ff87SDaniel Beauregard 	if (*off >= UNM_CRB_MAX) {
510eb82ff87SDaniel Beauregard 		EL(ha, "%llx >= %llx\n", *off, UNM_CRB_MAX);
511eb82ff87SDaniel Beauregard 		return (-1);
512eb82ff87SDaniel Beauregard 	}
513eb82ff87SDaniel Beauregard 
514eb82ff87SDaniel Beauregard 	if (*off >= UNM_PCI_CAMQM && (*off < UNM_PCI_CAMQM_2M_END)) {
515eb82ff87SDaniel Beauregard 		*off = (*off - UNM_PCI_CAMQM) + UNM_PCI_CAMQM_2M_BASE +
516eb82ff87SDaniel Beauregard 		    (uintptr_t)ha->nx_pcibase;
517eb82ff87SDaniel Beauregard 		return (0);
518eb82ff87SDaniel Beauregard 	}
519eb82ff87SDaniel Beauregard 
520eb82ff87SDaniel Beauregard 	if (*off < UNM_PCI_CRBSPACE) {
521eb82ff87SDaniel Beauregard 		EL(ha, "%llx < %llx\n", *off, UNM_PCI_CRBSPACE);
522eb82ff87SDaniel Beauregard 		return (-1);
523eb82ff87SDaniel Beauregard 	}
524eb82ff87SDaniel Beauregard 
525eb82ff87SDaniel Beauregard 	*off -= UNM_PCI_CRBSPACE;
526eb82ff87SDaniel Beauregard 	/*
527eb82ff87SDaniel Beauregard 	 * Try direct map
528eb82ff87SDaniel Beauregard 	 */
529eb82ff87SDaniel Beauregard 
530eb82ff87SDaniel Beauregard 	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
531eb82ff87SDaniel Beauregard 
532eb82ff87SDaniel Beauregard 	if (m->valid && ((uint64_t)m->start_128M <= *off) &&
533eb82ff87SDaniel Beauregard 	    ((uint64_t)m->end_128M > *off)) {
534eb82ff87SDaniel Beauregard 		*off = (uint64_t)(*off + m->start_2M - m->start_128M +
535eb82ff87SDaniel Beauregard 		    (uintptr_t)ha->nx_pcibase);
536eb82ff87SDaniel Beauregard 		return (0);
537eb82ff87SDaniel Beauregard 	}
538eb82ff87SDaniel Beauregard 
539eb82ff87SDaniel Beauregard 	/*
540eb82ff87SDaniel Beauregard 	 * Not in direct map, use crb window
541eb82ff87SDaniel Beauregard 	 */
542eb82ff87SDaniel Beauregard 	return (1);
543eb82ff87SDaniel Beauregard }
544eb82ff87SDaniel Beauregard 
545eb82ff87SDaniel Beauregard /*
546eb82ff87SDaniel Beauregard  * check memory access boundary.
547eb82ff87SDaniel Beauregard  * used by test agent. support ddr access only for now
548eb82ff87SDaniel Beauregard  */
549eb82ff87SDaniel Beauregard /* ARGSUSED */
550eb82ff87SDaniel Beauregard static uint32_t
551eb82ff87SDaniel Beauregard ql_8021_pci_mem_bound_check(ql_adapter_state_t *ha, uint64_t addr,
552eb82ff87SDaniel Beauregard     uint32_t size)
553eb82ff87SDaniel Beauregard {
554eb82ff87SDaniel Beauregard 	/*LINTED suspicious 0 comparison*/
555eb82ff87SDaniel Beauregard 	if (!QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
556eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX) ||
557eb82ff87SDaniel Beauregard 	    /*LINTED suspicious 0 comparison*/
558eb82ff87SDaniel Beauregard 	    !QL_8021_ADDR_IN_RANGE(addr + size - 1, UNM_ADDR_DDR_NET,
559eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX) ||
560eb82ff87SDaniel Beauregard 	    ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
561eb82ff87SDaniel Beauregard 		return (0);
562eb82ff87SDaniel Beauregard 	}
563eb82ff87SDaniel Beauregard 
564eb82ff87SDaniel Beauregard 	return (1);
565eb82ff87SDaniel Beauregard }
566eb82ff87SDaniel Beauregard 
567eb82ff87SDaniel Beauregard static uint64_t
568eb82ff87SDaniel Beauregard ql_8021_pci_set_window(ql_adapter_state_t *ha, uint64_t addr)
569eb82ff87SDaniel Beauregard {
570eb82ff87SDaniel Beauregard 	uint32_t	window, win_read;
571eb82ff87SDaniel Beauregard 
572eb82ff87SDaniel Beauregard 	/*LINTED suspicious 0 comparison*/
573eb82ff87SDaniel Beauregard 	if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
574eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX)) {
575eb82ff87SDaniel Beauregard 		/* DDR network side */
576eb82ff87SDaniel Beauregard 		window = (uint32_t)MN_WIN(addr);
577eb82ff87SDaniel Beauregard 		ha->ddr_mn_window = window;
578eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
579eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
580eb82ff87SDaniel Beauregard 		    &win_read);
581eb82ff87SDaniel Beauregard 		if ((win_read << 17) != window) {
582eb82ff87SDaniel Beauregard 			EL(ha, "Warning, Written MNwin (0x%x) != Read MNwin "
583eb82ff87SDaniel Beauregard 			    "(0x%x)\n", window, win_read);
584eb82ff87SDaniel Beauregard 		}
585eb82ff87SDaniel Beauregard 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
586eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
587eb82ff87SDaniel Beauregard 	    UNM_ADDR_OCM0_MAX)) {
588eb82ff87SDaniel Beauregard 		uint32_t	temp1;
589eb82ff87SDaniel Beauregard 
590eb82ff87SDaniel Beauregard 		if ((addr & 0x00ff800) == 0xff800) {
591eb82ff87SDaniel Beauregard 			/* if bits 19:18&17:11 are on */
592eb82ff87SDaniel Beauregard 			EL(ha, "QM access not handled\n");
593eb82ff87SDaniel Beauregard 			addr = -1UL;
594eb82ff87SDaniel Beauregard 		}
595eb82ff87SDaniel Beauregard 
596eb82ff87SDaniel Beauregard 		window = (uint32_t)OCM_WIN(addr);
597eb82ff87SDaniel Beauregard 		ha->ddr_mn_window = window;
598eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
599eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
600eb82ff87SDaniel Beauregard 		    &win_read);
601eb82ff87SDaniel Beauregard 		temp1 = ((window & 0x1FF) << 7) |
602eb82ff87SDaniel Beauregard 		    ((window & 0x0FFFE0000) >> 17);
603eb82ff87SDaniel Beauregard 		if (win_read != temp1) {
604eb82ff87SDaniel Beauregard 			EL(ha, "Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
605eb82ff87SDaniel Beauregard 			    temp1, win_read);
606eb82ff87SDaniel Beauregard 		}
607eb82ff87SDaniel Beauregard 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
608eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
609eb82ff87SDaniel Beauregard 	    NX_P3_ADDR_QDR_NET_MAX)) {
610eb82ff87SDaniel Beauregard 		/* QDR network side */
611eb82ff87SDaniel Beauregard 		window = (uint32_t)MS_WIN(addr);
612eb82ff87SDaniel Beauregard 		ha->qdr_sn_window = window;
613eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
614eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
615eb82ff87SDaniel Beauregard 		    &win_read);
616eb82ff87SDaniel Beauregard 		if (win_read != window) {
617eb82ff87SDaniel Beauregard 			EL(ha, "Written MSwin (0x%x) != Read MSwin (0x%x)\n",
618eb82ff87SDaniel Beauregard 			    window, win_read);
619eb82ff87SDaniel Beauregard 		}
620eb82ff87SDaniel Beauregard 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
621eb82ff87SDaniel Beauregard 	} else {
622eb82ff87SDaniel Beauregard 		/*
623eb82ff87SDaniel Beauregard 		 * peg gdb frequently accesses memory that doesn't exist,
624eb82ff87SDaniel Beauregard 		 * this limits the chit chat so debugging isn't slowed down.
625eb82ff87SDaniel Beauregard 		 */
626eb82ff87SDaniel Beauregard 		if ((pci_set_window_warning_count++ < 8) ||
627eb82ff87SDaniel Beauregard 		    (pci_set_window_warning_count % 64 == 0)) {
628eb82ff87SDaniel Beauregard 			EL(ha, "Unknown address range\n");
629eb82ff87SDaniel Beauregard 		}
630eb82ff87SDaniel Beauregard 		addr = -1UL;
631eb82ff87SDaniel Beauregard 	}
632eb82ff87SDaniel Beauregard 
633eb82ff87SDaniel Beauregard 	return (addr);
634eb82ff87SDaniel Beauregard }
635eb82ff87SDaniel Beauregard 
636eb82ff87SDaniel Beauregard /* check if address is in the same windows as the previous access */
637eb82ff87SDaniel Beauregard static int
638eb82ff87SDaniel Beauregard ql_8021_pci_is_same_window(ql_adapter_state_t *ha, uint64_t addr)
639eb82ff87SDaniel Beauregard {
640eb82ff87SDaniel Beauregard 	uint32_t	window;
641eb82ff87SDaniel Beauregard 	uint64_t	qdr_max;
642eb82ff87SDaniel Beauregard 
643eb82ff87SDaniel Beauregard 	qdr_max = NX_P3_ADDR_QDR_NET_MAX;
644eb82ff87SDaniel Beauregard 
645eb82ff87SDaniel Beauregard 	/*LINTED suspicious 0 comparison*/
646eb82ff87SDaniel Beauregard 	if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
647eb82ff87SDaniel Beauregard 	    UNM_ADDR_DDR_NET_MAX)) {
648eb82ff87SDaniel Beauregard 		/* DDR network side */
649eb82ff87SDaniel Beauregard 		EL(ha, "DDR network side\n");
650eb82ff87SDaniel Beauregard 		return (0);	/* MN access can not come here */
651eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
652eb82ff87SDaniel Beauregard 	    UNM_ADDR_OCM0_MAX)) {
653eb82ff87SDaniel Beauregard 		return (1);
654eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM1,
655eb82ff87SDaniel Beauregard 	    UNM_ADDR_OCM1_MAX)) {
656eb82ff87SDaniel Beauregard 		return (1);
657eb82ff87SDaniel Beauregard 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
658eb82ff87SDaniel Beauregard 		/* QDR network side */
659eb82ff87SDaniel Beauregard 		window = (uint32_t)(((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f);
660eb82ff87SDaniel Beauregard 		if (ha->qdr_sn_window == window) {
661eb82ff87SDaniel Beauregard 			return (1);
662eb82ff87SDaniel Beauregard 		}
663eb82ff87SDaniel Beauregard 	}
664eb82ff87SDaniel Beauregard 
665eb82ff87SDaniel Beauregard 	return (0);
666eb82ff87SDaniel Beauregard }
667eb82ff87SDaniel Beauregard 
668eb82ff87SDaniel Beauregard static int
669eb82ff87SDaniel Beauregard ql_8021_pci_mem_read_direct(ql_adapter_state_t *ha, uint64_t off, void *data,
670eb82ff87SDaniel Beauregard     uint32_t size)
671eb82ff87SDaniel Beauregard {
672eb82ff87SDaniel Beauregard 	void		*addr;
673eb82ff87SDaniel Beauregard 	int		ret = 0;
674eb82ff87SDaniel Beauregard 	uint64_t	start;
675eb82ff87SDaniel Beauregard 
676eb82ff87SDaniel Beauregard 	/*
677eb82ff87SDaniel Beauregard 	 * If attempting to access unknown address or straddle hw windows,
678eb82ff87SDaniel Beauregard 	 * do not access.
679eb82ff87SDaniel Beauregard 	 */
680eb82ff87SDaniel Beauregard 	if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
681eb82ff87SDaniel Beauregard 	    (ql_8021_pci_is_same_window(ha, off + size - 1) == 0)) {
682eb82ff87SDaniel Beauregard 		EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
683eb82ff87SDaniel Beauregard 		    off);
684eb82ff87SDaniel Beauregard 		return (-1);
685eb82ff87SDaniel Beauregard 	}
686eb82ff87SDaniel Beauregard 
687eb82ff87SDaniel Beauregard 	addr = ql_8021_pci_base_offsetfset(ha, start);
688eb82ff87SDaniel Beauregard 	if (!addr) {
689eb82ff87SDaniel Beauregard 		addr = (void *)((uint8_t *)ha->nx_pcibase + start);
690eb82ff87SDaniel Beauregard 	}
691eb82ff87SDaniel Beauregard 
692eb82ff87SDaniel Beauregard 	switch (size) {
693eb82ff87SDaniel Beauregard 	case 1:
694eb82ff87SDaniel Beauregard 		*(uint8_t  *)data = RD_REG_BYTE(ha, addr);
695eb82ff87SDaniel Beauregard 		break;
696eb82ff87SDaniel Beauregard 	case 2:
697eb82ff87SDaniel Beauregard 		*(uint16_t  *)data = RD_REG_WORD(ha, addr);
698eb82ff87SDaniel Beauregard 		break;
699eb82ff87SDaniel Beauregard 	case 4:
700eb82ff87SDaniel Beauregard 		*(uint32_t  *)data = RD_REG_DWORD(ha, addr);
701eb82ff87SDaniel Beauregard 		break;
702eb82ff87SDaniel Beauregard 	case 8:
703eb82ff87SDaniel Beauregard 		*(uint64_t  *)data = RD_REG_DDWORD(ha, addr);
704eb82ff87SDaniel Beauregard 		break;
705eb82ff87SDaniel Beauregard 	default:
706eb82ff87SDaniel Beauregard 		EL(ha, "invalid size=%x\n", size);
707eb82ff87SDaniel Beauregard 		ret = -1;
708eb82ff87SDaniel Beauregard 		break;
709eb82ff87SDaniel Beauregard 	}
710eb82ff87SDaniel Beauregard 
711eb82ff87SDaniel Beauregard 	return (ret);
712eb82ff87SDaniel Beauregard }
713eb82ff87SDaniel Beauregard 
714eb82ff87SDaniel Beauregard static int
715eb82ff87SDaniel Beauregard ql_8021_pci_mem_write_direct(ql_adapter_state_t *ha, uint64_t off, void *data,
716eb82ff87SDaniel Beauregard     uint32_t size)
717eb82ff87SDaniel Beauregard {
718eb82ff87SDaniel Beauregard 	void		*addr;
719eb82ff87SDaniel Beauregard 	int		ret = 0;
720eb82ff87SDaniel Beauregard 	uint64_t	start;
721eb82ff87SDaniel Beauregard 
722eb82ff87SDaniel Beauregard 	/*
723eb82ff87SDaniel Beauregard 	 * If attempting to access unknown address or straddle hw windows,
724eb82ff87SDaniel Beauregard 	 * do not access.
725eb82ff87SDaniel Beauregard 	 */
726eb82ff87SDaniel Beauregard 	if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
727eb82ff87SDaniel Beauregard 	    (ql_8021_pci_is_same_window(ha, off + size -1) == 0)) {
728eb82ff87SDaniel Beauregard 		EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
729eb82ff87SDaniel Beauregard 		    off);
730eb82ff87SDaniel Beauregard 		return (-1);
731eb82ff87SDaniel Beauregard 	}
732eb82ff87SDaniel Beauregard 
733eb82ff87SDaniel Beauregard 	addr = ql_8021_pci_base_offsetfset(ha, start);
734eb82ff87SDaniel Beauregard 	if (!addr) {
735eb82ff87SDaniel Beauregard 		addr = (void *)((uint8_t *)ha->nx_pcibase + start);
736eb82ff87SDaniel Beauregard 	}
737eb82ff87SDaniel Beauregard 
738eb82ff87SDaniel Beauregard 	switch (size) {
739eb82ff87SDaniel Beauregard 	case 1:
740eb82ff87SDaniel Beauregard 		WRT_REG_BYTE(ha, addr, *(uint8_t *)data);
741eb82ff87SDaniel Beauregard 		break;
742eb82ff87SDaniel Beauregard 	case 2:
743eb82ff87SDaniel Beauregard 		WRT_REG_WORD(ha, addr, *(uint16_t *)data);
744eb82ff87SDaniel Beauregard 		break;
745eb82ff87SDaniel Beauregard 	case 4:
746eb82ff87SDaniel Beauregard 		WRT_REG_DWORD(ha, addr, *(uint32_t *)data);
747eb82ff87SDaniel Beauregard 		break;
748eb82ff87SDaniel Beauregard 	case 8:
749eb82ff87SDaniel Beauregard 		WRT_REG_DDWORD(ha, addr, *(uint64_t *)data);
750eb82ff87SDaniel Beauregard 		break;
751eb82ff87SDaniel Beauregard 	default:
752eb82ff87SDaniel Beauregard 		EL(ha, "invalid size=%x\n", size);
753eb82ff87SDaniel Beauregard 		ret = -1;
754eb82ff87SDaniel Beauregard 		break;
755eb82ff87SDaniel Beauregard 	}
756eb82ff87SDaniel Beauregard 
757eb82ff87SDaniel Beauregard 	return (ret);
758eb82ff87SDaniel Beauregard }
759eb82ff87SDaniel Beauregard 
760eb82ff87SDaniel Beauregard static int
761eb82ff87SDaniel Beauregard ql_8021_pci_mem_read_2M(ql_adapter_state_t *ha, uint64_t off, void *data,
762eb82ff87SDaniel Beauregard     uint32_t size)
763eb82ff87SDaniel Beauregard {
764eb82ff87SDaniel Beauregard 	int		j = 0;
765eb82ff87SDaniel Beauregard 	uint32_t	i, temp, sz[2], loop, shift_amount;
766eb82ff87SDaniel Beauregard 	uint64_t	start, end, k;
767eb82ff87SDaniel Beauregard 	uint64_t	off8, off0[2], val, mem_crb, word[2] = {0, 0};
768eb82ff87SDaniel Beauregard 
769eb82ff87SDaniel Beauregard 	/*
770eb82ff87SDaniel Beauregard 	 * If not MN, go check for MS or invalid.
771eb82ff87SDaniel Beauregard 	 */
772eb82ff87SDaniel Beauregard 
773eb82ff87SDaniel Beauregard 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
774eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_QDR_NET;
775eb82ff87SDaniel Beauregard 	} else {
776eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_DDR_NET;
777eb82ff87SDaniel Beauregard 		if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) {
778eb82ff87SDaniel Beauregard 			return (ql_8021_pci_mem_read_direct(ha, off, data,
779eb82ff87SDaniel Beauregard 			    size));
780eb82ff87SDaniel Beauregard 		}
781eb82ff87SDaniel Beauregard 	}
782eb82ff87SDaniel Beauregard 
783eb82ff87SDaniel Beauregard 	if (NX_IS_REVISION_P3PLUS(ha->rev_id)) {
784eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff0;
785eb82ff87SDaniel Beauregard 		off0[0] = off & 0xf;
786eb82ff87SDaniel Beauregard 		sz[0] = (uint32_t)(((uint64_t)size < (16 - off0[0])) ? size :
787eb82ff87SDaniel Beauregard 		    (16 - off0[0]));
788eb82ff87SDaniel Beauregard 		shift_amount = 4;
789eb82ff87SDaniel Beauregard 	} else {
790eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff8;
791eb82ff87SDaniel Beauregard 		off0[0] = off & 0x7;
792eb82ff87SDaniel Beauregard 		sz[0] = (uint32_t)(((uint64_t)size < (8 - off0[0])) ? size :
793eb82ff87SDaniel Beauregard 		    (8 - off0[0]));
794eb82ff87SDaniel Beauregard 		shift_amount = 3;
795eb82ff87SDaniel Beauregard 	}
796eb82ff87SDaniel Beauregard 	loop = (uint32_t)(((off0[0] + size - 1) >> shift_amount) + 1);
797eb82ff87SDaniel Beauregard 	off0[1] = 0;
798eb82ff87SDaniel Beauregard 	sz[1] = size - sz[0];
799eb82ff87SDaniel Beauregard 
800eb82ff87SDaniel Beauregard 	/*
801eb82ff87SDaniel Beauregard 	 * don't lock here - write_wx gets the lock if each time
802eb82ff87SDaniel Beauregard 	 * write_lock_irqsave(&adapter->adapter_lock, flags);
803eb82ff87SDaniel Beauregard 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
804eb82ff87SDaniel Beauregard 	 */
805eb82ff87SDaniel Beauregard 
806eb82ff87SDaniel Beauregard 	for (i = 0; i < loop; i++) {
807eb82ff87SDaniel Beauregard 		temp = (uint32_t)(off8 + (i << shift_amount));
808eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
809eb82ff87SDaniel Beauregard 		temp = 0;
810eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
811eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_ENABLE;
812eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
813eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
814eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
815eb82ff87SDaniel Beauregard 
816eb82ff87SDaniel Beauregard 		for (j = 0; j < MAX_CTL_CHECK; j++) {
817eb82ff87SDaniel Beauregard 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp);
818eb82ff87SDaniel Beauregard 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
819eb82ff87SDaniel Beauregard 				break;
820eb82ff87SDaniel Beauregard 			}
821eb82ff87SDaniel Beauregard 		}
822eb82ff87SDaniel Beauregard 
823eb82ff87SDaniel Beauregard 		if (j >= MAX_CTL_CHECK) {
824eb82ff87SDaniel Beauregard 			EL(ha, "failed to read through agent\n");
825eb82ff87SDaniel Beauregard 			break;
826eb82ff87SDaniel Beauregard 		}
827eb82ff87SDaniel Beauregard 
828eb82ff87SDaniel Beauregard 		start = off0[i] >> 2;
829eb82ff87SDaniel Beauregard 		end = (off0[i] + sz[i] - 1) >> 2;
830eb82ff87SDaniel Beauregard 		for (k = start; k <= end; k++) {
831eb82ff87SDaniel Beauregard 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_RDDATA(k),
832eb82ff87SDaniel Beauregard 			    &temp);
833eb82ff87SDaniel Beauregard 			word[i] |= ((uint64_t)temp << (32 * (k & 1)));
834eb82ff87SDaniel Beauregard 		}
835eb82ff87SDaniel Beauregard 	}
836eb82ff87SDaniel Beauregard 
837eb82ff87SDaniel Beauregard 	/*
838eb82ff87SDaniel Beauregard 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
839eb82ff87SDaniel Beauregard 	 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
840eb82ff87SDaniel Beauregard 	 */
841eb82ff87SDaniel Beauregard 
842eb82ff87SDaniel Beauregard 	if (j >= MAX_CTL_CHECK) {
843eb82ff87SDaniel Beauregard 		return (-1);
844eb82ff87SDaniel Beauregard 	}
845eb82ff87SDaniel Beauregard 
846eb82ff87SDaniel Beauregard 	if ((off0[0] & 7) == 0) {
847eb82ff87SDaniel Beauregard 		val = word[0];
848eb82ff87SDaniel Beauregard 	} else {
849eb82ff87SDaniel Beauregard 		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
850eb82ff87SDaniel Beauregard 		    ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
851eb82ff87SDaniel Beauregard 	}
852eb82ff87SDaniel Beauregard 
853eb82ff87SDaniel Beauregard 	switch (size) {
854eb82ff87SDaniel Beauregard 	case 1:
855eb82ff87SDaniel Beauregard 		*(uint8_t *)data = (uint8_t)val;
856eb82ff87SDaniel Beauregard 		break;
857eb82ff87SDaniel Beauregard 	case 2:
858eb82ff87SDaniel Beauregard 		*(uint16_t *)data = (uint16_t)val;
859eb82ff87SDaniel Beauregard 		break;
860eb82ff87SDaniel Beauregard 	case 4:
861eb82ff87SDaniel Beauregard 		*(uint32_t *)data = (uint32_t)val;
862eb82ff87SDaniel Beauregard 		break;
863eb82ff87SDaniel Beauregard 	case 8:
864eb82ff87SDaniel Beauregard 		*(uint64_t *)data = val;
865eb82ff87SDaniel Beauregard 		break;
866eb82ff87SDaniel Beauregard 	}
867eb82ff87SDaniel Beauregard 
868eb82ff87SDaniel Beauregard 	return (0);
869eb82ff87SDaniel Beauregard }
870eb82ff87SDaniel Beauregard 
871eb82ff87SDaniel Beauregard static int
872eb82ff87SDaniel Beauregard ql_8021_pci_mem_write_2M(ql_adapter_state_t *ha, uint64_t off, void *data,
873eb82ff87SDaniel Beauregard     uint32_t size)
874eb82ff87SDaniel Beauregard {
875eb82ff87SDaniel Beauregard 	int		j, ret = 0;
876eb82ff87SDaniel Beauregard 	uint32_t	i, temp, loop, sz[2];
877eb82ff87SDaniel Beauregard 	uint32_t	scale, shift_amount, p3p, startword;
878eb82ff87SDaniel Beauregard 	uint64_t	off8, off0, mem_crb, tmpw, word[2] = {0, 0};
879eb82ff87SDaniel Beauregard 
880eb82ff87SDaniel Beauregard 	/*
881eb82ff87SDaniel Beauregard 	 * If not MN, go check for MS or invalid.
882eb82ff87SDaniel Beauregard 	 */
883eb82ff87SDaniel Beauregard 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
884eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_QDR_NET;
885eb82ff87SDaniel Beauregard 	} else {
886eb82ff87SDaniel Beauregard 		mem_crb = UNM_CRB_DDR_NET;
887eb82ff87SDaniel Beauregard 		if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) {
888eb82ff87SDaniel Beauregard 			return (ql_8021_pci_mem_write_direct(ha, off, data,
889eb82ff87SDaniel Beauregard 			    size));
890eb82ff87SDaniel Beauregard 		}
891eb82ff87SDaniel Beauregard 	}
892eb82ff87SDaniel Beauregard 
893eb82ff87SDaniel Beauregard 	off0 = off & 0x7;
894eb82ff87SDaniel Beauregard 	sz[0] = (uint32_t)(((uint64_t)size < (8 - off0)) ? size : (8 - off0));
895eb82ff87SDaniel Beauregard 	sz[1] = size - sz[0];
896eb82ff87SDaniel Beauregard 
897eb82ff87SDaniel Beauregard 	if (NX_IS_REVISION_P3PLUS(ha->rev_id)) {
898eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff0;
899eb82ff87SDaniel Beauregard 		loop = (uint32_t)((((off & 0xf) + size - 1) >> 4) + 1);
900eb82ff87SDaniel Beauregard 		shift_amount = 4;
901eb82ff87SDaniel Beauregard 		scale = 2;
902eb82ff87SDaniel Beauregard 		p3p = 1;
903eb82ff87SDaniel Beauregard 		startword = (uint32_t)((off & 0xf) / 8);
904eb82ff87SDaniel Beauregard 	} else {
905eb82ff87SDaniel Beauregard 		off8 = off & 0xfffffff8;
906eb82ff87SDaniel Beauregard 		loop = (uint32_t)(((off0 + size - 1) >> 3) + 1);
907eb82ff87SDaniel Beauregard 		shift_amount = 3;
908eb82ff87SDaniel Beauregard 		scale = 1;
909eb82ff87SDaniel Beauregard 		p3p = 0;
910eb82ff87SDaniel Beauregard 		startword = 0;
911eb82ff87SDaniel Beauregard 	}
912eb82ff87SDaniel Beauregard 
913eb82ff87SDaniel Beauregard 	if (p3p || (size != 8) || (off0 != 0)) {
914eb82ff87SDaniel Beauregard 		for (i = 0; i < loop; i++) {
915eb82ff87SDaniel Beauregard 			if (ql_8021_pci_mem_read_2M(ha, off8 +
916eb82ff87SDaniel Beauregard 			    (i << shift_amount), &word[i * scale], 8)) {
917eb82ff87SDaniel Beauregard 				EL(ha, "8021_pci_mem_read_2M != 0\n");
918eb82ff87SDaniel Beauregard 				return (-1);
919eb82ff87SDaniel Beauregard 			}
920eb82ff87SDaniel Beauregard 		}
921eb82ff87SDaniel Beauregard 	}
922eb82ff87SDaniel Beauregard 
923eb82ff87SDaniel Beauregard 	switch (size) {
924eb82ff87SDaniel Beauregard 	case 1:
925eb82ff87SDaniel Beauregard 		tmpw = (uint64_t)(*((uint8_t *)data));
926eb82ff87SDaniel Beauregard 		break;
927eb82ff87SDaniel Beauregard 	case 2:
928eb82ff87SDaniel Beauregard 		tmpw = (uint64_t)(*((uint16_t *)data));
929eb82ff87SDaniel Beauregard 		break;
930eb82ff87SDaniel Beauregard 	case 4:
931eb82ff87SDaniel Beauregard 		tmpw = (uint64_t)(*((uint32_t *)data));
932eb82ff87SDaniel Beauregard 		break;
933eb82ff87SDaniel Beauregard 	case 8:
934eb82ff87SDaniel Beauregard 	default:
935eb82ff87SDaniel Beauregard 		tmpw = *((uint64_t *)data);
936eb82ff87SDaniel Beauregard 		break;
937eb82ff87SDaniel Beauregard 	}
938eb82ff87SDaniel Beauregard 
939eb82ff87SDaniel Beauregard 	if (p3p) {
940eb82ff87SDaniel Beauregard 		if (sz[0] == 8) {
941eb82ff87SDaniel Beauregard 			word[startword] = tmpw;
942eb82ff87SDaniel Beauregard 		} else {
943eb82ff87SDaniel Beauregard 			word[startword] &= ~((~(~0ULL << (sz[0] * 8))) <<
944eb82ff87SDaniel Beauregard 			    (off0 * 8));
945eb82ff87SDaniel Beauregard 			word[startword] |= tmpw << (off0 * 8);
946eb82ff87SDaniel Beauregard 		}
947eb82ff87SDaniel Beauregard 		if (sz[1] != 0) {
948eb82ff87SDaniel Beauregard 			word[startword+1] &= ~(~0ULL << (sz[1] * 8));
949eb82ff87SDaniel Beauregard 			word[startword+1] |= tmpw >> (sz[0] * 8);
950eb82ff87SDaniel Beauregard 		}
951eb82ff87SDaniel Beauregard 	} else {
952eb82ff87SDaniel Beauregard 		word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
953eb82ff87SDaniel Beauregard 		word[startword] |= tmpw << (off0 * 8);
954eb82ff87SDaniel Beauregard 
955eb82ff87SDaniel Beauregard 		if (loop == 2) {
956eb82ff87SDaniel Beauregard 			word[1] &= ~(~0ULL << (sz[1] * 8));
957eb82ff87SDaniel Beauregard 			word[1] |= tmpw >> (sz[0] * 8);
958eb82ff87SDaniel Beauregard 		}
959eb82ff87SDaniel Beauregard 	}
960eb82ff87SDaniel Beauregard 
961eb82ff87SDaniel Beauregard 	/*
962eb82ff87SDaniel Beauregard 	 * don't lock here - write_wx gets the lock if each time
963eb82ff87SDaniel Beauregard 	 * write_lock_irqsave(&adapter->adapter_lock, flags);
964eb82ff87SDaniel Beauregard 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
965eb82ff87SDaniel Beauregard 	 */
966eb82ff87SDaniel Beauregard 
967eb82ff87SDaniel Beauregard 	for (i = 0; i < loop; i++) {
968eb82ff87SDaniel Beauregard 		temp = (uint32_t)(off8 + (i << shift_amount));
969eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
970eb82ff87SDaniel Beauregard 		temp = 0;
971eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
972eb82ff87SDaniel Beauregard 		temp = (uint32_t)(word[i * scale] & 0xffffffff);
973eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_LO, temp);
974eb82ff87SDaniel Beauregard 		temp = (uint32_t)((word[i * scale] >> 32) & 0xffffffff);
975eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_HI, temp);
976eb82ff87SDaniel Beauregard 		if (p3p) {
977eb82ff87SDaniel Beauregard 			temp = (uint32_t)(word[i * scale + 1] & 0xffffffff);
978eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha,
979eb82ff87SDaniel Beauregard 			    mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
980eb82ff87SDaniel Beauregard 			temp = (uint32_t)((word[i * scale + 1] >> 32) &
981eb82ff87SDaniel Beauregard 			    0xffffffff);
982eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha,
983eb82ff87SDaniel Beauregard 			    mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
984eb82ff87SDaniel Beauregard 		}
985eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
986eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
987eb82ff87SDaniel Beauregard 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
988eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
989eb82ff87SDaniel Beauregard 
990eb82ff87SDaniel Beauregard 		for (j = 0; j < MAX_CTL_CHECK; j++) {
991eb82ff87SDaniel Beauregard 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp);
992eb82ff87SDaniel Beauregard 			if ((temp & MIU_TA_CTL_BUSY) == 0)
993eb82ff87SDaniel Beauregard 				break;
994eb82ff87SDaniel Beauregard 		}
995eb82ff87SDaniel Beauregard 
996eb82ff87SDaniel Beauregard 		if (j >= MAX_CTL_CHECK) {
997eb82ff87SDaniel Beauregard 			EL(ha, "failed to write through agent\n");
998eb82ff87SDaniel Beauregard 			ret = -1;
999eb82ff87SDaniel Beauregard 			break;
1000eb82ff87SDaniel Beauregard 		}
1001eb82ff87SDaniel Beauregard 	}
1002eb82ff87SDaniel Beauregard 
1003eb82ff87SDaniel Beauregard 	return (ret);
1004eb82ff87SDaniel Beauregard }
1005eb82ff87SDaniel Beauregard 
1006eb82ff87SDaniel Beauregard static uint32_t
1007eb82ff87SDaniel Beauregard ql_8021_decode_crb_addr(ql_adapter_state_t *ha, uint32_t addr)
1008eb82ff87SDaniel Beauregard {
1009eb82ff87SDaniel Beauregard 	int		i;
1010eb82ff87SDaniel Beauregard 	uint32_t	base_addr, offset, pci_base;
1011eb82ff87SDaniel Beauregard 
1012eb82ff87SDaniel Beauregard 	if (!crb_table_initialized) {
1013eb82ff87SDaniel Beauregard 		ql_crb_addr_transform_setup(ha);
1014eb82ff87SDaniel Beauregard 	}
1015eb82ff87SDaniel Beauregard 
1016eb82ff87SDaniel Beauregard 	pci_base = ADDR_ERROR;
1017eb82ff87SDaniel Beauregard 	base_addr = addr & 0xfff00000;
1018eb82ff87SDaniel Beauregard 	offset = addr & 0x000fffff;
1019eb82ff87SDaniel Beauregard 
1020eb82ff87SDaniel Beauregard 	for (i = 0; i < MAX_CRB_XFORM; i++) {
1021eb82ff87SDaniel Beauregard 		if (crb_addr_xform[i] == base_addr) {
1022eb82ff87SDaniel Beauregard 			pci_base = i << 20;
1023eb82ff87SDaniel Beauregard 			break;
1024eb82ff87SDaniel Beauregard 		}
1025eb82ff87SDaniel Beauregard 	}
1026eb82ff87SDaniel Beauregard 	if (pci_base == ADDR_ERROR) {
1027eb82ff87SDaniel Beauregard 		return (pci_base);
1028eb82ff87SDaniel Beauregard 	} else {
1029eb82ff87SDaniel Beauregard 		return (pci_base + offset);
1030eb82ff87SDaniel Beauregard 	}
1031eb82ff87SDaniel Beauregard }
1032eb82ff87SDaniel Beauregard 
1033eb82ff87SDaniel Beauregard static int
1034eb82ff87SDaniel Beauregard ql_8021_hw_lock(ql_adapter_state_t *ha, uint32_t timer)
1035eb82ff87SDaniel Beauregard {
1036eb82ff87SDaniel Beauregard 	uint32_t	done = 0, timeout = 0;
1037eb82ff87SDaniel Beauregard 
1038eb82ff87SDaniel Beauregard 	while (!done) {
1039eb82ff87SDaniel Beauregard 		/* acquire semaphore5 from PCI HW block */
1040eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_LOCK), &done);
1041eb82ff87SDaniel Beauregard 		if (done == 1) {
1042eb82ff87SDaniel Beauregard 			break;
1043eb82ff87SDaniel Beauregard 		}
1044eb82ff87SDaniel Beauregard 		if (timeout >= timer) {
1045eb82ff87SDaniel Beauregard 			EL(ha, "timeout\n");
1046eb82ff87SDaniel Beauregard 			return (-1);
1047eb82ff87SDaniel Beauregard 		}
1048eb82ff87SDaniel Beauregard 		timeout++;
1049eb82ff87SDaniel Beauregard 
1050eb82ff87SDaniel Beauregard 		/*
1051eb82ff87SDaniel Beauregard 		 * Yield CPU
1052eb82ff87SDaniel Beauregard 		 */
1053eb82ff87SDaniel Beauregard 		delay(1);
1054eb82ff87SDaniel Beauregard 	}
1055eb82ff87SDaniel Beauregard 
1056eb82ff87SDaniel Beauregard 	return (0);
1057eb82ff87SDaniel Beauregard }
1058eb82ff87SDaniel Beauregard 
1059eb82ff87SDaniel Beauregard static void
1060eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ql_adapter_state_t *ha)
1061eb82ff87SDaniel Beauregard {
1062eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_UNLOCK), NULL);
1063eb82ff87SDaniel Beauregard }
1064eb82ff87SDaniel Beauregard 
1065eb82ff87SDaniel Beauregard static int
1066eb82ff87SDaniel Beauregard ql_8021_rom_lock(ql_adapter_state_t *ha)
1067eb82ff87SDaniel Beauregard {
1068eb82ff87SDaniel Beauregard 	uint32_t	done = 0, timeout = 0;
1069eb82ff87SDaniel Beauregard 
1070eb82ff87SDaniel Beauregard 	while (!done) {
1071eb82ff87SDaniel Beauregard 		/* acquire semaphore2 from PCI HW block */
1072eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done);
1073eb82ff87SDaniel Beauregard 		if (done == 1) {
1074eb82ff87SDaniel Beauregard 			break;
1075eb82ff87SDaniel Beauregard 		}
1076eb82ff87SDaniel Beauregard 		if (timeout >= ROM_LOCK_TIMEOUT) {
1077eb82ff87SDaniel Beauregard 			EL(ha, "timeout\n");
1078eb82ff87SDaniel Beauregard 			return (-1);
1079eb82ff87SDaniel Beauregard 		}
1080eb82ff87SDaniel Beauregard 		timeout++;
1081eb82ff87SDaniel Beauregard 
1082eb82ff87SDaniel Beauregard 		/*
1083eb82ff87SDaniel Beauregard 		 * Yield CPU
1084eb82ff87SDaniel Beauregard 		 */
1085eb82ff87SDaniel Beauregard 		delay(1);
1086eb82ff87SDaniel Beauregard 	}
1087eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER);
1088eb82ff87SDaniel Beauregard 
1089eb82ff87SDaniel Beauregard 	return (0);
1090eb82ff87SDaniel Beauregard }
1091eb82ff87SDaniel Beauregard 
1092eb82ff87SDaniel Beauregard static void
1093eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ql_adapter_state_t *ha)
1094eb82ff87SDaniel Beauregard {
1095eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), NULL);
1096eb82ff87SDaniel Beauregard }
1097eb82ff87SDaniel Beauregard 
1098eb82ff87SDaniel Beauregard static int
1099eb82ff87SDaniel Beauregard ql_8021_wait_rom_done(ql_adapter_state_t *ha)
1100eb82ff87SDaniel Beauregard {
1101eb82ff87SDaniel Beauregard 	uint32_t	timeout = 0, done = 0;
1102eb82ff87SDaniel Beauregard 
1103eb82ff87SDaniel Beauregard 	while (done == 0) {
1104eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_ROMUSB_GLB_STATUS, &done);
1105eb82ff87SDaniel Beauregard 		done &= 2;
1106eb82ff87SDaniel Beauregard 		timeout++;
1107eb82ff87SDaniel Beauregard 		if (timeout >= ROM_MAX_TIMEOUT) {
1108eb82ff87SDaniel Beauregard 			EL(ha, "Timeout reached waiting for rom done\n");
1109eb82ff87SDaniel Beauregard 			return (-1);
1110eb82ff87SDaniel Beauregard 		}
1111eb82ff87SDaniel Beauregard 	}
1112eb82ff87SDaniel Beauregard 
1113eb82ff87SDaniel Beauregard 	return (0);
1114eb82ff87SDaniel Beauregard }
1115eb82ff87SDaniel Beauregard 
1116eb82ff87SDaniel Beauregard static int
1117eb82ff87SDaniel Beauregard ql_8021_wait_flash_done(ql_adapter_state_t *ha)
1118eb82ff87SDaniel Beauregard {
1119eb82ff87SDaniel Beauregard 	clock_t		timer;
1120eb82ff87SDaniel Beauregard 	uint32_t	status;
1121eb82ff87SDaniel Beauregard 
1122eb82ff87SDaniel Beauregard 	for (timer = 30 * drv_usectohz(1000000); timer; timer--) {
1123eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1124eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1125eb82ff87SDaniel Beauregard 		    UNM_ROMUSB_ROM_RDSR_INSTR);
1126eb82ff87SDaniel Beauregard 		if (ql_8021_wait_rom_done(ha)) {
1127eb82ff87SDaniel Beauregard 			EL(ha, "Error waiting for rom done2\n");
1128eb82ff87SDaniel Beauregard 			return (-1);
1129eb82ff87SDaniel Beauregard 		}
1130eb82ff87SDaniel Beauregard 
1131eb82ff87SDaniel Beauregard 		/* Get status. */
1132eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, &status);
1133eb82ff87SDaniel Beauregard 		if (!(status & BIT_0)) {
1134eb82ff87SDaniel Beauregard 			return (0);
1135eb82ff87SDaniel Beauregard 		}
1136eb82ff87SDaniel Beauregard 		delay(1);
1137eb82ff87SDaniel Beauregard 	}
1138eb82ff87SDaniel Beauregard 
1139eb82ff87SDaniel Beauregard 	EL(ha, "timeout status=%x\n", status);
1140eb82ff87SDaniel Beauregard 	return (-1);
1141eb82ff87SDaniel Beauregard }
1142eb82ff87SDaniel Beauregard 
1143eb82ff87SDaniel Beauregard static int
1144eb82ff87SDaniel Beauregard ql_8021_do_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
1145eb82ff87SDaniel Beauregard {
1146eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
1147eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
1148eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
1149eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1150eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_FAST_RD_INSTR);
1151eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1152eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done\n");
1153eb82ff87SDaniel Beauregard 		return (-1);
1154eb82ff87SDaniel Beauregard 	}
1155eb82ff87SDaniel Beauregard 	/* reset abyte_cnt and dummy_byte_cnt */
1156eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
1157eb82ff87SDaniel Beauregard 	drv_usecwait(10);
1158eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1159eb82ff87SDaniel Beauregard 
1160eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, valp);
1161eb82ff87SDaniel Beauregard 
1162eb82ff87SDaniel Beauregard 	return (0);
1163eb82ff87SDaniel Beauregard }
1164eb82ff87SDaniel Beauregard 
1165eb82ff87SDaniel Beauregard int
1166eb82ff87SDaniel Beauregard ql_8021_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
1167eb82ff87SDaniel Beauregard {
1168eb82ff87SDaniel Beauregard 	int	ret, loops = 0;
1169eb82ff87SDaniel Beauregard 
1170eb82ff87SDaniel Beauregard 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1171eb82ff87SDaniel Beauregard 		drv_usecwait(100);
1172eb82ff87SDaniel Beauregard 		loops++;
1173eb82ff87SDaniel Beauregard 	}
1174eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1175eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1176eb82ff87SDaniel Beauregard 		return (-1);
1177eb82ff87SDaniel Beauregard 	}
1178eb82ff87SDaniel Beauregard 	ret = ql_8021_do_rom_fast_read(ha, addr, valp);
1179eb82ff87SDaniel Beauregard 	ql_8021_rom_unlock(ha);
1180eb82ff87SDaniel Beauregard 
1181eb82ff87SDaniel Beauregard 	return (ret);
1182eb82ff87SDaniel Beauregard }
1183eb82ff87SDaniel Beauregard 
1184eb82ff87SDaniel Beauregard static int
1185eb82ff87SDaniel Beauregard ql_8021_do_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
1186eb82ff87SDaniel Beauregard {
1187eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1188eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1189eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_WREN_INSTR);
1190eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1191eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done\n");
1192eb82ff87SDaniel Beauregard 		return (-1);
1193eb82ff87SDaniel Beauregard 	}
1194eb82ff87SDaniel Beauregard 
1195eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data);
1196eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
1197eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
1198eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1199eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_PP_INSTR);
1200eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1201eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done1\n");
1202eb82ff87SDaniel Beauregard 		return (-1);
1203eb82ff87SDaniel Beauregard 	}
1204eb82ff87SDaniel Beauregard 
1205eb82ff87SDaniel Beauregard 	if (ql_8021_wait_flash_done(ha)) {
1206eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for flash done\n");
1207eb82ff87SDaniel Beauregard 		return (-1);
1208eb82ff87SDaniel Beauregard 	}
1209eb82ff87SDaniel Beauregard 
1210eb82ff87SDaniel Beauregard 	return (0);
1211eb82ff87SDaniel Beauregard }
1212eb82ff87SDaniel Beauregard 
1213eb82ff87SDaniel Beauregard static int
1214eb82ff87SDaniel Beauregard ql_8021_do_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
1215eb82ff87SDaniel Beauregard {
1216eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1217eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1218eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_WREN_INSTR);
1219eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1220eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done\n");
1221eb82ff87SDaniel Beauregard 		return (-1);
1222eb82ff87SDaniel Beauregard 	}
1223eb82ff87SDaniel Beauregard 
1224eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
1225eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
1226eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1227eb82ff87SDaniel Beauregard 	    UNM_ROMUSB_ROM_SE_INSTR);
1228eb82ff87SDaniel Beauregard 	if (ql_8021_wait_rom_done(ha)) {
1229eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for rom done1\n");
1230eb82ff87SDaniel Beauregard 		return (-1);
1231eb82ff87SDaniel Beauregard 	}
1232eb82ff87SDaniel Beauregard 
1233eb82ff87SDaniel Beauregard 	if (ql_8021_wait_flash_done(ha)) {
1234eb82ff87SDaniel Beauregard 		EL(ha, "Error waiting for flash done\n");
1235eb82ff87SDaniel Beauregard 		return (-1);
1236eb82ff87SDaniel Beauregard 	}
1237eb82ff87SDaniel Beauregard 
1238eb82ff87SDaniel Beauregard 	return (0);
1239eb82ff87SDaniel Beauregard }
1240eb82ff87SDaniel Beauregard 
1241eb82ff87SDaniel Beauregard int
1242eb82ff87SDaniel Beauregard ql_8021_rom_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *bp)
1243eb82ff87SDaniel Beauregard {
1244eb82ff87SDaniel Beauregard 	int	ret;
1245eb82ff87SDaniel Beauregard 
1246eb82ff87SDaniel Beauregard 	ret = ql_8021_rom_fast_read(ha, addr << 2, bp) == 0 ? QL_SUCCESS :
1247eb82ff87SDaniel Beauregard 	    QL_FUNCTION_FAILED;
1248eb82ff87SDaniel Beauregard 
1249eb82ff87SDaniel Beauregard 	return (ret);
1250eb82ff87SDaniel Beauregard }
1251eb82ff87SDaniel Beauregard 
1252eb82ff87SDaniel Beauregard int
1253eb82ff87SDaniel Beauregard ql_8021_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
1254eb82ff87SDaniel Beauregard {
1255eb82ff87SDaniel Beauregard 	int	ret, loops = 0;
1256eb82ff87SDaniel Beauregard 
1257eb82ff87SDaniel Beauregard 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1258eb82ff87SDaniel Beauregard 		drv_usecwait(100);
1259eb82ff87SDaniel Beauregard 		loops++;
1260eb82ff87SDaniel Beauregard 	}
1261eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1262eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1263eb82ff87SDaniel Beauregard 		ret = QL_FUNCTION_TIMEOUT;
1264eb82ff87SDaniel Beauregard 	} else {
1265eb82ff87SDaniel Beauregard 		ret = ql_8021_do_rom_write(ha, addr << 2, data) == 0 ?
1266eb82ff87SDaniel Beauregard 		    QL_SUCCESS : QL_FUNCTION_FAILED;
1267eb82ff87SDaniel Beauregard 		ql_8021_rom_unlock(ha);
1268eb82ff87SDaniel Beauregard 	}
1269eb82ff87SDaniel Beauregard 
1270eb82ff87SDaniel Beauregard 	return (ret);
1271eb82ff87SDaniel Beauregard }
1272eb82ff87SDaniel Beauregard 
1273eb82ff87SDaniel Beauregard int
1274eb82ff87SDaniel Beauregard ql_8021_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
1275eb82ff87SDaniel Beauregard {
1276eb82ff87SDaniel Beauregard 	int	ret, loops = 0;
1277eb82ff87SDaniel Beauregard 
1278eb82ff87SDaniel Beauregard 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1279eb82ff87SDaniel Beauregard 		drv_usecwait(100);
1280eb82ff87SDaniel Beauregard 		loops++;
1281eb82ff87SDaniel Beauregard 	}
1282eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1283eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1284eb82ff87SDaniel Beauregard 		ret = QL_FUNCTION_TIMEOUT;
1285eb82ff87SDaniel Beauregard 	} else {
1286eb82ff87SDaniel Beauregard 		ret = ql_8021_do_rom_erase(ha, addr << 2) == 0 ? QL_SUCCESS :
1287eb82ff87SDaniel Beauregard 		    QL_FUNCTION_FAILED;
1288eb82ff87SDaniel Beauregard 		ql_8021_rom_unlock(ha);
1289eb82ff87SDaniel Beauregard 	}
1290eb82ff87SDaniel Beauregard 
1291eb82ff87SDaniel Beauregard 	return (ret);
1292eb82ff87SDaniel Beauregard }
1293eb82ff87SDaniel Beauregard 
1294eb82ff87SDaniel Beauregard int
1295eb82ff87SDaniel Beauregard ql_8021_rom_wrsr(ql_adapter_state_t *ha, uint32_t data)
1296eb82ff87SDaniel Beauregard {
1297eb82ff87SDaniel Beauregard 	int	ret = QL_SUCCESS, loops = 0;
1298eb82ff87SDaniel Beauregard 
1299eb82ff87SDaniel Beauregard 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1300eb82ff87SDaniel Beauregard 		drv_usecwait(100);
1301eb82ff87SDaniel Beauregard 		loops++;
1302eb82ff87SDaniel Beauregard 	}
1303eb82ff87SDaniel Beauregard 	if (loops >= 50000) {
1304eb82ff87SDaniel Beauregard 		EL(ha, "rom_lock failed\n");
1305eb82ff87SDaniel Beauregard 		ret = QL_FUNCTION_TIMEOUT;
1306eb82ff87SDaniel Beauregard 	} else {
1307eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1308eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1309eb82ff87SDaniel Beauregard 		    UNM_ROMUSB_ROM_WREN_INSTR);
1310eb82ff87SDaniel Beauregard 		if (ql_8021_wait_rom_done(ha)) {
1311eb82ff87SDaniel Beauregard 			EL(ha, "Error waiting for rom done\n");
1312eb82ff87SDaniel Beauregard 			ret = QL_FUNCTION_FAILED;
1313eb82ff87SDaniel Beauregard 		} else {
1314eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data);
1315eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1316eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1317eb82ff87SDaniel Beauregard 			    UNM_ROMUSB_ROM_WRSR_INSTR);
1318eb82ff87SDaniel Beauregard 			if (ql_8021_wait_rom_done(ha)) {
1319eb82ff87SDaniel Beauregard 				EL(ha, "Error waiting for rom done1\n");
1320eb82ff87SDaniel Beauregard 				ret = QL_FUNCTION_FAILED;
1321eb82ff87SDaniel Beauregard 			} else if (ql_8021_wait_flash_done(ha)) {
1322eb82ff87SDaniel Beauregard 				EL(ha, "Error waiting for flash done\n");
1323eb82ff87SDaniel Beauregard 				ret = QL_FUNCTION_FAILED;
1324eb82ff87SDaniel Beauregard 			}
1325eb82ff87SDaniel Beauregard 		}
1326eb82ff87SDaniel Beauregard 		ql_8021_rom_unlock(ha);
1327eb82ff87SDaniel Beauregard 	}
1328eb82ff87SDaniel Beauregard 
1329eb82ff87SDaniel Beauregard 	return (ret);
1330eb82ff87SDaniel Beauregard }
1331eb82ff87SDaniel Beauregard 
1332eb82ff87SDaniel Beauregard static int
1333eb82ff87SDaniel Beauregard ql_8021_phantom_init(ql_adapter_state_t *ha)
1334eb82ff87SDaniel Beauregard {
1335eb82ff87SDaniel Beauregard 	uint32_t	val = 0, err = 0;
1336eb82ff87SDaniel Beauregard 	int		retries = 60;
1337eb82ff87SDaniel Beauregard 
1338eb82ff87SDaniel Beauregard 	do {
1339eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_CMDPEG_STATE, &val);
1340eb82ff87SDaniel Beauregard 
1341eb82ff87SDaniel Beauregard 		switch (val) {
1342eb82ff87SDaniel Beauregard 		case PHAN_INITIALIZE_COMPLETE:
1343eb82ff87SDaniel Beauregard 		case PHAN_INITIALIZE_ACK:
1344eb82ff87SDaniel Beauregard 			EL(ha, "success=%xh\n", val);
1345eb82ff87SDaniel Beauregard 			return (0);
1346eb82ff87SDaniel Beauregard 		case PHAN_INITIALIZE_FAILED:
1347eb82ff87SDaniel Beauregard 			EL(ha, "PHAN_INITIALIZE_FAILED\n");
1348eb82ff87SDaniel Beauregard 			err = 1;
1349eb82ff87SDaniel Beauregard 			break;
1350eb82ff87SDaniel Beauregard 		default:
1351eb82ff87SDaniel Beauregard 			break;
1352eb82ff87SDaniel Beauregard 		}
1353eb82ff87SDaniel Beauregard 
1354eb82ff87SDaniel Beauregard 		if (err) {
1355eb82ff87SDaniel Beauregard 			break;
1356eb82ff87SDaniel Beauregard 		}
1357eb82ff87SDaniel Beauregard 		/* 500 msec wait */
1358eb82ff87SDaniel Beauregard 		delay(50);
1359eb82ff87SDaniel Beauregard 
1360eb82ff87SDaniel Beauregard 	} while (--retries);
1361eb82ff87SDaniel Beauregard 
1362eb82ff87SDaniel Beauregard 	if (!err) {
1363eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
1364eb82ff87SDaniel Beauregard 	}
1365eb82ff87SDaniel Beauregard 
1366eb82ff87SDaniel Beauregard 	EL(ha, "firmware init failed=%x\n", val);
1367eb82ff87SDaniel Beauregard 	return (-1);
1368eb82ff87SDaniel Beauregard }
1369eb82ff87SDaniel Beauregard 
1370eb82ff87SDaniel Beauregard static int
1371eb82ff87SDaniel Beauregard ql_8021_pinit_from_rom(ql_adapter_state_t *ha)
1372eb82ff87SDaniel Beauregard {
1373eb82ff87SDaniel Beauregard 	int			init_delay = 0;
1374eb82ff87SDaniel Beauregard 	struct crb_addr_pair	*buf;
1375eb82ff87SDaniel Beauregard 	uint32_t		offset, off, i, n, addr, val;
1376eb82ff87SDaniel Beauregard 
1377eb82ff87SDaniel Beauregard 	/* Grab the lock so that no one can read flash when we reset the chip */
1378eb82ff87SDaniel Beauregard 	(void) ql_8021_rom_lock(ha);
1379eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0xffffffff);
1380eb82ff87SDaniel Beauregard 	/* Just in case it was held when we reset the chip */
1381eb82ff87SDaniel Beauregard 	ql_8021_rom_unlock(ha);
1382eb82ff87SDaniel Beauregard 
1383eb82ff87SDaniel Beauregard 	if (ql_8021_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafe ||
1384eb82ff87SDaniel Beauregard 	    ql_8021_rom_fast_read(ha, 4, &n) != 0) {
1385eb82ff87SDaniel Beauregard 		EL(ha, "ERROR Reading crb_init area: n: %08x\n", n);
1386eb82ff87SDaniel Beauregard 		return (-1);
1387eb82ff87SDaniel Beauregard 	}
1388eb82ff87SDaniel Beauregard 	offset = n & 0xffff;
1389eb82ff87SDaniel Beauregard 	n = (n >> 16) & 0xffff;
1390eb82ff87SDaniel Beauregard 	if (n >= 1024) {
1391eb82ff87SDaniel Beauregard 		EL(ha, "n=0x%x Error! NetXen card flash not initialized\n", n);
1392eb82ff87SDaniel Beauregard 		return (-1);
1393eb82ff87SDaniel Beauregard 	}
1394eb82ff87SDaniel Beauregard 
1395eb82ff87SDaniel Beauregard 	buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP);
1396eb82ff87SDaniel Beauregard 	if (buf == NULL) {
1397eb82ff87SDaniel Beauregard 		EL(ha, "Unable to zalloc memory\n");
1398eb82ff87SDaniel Beauregard 		return (-1);
1399eb82ff87SDaniel Beauregard 	}
1400eb82ff87SDaniel Beauregard 
1401eb82ff87SDaniel Beauregard 	for (i = 0; i < n; i++) {
1402eb82ff87SDaniel Beauregard 		if (ql_8021_rom_fast_read(ha, 8 * i + 4 * offset, &val) != 0 ||
1403eb82ff87SDaniel Beauregard 		    ql_8021_rom_fast_read(ha, 8 * i + 4 * offset + 4, &addr) !=
1404eb82ff87SDaniel Beauregard 		    0) {
1405eb82ff87SDaniel Beauregard 			kmem_free(buf, n * sizeof (struct crb_addr_pair));
1406eb82ff87SDaniel Beauregard 			EL(ha, "ql_8021_rom_fast_read != 0 to zalloc memory\n");
1407eb82ff87SDaniel Beauregard 			return (-1);
1408eb82ff87SDaniel Beauregard 		}
1409eb82ff87SDaniel Beauregard 
1410eb82ff87SDaniel Beauregard 		buf[i].addr = addr;
1411eb82ff87SDaniel Beauregard 		buf[i].data = val;
1412eb82ff87SDaniel Beauregard 	}
1413eb82ff87SDaniel Beauregard 
1414eb82ff87SDaniel Beauregard 	for (i = 0; i < n; i++) {
1415eb82ff87SDaniel Beauregard 		off = ql_8021_decode_crb_addr(ha, buf[i].addr);
1416eb82ff87SDaniel Beauregard 		if (off == ADDR_ERROR) {
1417eb82ff87SDaniel Beauregard 			EL(ha, "Err: Unknown addr: 0x%lx\n", buf[i].addr);
1418eb82ff87SDaniel Beauregard 			continue;
1419eb82ff87SDaniel Beauregard 		}
1420eb82ff87SDaniel Beauregard 		off += UNM_PCI_CRBSPACE;
1421eb82ff87SDaniel Beauregard 
1422eb82ff87SDaniel Beauregard 		if (off & 1) {
1423eb82ff87SDaniel Beauregard 			continue;
1424eb82ff87SDaniel Beauregard 		}
1425eb82ff87SDaniel Beauregard 
1426eb82ff87SDaniel Beauregard 		/* skipping cold reboot MAGIC */
1427eb82ff87SDaniel Beauregard 		if (off == UNM_RAM_COLD_BOOT) {
1428eb82ff87SDaniel Beauregard 			continue;
1429eb82ff87SDaniel Beauregard 		}
1430eb82ff87SDaniel Beauregard 		if (off == (UNM_CRB_I2C0 + 0x1c)) {
1431eb82ff87SDaniel Beauregard 			continue;
1432eb82ff87SDaniel Beauregard 		}
1433eb82ff87SDaniel Beauregard 		/* do not reset PCI */
1434eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0xbc)) {
1435eb82ff87SDaniel Beauregard 			continue;
1436eb82ff87SDaniel Beauregard 		}
1437eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0xa8)) {
1438eb82ff87SDaniel Beauregard 			continue;
1439eb82ff87SDaniel Beauregard 		}
1440eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0xc8)) {	/* core clock */
1441eb82ff87SDaniel Beauregard 			continue;
1442eb82ff87SDaniel Beauregard 		}
1443eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0x24)) {	/* MN clock */
1444eb82ff87SDaniel Beauregard 			continue;
1445eb82ff87SDaniel Beauregard 		}
1446eb82ff87SDaniel Beauregard 		if (off == (ROMUSB_GLB + 0x1c)) {	/* MS clock */
1447eb82ff87SDaniel Beauregard 			continue;
1448eb82ff87SDaniel Beauregard 		}
1449eb82ff87SDaniel Beauregard 		if ((off & 0x0ff00000) == UNM_CRB_DDR_NET) {
1450eb82ff87SDaniel Beauregard 			continue;
1451eb82ff87SDaniel Beauregard 		}
1452eb82ff87SDaniel Beauregard 		if (off == (UNM_CRB_PEG_NET_1 + 0x18) &&
1453eb82ff87SDaniel Beauregard 		    !NX_IS_REVISION_P3PLUS(ha->rev_id)) {
1454eb82ff87SDaniel Beauregard 			buf[i].data = 0x1020;
1455eb82ff87SDaniel Beauregard 		}
1456eb82ff87SDaniel Beauregard 		/* skip the function enable register */
1457eb82ff87SDaniel Beauregard 		if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) {
1458eb82ff87SDaniel Beauregard 			continue;
1459eb82ff87SDaniel Beauregard 		}
1460eb82ff87SDaniel Beauregard 		if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) {
1461eb82ff87SDaniel Beauregard 			continue;
1462eb82ff87SDaniel Beauregard 		}
1463eb82ff87SDaniel Beauregard 		if ((off & 0x0ff00000) == UNM_CRB_SMB) {
1464eb82ff87SDaniel Beauregard 			continue;
1465eb82ff87SDaniel Beauregard 		}
1466eb82ff87SDaniel Beauregard 
1467eb82ff87SDaniel Beauregard 		/* After writing this register, HW needs time for CRB */
1468eb82ff87SDaniel Beauregard 		/* to quiet down (else crb_window returns 0xffffffff) */
1469eb82ff87SDaniel Beauregard 		init_delay = 1;
1470eb82ff87SDaniel Beauregard 		if (off == UNM_ROMUSB_GLB_SW_RESET) {
1471eb82ff87SDaniel Beauregard 			init_delay = 100;	/* Sleep 1000 msecs */
1472eb82ff87SDaniel Beauregard 		}
1473eb82ff87SDaniel Beauregard 
1474eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, off, buf[i].data);
1475eb82ff87SDaniel Beauregard 
1476eb82ff87SDaniel Beauregard 		delay(init_delay);
1477eb82ff87SDaniel Beauregard 	}
1478eb82ff87SDaniel Beauregard 	kmem_free(buf, n * sizeof (struct crb_addr_pair));
1479eb82ff87SDaniel Beauregard 
1480eb82ff87SDaniel Beauregard 	/* disable_peg_cache_all */
1481eb82ff87SDaniel Beauregard 
1482eb82ff87SDaniel Beauregard 	/* p2dn replyCount */
1483eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0xec, 0x1e);
1484eb82ff87SDaniel Beauregard 	/* disable_peg_cache 0 */
1485eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0x4c, 8);
1486eb82ff87SDaniel Beauregard 	/* disable_peg_cache 1 */
1487eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_I + 0x4c, 8);
1488eb82ff87SDaniel Beauregard 
1489eb82ff87SDaniel Beauregard 	/* peg_clr_all */
1490eb82ff87SDaniel Beauregard 	/* peg_clr 0 */
1491eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x8, 0);
1492eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0xc, 0);
1493eb82ff87SDaniel Beauregard 	/* peg_clr 1 */
1494eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0x8, 0);
1495eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0xc, 0);
1496eb82ff87SDaniel Beauregard 	/* peg_clr 2 */
1497eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0x8, 0);
1498eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0xc, 0);
1499eb82ff87SDaniel Beauregard 	/* peg_clr 3 */
1500eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0x8, 0);
1501eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0xc, 0);
1502eb82ff87SDaniel Beauregard 
1503eb82ff87SDaniel Beauregard 	return (0);
1504eb82ff87SDaniel Beauregard }
1505eb82ff87SDaniel Beauregard 
1506eb82ff87SDaniel Beauregard static int
1507eb82ff87SDaniel Beauregard ql_8021_load_from_flash(ql_adapter_state_t *ha)
1508eb82ff87SDaniel Beauregard {
1509eb82ff87SDaniel Beauregard 	int		i;
1510eb82ff87SDaniel Beauregard 	uint32_t	flashaddr, memaddr;
1511eb82ff87SDaniel Beauregard 	uint32_t	high, low, size;
1512eb82ff87SDaniel Beauregard 	uint64_t	data;
1513eb82ff87SDaniel Beauregard 
1514eb82ff87SDaniel Beauregard 	size = ha->bootloader_size / 2;
1515eb82ff87SDaniel Beauregard 	flashaddr = ha->bootloader_addr << 2;
1516eb82ff87SDaniel Beauregard 	memaddr = BOOTLD_START;
1517eb82ff87SDaniel Beauregard 
1518eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1519eb82ff87SDaniel Beauregard 		if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
1520eb82ff87SDaniel Beauregard 		    (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
1521eb82ff87SDaniel Beauregard 			EL(ha, "ql_8021_rom_fast_read != 0\n");
1522eb82ff87SDaniel Beauregard 			return (-1);
1523eb82ff87SDaniel Beauregard 		}
1524eb82ff87SDaniel Beauregard 		data = ((uint64_t)high << 32) | low;
1525eb82ff87SDaniel Beauregard 		(void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
1526eb82ff87SDaniel Beauregard 		flashaddr += 8;
1527eb82ff87SDaniel Beauregard 		memaddr += 8;
1528eb82ff87SDaniel Beauregard 	}
1529eb82ff87SDaniel Beauregard 
1530eb82ff87SDaniel Beauregard 	size = ha->flash_fw_size / 2;
1531eb82ff87SDaniel Beauregard 	flashaddr = ha->flash_fw_addr << 2;
1532eb82ff87SDaniel Beauregard 	memaddr = IMAGE_START;
1533eb82ff87SDaniel Beauregard 
1534eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1535eb82ff87SDaniel Beauregard 		if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
1536eb82ff87SDaniel Beauregard 		    (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
1537eb82ff87SDaniel Beauregard 			EL(ha, "ql_8021_rom_fast_read3 != 0\n");
1538eb82ff87SDaniel Beauregard 			return (-1);
1539eb82ff87SDaniel Beauregard 		}
1540eb82ff87SDaniel Beauregard 		data = ((uint64_t)high << 32) | low;
1541eb82ff87SDaniel Beauregard 		(void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
1542eb82ff87SDaniel Beauregard 		flashaddr += 8;
1543eb82ff87SDaniel Beauregard 		memaddr += 8;
1544eb82ff87SDaniel Beauregard 	}
1545eb82ff87SDaniel Beauregard 
1546eb82ff87SDaniel Beauregard 	return (0);
1547eb82ff87SDaniel Beauregard }
1548eb82ff87SDaniel Beauregard 
1549eb82ff87SDaniel Beauregard static int
1550eb82ff87SDaniel Beauregard ql_8021_load_firmware(ql_adapter_state_t *ha)
1551eb82ff87SDaniel Beauregard {
1552eb82ff87SDaniel Beauregard 	uint64_t	data;
1553eb82ff87SDaniel Beauregard 	uint32_t	i, flashaddr, size;
1554eb82ff87SDaniel Beauregard 	uint8_t		*bp, n, *dp;
1555eb82ff87SDaniel Beauregard 
1556eb82ff87SDaniel Beauregard 	bp = (uint8_t *)(ha->risc_fw[0].code);
1557eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&size;
1558eb82ff87SDaniel Beauregard 	for (n = 0; n < 4; n++) {
1559eb82ff87SDaniel Beauregard 		dp[n] = *bp++;
1560eb82ff87SDaniel Beauregard 	}
1561eb82ff87SDaniel Beauregard 	LITTLE_ENDIAN_32(&size);
1562eb82ff87SDaniel Beauregard 	EL(ha, "signature=%x\n", size);
1563eb82ff87SDaniel Beauregard 
1564eb82ff87SDaniel Beauregard 	size = (IMAGE_START - BOOTLD_START) / 8;
1565eb82ff87SDaniel Beauregard 
1566eb82ff87SDaniel Beauregard 	bp = (uint8_t *)(ha->risc_fw[0].code + BOOTLD_START);
1567eb82ff87SDaniel Beauregard 	flashaddr = BOOTLD_START;
1568eb82ff87SDaniel Beauregard 
1569eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&data;
1570eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1571eb82ff87SDaniel Beauregard 		for (n = 0; n < 8; n++) {
1572eb82ff87SDaniel Beauregard 			dp[n] = *bp++;
1573eb82ff87SDaniel Beauregard 		}
1574eb82ff87SDaniel Beauregard 		LITTLE_ENDIAN_64(&data);
1575eb82ff87SDaniel Beauregard 		(void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8);
1576eb82ff87SDaniel Beauregard 		flashaddr += 8;
1577eb82ff87SDaniel Beauregard 	}
1578eb82ff87SDaniel Beauregard 
1579eb82ff87SDaniel Beauregard 	bp = (uint8_t *)(ha->risc_fw[0].code + FW_SIZE_OFFSET);
1580eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&size;
1581eb82ff87SDaniel Beauregard 	for (n = 0; n < 4; n++) {
1582eb82ff87SDaniel Beauregard 		dp[n] = *bp++;
1583eb82ff87SDaniel Beauregard 	}
1584eb82ff87SDaniel Beauregard 	LITTLE_ENDIAN_32(&size);
1585eb82ff87SDaniel Beauregard 	EL(ha, "IMAGE_START size=%llx\n", size);
1586eb82ff87SDaniel Beauregard 	size = (size + 7) / 8;
1587eb82ff87SDaniel Beauregard 
1588eb82ff87SDaniel Beauregard 	bp = (uint8_t *)(ha->risc_fw[0].code + IMAGE_START);
1589eb82ff87SDaniel Beauregard 	flashaddr = IMAGE_START;
1590eb82ff87SDaniel Beauregard 
1591eb82ff87SDaniel Beauregard 	dp = (uint8_t *)&data;
1592eb82ff87SDaniel Beauregard 	for (i = 0; i < size; i++) {
1593eb82ff87SDaniel Beauregard 		for (n = 0; n < 8; n++) {
1594eb82ff87SDaniel Beauregard 			dp[n] = *bp++;
1595eb82ff87SDaniel Beauregard 		}
1596eb82ff87SDaniel Beauregard 		LITTLE_ENDIAN_64(&data);
1597eb82ff87SDaniel Beauregard 		(void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8);
1598eb82ff87SDaniel Beauregard 		flashaddr += 8;
1599eb82ff87SDaniel Beauregard 	}
1600eb82ff87SDaniel Beauregard 
1601eb82ff87SDaniel Beauregard 	return (0);
1602eb82ff87SDaniel Beauregard }
1603eb82ff87SDaniel Beauregard 
1604eb82ff87SDaniel Beauregard static int
1605eb82ff87SDaniel Beauregard ql_8021_init_p3p(ql_adapter_state_t *ha)
1606eb82ff87SDaniel Beauregard {
1607eb82ff87SDaniel Beauregard 	uint32_t	data;
1608eb82ff87SDaniel Beauregard 
1609eb82ff87SDaniel Beauregard 	/* ??? */
1610eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_PORT_MODE_ADDR, UNM_PORT_MODE_AUTO_NEG);
1611eb82ff87SDaniel Beauregard 	delay(drv_usectohz(1000000));
1612eb82ff87SDaniel Beauregard 
1613eb82ff87SDaniel Beauregard 	/* CAM RAM Cold Boot Register */
1614eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_RAM_COLD_BOOT, &data);
1615eb82ff87SDaniel Beauregard 	if (data == 0x55555555) {
1616eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &data);
1617eb82ff87SDaniel Beauregard 		if (data != 0x80000f) {
1618eb82ff87SDaniel Beauregard 			EL(ha, "CRB_UNM_GLB_SW_RST=%x exit\n", data);
1619eb82ff87SDaniel Beauregard 			return (-1);
1620eb82ff87SDaniel Beauregard 		}
1621eb82ff87SDaniel Beauregard 		ql_8021_wr_32(ha, UNM_RAM_COLD_BOOT, 0);
1622eb82ff87SDaniel Beauregard 	}
1623eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, &data);
1624eb82ff87SDaniel Beauregard 	data |= 1;
1625eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, data);
1626eb82ff87SDaniel Beauregard 
1627eb82ff87SDaniel Beauregard 	/*
1628eb82ff87SDaniel Beauregard 	 * ???
1629eb82ff87SDaniel Beauregard 	 * data = ha->pci_bus_addr | BIT_31;
1630eb82ff87SDaniel Beauregard 	 * ql_8021_wr_32(ha, UNM_BUS_DEV_NO, data);
1631eb82ff87SDaniel Beauregard 	 */
1632eb82ff87SDaniel Beauregard 
1633eb82ff87SDaniel Beauregard 	return (0);
1634eb82ff87SDaniel Beauregard }
1635eb82ff87SDaniel Beauregard 
1636eb82ff87SDaniel Beauregard /* ARGSUSED */
1637eb82ff87SDaniel Beauregard void
1638eb82ff87SDaniel Beauregard ql_8021_reset_chip(ql_adapter_state_t *ha)
1639eb82ff87SDaniel Beauregard {
1640*f885d00fSDaniel Beauregard 	/*
1641*f885d00fSDaniel Beauregard 	 * Disable interrupts does not work on a per function bases
1642*f885d00fSDaniel Beauregard 	 * leave them enabled
1643*f885d00fSDaniel Beauregard 	 */
1644eb82ff87SDaniel Beauregard 	ql_8021_enable_intrs(ha);
1645eb82ff87SDaniel Beauregard 
1646eb82ff87SDaniel Beauregard 	ADAPTER_STATE_LOCK(ha);
1647eb82ff87SDaniel Beauregard 	ha->flags |= INTERRUPTS_ENABLED;
1648eb82ff87SDaniel Beauregard 	ADAPTER_STATE_UNLOCK(ha);
1649*f885d00fSDaniel Beauregard 
1650*f885d00fSDaniel Beauregard 	(void) ql_stop_firmware(ha);
1651eb82ff87SDaniel Beauregard }
1652eb82ff87SDaniel Beauregard 
1653eb82ff87SDaniel Beauregard static int
1654eb82ff87SDaniel Beauregard ql_8021_reset_hw(ql_adapter_state_t *ha, int type)
1655eb82ff87SDaniel Beauregard {
1656eb82ff87SDaniel Beauregard 	int		ret;
1657eb82ff87SDaniel Beauregard 	uint32_t	rst;
1658eb82ff87SDaniel Beauregard 
1659eb82ff87SDaniel Beauregard 	/* scrub dma mask expansion register */
1660eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
1661eb82ff87SDaniel Beauregard 
1662eb82ff87SDaniel Beauregard 	/* Overwrite stale initialization register values */
1663eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_CMDPEG_STATE, 0);
1664eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_RCVPEG_STATE, 0);
1665eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0);
1666eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0);
1667eb82ff87SDaniel Beauregard 
1668eb82ff87SDaniel Beauregard 	(void) ql_8021_pinit_from_rom(ha);
1669eb82ff87SDaniel Beauregard 	delay(1);
1670eb82ff87SDaniel Beauregard 
1671eb82ff87SDaniel Beauregard 	/* Bring QM and CAMRAM out of reset */
1672eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &rst);
1673eb82ff87SDaniel Beauregard 	rst &= ~((1 << 28) | (1 << 24));
1674eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, rst);
1675eb82ff87SDaniel Beauregard 
1676eb82ff87SDaniel Beauregard 	switch (type) {
1677eb82ff87SDaniel Beauregard 	case 0:
1678eb82ff87SDaniel Beauregard 		ret = ql_8021_init_p3p(ha);
1679eb82ff87SDaniel Beauregard 		break;
1680eb82ff87SDaniel Beauregard 	case 1:
1681eb82ff87SDaniel Beauregard 		ret = ql_8021_load_from_flash(ha);
1682eb82ff87SDaniel Beauregard 		break;
1683eb82ff87SDaniel Beauregard 	case 2:
1684eb82ff87SDaniel Beauregard 		ret = ql_8021_load_firmware(ha);
1685eb82ff87SDaniel Beauregard 		break;
1686eb82ff87SDaniel Beauregard 	}
1687eb82ff87SDaniel Beauregard 	delay(1);
1688eb82ff87SDaniel Beauregard 
1689eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x18, 0x1020);
1690eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0x80001e);
1691eb82ff87SDaniel Beauregard 
1692eb82ff87SDaniel Beauregard 	if (ret) {
1693eb82ff87SDaniel Beauregard 		EL(ha, "type=%d, ret=%d\n", type, ret);
1694eb82ff87SDaniel Beauregard 	} else {
1695eb82ff87SDaniel Beauregard 		ret = ql_8021_phantom_init(ha);
1696eb82ff87SDaniel Beauregard 	}
1697eb82ff87SDaniel Beauregard 	return (ret);
1698eb82ff87SDaniel Beauregard }
1699eb82ff87SDaniel Beauregard 
1700eb82ff87SDaniel Beauregard int
1701eb82ff87SDaniel Beauregard ql_8021_load_risc(ql_adapter_state_t *ha)
1702eb82ff87SDaniel Beauregard {
1703eb82ff87SDaniel Beauregard 	int		rv = 0;
1704eb82ff87SDaniel Beauregard 	static int	ql_8021_fw_loaded = 0;
1705eb82ff87SDaniel Beauregard 
1706eb82ff87SDaniel Beauregard 	GLOBAL_HW_LOCK();
1707eb82ff87SDaniel Beauregard 	if (!ql_8021_fw_loaded) {
1708eb82ff87SDaniel Beauregard 		if (ha->risc_fw[0].code) {
1709eb82ff87SDaniel Beauregard 			EL(ha, "from driver\n");
1710eb82ff87SDaniel Beauregard 			rv = ql_8021_reset_hw(ha, 2);
1711eb82ff87SDaniel Beauregard 		} else {
1712eb82ff87SDaniel Beauregard 			/*
1713eb82ff87SDaniel Beauregard 			 * BIOS method
1714eb82ff87SDaniel Beauregard 			 * ql_8021_reset_hw(ha, 0)
1715eb82ff87SDaniel Beauregard 			 */
1716eb82ff87SDaniel Beauregard 			EL(ha, "from flash\n");
1717eb82ff87SDaniel Beauregard 			rv = ql_8021_reset_hw(ha, 1);
1718eb82ff87SDaniel Beauregard 		}
1719eb82ff87SDaniel Beauregard 		if (rv == 0) {
1720eb82ff87SDaniel Beauregard 			ql_8021_fw_loaded = 1;
1721eb82ff87SDaniel Beauregard 
1722eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
1723eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0x0);
1724eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0x0);
1725eb82ff87SDaniel Beauregard 
1726eb82ff87SDaniel Beauregard 			GLOBAL_HW_UNLOCK();
1727eb82ff87SDaniel Beauregard 
1728eb82ff87SDaniel Beauregard 			ADAPTER_STATE_LOCK(ha);
1729eb82ff87SDaniel Beauregard 			ha->flags &= ~INTERRUPTS_ENABLED;
1730eb82ff87SDaniel Beauregard 			ADAPTER_STATE_UNLOCK(ha);
1731eb82ff87SDaniel Beauregard 
1732eb82ff87SDaniel Beauregard 			(void) ql_8021_enable_intrs(ha);
1733eb82ff87SDaniel Beauregard 
1734eb82ff87SDaniel Beauregard 			ADAPTER_STATE_LOCK(ha);
1735eb82ff87SDaniel Beauregard 			ha->flags |= INTERRUPTS_ENABLED;
1736eb82ff87SDaniel Beauregard 			ADAPTER_STATE_UNLOCK(ha);
1737eb82ff87SDaniel Beauregard 		} else {
1738eb82ff87SDaniel Beauregard 			GLOBAL_HW_UNLOCK();
1739eb82ff87SDaniel Beauregard 		}
1740eb82ff87SDaniel Beauregard 	} else {
1741eb82ff87SDaniel Beauregard 		GLOBAL_HW_UNLOCK();
1742eb82ff87SDaniel Beauregard 		EL(ha, "Firmware loaded by other function\n");
1743eb82ff87SDaniel Beauregard 	}
1744eb82ff87SDaniel Beauregard 
1745eb82ff87SDaniel Beauregard 	if (rv == 0) {
1746eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR, &ha->fw_major_version);
1747eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR, &ha->fw_minor_version);
1748eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, UNM_FW_VERSION_SUB, &ha->fw_subminor_version);
1749eb82ff87SDaniel Beauregard 		EL(ha, "fw v%d.%02d.%02d\n", ha->fw_major_version,
1750eb82ff87SDaniel Beauregard 		    ha->fw_minor_version, ha->fw_subminor_version);
1751eb82ff87SDaniel Beauregard 	} else {
1752eb82ff87SDaniel Beauregard 		EL(ha, "status = -1\n");
1753eb82ff87SDaniel Beauregard 		return (QL_FUNCTION_FAILED);
1754eb82ff87SDaniel Beauregard 	}
1755eb82ff87SDaniel Beauregard 
1756eb82ff87SDaniel Beauregard 	return (QL_SUCCESS);
1757eb82ff87SDaniel Beauregard }
1758eb82ff87SDaniel Beauregard 
1759eb82ff87SDaniel Beauregard void
1760eb82ff87SDaniel Beauregard ql_8021_clr_hw_intr(ql_adapter_state_t *ha)
1761eb82ff87SDaniel Beauregard {
1762eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
1763eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
1764eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
1765eb82ff87SDaniel Beauregard }
1766eb82ff87SDaniel Beauregard 
1767eb82ff87SDaniel Beauregard void
1768eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ql_adapter_state_t *ha)
1769eb82ff87SDaniel Beauregard {
1770eb82ff87SDaniel Beauregard 	WRT32_IO_REG(ha, nx_risc_int, 0);
1771eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xfbff);
1772eb82ff87SDaniel Beauregard }
1773eb82ff87SDaniel Beauregard 
1774eb82ff87SDaniel Beauregard void
1775eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ql_adapter_state_t *ha)
1776eb82ff87SDaniel Beauregard {
1777eb82ff87SDaniel Beauregard 	GLOBAL_HW_LOCK();
1778eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
1779eb82ff87SDaniel Beauregard 	GLOBAL_HW_UNLOCK();
1780eb82ff87SDaniel Beauregard 	(void) ql_toggle_interrupt(ha, 1);
1781eb82ff87SDaniel Beauregard }
1782eb82ff87SDaniel Beauregard 
1783eb82ff87SDaniel Beauregard void
1784eb82ff87SDaniel Beauregard ql_8021_disable_intrs(ql_adapter_state_t *ha)
1785eb82ff87SDaniel Beauregard {
1786eb82ff87SDaniel Beauregard 	(void) ql_toggle_interrupt(ha, 0);
1787eb82ff87SDaniel Beauregard 	GLOBAL_HW_LOCK();
1788eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
1789eb82ff87SDaniel Beauregard 	GLOBAL_HW_UNLOCK();
1790eb82ff87SDaniel Beauregard }
1791eb82ff87SDaniel Beauregard 
1792eb82ff87SDaniel Beauregard void
1793eb82ff87SDaniel Beauregard ql_8021_update_crb_int_ptr(ql_adapter_state_t *ha)
1794eb82ff87SDaniel Beauregard {
1795eb82ff87SDaniel Beauregard 	struct legacy_intr_set	*nx_legacy_intr;
1796eb82ff87SDaniel Beauregard 
1797eb82ff87SDaniel Beauregard 	ha->qdr_sn_window = (uint32_t)-1;
1798eb82ff87SDaniel Beauregard 	ha->ddr_mn_window = (uint32_t)-1;
1799eb82ff87SDaniel Beauregard 	nx_legacy_intr = &legacy_intr[ha->function_number];
1800eb82ff87SDaniel Beauregard 
1801eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
1802eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg;
1803eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
1804eb82ff87SDaniel Beauregard 	ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
1805eb82ff87SDaniel Beauregard }
1806eb82ff87SDaniel Beauregard 
1807eb82ff87SDaniel Beauregard void
1808eb82ff87SDaniel Beauregard ql_8021_set_drv_active(ql_adapter_state_t *ha)
1809eb82ff87SDaniel Beauregard {
1810eb82ff87SDaniel Beauregard 	uint32_t	val;
1811eb82ff87SDaniel Beauregard 
1812eb82ff87SDaniel Beauregard 	if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
1813eb82ff87SDaniel Beauregard 		return;
1814eb82ff87SDaniel Beauregard 	}
1815eb82ff87SDaniel Beauregard 
1816eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
1817eb82ff87SDaniel Beauregard 	if (val == 0xffffffff) {
1818eb82ff87SDaniel Beauregard 		val = (1 << (ha->function_number * 4));
1819eb82ff87SDaniel Beauregard 	} else {
1820eb82ff87SDaniel Beauregard 		val |= (1 << (ha->function_number * 4));
1821eb82ff87SDaniel Beauregard 	}
1822eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
1823eb82ff87SDaniel Beauregard 
1824eb82ff87SDaniel Beauregard 	ql_8021_hw_unlock(ha);
1825eb82ff87SDaniel Beauregard }
1826eb82ff87SDaniel Beauregard 
1827eb82ff87SDaniel Beauregard void
1828eb82ff87SDaniel Beauregard ql_8021_clr_drv_active(ql_adapter_state_t *ha)
1829eb82ff87SDaniel Beauregard {
1830eb82ff87SDaniel Beauregard 	uint32_t	val;
1831eb82ff87SDaniel Beauregard 
1832eb82ff87SDaniel Beauregard 	if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
1833eb82ff87SDaniel Beauregard 		return;
1834eb82ff87SDaniel Beauregard 	}
1835eb82ff87SDaniel Beauregard 
1836eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
1837eb82ff87SDaniel Beauregard 	val &= ~(1 << (ha->function_number * 4));
1838eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
1839eb82ff87SDaniel Beauregard 
1840eb82ff87SDaniel Beauregard 	ql_8021_hw_unlock(ha);
1841eb82ff87SDaniel Beauregard }
1842eb82ff87SDaniel Beauregard 
1843eb82ff87SDaniel Beauregard static void
1844eb82ff87SDaniel Beauregard ql_8021_need_reset_handler(ql_adapter_state_t *ha)
1845eb82ff87SDaniel Beauregard {
1846eb82ff87SDaniel Beauregard 	uint32_t	drv_state, drv_active;
1847eb82ff87SDaniel Beauregard 	clock_t		timer;
1848eb82ff87SDaniel Beauregard 
1849eb82ff87SDaniel Beauregard 	(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1850eb82ff87SDaniel Beauregard 
1851eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1852eb82ff87SDaniel Beauregard 	drv_state |= (1 << (ha->function_number * 4));
1853eb82ff87SDaniel Beauregard 	ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
1854eb82ff87SDaniel Beauregard 
1855eb82ff87SDaniel Beauregard 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
1856eb82ff87SDaniel Beauregard 
1857eb82ff87SDaniel Beauregard 	ql_8021_hw_unlock(ha);
1858eb82ff87SDaniel Beauregard 
1859eb82ff87SDaniel Beauregard 	for (timer = 30; timer && drv_state != drv_active; timer--) {
1860eb82ff87SDaniel Beauregard 		delay(100);
1861eb82ff87SDaniel Beauregard 
1862eb82ff87SDaniel Beauregard 		(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1863eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1864eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
1865eb82ff87SDaniel Beauregard 		ql_8021_hw_unlock(ha);
1866eb82ff87SDaniel Beauregard 	}
1867eb82ff87SDaniel Beauregard }
1868eb82ff87SDaniel Beauregard 
1869eb82ff87SDaniel Beauregard uint32_t
1870eb82ff87SDaniel Beauregard ql_8021_idc_handler(ql_adapter_state_t *ha)
1871eb82ff87SDaniel Beauregard {
1872eb82ff87SDaniel Beauregard 	uint32_t	dev_state, drv_state, rval;
1873eb82ff87SDaniel Beauregard 	clock_t		timer;
1874eb82ff87SDaniel Beauregard 	ql_mbx_data_t	mr;
1875eb82ff87SDaniel Beauregard 	boolean_t	stalled = B_FALSE, lock = B_FALSE;
1876eb82ff87SDaniel Beauregard 
1877eb82ff87SDaniel Beauregard 	/* wait for 30 seconds for device to go ready */
1878eb82ff87SDaniel Beauregard 	timer = 30;
1879eb82ff87SDaniel Beauregard 	while (timer) {
1880eb82ff87SDaniel Beauregard 		if (lock == B_FALSE) {
1881eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1882eb82ff87SDaniel Beauregard 			lock = B_TRUE;
1883eb82ff87SDaniel Beauregard 		}
1884eb82ff87SDaniel Beauregard 		ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
1885eb82ff87SDaniel Beauregard 
1886eb82ff87SDaniel Beauregard 		switch (dev_state) {
1887eb82ff87SDaniel Beauregard 		case 0xffffffff:
1888eb82ff87SDaniel Beauregard 		case NX_DEV_COLD:
1889eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=NX_DEV_COLD\n");
1890eb82ff87SDaniel Beauregard 			rval = NX_DEV_COLD;
1891eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING);
1892eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DRV_IDC_VERSION, NX_IDC_VERSION);
1893eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_unlock(ha);
1894eb82ff87SDaniel Beauregard 			if (ql_get_fw_version(ha, &mr, 2) == QL_SUCCESS &&
1895eb82ff87SDaniel Beauregard 			    (mr.mb[1] | mr.mb[2] | mr.mb[3])) {
1896eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR,
1897eb82ff87SDaniel Beauregard 				    &ha->fw_major_version);
1898eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR,
1899eb82ff87SDaniel Beauregard 				    &ha->fw_minor_version);
1900eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, UNM_FW_VERSION_SUB,
1901eb82ff87SDaniel Beauregard 				    &ha->fw_subminor_version);
1902eb82ff87SDaniel Beauregard 				rval = NX_DEV_READY;
1903eb82ff87SDaniel Beauregard 			} else if (ql_8021_load_risc(ha) == QL_SUCCESS) {
1904eb82ff87SDaniel Beauregard 				rval = NX_DEV_READY;
1905eb82ff87SDaniel Beauregard 			}
1906eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1907eb82ff87SDaniel Beauregard 			ql_8021_wr_32(ha, CRB_DEV_STATE, rval);
1908eb82ff87SDaniel Beauregard 			break;
1909eb82ff87SDaniel Beauregard 		case NX_DEV_READY:
1910eb82ff87SDaniel Beauregard 			rval = NX_DEV_READY;
1911eb82ff87SDaniel Beauregard 			timer = 0;
1912eb82ff87SDaniel Beauregard 			break;
1913eb82ff87SDaniel Beauregard 		case NX_DEV_FAILED:
1914eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=NX_DEV_FAILED\n");
1915eb82ff87SDaniel Beauregard 			rval = NX_DEV_FAILED;
1916eb82ff87SDaniel Beauregard 			timer = 0;
1917eb82ff87SDaniel Beauregard 			break;
1918eb82ff87SDaniel Beauregard 
1919eb82ff87SDaniel Beauregard 		case NX_DEV_NEED_RESET:
1920eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=NX_DEV_NEED_RESET\n");
1921eb82ff87SDaniel Beauregard 			rval = NX_DEV_NEED_RESET;
1922eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_unlock(ha);
1923eb82ff87SDaniel Beauregard 			lock = B_FALSE;
1924eb82ff87SDaniel Beauregard 			if (ql_stall_driver(ha, 0) == QL_SUCCESS) {
1925eb82ff87SDaniel Beauregard 				stalled = B_TRUE;
1926eb82ff87SDaniel Beauregard 				ql_8021_need_reset_handler(ha);
1927eb82ff87SDaniel Beauregard 			}
1928eb82ff87SDaniel Beauregard 			break;
1929eb82ff87SDaniel Beauregard 
1930eb82ff87SDaniel Beauregard 		case NX_DEV_NEED_QUIESCENT:
1931eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=NX_DEV_NEED_QUIESCENT\n");
1932eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_unlock(ha);
1933eb82ff87SDaniel Beauregard 			lock = B_FALSE;
1934eb82ff87SDaniel Beauregard 			rval = ql_stall_driver(ha, 0);
1935eb82ff87SDaniel Beauregard 			if (rval == QL_SUCCESS) {
1936eb82ff87SDaniel Beauregard 				stalled = B_TRUE;
1937eb82ff87SDaniel Beauregard 				(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1938eb82ff87SDaniel Beauregard 				lock = B_TRUE;
1939eb82ff87SDaniel Beauregard 				ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1940eb82ff87SDaniel Beauregard 				drv_state |=
1941eb82ff87SDaniel Beauregard 				    (2 << (ha->function_number * 4));
1942eb82ff87SDaniel Beauregard 				ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
1943eb82ff87SDaniel Beauregard 			}
1944eb82ff87SDaniel Beauregard 			break;
1945eb82ff87SDaniel Beauregard 
1946eb82ff87SDaniel Beauregard 		case NX_DEV_INITIALIZING:
1947eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=NX_DEV_INITIALIZING\n");
1948eb82ff87SDaniel Beauregard 			break;
1949eb82ff87SDaniel Beauregard 		case NX_DEV_QUIESCENT:
1950eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=NX_DEV_QUIESCENT\n");
1951eb82ff87SDaniel Beauregard 			break;
1952eb82ff87SDaniel Beauregard 		default:
1953eb82ff87SDaniel Beauregard 			EL(ha, "dev_state=%x, default\n", dev_state);
1954eb82ff87SDaniel Beauregard 			break;
1955eb82ff87SDaniel Beauregard 		}
1956eb82ff87SDaniel Beauregard 		if (lock == B_TRUE) {
1957eb82ff87SDaniel Beauregard 			(void) ql_8021_hw_unlock(ha);
1958eb82ff87SDaniel Beauregard 			lock = B_FALSE;
1959eb82ff87SDaniel Beauregard 		}
1960eb82ff87SDaniel Beauregard 
1961eb82ff87SDaniel Beauregard 		if (timer) {
1962eb82ff87SDaniel Beauregard 			delay(100);
1963eb82ff87SDaniel Beauregard 			timer--;
1964eb82ff87SDaniel Beauregard 		}
1965eb82ff87SDaniel Beauregard 	}
1966eb82ff87SDaniel Beauregard 
1967eb82ff87SDaniel Beauregard 	if (stalled) {
1968eb82ff87SDaniel Beauregard 		ql_restart_driver(ha);
1969eb82ff87SDaniel Beauregard 	}
1970eb82ff87SDaniel Beauregard 	return (rval);
1971eb82ff87SDaniel Beauregard }
1972