xref: /illumos-gate/usr/src/uts/common/io/ntxn/unm_nic_hw.c (revision 3afe87ebb25691cb6d158edaa34a6fb9b703a691)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 NetXen, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #include <sys/types.h>
26 #include <sys/conf.h>
27 #include <sys/debug.h>
28 #include <sys/stropts.h>
29 #include <sys/stream.h>
30 #include <sys/strlog.h>
31 #include <sys/kmem.h>
32 #include <sys/stat.h>
33 #include <sys/kstat.h>
34 #include <sys/vtrace.h>
35 #include <sys/dlpi.h>
36 #include <sys/strsun.h>
37 #include <sys/ethernet.h>
38 #include <sys/modctl.h>
39 #include <sys/errno.h>
40 #include <sys/dditypes.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/sysmacros.h>
44 
45 #include <sys/pci.h>
46 
47 #include "unm_nic.h"
48 #include "unm_nic_hw.h"
49 #include "nic_cmn.h"
50 #include "unm_brdcfg.h"
51 #include "driver_info.h"
52 
53 long unm_niu_gbe_phy_read(struct unm_adapter_s *,
54 		long reg, unm_crbword_t *readval);
55 
56 #define	MASK(n)			((1ULL<<(n))-1)
57 #define	MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
58 #define	OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) |	\
59 		((addr >> 25) & 0x3ff)) // 64K?
60 #define	MS_WIN(addr) (addr & 0x0ffc0000)
61 #define	UNM_PCI_MN_2M   (0)
62 #define	UNM_PCI_MS_2M   (0x80000)
63 #define	UNM_PCI_OCM0_2M (0xc0000)
64 #define	VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800)
65 #define	GET_MEM_OFFS_2M(addr) (addr & MASK(18))
66 
67 #define	CRB_BLK(off)	((off >> 20) & 0x3f)
68 #define	CRB_SUBBLK(off)	((off >> 16) & 0xf)
69 #define	CRB_WINDOW_2M	(0x130060)
70 #define	UNM_PCI_CAMQM_2M_END	(0x04800800UL)
71 #define	CRB_HI(off)	((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
72 #define	UNM_PCI_CAMQM_2M_BASE	(0x000ff800UL)
73 #define	CRB_INDIRECT_2M	(0x1e0000UL)
74 
75 static crb_128M_2M_block_map_t	crb_128M_2M_map[64] = {
76 	    {{{0, 0, 0, 0}}}, /* 0: PCI */
77 	    {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
78 	    {1, 0x0110000, 0x0120000, 0x130000},
79 	    {1, 0x0120000, 0x0122000, 0x124000},
80 	    {1, 0x0130000, 0x0132000, 0x126000},
81 	    {1, 0x0140000, 0x0142000, 0x128000},
82 	    {1, 0x0150000, 0x0152000, 0x12a000},
83 	    {1, 0x0160000, 0x0170000, 0x110000},
84 	    {1, 0x0170000, 0x0172000, 0x12e000},
85 	    {0, 0x0000000, 0x0000000, 0x000000},
86 	    {0, 0x0000000, 0x0000000, 0x000000},
87 	    {0, 0x0000000, 0x0000000, 0x000000},
88 	    {0, 0x0000000, 0x0000000, 0x000000},
89 	    {0, 0x0000000, 0x0000000, 0x000000},
90 	    {0, 0x0000000, 0x0000000, 0x000000},
91 	    {1, 0x01e0000, 0x01e0800, 0x122000},
92 	    {0, 0x0000000, 0x0000000, 0x000000}}},
93 	    {{{1, 0x0200000, 0x0210000, 0x180000}}}, /* 2: MN */
94 	    {{{0, 0, 0, 0}}}, /* 3: */
95 	    {{{1, 0x0400000, 0x0401000, 0x169000}}}, /* 4: P2NR1 */
96 	    {{{1, 0x0500000, 0x0510000, 0x140000}}}, /* 5: SRE   */
97 	    {{{1, 0x0600000, 0x0610000, 0x1c0000}}}, /* 6: NIU   */
98 	    {{{1, 0x0700000, 0x0704000, 0x1b8000}}}, /* 7: QM    */
99 	    {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0  */
100 	    {0, 0x0000000, 0x0000000, 0x000000},
101 	    {0, 0x0000000, 0x0000000, 0x000000},
102 	    {0, 0x0000000, 0x0000000, 0x000000},
103 	    {0, 0x0000000, 0x0000000, 0x000000},
104 	    {0, 0x0000000, 0x0000000, 0x000000},
105 	    {0, 0x0000000, 0x0000000, 0x000000},
106 	    {0, 0x0000000, 0x0000000, 0x000000},
107 	    {0, 0x0000000, 0x0000000, 0x000000},
108 	    {0, 0x0000000, 0x0000000, 0x000000},
109 	    {0, 0x0000000, 0x0000000, 0x000000},
110 	    {0, 0x0000000, 0x0000000, 0x000000},
111 	    {0, 0x0000000, 0x0000000, 0x000000},
112 	    {0, 0x0000000, 0x0000000, 0x000000},
113 	    {0, 0x0000000, 0x0000000, 0x000000},
114 	    {1, 0x08f0000, 0x08f2000, 0x172000}}},
115 	    {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1 */
116 	    {0, 0x0000000, 0x0000000, 0x000000},
117 	    {0, 0x0000000, 0x0000000, 0x000000},
118 	    {0, 0x0000000, 0x0000000, 0x000000},
119 	    {0, 0x0000000, 0x0000000, 0x000000},
120 	    {0, 0x0000000, 0x0000000, 0x000000},
121 	    {0, 0x0000000, 0x0000000, 0x000000},
122 	    {0, 0x0000000, 0x0000000, 0x000000},
123 	    {0, 0x0000000, 0x0000000, 0x000000},
124 	    {0, 0x0000000, 0x0000000, 0x000000},
125 	    {0, 0x0000000, 0x0000000, 0x000000},
126 	    {0, 0x0000000, 0x0000000, 0x000000},
127 	    {0, 0x0000000, 0x0000000, 0x000000},
128 	    {0, 0x0000000, 0x0000000, 0x000000},
129 	    {0, 0x0000000, 0x0000000, 0x000000},
130 	    {1, 0x09f0000, 0x09f2000, 0x176000}}},
131 	    {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2 */
132 	    {0, 0x0000000, 0x0000000, 0x000000},
133 	    {0, 0x0000000, 0x0000000, 0x000000},
134 	    {0, 0x0000000, 0x0000000, 0x000000},
135 	    {0, 0x0000000, 0x0000000, 0x000000},
136 	    {0, 0x0000000, 0x0000000, 0x000000},
137 	    {0, 0x0000000, 0x0000000, 0x000000},
138 	    {0, 0x0000000, 0x0000000, 0x000000},
139 	    {0, 0x0000000, 0x0000000, 0x000000},
140 	    {0, 0x0000000, 0x0000000, 0x000000},
141 	    {0, 0x0000000, 0x0000000, 0x000000},
142 	    {0, 0x0000000, 0x0000000, 0x000000},
143 	    {0, 0x0000000, 0x0000000, 0x000000},
144 	    {0, 0x0000000, 0x0000000, 0x000000},
145 	    {0, 0x0000000, 0x0000000, 0x000000},
146 	    {1, 0x0af0000, 0x0af2000, 0x17a000}}},
147 	    {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3 */
148 	    {0, 0x0000000, 0x0000000, 0x000000},
149 	    {0, 0x0000000, 0x0000000, 0x000000},
150 	    {0, 0x0000000, 0x0000000, 0x000000},
151 	    {0, 0x0000000, 0x0000000, 0x000000},
152 	    {0, 0x0000000, 0x0000000, 0x000000},
153 	    {0, 0x0000000, 0x0000000, 0x000000},
154 	    {0, 0x0000000, 0x0000000, 0x000000},
155 	    {0, 0x0000000, 0x0000000, 0x000000},
156 	    {0, 0x0000000, 0x0000000, 0x000000},
157 	    {0, 0x0000000, 0x0000000, 0x000000},
158 	    {0, 0x0000000, 0x0000000, 0x000000},
159 	    {0, 0x0000000, 0x0000000, 0x000000},
160 	    {0, 0x0000000, 0x0000000, 0x000000},
161 	    {0, 0x0000000, 0x0000000, 0x000000},
162 	    {1, 0x0bf0000, 0x0bf2000, 0x17e000}}},
163 	    {{{1, 0x0c00000, 0x0c04000, 0x1d4000}}}, /* 12: I2Q */
164 	    {{{1, 0x0d00000, 0x0d04000, 0x1a4000}}}, /* 13: TMR */
165 	    {{{1, 0x0e00000, 0x0e04000, 0x1a0000}}}, /* 14: ROMUSB */
166 	    {{{1, 0x0f00000, 0x0f01000, 0x164000}}}, /* 15: PEG4 */
167 	    {{{0, 0x1000000, 0x1004000, 0x1a8000}}}, /* 16: XDMA */
168 	    {{{1, 0x1100000, 0x1101000, 0x160000}}}, /* 17: PEG0 */
169 	    {{{1, 0x1200000, 0x1201000, 0x161000}}}, /* 18: PEG1 */
170 	    {{{1, 0x1300000, 0x1301000, 0x162000}}}, /* 19: PEG2 */
171 	    {{{1, 0x1400000, 0x1401000, 0x163000}}}, /* 20: PEG3 */
172 	    {{{1, 0x1500000, 0x1501000, 0x165000}}}, /* 21: P2ND */
173 	    {{{1, 0x1600000, 0x1601000, 0x166000}}}, /* 22: P2NI */
174 	    {{{0, 0, 0, 0}}}, /* 23: */
175 	    {{{0, 0, 0, 0}}}, /* 24: */
176 	    {{{0, 0, 0, 0}}}, /* 25: */
177 	    {{{0, 0, 0, 0}}}, /* 26: */
178 	    {{{0, 0, 0, 0}}}, /* 27: */
179 	    {{{0, 0, 0, 0}}}, /* 28: */
180 	    {{{1, 0x1d00000, 0x1d10000, 0x190000}}}, /* 29: MS */
181 	    {{{1, 0x1e00000, 0x1e01000, 0x16a000}}}, /* 30: P2NR2 */
182 	    {{{1, 0x1f00000, 0x1f10000, 0x150000}}}, /* 31: EPG */
183 	    {{{0}}}, /* 32: PCI */
184 	    {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
185 	    {1, 0x2110000, 0x2120000, 0x130000},
186 	    {1, 0x2120000, 0x2122000, 0x124000},
187 	    {1, 0x2130000, 0x2132000, 0x126000},
188 	    {1, 0x2140000, 0x2142000, 0x128000},
189 	    {1, 0x2150000, 0x2152000, 0x12a000},
190 	    {1, 0x2160000, 0x2170000, 0x110000},
191 	    {1, 0x2170000, 0x2172000, 0x12e000},
192 	    {0, 0x0000000, 0x0000000, 0x000000},
193 	    {0, 0x0000000, 0x0000000, 0x000000},
194 	    {0, 0x0000000, 0x0000000, 0x000000},
195 	    {0, 0x0000000, 0x0000000, 0x000000},
196 	    {0, 0x0000000, 0x0000000, 0x000000},
197 	    {0, 0x0000000, 0x0000000, 0x000000},
198 	    {0, 0x0000000, 0x0000000, 0x000000},
199 	    {0, 0x0000000, 0x0000000, 0x000000}}},
200 	    {{{1, 0x2200000, 0x2204000, 0x1b0000}}}, /* 34: CAM */
201 	    {{{0}}}, /* 35: */
202 	    {{{0}}}, /* 36: */
203 	    {{{0}}}, /* 37: */
204 	    {{{0}}}, /* 38: */
205 	    {{{0}}}, /* 39: */
206 	    {{{1, 0x2800000, 0x2804000, 0x1a4000}}}, /* 40: TMR */
207 	    {{{1, 0x2900000, 0x2901000, 0x16b000}}}, /* 41: P2NR3 */
208 	    {{{1, 0x2a00000, 0x2a00400, 0x1ac400}}}, /* 42: RPMX1 */
209 	    {{{1, 0x2b00000, 0x2b00400, 0x1ac800}}}, /* 43: RPMX2 */
210 	    {{{1, 0x2c00000, 0x2c00400, 0x1acc00}}}, /* 44: RPMX3 */
211 	    {{{1, 0x2d00000, 0x2d00400, 0x1ad000}}}, /* 45: RPMX4 */
212 	    {{{1, 0x2e00000, 0x2e00400, 0x1ad400}}}, /* 46: RPMX5 */
213 	    {{{1, 0x2f00000, 0x2f00400, 0x1ad800}}}, /* 47: RPMX6 */
214 	    {{{1, 0x3000000, 0x3000400, 0x1adc00}}}, /* 48: RPMX7 */
215 	    {{{0, 0x3100000, 0x3104000, 0x1a8000}}}, /* 49: XDMA */
216 	    {{{1, 0x3200000, 0x3204000, 0x1d4000}}}, /* 50: I2Q */
217 	    {{{1, 0x3300000, 0x3304000, 0x1a0000}}}, /* 51: ROMUSB */
218 	    {{{0}}}, /* 52: */
219 	    {{{1, 0x3500000, 0x3500400, 0x1ac000}}}, /* 53: RPMX0 */
220 	    {{{1, 0x3600000, 0x3600400, 0x1ae000}}}, /* 54: RPMX8 */
221 	    {{{1, 0x3700000, 0x3700400, 0x1ae400}}}, /* 55: RPMX9 */
222 	    {{{1, 0x3800000, 0x3804000, 0x1d0000}}}, /* 56: OCM0 */
223 	    {{{1, 0x3900000, 0x3904000, 0x1b4000}}}, /* 57: CRYPTO */
224 	    {{{1, 0x3a00000, 0x3a04000, 0x1d8000}}}, /* 58: SMB */
225 	    {{{0}}}, /* 59: I2C0 */
226 	    {{{0}}}, /* 60: I2C1 */
227 	    {{{1, 0x3d00000, 0x3d04000, 0x1d8000}}}, /* 61: LPC */
228 	    {{{1, 0x3e00000, 0x3e01000, 0x167000}}}, /* 62: P2NC */
229 	    {{{1, 0x3f00000, 0x3f01000, 0x168000}}} /* 63: P2NR0 */
230 };
231 
232 /*
233  * top 12 bits of crb internal address (hub, agent)
234  */
235 static unsigned crb_hub_agt[64] = {
236 	0,
237 	UNM_HW_CRB_HUB_AGT_ADR_PS,
238 	UNM_HW_CRB_HUB_AGT_ADR_MN,
239 	UNM_HW_CRB_HUB_AGT_ADR_MS,
240 	0,
241 	UNM_HW_CRB_HUB_AGT_ADR_SRE,
242 	UNM_HW_CRB_HUB_AGT_ADR_NIU,
243 	UNM_HW_CRB_HUB_AGT_ADR_QMN,
244 	UNM_HW_CRB_HUB_AGT_ADR_SQN0,
245 	UNM_HW_CRB_HUB_AGT_ADR_SQN1,
246 	UNM_HW_CRB_HUB_AGT_ADR_SQN2,
247 	UNM_HW_CRB_HUB_AGT_ADR_SQN3,
248 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
249 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
250 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
251 	UNM_HW_CRB_HUB_AGT_ADR_PGN4,
252 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
253 	UNM_HW_CRB_HUB_AGT_ADR_PGN0,
254 	UNM_HW_CRB_HUB_AGT_ADR_PGN1,
255 	UNM_HW_CRB_HUB_AGT_ADR_PGN2,
256 	UNM_HW_CRB_HUB_AGT_ADR_PGN3,
257 	UNM_HW_CRB_HUB_AGT_ADR_PGND,
258 	UNM_HW_CRB_HUB_AGT_ADR_PGNI,
259 	UNM_HW_CRB_HUB_AGT_ADR_PGS0,
260 	UNM_HW_CRB_HUB_AGT_ADR_PGS1,
261 	UNM_HW_CRB_HUB_AGT_ADR_PGS2,
262 	UNM_HW_CRB_HUB_AGT_ADR_PGS3,
263 	0,
264 	UNM_HW_CRB_HUB_AGT_ADR_PGSI,
265 	UNM_HW_CRB_HUB_AGT_ADR_SN,
266 	0,
267 	UNM_HW_CRB_HUB_AGT_ADR_EG,
268 	0,
269 	UNM_HW_CRB_HUB_AGT_ADR_PS,
270 	UNM_HW_CRB_HUB_AGT_ADR_CAM,
271 	0,
272 	0,
273 	0,
274 	0,
275 	0,
276 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
277 	0,
278 	UNM_HW_CRB_HUB_AGT_ADR_RPMX1,
279 	UNM_HW_CRB_HUB_AGT_ADR_RPMX2,
280 	UNM_HW_CRB_HUB_AGT_ADR_RPMX3,
281 	UNM_HW_CRB_HUB_AGT_ADR_RPMX4,
282 	UNM_HW_CRB_HUB_AGT_ADR_RPMX5,
283 	UNM_HW_CRB_HUB_AGT_ADR_RPMX6,
284 	UNM_HW_CRB_HUB_AGT_ADR_RPMX7,
285 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
286 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
287 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
288 	0,
289 	UNM_HW_CRB_HUB_AGT_ADR_RPMX0,
290 	UNM_HW_CRB_HUB_AGT_ADR_RPMX8,
291 	UNM_HW_CRB_HUB_AGT_ADR_RPMX9,
292 	UNM_HW_CRB_HUB_AGT_ADR_OCM0,
293 	0,
294 	UNM_HW_CRB_HUB_AGT_ADR_SMB,
295 	UNM_HW_CRB_HUB_AGT_ADR_I2C0,
296 	UNM_HW_CRB_HUB_AGT_ADR_I2C1,
297 	0,
298 	UNM_HW_CRB_HUB_AGT_ADR_PGNC,
299 	0,
300 };
301 
302 #define	CRB_WIN_LOCK_TIMEOUT 100000000
303 
304 static void
305 crb_win_lock(struct unm_adapter_s *adapter)
306 {
307 	int i;
308 	int done = 0, timeout = 0;
309 
310 	while (!done) {
311 		/* acquire semaphore3 from PCI HW block */
312 		adapter->unm_nic_hw_read_wx(adapter,
313 		    UNM_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
314 		if (done == 1)
315 			break;
316 		if (timeout >= CRB_WIN_LOCK_TIMEOUT) {
317 			cmn_err(CE_WARN, "%s%d: crb_win_lock timed out\n",
318 			    adapter->name, adapter->instance);
319 			return;
320 		}
321 		timeout++;
322 		/*
323 		 *  Yield CPU
324 		 */
325 		for (i = 0; i < 20; i++);
326 	}
327 	adapter->unm_crb_writelit_adapter(adapter, UNM_CRB_WIN_LOCK_ID,
328 	    adapter->portnum);
329 }
330 
331 static void
332 crb_win_unlock(struct unm_adapter_s *adapter)
333 {
334 	int	val;
335 
336 	adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_SEM7_UNLOCK),
337 	    &val, 4);
338 }
339 
340 /*
341  * Changes the CRB window to the specified window.
342  */
343 void
344 unm_nic_pci_change_crbwindow_128M(unm_adapter *adapter, uint32_t wndw)
345 {
346 	unm_pcix_crb_window_t	window;
347 	unsigned long			offset;
348 	uint32_t				tmp;
349 
350 	if (adapter->curr_window == wndw) {
351 		return;
352 	}
353 
354 	/*
355 	 * Move the CRB window.
356 	 * We need to write to the "direct access" region of PCI
357 	 * to avoid a race condition where the window register has
358 	 * not been successfully written across CRB before the target
359 	 * register address is received by PCI. The direct region bypasses
360 	 * the CRB bus.
361 	 */
362 	offset = PCI_OFFSET_SECOND_RANGE(adapter,
363 	    UNM_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(adapter->ahw.pci_func)));
364 
365 	*(unm_crbword_t *)&window = 0;
366 	window.addrbit = wndw;
367 	UNM_NIC_PCI_WRITE_32(*(unsigned int *)&window, (void*) (offset));
368 	/* MUST make sure window is set before we forge on... */
369 	while ((tmp = UNM_NIC_PCI_READ_32((void*) offset)) !=
370 	    *(uint32_t *)&window) {
371 		cmn_err(CE_WARN, "%s: %s WARNING: CRB window value not "
372 		    "registered properly: 0x%08x.\n",
373 		    unm_nic_driver_name, __FUNCTION__, tmp);
374 	}
375 
376 	adapter->curr_window = wndw;
377 }
378 
379 
380 /*
381  * Changes the CRB window to the specified window.
382  */
383 /* ARGSUSED */
384 void
385 unm_nic_pci_change_crbwindow_2M(unm_adapter *adapter, uint32_t wndw)
386 {
387 }
388 
389 
390 uint32_t
391 unm_nic_get_crbwindow(unm_adapter *adapter)
392 {
393 	return (adapter->curr_window);
394 }
395 
396 /*
397  * Return -1 if off is not valid,
398  *	 1 if window access is needed. 'off' is set to offset from
399  *	   CRB space in 128M pci map
400  *	 0 if no window access is needed. 'off' is set to 2M addr
401  * In: 'off' is offset from base in 128M pci map
402  */
403 int
404 unm_nic_pci_get_crb_addr_2M(unm_adapter *adapter, u64 *off, int len)
405 {
406 	unsigned long end = *off + len;
407 	crb_128M_2M_sub_block_map_t *m;
408 
409 
410 	if (*off >= UNM_CRB_MAX)
411 		return (-1);
412 
413 	if (*off >= UNM_PCI_CAMQM && (end <= UNM_PCI_CAMQM_2M_END)) {
414 		*off = (*off - UNM_PCI_CAMQM) + UNM_PCI_CAMQM_2M_BASE +
415 		    adapter->ahw.pci_base0;
416 		return (0);
417 	}
418 
419 	if (*off < UNM_PCI_CRBSPACE)
420 		return (-1);
421 
422 	*off -= UNM_PCI_CRBSPACE;
423 	end = *off + len;
424 	/*
425 	 * Try direct map
426 	 */
427 
428 	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
429 
430 	if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
431 		*off = *off + m->start_2M - m->start_128M +
432 		    adapter->ahw.pci_base0;
433 		return (0);
434 	}
435 
436 	/*
437 	 * Not in direct map, use crb window
438 	 */
439 	return (1);
440 }
441 /*
442  * In: 'off' is offset from CRB space in 128M pci map
443  * Out: 'off' is 2M pci map addr
444  * side effect: lock crb window
445  */
446 static void
447 unm_nic_pci_set_crbwindow_2M(unm_adapter *adapter, u64 *off)
448 {
449 	u32 win_read;
450 
451 	adapter->crb_win = CRB_HI(*off);
452 	UNM_NIC_PCI_WRITE_32(adapter->crb_win, (void *) (CRB_WINDOW_2M +
453 	    adapter->ahw.pci_base0));
454 	/*
455 	 * Read back value to make sure write has gone through before trying
456 	 * to use it.
457 	 */
458 	win_read = UNM_NIC_PCI_READ_32((void *)
459 	    (CRB_WINDOW_2M + adapter->ahw.pci_base0));
460 	if (win_read != adapter->crb_win) {
461 		cmn_err(CE_WARN, "%s: Written crbwin (0x%x) != Read crbwin "
462 		    "(0x%x), off=0x%llx\n", __FUNCTION__, adapter->crb_win,
463 		    win_read, *off);
464 	}
465 	*off = (*off & MASK(16)) + CRB_INDIRECT_2M +
466 	    adapter->ahw.pci_base0;
467 }
468 
469 int
470 unm_nic_hw_write_ioctl_128M(unm_adapter *adapter, u64 off, void *data, int len)
471 {
472 	void		*addr;
473 	u64		offset = off;
474 
475 	if (ADDR_IN_WINDOW1(off)) { // Window 1
476 		addr = CRB_NORMALIZE(adapter, off);
477 		if (!addr) {
478 			offset = CRB_NORMAL(off);
479 			if (adapter->ahw.pci_len0 == 0)
480 				offset -= UNM_PCI_CRBSPACE;
481 			addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
482 			    offset);
483 		}
484 		UNM_READ_LOCK(&adapter->adapter_lock);
485 	} else {// Window 0
486 		addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
487 		if (!addr) {
488 			offset = off;
489 			addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
490 			    offset);
491 		}
492 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
493 		unm_nic_pci_change_crbwindow_128M(adapter, 0);
494 	}
495 
496 	switch (len) {
497 		case 1:
498 			UNM_NIC_PCI_WRITE_8 (*(__uint8_t *)data, addr);
499 			break;
500 		case 2:
501 			UNM_NIC_PCI_WRITE_16 (*(__uint16_t *)data, addr);
502 			break;
503 		case 4:
504 			UNM_NIC_PCI_WRITE_32 (*(__uint32_t *)data, addr);
505 			break;
506 		case 8:
507 			UNM_NIC_PCI_WRITE_64 (*(__uint64_t *)data, addr);
508 			break;
509 		default:
510 #if !defined(NDEBUG)
511 		if ((len & 0x7) != 0)
512 			cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
513 			    unm_nic_driver_name, __FUNCTION__, len);
514 #endif
515 		UNM_NIC_HW_BLOCK_WRITE_64(data, addr, (len>>3));
516 		break;
517 	}
518 	if (ADDR_IN_WINDOW1(off)) {// Window 1
519 		UNM_READ_UNLOCK(&adapter->adapter_lock);
520 	} else {// Window 0
521 		unm_nic_pci_change_crbwindow_128M(adapter, 1);
522 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
523 	}
524 
525 	return (0);
526 }
527 
528 /*
529  * Note : 'len' argument should be either 1, 2, 4, or a multiple of 8.
530  */
531 int
532 unm_nic_hw_write_wx_128M(unm_adapter *adapter, u64 off, void *data, int len)
533 {
534 	/*
535 	 * This is modified from _unm_nic_hw_write().
536 	 * unm_nic_hw_write does not exist now.
537 	 */
538 
539 	void *addr;
540 
541 	if (ADDR_IN_WINDOW1(off)) {// Window 1
542 		addr = CRB_NORMALIZE(adapter, off);
543 		UNM_READ_LOCK(&adapter->adapter_lock);
544 	} else {// Window 0
545 		addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
546 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
547 		unm_nic_pci_change_crbwindow_128M(adapter, 0);
548 	}
549 
550 
551 	if (!addr) {
552 		if (ADDR_IN_WINDOW1(off)) {// Window 1
553 			UNM_READ_UNLOCK(&adapter->adapter_lock);
554 		} else {// Window 0
555 			unm_nic_pci_change_crbwindow_128M(adapter, 1);
556 			UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
557 		}
558 		return (1);
559 	}
560 
561 	switch (len) {
562 		case 1:
563 			UNM_NIC_PCI_WRITE_8 (*(__uint8_t *)data, addr);
564 			break;
565 		case 2:
566 			UNM_NIC_PCI_WRITE_16 (*(__uint16_t *)data, addr);
567 			break;
568 		case 4:
569 			UNM_NIC_PCI_WRITE_32 (*(__uint32_t *)data, addr);
570 			break;
571 		case 8:
572 			UNM_NIC_PCI_WRITE_64 (*(__uint64_t *)data, addr);
573 			break;
574 		default:
575 #if !defined(NDEBUG)
576 			if ((len & 0x7) != 0)
577 				cmn_err(CE_WARN,
578 				    "%s: %s  len(%d) not multiple of 8.\n",
579 				    unm_nic_driver_name, __FUNCTION__, len);
580 #endif
581 			UNM_NIC_HW_BLOCK_WRITE_64(data, addr, (len>>3));
582 			break;
583 	}
584 	if (ADDR_IN_WINDOW1(off)) {// Window 1
585 		UNM_READ_UNLOCK(&adapter->adapter_lock);
586 	} else {// Window 0
587 		unm_nic_pci_change_crbwindow_128M(adapter, 1);
588 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
589 	}
590 
591 	return (0);
592 }
593 
594 /*
595  * Note : only 32-bit writes!
596  */
597 void
598 unm_nic_pci_write_normalize_128M(unm_adapter *adapter, u64 off, u32 data)
599 {
600 	UNM_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off));
601 }
602 
603 /*
604  * Note : only 32-bit reads!
605  */
606 u32
607 unm_nic_pci_read_normalize_128M(unm_adapter *adapter, u64 off)
608 {
609 	return (UNM_NIC_PCI_READ_32(CRB_NORMALIZE(adapter, off)));
610 }
611 
612 /*
613  * Note : only 32-bit writes!
614  */
615 int
616 unm_nic_pci_write_immediate_128M(unm_adapter *adapter, u64 off, u32 *data)
617 {
618 	UNM_NIC_PCI_WRITE_32(*data,
619 	    (void *) (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
620 	return (0);
621 }
622 
623 /*
624  * Note : only 32-bit reads!
625  */
626 int
627 unm_nic_pci_read_immediate_128M(unm_adapter *adapter, u64 off, u32 *data)
628 {
629 	*data = UNM_NIC_PCI_READ_32((void *)
630 	    (uptr_t)(pci_base_offset(adapter, off)));
631 	return (0);
632 }
633 
634 /*
635  * Note : only 32-bit writes!
636  */
637 void
638 unm_nic_pci_write_normalize_2M(unm_adapter *adapter, u64 off, u32 data)
639 {
640 	u32 temp = data;
641 
642 	adapter->unm_nic_hw_write_wx(adapter, off, &temp, 4);
643 }
644 
645 /*
646  * Note : only 32-bit reads!
647  */
648 u32
649 unm_nic_pci_read_normalize_2M(unm_adapter *adapter, u64 off)
650 {
651 	u32 temp;
652 
653 	adapter->unm_nic_hw_read_wx(adapter, off, &temp, 4);
654 
655 	return (temp);
656 }
657 
658 /*
659  * Note : only 32-bit writes!
660  */
661 int
662 unm_nic_pci_write_immediate_2M(unm_adapter *adapter, u64 off, u32 *data)
663 {
664 	u32 temp = *data;
665 
666 	adapter->unm_nic_hw_write_wx(adapter, off, &temp, 4);
667 
668 	return (0);
669 }
670 
671 /*
672  * Note : only 32-bit reads!
673  */
674 int
675 unm_nic_pci_read_immediate_2M(unm_adapter *adapter, u64 off, u32 *data)
676 {
677 	u32 temp;
678 
679 	adapter->unm_nic_hw_read_wx(adapter, off, &temp, 4);
680 
681 	*data = temp;
682 
683 	return (0);
684 }
685 
686 /*
687  * write cross hw window boundary is not supported
688  * 'len' should be either 1, 2, 4, or multiple of 8
689  */
690 int
691 unm_nic_hw_write_wx_2M(unm_adapter *adapter, u64 off, void *data, int len)
692 {
693 	int rv;
694 
695 	rv = unm_nic_pci_get_crb_addr_2M(adapter, &off, len);
696 
697 	if (rv == -1) {
698 		cmn_err(CE_PANIC, "%s: invalid offset: 0x%016llx\n",
699 		    __FUNCTION__, off);
700 		return (-1);
701 	}
702 
703 	if (rv == 1) {
704 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
705 		crb_win_lock(adapter);
706 		unm_nic_pci_set_crbwindow_2M(adapter, &off);
707 	}
708 
709 	switch (len) {
710 	case 1:
711 		UNM_NIC_PCI_WRITE_8(*(__uint8_t *)data, (void *) (uptr_t)off);
712 		break;
713 	case 2:
714 		UNM_NIC_PCI_WRITE_16(*(__uint16_t *)data, (void *) (uptr_t)off);
715 		break;
716 	case 4:
717 		UNM_NIC_PCI_WRITE_32(*(__uint32_t *)data, (void *) (uptr_t)off);
718 		break;
719 	case 8:
720 		UNM_NIC_PCI_WRITE_64(*(__uint64_t *)data, (void *) (uptr_t)off);
721 		break;
722 	default:
723 #if !defined(NDEBUG)
724 		if ((len & 0x7) != 0)
725 			cmn_err(CE_WARN, "%s: %s  len(%d) not multiple of 8.\n",
726 			    unm_nic_driver_name, __FUNCTION__, len);
727 #endif
728 		UNM_NIC_HW_BLOCK_WRITE_64(data, (uptr_t)off, (len>>3));
729 		break;
730 	}
731 	if (rv == 1) {
732 		crb_win_unlock(adapter);
733 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
734 	}
735 
736 	return (0);
737 }
738 
739 int
740 unm_nic_hw_read_ioctl_128M(unm_adapter *adapter, u64 off, void *data, int len)
741 {
742 	void		*addr;
743 	u64		offset;
744 
745 	if (ADDR_IN_WINDOW1(off)) {// Window 1
746 		addr = CRB_NORMALIZE(adapter, off);
747 		if (!addr) {
748 			offset = CRB_NORMAL(off);
749 			if (adapter->ahw.pci_len0 == 0)
750 				offset -= UNM_PCI_CRBSPACE;
751 			addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
752 			    offset);
753 		}
754 		UNM_READ_LOCK(&adapter->adapter_lock);
755 	} else {// Window 0
756 		addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
757 		if (!addr) {
758 			offset = off;
759 			addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
760 			    offset);
761 		}
762 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
763 		unm_nic_pci_change_crbwindow_128M(adapter, 0);
764 	}
765 
766 	switch (len) {
767 	case 1:
768 		*(__uint8_t  *)data = UNM_NIC_PCI_READ_8(addr);
769 		break;
770 	case 2:
771 		*(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
772 		break;
773 	case 4:
774 		*(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
775 		break;
776 	case 8:
777 		*(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
778 		break;
779 	default:
780 #if !defined(NDEBUG)
781 		if ((len & 0x7) != 0)
782 			cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
783 			    unm_nic_driver_name, __FUNCTION__, len);
784 #endif
785 		UNM_NIC_HW_BLOCK_READ_64(data, addr, (len>>3));
786 		break;
787 	}
788 
789 	if (ADDR_IN_WINDOW1(off)) {// Window 1
790 		UNM_READ_UNLOCK(&adapter->adapter_lock);
791 	} else {// Window 0
792 		unm_nic_pci_change_crbwindow_128M(adapter, 1);
793 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
794 	}
795 
796 	return (0);
797 }
798 
799 int
800 unm_nic_hw_read_wx_2M(unm_adapter *adapter, u64 off, void *data, int len)
801 {
802 	int rv;
803 
804 	rv = unm_nic_pci_get_crb_addr_2M(adapter, &off, len);
805 
806 	if (rv == -1) {
807 		cmn_err(CE_PANIC, "%s: invalid offset: 0x%016llx\n",
808 		    __FUNCTION__, off);
809 		return (-1);
810 	}
811 
812 	if (rv == 1) {
813 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
814 		crb_win_lock(adapter);
815 		unm_nic_pci_set_crbwindow_2M(adapter, &off);
816 	}
817 
818 	switch (len) {
819 	case 1:
820 		*(__uint8_t  *)data = UNM_NIC_PCI_READ_8((void *) (uptr_t)off);
821 		break;
822 	case 2:
823 		*(__uint16_t *)data = UNM_NIC_PCI_READ_16((void *) (uptr_t)off);
824 		break;
825 	case 4:
826 		*(__uint32_t *)data = UNM_NIC_PCI_READ_32((void *) (uptr_t)off);
827 		break;
828 	case 8:
829 		*(__uint64_t *)data = UNM_NIC_PCI_READ_64((void *) (uptr_t)off);
830 		break;
831 	default:
832 #if !defined(NDEBUG)
833 		if ((len & 0x7) != 0)
834 			cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
835 			    unm_nic_driver_name, __FUNCTION__, len);
836 #endif
837 		UNM_NIC_HW_BLOCK_READ_64(data, (void *) (uptr_t)off, (len>>3));
838 		break;
839 	}
840 
841 	if (rv == 1) {
842 		crb_win_unlock(adapter);
843 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
844 	}
845 
846 	return (0);
847 }
848 
849 int
850 unm_nic_hw_read_wx_128M(unm_adapter *adapter, u64 off, void *data, int len)
851 {
852 	void *addr;
853 
854 	if (ADDR_IN_WINDOW1(off)) {
855 		// Window 1
856 		addr = CRB_NORMALIZE(adapter, off);
857 		UNM_READ_LOCK(&adapter->adapter_lock);
858 	} else {// Window 0
859 		addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
860 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
861 		unm_nic_pci_change_crbwindow_128M(adapter, 0);
862 	}
863 
864 	if (!addr) {
865 		if (ADDR_IN_WINDOW1(off)) {// Window 1
866 			UNM_READ_UNLOCK(&adapter->adapter_lock);
867 		} else {// Window 0
868 			unm_nic_pci_change_crbwindow_128M(adapter, 1);
869 			UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
870 		}
871 		return (1);
872 	}
873 
874 	switch (len) {
875 		case 1:
876 			*(__uint8_t  *)data = UNM_NIC_PCI_READ_8(addr);
877 			break;
878 		case 2:
879 			*(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
880 			break;
881 		case 4:
882 			*(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
883 			break;
884 		case 8:
885 			*(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
886 			break;
887 		default:
888 #if !defined(NDEBUG)
889 			if ((len & 0x7) != 0)
890 				cmn_err(CE_WARN,
891 				    "%s: %s len(%d) not multiple of 8.\n",
892 				    unm_nic_driver_name, __FUNCTION__, len);
893 #endif
894 			UNM_NIC_HW_BLOCK_READ_64(data, addr, (len>>3));
895 			break;
896 	}
897 
898 	if (ADDR_IN_WINDOW1(off)) {// Window 1
899 		UNM_READ_UNLOCK(&adapter->adapter_lock);
900 	} else {// Window 0
901 		unm_nic_pci_change_crbwindow_128M(adapter, 1);
902 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
903 	}
904 
905 	return (0);
906 }
907 
908 /*  PCI Windowing for DDR regions.  */
909 #define	ADDR_IN_RANGE(addr, low, high)	    \
910 	(((addr) <= (high)) && ((low) ? ((addr) >= (low)) : 1))
911 
912 /*
913  * check memory access boundary.
914  * used by test agent. support ddr access only for now
915  */
916 /* ARGSUSED */
917 static unsigned long
918 unm_nic_pci_mem_bound_check(struct unm_adapter_s *adapter,
919     unsigned long long addr, int size)
920 {
921 	if (!ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX) ||
922 	    !ADDR_IN_RANGE(addr + size -1, UNM_ADDR_DDR_NET,
923 	    UNM_ADDR_DDR_NET_MAX) || ((size != 1) && (size != 2) &&
924 	    (size != 4) && (size != 8)))
925 		return (0);
926 
927 	return (1);
928 }
929 
930 int unm_pci_set_window_warning_count = 0;
931 
932 unsigned long long
933 unm_nic_pci_set_window_128M(struct unm_adapter_s *adapter,
934     unsigned long long addr)
935 {
936 	int		window;
937 	unsigned long long	qdr_max;
938 
939 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
940 		qdr_max = NX_P2_ADDR_QDR_NET_MAX;
941 	} else {
942 		qdr_max = NX_P3_ADDR_QDR_NET_MAX;
943 	}
944 
945 	if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
946 		/* DDR network side */
947 		/* MN access should never come here */
948 		cmn_err(CE_PANIC, "%s\n", __FUNCTION__);
949 		addr = -1ULL;
950 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
951 		addr -= UNM_ADDR_OCM0;
952 		addr += UNM_PCI_OCM0;
953 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, UNM_ADDR_OCM1_MAX)) {
954 		addr -= UNM_ADDR_OCM1;
955 		addr += UNM_PCI_OCM1;
956 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
957 		/* QDR network side */
958 		addr -= UNM_ADDR_QDR_NET;
959 		window = (addr >> 22) & 0x3f;
960 		if (adapter->ahw.qdr_sn_window != window) {
961 			adapter->ahw.qdr_sn_window = window;
962 			UNM_NIC_PCI_WRITE_32((window << 22),
963 			    (void *) (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter,
964 			    UNM_PCIX_PH_REG(PCIE_SN_WINDOW_REG(
965 			    adapter->ahw.pci_func)))));
966 			/* MUST make sure window is set before we forge on... */
967 			(void) UNM_NIC_PCI_READ_32((void *)
968 			    (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter,
969 			    UNM_PCIX_PH_REG(PCIE_SN_WINDOW_REG(
970 			    adapter->ahw.pci_func)))));
971 		}
972 		addr -= (window * 0x400000);
973 		addr += UNM_PCI_QDR_NET;
974 	} else {
975 		/*
976 		 * peg gdb frequently accesses memory that doesn't exist,
977 		 * this limits the chit chat so debugging isn't slowed down.
978 		 */
979 		if ((unm_pci_set_window_warning_count++ < 8) ||
980 		    (unm_pci_set_window_warning_count%64 == 0)) {
981 			cmn_err(CE_WARN, "%s: Warning:unm_nic_pci_set_window() "
982 			    "Unknown address range!\n", unm_nic_driver_name);
983 		}
984 		addr = -1ULL;
985 	}
986 	return (addr);
987 }
988 
989 unsigned long long
990 unm_nic_pci_set_window_2M(struct unm_adapter_s *adapter,
991     unsigned long long addr)
992 {
993 	int window;
994 	u32 win_read;
995 
996 	if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
997 		/* DDR network side */
998 		window = MN_WIN(addr);
999 		adapter->ahw.ddr_mn_window = window;
1000 		adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.mn_win_crb |
1001 		    UNM_PCI_CRBSPACE, &window, 4);
1002 		adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.mn_win_crb |
1003 		    UNM_PCI_CRBSPACE, &win_read, 4);
1004 		if ((win_read << 17) != window) {
1005 			cmn_err(CE_WARN,
1006 			    "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",
1007 			    __FUNCTION__, window, win_read);
1008 		}
1009 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
1010 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
1011 		unsigned int temp1;
1012 // OCM: pci_addr[20:18] == 011 && pci_addr[17:11] != 7f
1013 		if ((addr & 0x00ff800) == 0xff800) {
1014 			// if bits 19:18&17:11 are on
1015 			cmn_err(CE_WARN, "%s: QM access not handled.\n",
1016 			    __FUNCTION__);
1017 			addr = -1ULL;
1018 		}
1019 
1020 		window = OCM_WIN(addr);
1021 		adapter->ahw.ddr_mn_window = window;
1022 		adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.mn_win_crb |
1023 		    UNM_PCI_CRBSPACE, &window, 4);
1024 		adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.mn_win_crb |
1025 		    UNM_PCI_CRBSPACE, &win_read, 4);
1026 		temp1 = ((window & 0x1FF) << 7) |
1027 		    ((window & 0x0FFFE0000) >> 17);
1028 		if (win_read != temp1) {
1029 			cmn_err(CE_WARN,
1030 			    "%s: Written OCMwin(0x%x) != Read OCMwin(0x%x)\n",
1031 			    __FUNCTION__, temp1, win_read);
1032 		}
1033 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
1034 
1035 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
1036 	    NX_P3_ADDR_QDR_NET_MAX)) {
1037 		/* QDR network side */
1038 		window = MS_WIN(addr);
1039 		adapter->ahw.qdr_sn_window = window;
1040 		adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.ms_win_crb |
1041 		    UNM_PCI_CRBSPACE, &window, 4);
1042 		adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.ms_win_crb |
1043 		    UNM_PCI_CRBSPACE, &win_read, 4);
1044 		if (win_read != window) {
1045 			cmn_err(CE_WARN,
1046 			    "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n",
1047 			    __FUNCTION__, window, win_read);
1048 		}
1049 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
1050 
1051 	} else {
1052 		/*
1053 		 * peg gdb frequently accesses memory that doesn't exist,
1054 		 * this limits the chit chat so debugging isn't slowed down.
1055 		 */
1056 		if ((unm_pci_set_window_warning_count++ < 8) ||
1057 		    (unm_pci_set_window_warning_count%64 == 0)) {
1058 			cmn_err(CE_WARN, "%s%d: %s Unknown address range!\n",
1059 			    adapter->name, adapter->instance, __FUNCTION__);
1060 		}
1061 		addr = -1ULL;
1062 	}
1063 	return (addr);
1064 }
1065 
1066 /* check if address is in the same windows as the previous access */
1067 static unsigned long
1068 unm_nic_pci_is_same_window(struct unm_adapter_s *adapter,
1069     unsigned long long addr)
1070 {
1071 	int			window;
1072 	unsigned long long	qdr_max;
1073 
1074 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1075 		qdr_max = NX_P2_ADDR_QDR_NET_MAX;
1076 	} else {
1077 		qdr_max = NX_P3_ADDR_QDR_NET_MAX;
1078 	}
1079 
1080 	if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
1081 		/* DDR network side */
1082 		/* MN access can not come here */
1083 		cmn_err(CE_PANIC, "%s\n", __FUNCTION__);
1084 #if 0
1085 		window = ((addr - UNM_ADDR_DDR_NET) >> 25) & 0x3ff;
1086 		if (adapter->ahw.ddr_mn_window == window) {
1087 			return (1);
1088 		}
1089 #endif
1090 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
1091 		return (1);
1092 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, UNM_ADDR_OCM1_MAX)) {
1093 		return (1);
1094 	} else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
1095 		/* QDR network side */
1096 		window = ((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f;
1097 		if (adapter->ahw.qdr_sn_window == window) {
1098 			return (1);
1099 		}
1100 	}
1101 
1102 	return (0);
1103 }
1104 
1105 static int
1106 unm_nic_pci_mem_read_direct(struct unm_adapter_s *adapter,
1107     u64 off, void *data, int size)
1108 {
1109 	void			*addr;
1110 	int				ret = 0;
1111 	u64				start;
1112 
1113 #if 0
1114 	/*
1115 	 * This check can not be currently executed, since phanmon findq
1116 	 * command breaks this check whereby 8 byte reads are being attempted
1117 	 * on "aligned-by-4" addresses on x86. Reason this works is our version
1118 	 * breaks up the access into 2 consecutive 4 byte writes; on other
1119 	 * architectures, this might require "aligned-by-8" addresses and we
1120 	 * will run into trouble.
1121 	 *
1122 	 * Check alignment for expected sizes of 1, 2, 4, 8. Other size
1123 	 * values will not trigger access.
1124 	 */
1125 	if ((off & (size - 1)) != 0)
1126 		return (-1);
1127 #endif
1128 
1129 	UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1130 
1131 	/*
1132 	 * If attempting to access unknown address or straddle hw windows,
1133 	 * do not access.
1134 	 */
1135 	if (((start = adapter->unm_nic_pci_set_window(adapter, off)) == -1UL) ||
1136 	    (unm_nic_pci_is_same_window(adapter, off + size -1) == 0)) {
1137 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1138 		cmn_err(CE_WARN, "%s out of bound pci memory access. "
1139 		    "offset is 0x%llx\n", unm_nic_driver_name, off);
1140 		return (-1);
1141 	}
1142 
1143 	addr = (void *) (uptr_t)(pci_base_offset(adapter, start));
1144 	if (!addr)
1145 		addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 + start);
1146 
1147 	switch (size) {
1148 		case 1:
1149 			*(__uint8_t  *)data = UNM_NIC_PCI_READ_8(addr);
1150 			break;
1151 		case 2:
1152 			*(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
1153 			break;
1154 		case 4:
1155 			*(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
1156 			break;
1157 		case 8:
1158 			*(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
1159 			break;
1160 		default:
1161 			ret = -1;
1162 			break;
1163 	}
1164 
1165 	UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1166 	return (ret);
1167 }
1168 
1169 static int
1170 unm_nic_pci_mem_write_direct(struct unm_adapter_s *adapter, u64 off,
1171     void *data, int size)
1172 {
1173 	void	*addr;
1174 	int		ret = 0;
1175 	u64		start;
1176 
1177 #if 0
1178 	/*
1179 	 * This check can not be currently executed, since firmware load
1180 	 * breaks this check whereby 8 byte writes are being attempted on
1181 	 * "aligned-by-4" addresses on x86. Reason this works is our version
1182 	 * breaks up the access into 2 consecutive 4 byte writes; on other
1183 	 * architectures, this might require "aligned-by-8" addresses and we
1184 	 * will run into trouble.
1185 	 *
1186 	 * Check alignment for expected sizes of 1, 2, 4, 8. Other size
1187 	 * values will not trigger access.
1188 	 */
1189 	if ((off & (size - 1)) != 0)
1190 		return (-1);
1191 #endif
1192 
1193 	UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1194 
1195 	/*
1196 	 * If attempting to access unknown address or straddle hw windows,
1197 	 * do not access.
1198 	 */
1199 	if (((start = adapter->unm_nic_pci_set_window(adapter, off)) == -1UL) ||
1200 	    (unm_nic_pci_is_same_window(adapter, off + size -1) == 0)) {
1201 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1202 		cmn_err(CE_WARN, "%s out of bound pci memory access. "
1203 		    "offset is 0x%llx\n", unm_nic_driver_name, off);
1204 		return (-1);
1205 	}
1206 
1207 	addr = (void *) (uptr_t)(pci_base_offset(adapter, start));
1208 	if (!addr)
1209 		addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 + start);
1210 
1211 	switch (size) {
1212 		case 1:
1213 			UNM_NIC_PCI_WRITE_8(*(__uint8_t  *)data, addr);
1214 			break;
1215 		case 2:
1216 			UNM_NIC_PCI_WRITE_16(*(__uint16_t *)data, addr);
1217 			break;
1218 		case 4:
1219 			UNM_NIC_PCI_WRITE_32(*(__uint32_t *)data, addr);
1220 			break;
1221 		case 8:
1222 			UNM_NIC_PCI_WRITE_64(*(__uint64_t *)data, addr);
1223 			break;
1224 		default:
1225 			ret = -1;
1226 			break;
1227 	}
1228 	UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1229 	return (ret);
1230 }
1231 
1232 
1233 int
1234 unm_nic_pci_mem_write_128M(struct unm_adapter_s *adapter, u64 off, void *data,
1235     int size)
1236 {
1237 	int		i, j, ret = 0, loop, sz[2], off0;
1238 	__uint32_t		temp;
1239 	__uint64_t		off8, mem_crb, tmpw, word[2] = {0, 0};
1240 #define	MAX_CTL_CHECK   1000
1241 
1242 	/*
1243 	 * If not MN, go check for MS or invalid.
1244 	 */
1245 	if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1246 		return (unm_nic_pci_mem_write_direct(adapter, off, data, size));
1247 
1248 	off8 = off & 0xfffffff8;
1249 	off0 = off & 0x7;
1250 	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
1251 	sz[1] = size - sz[0];
1252 	loop = ((off0 + size - 1) >> 3) + 1;
1253 	/* LINTED: E_FALSE_LOGICAL_EXPR */
1254 	mem_crb = (uptr_t)(pci_base_offset(adapter, UNM_CRB_DDR_NET));
1255 
1256 	if ((size != 8) || (off0 != 0))  {
1257 		for (i = 0; i < loop; i++) {
1258 			if (adapter->unm_nic_pci_mem_read(adapter,
1259 			    off8 + (i << 3), &word[i], 8))
1260 				return (-1);
1261 		}
1262 	}
1263 
1264 	switch (size) {
1265 		case 1:
1266 			tmpw = *((__uint8_t *)data);
1267 			break;
1268 		case 2:
1269 			tmpw = *((__uint16_t *)data);
1270 			break;
1271 		case 4:
1272 			tmpw = *((__uint32_t *)data);
1273 			break;
1274 		case 8:
1275 		default:
1276 			tmpw = *((__uint64_t *)data);
1277 			break;
1278 	}
1279 	word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
1280 	word[0] |= tmpw << (off0 * 8);
1281 
1282 	if (loop == 2) {
1283 		word[1] &= ~(~0ULL << (sz[1] * 8));
1284 		word[1] |= tmpw >> (sz[0] * 8);
1285 	}
1286 
1287 	UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1288 	unm_nic_pci_change_crbwindow_128M(adapter, 0);
1289 
1290 	for (i = 0; i < loop; i++) {
1291 		UNM_NIC_PCI_WRITE_32((__uint32_t)(off8 + (i << 3)),
1292 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_LO));
1293 		UNM_NIC_PCI_WRITE_32(0,
1294 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_HI));
1295 		UNM_NIC_PCI_WRITE_32(word[i] & 0xffffffff,
1296 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
1297 		UNM_NIC_PCI_WRITE_32((word[i] >> 32) & 0xffffffff,
1298 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
1299 		UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
1300 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1301 		UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE |
1302 		    MIU_TA_CTL_WRITE,
1303 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1304 
1305 		for (j = 0; j < MAX_CTL_CHECK; j++) {
1306 			temp = UNM_NIC_PCI_READ_32((void *)
1307 			    (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1308 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
1309 				break;
1310 			}
1311 		}
1312 
1313 		if (j >= MAX_CTL_CHECK) {
1314 			cmn_err(CE_WARN, "%s: %s Fail to write thru agent\n",
1315 			    __FUNCTION__, unm_nic_driver_name);
1316 			ret = -1;
1317 			break;
1318 		}
1319 	}
1320 
1321 	unm_nic_pci_change_crbwindow_128M(adapter, 1);
1322 	UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1323 	return (ret);
1324 }
1325 
1326 int
1327 unm_nic_pci_mem_read_128M(struct unm_adapter_s *adapter, u64 off, void *data,
1328     int size)
1329 {
1330 	int		i, j = 0, k, start, end, loop, sz[2], off0[2];
1331 	__uint32_t		temp;
1332 	__uint64_t		off8, val, mem_crb, word[2] = {0, 0};
1333 #define	MAX_CTL_CHECK   1000
1334 
1335 	/*
1336 	 * If not MN, go check for MS or invalid.
1337 	 */
1338 	if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1339 		return (unm_nic_pci_mem_read_direct(adapter, off, data, size));
1340 
1341 	off8 = off & 0xfffffff8;
1342 	off0[0] = off & 0x7;
1343 	off0[1] = 0;
1344 	sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
1345 	sz[1] = size - sz[0];
1346 	loop = ((off0[0] + size - 1) >> 3) + 1;
1347 	/* LINTED: E_FALSE_LOGICAL_EXPR */
1348 	mem_crb = (uptr_t)(pci_base_offset(adapter, UNM_CRB_DDR_NET));
1349 
1350 	UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1351 	unm_nic_pci_change_crbwindow_128M(adapter, 0);
1352 
1353 	for (i = 0; i < loop; i++) {
1354 		UNM_NIC_PCI_WRITE_32((__uint32_t)(off8 + (i << 3)),
1355 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_LO));
1356 		UNM_NIC_PCI_WRITE_32(0,
1357 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_HI));
1358 		UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_ENABLE,
1359 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1360 		UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
1361 		    (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1362 
1363 		for (j = 0; j < MAX_CTL_CHECK; j++) {
1364 			temp = UNM_NIC_PCI_READ_32((void *)
1365 			    (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1366 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
1367 				break;
1368 			}
1369 		}
1370 
1371 		if (j >= MAX_CTL_CHECK) {
1372 			cmn_err(CE_WARN, "%s: %s Fail to read through agent\n",
1373 			    __FUNCTION__, unm_nic_driver_name);
1374 			break;
1375 		}
1376 
1377 		start = off0[i] >> 2;
1378 		end   = (off0[i] + sz[i] - 1) >> 2;
1379 		word[i] = 0;
1380 		for (k = start; k <= end; k++) {
1381 			word[i] |= ((__uint64_t)UNM_NIC_PCI_READ_32(
1382 			    (void *) (uptr_t)(mem_crb +
1383 			    MIU_TEST_AGT_RDDATA(k))) << (32*k));
1384 		}
1385 	}
1386 
1387 	unm_nic_pci_change_crbwindow_128M(adapter, 1);
1388 	UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1389 
1390 	if (j >= MAX_CTL_CHECK)
1391 		return (-1);
1392 
1393 	if (sz[0] == 8) {
1394 		val = word[0];
1395 	} else {
1396 		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
1397 		    ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
1398 	}
1399 
1400 	switch (size) {
1401 	case 1:
1402 		*(__uint8_t  *)data = val;
1403 		break;
1404 	case 2:
1405 		*(__uint16_t *)data = val;
1406 		break;
1407 	case 4:
1408 		*(__uint32_t *)data = val;
1409 		break;
1410 	case 8:
1411 		*(__uint64_t *)data = val;
1412 		break;
1413 	}
1414 	return (0);
1415 }
1416 
1417 
1418 
1419 int
1420 unm_nic_pci_mem_write_2M(struct unm_adapter_s *adapter, u64 off, void *data,
1421     int size)
1422 {
1423 	int	i, j, ret = 0, loop, sz[2], off0;
1424 	__uint32_t	temp;
1425 	__uint64_t	off8, mem_crb, tmpw, word[2] = {0, 0};
1426 #define	MAX_CTL_CHECK   1000
1427 
1428 	/*
1429 	 * If not MN, go check for MS or invalid.
1430 	 */
1431 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
1432 		mem_crb = UNM_CRB_QDR_NET;
1433 	} else {
1434 		mem_crb = UNM_CRB_DDR_NET;
1435 		if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1436 			return (unm_nic_pci_mem_write_direct(adapter,
1437 			    off, data, size));
1438 	}
1439 
1440 	off8 = off & 0xfffffff8;
1441 	off0 = off & 0x7;
1442 	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
1443 	sz[1] = size - sz[0];
1444 	loop = ((off0 + size - 1) >> 3) + 1;
1445 
1446 	if ((size != 8) || (off0 != 0)) {
1447 		for (i = 0; i < loop; i++) {
1448 			if (adapter->unm_nic_pci_mem_read(adapter,
1449 			    off8 + (i << 3), &word[i], 8))
1450 				return (-1);
1451 		}
1452 	}
1453 
1454 	switch (size) {
1455 		case 1:
1456 			tmpw = *((__uint8_t *)data);
1457 			break;
1458 		case 2:
1459 			tmpw = *((__uint16_t *)data);
1460 			break;
1461 		case 4:
1462 			tmpw = *((__uint32_t *)data);
1463 			break;
1464 		case 8:
1465 		default:
1466 			tmpw = *((__uint64_t *)data);
1467 			break;
1468 	}
1469 
1470 	word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
1471 	word[0] |= tmpw << (off0 * 8);
1472 
1473 	if (loop == 2) {
1474 		word[1] &= ~(~0ULL << (sz[1] * 8));
1475 		word[1] |= tmpw >> (sz[0] * 8);
1476 	}
1477 
1478 // don't lock here - write_wx gets the lock if each time
1479 // UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1480 // unm_nic_pci_change_crbwindow_128M(adapter, 0);
1481 
1482 	for (i = 0; i < loop; i++) {
1483 		temp = off8 + (i << 3);
1484 		adapter->unm_nic_hw_write_wx(adapter,
1485 		    mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
1486 		temp = 0;
1487 		adapter->unm_nic_hw_write_wx(adapter,
1488 		    mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
1489 		temp = word[i] & 0xffffffff;
1490 		adapter->unm_nic_hw_write_wx(adapter,
1491 		    mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
1492 		temp = (word[i] >> 32) & 0xffffffff;
1493 		adapter->unm_nic_hw_write_wx(adapter,
1494 		    mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
1495 		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
1496 		adapter->unm_nic_hw_write_wx(adapter,
1497 		    mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
1498 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
1499 		adapter->unm_nic_hw_write_wx(adapter,
1500 		    mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
1501 
1502 		for (j = 0; j < MAX_CTL_CHECK; j++) {
1503 			adapter->unm_nic_hw_read_wx(adapter,
1504 			    mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1505 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
1506 				break;
1507 			}
1508 		}
1509 
1510 		if (j >= MAX_CTL_CHECK) {
1511 			cmn_err(CE_WARN, "%s: Fail to write through agent\n",
1512 			    unm_nic_driver_name);
1513 			ret = -1;
1514 			break;
1515 		}
1516 	}
1517 
1518 //  unm_nic_pci_change_crbwindow_128M(adapter, 1);
1519 //  UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1520 	return (ret);
1521 }
1522 
1523 int
1524 unm_nic_pci_mem_read_2M(struct unm_adapter_s *adapter, u64 off, void *data,
1525     int size)
1526 {
1527 // unsigned long   flags;
1528 	int		i, j = 0, k, start, end, loop, sz[2], off0[2];
1529 	__uint32_t	temp;
1530 	__uint64_t	off8, val, mem_crb, word[2] = {0, 0};
1531 #define	MAX_CTL_CHECK   1000
1532 
1533 	/*
1534 	 * If not MN, go check for MS or invalid.
1535 	 */
1536 
1537 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
1538 		mem_crb = UNM_CRB_QDR_NET;
1539 	} else {
1540 		mem_crb = UNM_CRB_DDR_NET;
1541 		if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1542 			return (unm_nic_pci_mem_read_direct(adapter,
1543 			    off, data, size));
1544 	}
1545 
1546 	off8 = off & 0xfffffff8;
1547 	off0[0] = off & 0x7;
1548 	off0[1] = 0;
1549 	sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
1550 	sz[1] = size - sz[0];
1551 	loop = ((off0[0] + size - 1) >> 3) + 1;
1552 
1553 // don't get lock - write_wx will get it
1554 // UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1555 // unm_nic_pci_change_crbwindow_128M(adapter, 0);
1556 
1557 	for (i = 0; i < loop; i++) {
1558 		temp = off8 + (i << 3);
1559 		adapter->unm_nic_hw_write_wx(adapter,
1560 		    mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
1561 		temp = 0;
1562 		adapter->unm_nic_hw_write_wx(adapter,
1563 		    mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
1564 		temp = MIU_TA_CTL_ENABLE;
1565 		adapter->unm_nic_hw_write_wx(adapter,
1566 		    mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1567 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
1568 		adapter->unm_nic_hw_write_wx(adapter,
1569 		    mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1570 
1571 		for (j = 0; j < MAX_CTL_CHECK; j++) {
1572 			adapter->unm_nic_hw_read_wx(adapter,
1573 			    mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1574 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
1575 				break;
1576 			}
1577 		}
1578 
1579 		if (j >= MAX_CTL_CHECK) {
1580 			cmn_err(CE_WARN, "%s: Fail to read through agent\n",
1581 			    unm_nic_driver_name);
1582 			break;
1583 		}
1584 
1585 		start = off0[i] >> 2;
1586 		end   = (off0[i] + sz[i] - 1) >> 2;
1587 		for (k = start; k <= end; k++) {
1588 			adapter->unm_nic_hw_read_wx(adapter,
1589 			    mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
1590 			word[i] |= ((__uint64_t)temp << (32 * k));
1591 		}
1592 	}
1593 
1594 // unm_nic_pci_change_crbwindow_128M(adapter, 1);
1595 // UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1596 
1597 	if (j >= MAX_CTL_CHECK)
1598 		return (-1);
1599 
1600 	if (sz[0] == 8) {
1601 		val = word[0];
1602 	} else {
1603 		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
1604 		    ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
1605 	}
1606 
1607 	switch (size) {
1608 		case 1:
1609 			*(__uint8_t  *)data = val;
1610 			break;
1611 		case 2:
1612 			*(__uint16_t *)data = val;
1613 			break;
1614 		case 4:
1615 			*(__uint32_t *)data = val;
1616 			break;
1617 		case 8:
1618 			*(__uint64_t *)data = val;
1619 			break;
1620 	}
1621 	return (0);
1622 }
1623 
1624 int
1625 unm_crb_writelit_adapter_2M(struct unm_adapter_s *adapter, unsigned long off,
1626     int data)
1627 {
1628 	return (unm_nic_hw_write_wx_2M(adapter, off, &data, 4));
1629 }
1630 
1631 int
1632 unm_crb_writelit_adapter_128M(struct unm_adapter_s *adapter, unsigned long off,
1633     int data)
1634 {
1635 	void *addr;
1636 
1637 	if (ADDR_IN_WINDOW1(off)) {
1638 		UNM_READ_LOCK(&adapter->adapter_lock);
1639 		UNM_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off));
1640 		UNM_READ_UNLOCK(&adapter->adapter_lock);
1641 	} else {
1642 		// unm_nic_write_w0 (adapter, off, data);
1643 		UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1644 		unm_nic_pci_change_crbwindow_128M(adapter, 0);
1645 		addr = (void *) (pci_base_offset(adapter, off));
1646 		UNM_NIC_PCI_WRITE_32(data, addr);
1647 		unm_nic_pci_change_crbwindow_128M(adapter, 1);
1648 		UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1649 	}
1650 
1651 	return (0);
1652 }
1653 
1654 int
1655 unm_nic_get_board_info(struct unm_adapter_s *adapter)
1656 {
1657 	int	rv = 0;
1658 	unm_board_info_t  *boardinfo;
1659 	int		i;
1660 	int		addr = BRDCFG_START;
1661 	uint32_t	  *ptr32;
1662 	uint32_t	gpioval;
1663 
1664 	boardinfo = &adapter->ahw.boardcfg;
1665 	ptr32 = (uint32_t *)boardinfo;
1666 
1667 	for (i = 0; i < sizeof (unm_board_info_t) / sizeof (uint32_t); i++) {
1668 		if (rom_fast_read(adapter, addr, (int *)ptr32) == -1) {
1669 			return (-1);
1670 		}
1671 		DPRINTF(1, (CE_WARN, "ROM(%d): %x\n", i, *ptr32));
1672 		ptr32++;
1673 		addr += sizeof (uint32_t);
1674 	}
1675 
1676 	if (boardinfo->magic != UNM_BDINFO_MAGIC) {
1677 		DPRINTF(1, (CE_WARN, "%s: ERROR reading board config."
1678 		    " Read %x, expected %x\n", unm_nic_driver_name,
1679 		    boardinfo->magic, UNM_BDINFO_MAGIC));
1680 		rv = -1;
1681 	}
1682 
1683 	if (boardinfo->header_version != UNM_BDINFO_VERSION) {
1684 		DPRINTF(1, (CE_WARN, "%s: Unknown board config version."
1685 		    " Read %x, expected %x\n", unm_nic_driver_name,
1686 		    boardinfo->header_version, UNM_BDINFO_VERSION));
1687 		rv = -1;
1688 	}
1689 
1690 	if (boardinfo->board_type == UNM_BRDTYPE_P3_4_GB_MM) {
1691 		gpioval = UNM_CRB_READ_VAL_ADAPTER(UNM_ROMUSB_GLB_PAD_GPIO_I,
1692 		    adapter);
1693 		if ((gpioval & 0x8000) == 0)
1694 			boardinfo->board_type = UNM_BRDTYPE_P3_10G_TRP;
1695 	}
1696 
1697 	DPRINTF(0, (CE_WARN, "Discovered board type:0x%x  ",
1698 	    boardinfo->board_type));
1699 
1700 	switch ((unm_brdtype_t)boardinfo->board_type) {
1701 	case UNM_BRDTYPE_P2_SB35_4G:
1702 		adapter->ahw.board_type = UNM_NIC_GBE;
1703 		break;
1704 	case UNM_BRDTYPE_P2_SB31_10G:
1705 	case UNM_BRDTYPE_P2_SB31_10G_IMEZ:
1706 	case UNM_BRDTYPE_P2_SB31_10G_HMEZ:
1707 	case UNM_BRDTYPE_P2_SB31_10G_CX4:
1708 	case UNM_BRDTYPE_P3_HMEZ:
1709 	case UNM_BRDTYPE_P3_XG_LOM:
1710 	case UNM_BRDTYPE_P3_10G_CX4:
1711 	case UNM_BRDTYPE_P3_10G_CX4_LP:
1712 	case UNM_BRDTYPE_P3_IMEZ:
1713 	case UNM_BRDTYPE_P3_10G_SFP_PLUS:
1714 	case UNM_BRDTYPE_P3_10G_XFP:
1715 	case UNM_BRDTYPE_P3_10000_BASE_T:
1716 		adapter->ahw.board_type = UNM_NIC_XGBE;
1717 		break;
1718 	case UNM_BRDTYPE_P3_REF_QG:
1719 	case UNM_BRDTYPE_P3_4_GB:
1720 	case UNM_BRDTYPE_P3_4_GB_MM:
1721 		adapter->ahw.board_type = UNM_NIC_GBE;
1722 		break;
1723 	case UNM_BRDTYPE_P1_BD:
1724 	case UNM_BRDTYPE_P1_SB:
1725 	case UNM_BRDTYPE_P1_SMAX:
1726 	case UNM_BRDTYPE_P1_SOCK:
1727 		adapter->ahw.board_type = UNM_NIC_GBE;
1728 		break;
1729 	case UNM_BRDTYPE_P3_10G_TRP:
1730 		if (adapter->portnum < 2)
1731 			adapter->ahw.board_type = UNM_NIC_XGBE;
1732 		else
1733 			adapter->ahw.board_type = UNM_NIC_GBE;
1734 		break;
1735 	default:
1736 		DPRINTF(1, (CE_WARN, "%s: Unknown(%x)\n", unm_nic_driver_name,
1737 		    boardinfo->board_type));
1738 		break;
1739 	}
1740 
1741 	return (rv);
1742 }
1743 
1744 /* NIU access sections */
1745 
1746 int
1747 unm_nic_macaddr_set(struct unm_adapter_s *adapter, __uint8_t *addr)
1748 {
1749 	int		ret = 0, i, retry_count = 10;
1750 	unsigned char		mac_addr[MAX_ADDR_LEN];
1751 
1752 	/* For P3, we should not set MAC in HW any more */
1753 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1754 		return (0);
1755 
1756 	switch (adapter->ahw.board_type) {
1757 		case UNM_NIC_GBE:
1758 	/*
1759 	 * Flaky Mac address registers on qgig require several writes.
1760 	 */
1761 			for (i = 0; i < retry_count; ++i) {
1762 				if (unm_niu_macaddr_set(adapter, addr) != 0)
1763 					return (-1);
1764 
1765 				(void) unm_niu_macaddr_get(adapter,
1766 				    (unsigned char *)mac_addr);
1767 				if (memcmp(mac_addr, addr, 6) == 0)
1768 					return (0);
1769 			}
1770 			cmn_err(CE_WARN, "%s: Flaky MAC addr registers\n",
1771 			    unm_nic_driver_name);
1772 			break;
1773 
1774 		case UNM_NIC_XGBE:
1775 			ret = unm_niu_xg_macaddr_set(adapter, addr);
1776 			break;
1777 
1778 		default:
1779 			cmn_err(CE_WARN,  "\r\nUnknown board type encountered"
1780 			    " while setting the MAC address.\n");
1781 			return (-1);
1782 	}
1783 	return (ret);
1784 }
1785 
1786 #define	MTU_FUDGE_FACTOR 100
1787 int
1788 unm_nic_set_mtu(struct unm_adapter_s *adapter, int new_mtu)
1789 {
1790 	long		port = adapter->physical_port;
1791 	int			ret = 0;
1792 	u32			port_mode = 0;
1793 
1794 	if (adapter->ahw.revision_id >= NX_P3_A2)
1795 		return (nx_fw_cmd_set_mtu(adapter, new_mtu));
1796 
1797 	new_mtu += MTU_FUDGE_FACTOR; /* so that MAC accepts frames > MTU */
1798 	switch (adapter->ahw.board_type) {
1799 		case UNM_NIC_GBE:
1800 			unm_nic_write_w0(adapter,
1801 			    UNM_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
1802 			    new_mtu);
1803 
1804 			break;
1805 
1806 		case UNM_NIC_XGBE:
1807 			adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
1808 			    &port_mode, 4);
1809 			if (port_mode == UNM_PORT_MODE_802_3_AP) {
1810 				unm_nic_write_w0(adapter,
1811 				    UNM_NIU_AP_MAX_FRAME_SIZE(port), new_mtu);
1812 			} else {
1813 				if (adapter->physical_port == 0) {
1814 					unm_nic_write_w0(adapter,
1815 					    UNM_NIU_XGE_MAX_FRAME_SIZE,
1816 					    new_mtu);
1817 				} else {
1818 					unm_nic_write_w0(adapter,
1819 					    UNM_NIU_XG1_MAX_FRAME_SIZE,
1820 					    new_mtu);
1821 				}
1822 			}
1823 			break;
1824 
1825 		default:
1826 			cmn_err(CE_WARN, "%s: Unknown brdtype\n",
1827 			    unm_nic_driver_name);
1828 	}
1829 
1830 	return (ret);
1831 }
1832 
1833 int
1834 unm_nic_set_promisc_mode(struct unm_adapter_s *adapter)
1835 {
1836 	int		ret;
1837 
1838 	if (adapter->promisc)
1839 		return (0);
1840 
1841 	switch (adapter->ahw.board_type) {
1842 		case UNM_NIC_GBE:
1843 			ret = unm_niu_set_promiscuous_mode(adapter,
1844 			    UNM_NIU_PROMISCOUS_MODE);
1845 			break;
1846 
1847 		case UNM_NIC_XGBE:
1848 			ret = unm_niu_xg_set_promiscuous_mode(adapter,
1849 			    UNM_NIU_PROMISCOUS_MODE);
1850 			break;
1851 
1852 		default:
1853 			cmn_err(CE_WARN, "%s: Unknown brdtype\n",
1854 			    unm_nic_driver_name);
1855 			ret = -1;
1856 			break;
1857 	}
1858 
1859 if (!ret)
1860 	adapter->promisc = 1;
1861 
1862 		return (ret);
1863 }
1864 
1865 int
1866 unm_nic_unset_promisc_mode(struct unm_adapter_s *adapter)
1867 {
1868 	int	ret = 0;
1869 
1870 	/*
1871 	 * P3 does not unset promiscous mode. Why?
1872 	 */
1873 	if (adapter->ahw.revision_id >= NX_P3_A2) {
1874 		return (0);
1875 	}
1876 
1877 	if (!adapter->promisc)
1878 		return (0);
1879 
1880 	switch (adapter->ahw.board_type) {
1881 		case UNM_NIC_GBE:
1882 			ret = unm_niu_set_promiscuous_mode(adapter,
1883 			    UNM_NIU_NON_PROMISCOUS_MODE);
1884 			break;
1885 
1886 		case UNM_NIC_XGBE:
1887 			ret = unm_niu_xg_set_promiscuous_mode(adapter,
1888 			    UNM_NIU_NON_PROMISCOUS_MODE);
1889 			break;
1890 
1891 		default:
1892 			cmn_err(CE_WARN, "%s: Unknown brdtype\n",
1893 			    unm_nic_driver_name);
1894 			ret = -1;
1895 			break;
1896 	}
1897 
1898 	if (!ret)
1899 		adapter->promisc = 0;
1900 
1901 	return (ret);
1902 }
1903 
1904 long
1905 unm_nic_phy_read(unm_adapter *adapter, long reg,
1906 		    __uint32_t *readval)
1907 {
1908 	long	ret = 0;
1909 
1910 	switch (adapter->ahw.board_type) {
1911 	case UNM_NIC_GBE:
1912 		ret = unm_niu_gbe_phy_read(adapter, reg, readval);
1913 		break;
1914 
1915 	case UNM_NIC_XGBE:
1916 		DPRINTF(1, (CE_WARN,
1917 		    "%s: Function %s is not implemented for XG\n",
1918 		    unm_nic_driver_name, __FUNCTION__));
1919 		break;
1920 
1921 	default:
1922 		DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
1923 		    unm_nic_driver_name));
1924 	}
1925 
1926 	return (ret);
1927 }
1928 
1929 long
1930 unm_nic_init_port(struct unm_adapter_s *adapter)
1931 {
1932 	long	portnum = adapter->physical_port;
1933 	long	ret = 0;
1934 	long	reg = 0;
1935 	unm_niu_gbe_ifmode_t	mode_dont_care = 0;
1936 	u32			port_mode = 0;
1937 
1938 	unm_nic_set_link_parameters(adapter);
1939 
1940 	switch (adapter->ahw.board_type) {
1941 	case UNM_NIC_GBE:
1942 		ret = unm_niu_enable_gbe_port(adapter, mode_dont_care);
1943 		break;
1944 
1945 	case UNM_NIC_XGBE:
1946 		adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
1947 		    &port_mode, 4);
1948 		if (port_mode == UNM_PORT_MODE_802_3_AP) {
1949 			ret = unm_niu_enable_gbe_port(adapter, mode_dont_care);
1950 		} else {
1951 			adapter->unm_crb_writelit_adapter(adapter,
1952 			    UNM_NIU_XGE_CONFIG_0 + (0x10000 * portnum), 0x5);
1953 			UNM_CRB_READ_CHECK_ADAPTER(UNM_NIU_XGE_CONFIG_1 +
1954 			    (0x10000 * portnum), &reg, adapter);
1955 			if (adapter->ahw.revision_id < NX_P3_A2)
1956 				reg = (reg & ~0x2000UL);
1957 			adapter->unm_crb_writelit_adapter(adapter,
1958 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * portnum), reg);
1959 		}
1960 		break;
1961 
1962 	default:
1963 		DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
1964 		    unm_nic_driver_name));
1965 	}
1966 
1967 	return (ret);
1968 }
1969 
1970 void
1971 unm_nic_stop_port(struct unm_adapter_s *adapter)
1972 {
1973 
1974 	mac_unregister(adapter->mach);
1975 
1976 	switch (adapter->ahw.board_type) {
1977 	case UNM_NIC_GBE:
1978 		(void) unm_niu_disable_gbe_port(adapter);
1979 		break;
1980 
1981 	case UNM_NIC_XGBE:
1982 		(void) unm_niu_disable_xg_port(adapter);
1983 		break;
1984 
1985 	default:
1986 		DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
1987 		    unm_nic_driver_name));
1988 	}
1989 }
1990 
1991 void
1992 unm_crb_write_adapter(unsigned long off, void *data,
1993     struct unm_adapter_s *adapter)
1994 {
1995 	(void) adapter->unm_nic_hw_write_wx(adapter, off, data, 4);
1996 }
1997 
1998 int
1999 unm_crb_read_adapter(unsigned long off, void *data,
2000     struct unm_adapter_s *adapter)
2001 {
2002 	return (adapter->unm_nic_hw_read_wx(adapter, off, data, 4));
2003 }
2004 
2005 int
2006 unm_crb_read_val_adapter(unsigned long off, struct unm_adapter_s *adapter)
2007 {
2008 	int data;
2009 
2010 	adapter->unm_nic_hw_read_wx(adapter, off, &data, 4);
2011 	return (data);
2012 }
2013 
2014 void
2015 unm_nic_set_link_parameters(struct unm_adapter_s *adapter)
2016 {
2017 	unm_niu_phy_status_t status;
2018 	uint16_t defval = (uint16_t)-1;
2019 	unm_niu_control_t mode;
2020 	u32 port_mode = 0;
2021 
2022 	unm_nic_read_w0(adapter, UNM_NIU_MODE, (uint32_t *)&mode);
2023 	if (mode.enable_ge) { // Gb 10/100/1000 Mbps mode
2024 		adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
2025 		    &port_mode, 4);
2026 		if (port_mode == UNM_PORT_MODE_802_3_AP) {
2027 			adapter->link_speed = MBPS_1000;
2028 			adapter->link_duplex = LINK_DUPLEX_FULL;
2029 		} else {
2030 		if (unm_nic_phy_read(adapter,
2031 		    UNM_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
2032 		    (unm_crbword_t *)&status) == 0) {
2033 			if (status.link) {
2034 				switch (status.speed) {
2035 				case 0: adapter->link_speed = MBPS_10;
2036 					break;
2037 				case 1: adapter->link_speed = MBPS_100;
2038 					break;
2039 				case 2: adapter->link_speed = MBPS_1000;
2040 					break;
2041 				default:
2042 					adapter->link_speed = defval;
2043 					break;
2044 				}
2045 				switch (status.duplex) {
2046 				case 0: adapter->link_duplex = LINK_DUPLEX_HALF;
2047 					break;
2048 				case 1: adapter->link_duplex = LINK_DUPLEX_FULL;
2049 					break;
2050 				default:
2051 					adapter->link_duplex = defval;
2052 					break;
2053 				}
2054 			} else {
2055 				adapter->link_speed = defval;
2056 				adapter->link_duplex = defval;
2057 			}
2058 		} else {
2059 			adapter->link_speed = defval;
2060 			adapter->link_duplex = defval;
2061 		}
2062 		}
2063 	}
2064 }
2065 
2066 void
2067 unm_nic_flash_print(struct unm_adapter_s *adapter)
2068 {
2069 	int valid = 1;
2070 	unm_board_info_t *board_info = &(adapter->ahw.boardcfg);
2071 
2072 	if (board_info->magic != UNM_BDINFO_MAGIC) {
2073 		cmn_err(CE_WARN, "%s UNM Unknown board config, Read 0x%x "
2074 		    "expected as 0x%x\n", unm_nic_driver_name,
2075 		    board_info->magic, UNM_BDINFO_MAGIC);
2076 		valid = 0;
2077 	}
2078 	if (board_info->header_version != UNM_BDINFO_VERSION) {
2079 		cmn_err(CE_WARN, "%s UNM Unknown board config version."
2080 		    " Read %x, expected %x\n", unm_nic_driver_name,
2081 		    board_info->header_version, UNM_BDINFO_VERSION);
2082 		valid = 0;
2083 	}
2084 	if (valid) {
2085 		unm_user_info_t  user_info;
2086 		int	i;
2087 		int	addr = USER_START;
2088 		int	*ptr32;
2089 
2090 		ptr32 = (int *)&user_info;
2091 		for (i = 0; i < sizeof (unm_user_info_t) / sizeof (uint32_t);
2092 		    i++) {
2093 			if (rom_fast_read(adapter, addr, ptr32) == -1) {
2094 				cmn_err(CE_WARN,
2095 				    "%s: ERROR reading %s board userarea.\n",
2096 				    unm_nic_driver_name, unm_nic_driver_name);
2097 				return;
2098 			}
2099 			ptr32++;
2100 			addr += sizeof (uint32_t);
2101 		}
2102 		if (verbmsg != 0) {
2103 			char	*brd_name;
2104 			GET_BRD_NAME_BY_TYPE(board_info->board_type, brd_name);
2105 			cmn_err(CE_NOTE, "%s %s Board S/N %s  Chip id 0x%x\n",
2106 			    unm_nic_driver_name, brd_name, user_info.serial_num,
2107 			    board_info->chip_id);
2108 		}
2109 	}
2110 }
2111 
2112 static int
2113 nx_nic_send_cmd_descs(unm_adapter *adapter, cmdDescType0_t *cmd_desc_arr,
2114     int nr_elements)
2115 {
2116 	struct unm_cmd_buffer	*pbuf;
2117 	unsigned int		i = 0, producer;
2118 
2119 	/*
2120 	 * We need to check if space is available.
2121 	 */
2122 	UNM_SPIN_LOCK(&adapter->tx_lock);
2123 	producer = adapter->cmdProducer;
2124 
2125 	do {
2126 		pbuf = &adapter->cmd_buf_arr[producer];
2127 		pbuf->head = pbuf->tail = NULL;
2128 		pbuf->msg = NULL;
2129 		(void) memcpy(&adapter->ahw.cmdDescHead[producer],
2130 		    &cmd_desc_arr[i], sizeof (cmdDescType0_t));
2131 		unm_desc_dma_sync(adapter->ahw.cmd_desc_dma_handle, producer,
2132 		    1, adapter->MaxTxDescCount, sizeof (cmdDescType0_t),
2133 		    DDI_DMA_SYNC_FORDEV);
2134 		producer = get_next_index(producer, adapter->MaxTxDescCount);
2135 		i++;
2136 	} while (i != nr_elements);
2137 
2138 	adapter->cmdProducer = adapter->ahw.cmdProducer = producer;
2139 	adapter->freecmds -= i;
2140 
2141 	unm_nic_update_cmd_producer(adapter, producer);
2142 
2143 	UNM_SPIN_UNLOCK(&adapter->tx_lock);
2144 	return (0);
2145 }
2146 
2147 typedef struct {
2148 	u64	qhdr, req_hdr, words[6];
2149 } nx_nic_req_t;
2150 
2151 typedef struct {
2152 	u8	op, tag, mac_addr[6];
2153 } nx_mac_req_t;
2154 
2155 static void
2156 nx_p3_sre_macaddr_change(unm_adapter *adapter, u8 *addr, u8 op)
2157 {
2158 	nx_nic_req_t	req;
2159 	nx_mac_req_t	mac_req;
2160 	int		rv;
2161 
2162 	(void) memset(&req, 0, sizeof (nx_nic_req_t));
2163 	req.qhdr |= (NX_NIC_REQUEST << 23);
2164 	req.req_hdr |= NX_MAC_EVENT;
2165 	req.req_hdr |= ((u64)adapter->portnum << 16);
2166 	mac_req.op = op;
2167 	(void) memcpy(&mac_req.mac_addr, addr, 6);
2168 	req.words[0] = HOST_TO_LE_64(*(u64 *)(uintptr_t)&mac_req);
2169 
2170 	rv = nx_nic_send_cmd_descs(adapter, (cmdDescType0_t *)&req, 1);
2171 	if (rv != 0)
2172 		cmn_err(CE_WARN, "%s%d: Could not send mac update\n",
2173 		    adapter->name, adapter->instance);
2174 }
2175 
2176 static int
2177 nx_p3_nic_set_promisc(unm_adapter *adapter, u32 mode)
2178 {
2179 	nx_nic_req_t	req;
2180 
2181 	(void) memset(&req, 0, sizeof (nx_nic_req_t));
2182 
2183 	req.qhdr |= (NX_HOST_REQUEST << 23);
2184 	req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE;
2185 	req.req_hdr |= ((u64)adapter->portnum << 16);
2186 	req.words[0] = HOST_TO_LE_64(mode);
2187 
2188 	return (nx_nic_send_cmd_descs(adapter, (cmdDescType0_t *)&req, 1));
2189 }
2190 
2191 /*
2192  * Currently only invoked at interface initialization time
2193  */
2194 void
2195 nx_p3_nic_set_multi(unm_adapter *adapter)
2196 {
2197 	u8	bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2198 
2199 	if (nx_p3_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL))
2200 		cmn_err(CE_WARN, "Could not set promisc mode\n");
2201 
2202 	nx_p3_sre_macaddr_change(adapter, adapter->mac_addr, NETXEN_MAC_ADD);
2203 	nx_p3_sre_macaddr_change(adapter, bcast_addr, NETXEN_MAC_ADD);
2204 }
2205