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