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