Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / ntxn / unm_nic_hw.c
blobc3f46d0e19572ffaf0c72d09050139e9effb2948
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.
28 * Copyright (c) 2018, Joyent, Inc.
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>
51 #include <sys/pci.h>
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"
59 long unm_niu_gbe_phy_read(struct unm_adapter_s *,
60 long reg, unm_crbword_t *readval);
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))
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)
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 */
239 * top 12 bits of crb internal address (hub, agent)
241 static unsigned crb_hub_agt[64] = {
243 UNM_HW_CRB_HUB_AGT_ADR_PS,
244 UNM_HW_CRB_HUB_AGT_ADR_MN,
245 UNM_HW_CRB_HUB_AGT_ADR_MS,
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,
270 UNM_HW_CRB_HUB_AGT_ADR_PGSI,
271 UNM_HW_CRB_HUB_AGT_ADR_SN,
273 UNM_HW_CRB_HUB_AGT_ADR_EG,
275 UNM_HW_CRB_HUB_AGT_ADR_PS,
276 UNM_HW_CRB_HUB_AGT_ADR_CAM,
282 UNM_HW_CRB_HUB_AGT_ADR_TIMR,
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,
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,
300 UNM_HW_CRB_HUB_AGT_ADR_SMB,
301 UNM_HW_CRB_HUB_AGT_ADR_I2C0,
302 UNM_HW_CRB_HUB_AGT_ADR_I2C1,
304 UNM_HW_CRB_HUB_AGT_ADR_PGNC,
308 #define CRB_WIN_LOCK_TIMEOUT 100000000
310 static void
311 crb_win_lock(struct unm_adapter_s *adapter)
313 int i;
314 int done = 0, timeout = 0;
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;
327 timeout++;
329 * Yield CPU
331 for (i = 0; i < 20; i++)
334 adapter->unm_crb_writelit_adapter(adapter, UNM_CRB_WIN_LOCK_ID,
335 adapter->portnum);
338 static void
339 crb_win_unlock(struct unm_adapter_s *adapter)
341 int val;
343 adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_SEM7_UNLOCK),
344 &val, 4);
348 * Changes the CRB window to the specified window.
350 void
351 unm_nic_pci_change_crbwindow_128M(unm_adapter *adapter, uint32_t wndw)
353 unm_pcix_crb_window_t window;
354 unsigned long offset;
355 uint32_t tmp;
357 if (adapter->curr_window == wndw) {
358 return;
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.
369 offset = PCI_OFFSET_SECOND_RANGE(adapter,
370 UNM_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(adapter->ahw.pci_func)));
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);
383 adapter->curr_window = wndw;
388 * Changes the CRB window to the specified window.
390 /* ARGSUSED */
391 void
392 unm_nic_pci_change_crbwindow_2M(unm_adapter *adapter, uint32_t wndw)
397 uint32_t
398 unm_nic_get_crbwindow(unm_adapter *adapter)
400 return (adapter->curr_window);
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
411 unm_nic_pci_get_crb_addr_2M(unm_adapter *adapter, u64 *off, int len)
413 unsigned long end = *off + len;
414 crb_128M_2M_sub_block_map_t *m;
417 if (*off >= UNM_CRB_MAX)
418 return (-1);
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);
426 if (*off < UNM_PCI_CRBSPACE)
427 return (-1);
429 *off -= UNM_PCI_CRBSPACE;
430 end = *off + len;
432 * Try direct map
435 m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
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);
444 * Not in direct map, use crb window
446 return (1);
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
453 static void
454 unm_nic_pci_set_crbwindow_2M(unm_adapter *adapter, u64 *off)
456 u32 win_read;
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));
462 * Read back value to make sure write has gone through before trying
463 * to use it.
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);
472 *off = (*off & MASK(16)) + CRB_INDIRECT_2M +
473 adapter->ahw.pci_base0;
477 unm_nic_hw_write_ioctl_128M(unm_adapter *adapter, u64 off, void *data, int len)
479 void *addr;
480 u64 offset = off;
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);
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);
499 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
500 unm_nic_pci_change_crbwindow_128M(adapter, 0);
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;
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);
532 return (0);
536 * Note : 'len' argument should be either 1, 2, 4, or a multiple of 8.
539 unm_nic_hw_write_wx_128M(unm_adapter *adapter, u64 off, void *data, int len)
542 * This is modified from _unm_nic_hw_write().
543 * unm_nic_hw_write does not exist now.
546 void *addr;
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);
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);
565 return (1);
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;
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);
598 return (0);
602 * Note : only 32-bit writes!
604 void
605 unm_nic_pci_write_normalize_128M(unm_adapter *adapter, u64 off, u32 data)
607 UNM_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off));
611 * Note : only 32-bit reads!
614 unm_nic_pci_read_normalize_128M(unm_adapter *adapter, u64 off)
616 return (UNM_NIC_PCI_READ_32(CRB_NORMALIZE(adapter, off)));
620 * Note : only 32-bit writes!
623 unm_nic_pci_write_immediate_128M(unm_adapter *adapter, u64 off, u32 *data)
625 UNM_NIC_PCI_WRITE_32(*data,
626 (void *) (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
627 return (0);
631 * Note : only 32-bit reads!
634 unm_nic_pci_read_immediate_128M(unm_adapter *adapter, u64 off, u32 *data)
636 *data = UNM_NIC_PCI_READ_32((void *)
637 (uptr_t)(pci_base_offset(adapter, off)));
638 return (0);
642 * Note : only 32-bit writes!
644 void
645 unm_nic_pci_write_normalize_2M(unm_adapter *adapter, u64 off, u32 data)
647 u32 temp = data;
649 adapter->unm_nic_hw_write_wx(adapter, off, &temp, 4);
653 * Note : only 32-bit reads!
656 unm_nic_pci_read_normalize_2M(unm_adapter *adapter, u64 off)
658 u32 temp;
660 adapter->unm_nic_hw_read_wx(adapter, off, &temp, 4);
662 return (temp);
666 * Note : only 32-bit writes!
669 unm_nic_pci_write_immediate_2M(unm_adapter *adapter, u64 off, u32 *data)
671 u32 temp = *data;
673 adapter->unm_nic_hw_write_wx(adapter, off, &temp, 4);
675 return (0);
679 * Note : only 32-bit reads!
682 unm_nic_pci_read_immediate_2M(unm_adapter *adapter, u64 off, u32 *data)
684 u32 temp;
686 adapter->unm_nic_hw_read_wx(adapter, off, &temp, 4);
688 *data = temp;
690 return (0);
694 * write cross hw window boundary is not supported
695 * 'len' should be either 1, 2, 4, or multiple of 8
698 unm_nic_hw_write_wx_2M(unm_adapter *adapter, u64 off, void *data, int len)
700 int rv;
702 rv = unm_nic_pci_get_crb_addr_2M(adapter, &off, len);
704 if (rv == -1) {
705 cmn_err(CE_PANIC, "%s: invalid offset: 0x%016llx\n",
706 __FUNCTION__, off);
707 return (-1);
710 if (rv == 1) {
711 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
712 crb_win_lock(adapter);
713 unm_nic_pci_set_crbwindow_2M(adapter, &off);
716 switch (len) {
717 case 1:
718 UNM_NIC_PCI_WRITE_8(*(__uint8_t *)data, (void *) (uptr_t)off);
719 break;
720 case 2:
721 UNM_NIC_PCI_WRITE_16(*(__uint16_t *)data, (void *) (uptr_t)off);
722 break;
723 case 4:
724 UNM_NIC_PCI_WRITE_32(*(__uint32_t *)data, (void *) (uptr_t)off);
725 break;
726 case 8:
727 UNM_NIC_PCI_WRITE_64(*(__uint64_t *)data, (void *) (uptr_t)off);
728 break;
729 default:
730 #if !defined(NDEBUG)
731 if ((len & 0x7) != 0)
732 cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
733 unm_nic_driver_name, __FUNCTION__, len);
734 #endif
735 UNM_NIC_HW_BLOCK_WRITE_64(data, (uptr_t)off, (len>>3));
736 break;
738 if (rv == 1) {
739 crb_win_unlock(adapter);
740 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
743 return (0);
747 unm_nic_hw_read_ioctl_128M(unm_adapter *adapter, u64 off, void *data, int len)
749 void *addr;
750 u64 offset;
752 if (ADDR_IN_WINDOW1(off)) {// Window 1
753 addr = CRB_NORMALIZE(adapter, off);
754 if (!addr) {
755 offset = CRB_NORMAL(off);
756 if (adapter->ahw.pci_len0 == 0)
757 offset -= UNM_PCI_CRBSPACE;
758 addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
759 offset);
761 UNM_READ_LOCK(&adapter->adapter_lock);
762 } else {// Window 0
763 addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
764 if (!addr) {
765 offset = off;
766 addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
767 offset);
769 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
770 unm_nic_pci_change_crbwindow_128M(adapter, 0);
773 switch (len) {
774 case 1:
775 *(__uint8_t *)data = UNM_NIC_PCI_READ_8(addr);
776 break;
777 case 2:
778 *(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
779 break;
780 case 4:
781 *(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
782 break;
783 case 8:
784 *(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
785 break;
786 default:
787 #if !defined(NDEBUG)
788 if ((len & 0x7) != 0)
789 cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
790 unm_nic_driver_name, __FUNCTION__, len);
791 #endif
792 UNM_NIC_HW_BLOCK_READ_64(data, addr, (len>>3));
793 break;
796 if (ADDR_IN_WINDOW1(off)) {// Window 1
797 UNM_READ_UNLOCK(&adapter->adapter_lock);
798 } else {// Window 0
799 unm_nic_pci_change_crbwindow_128M(adapter, 1);
800 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
803 return (0);
807 unm_nic_hw_read_wx_2M(unm_adapter *adapter, u64 off, void *data, int len)
809 int rv;
811 rv = unm_nic_pci_get_crb_addr_2M(adapter, &off, len);
813 if (rv == -1) {
814 cmn_err(CE_PANIC, "%s: invalid offset: 0x%016llx\n",
815 __FUNCTION__, off);
816 return (-1);
819 if (rv == 1) {
820 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
821 crb_win_lock(adapter);
822 unm_nic_pci_set_crbwindow_2M(adapter, &off);
825 switch (len) {
826 case 1:
827 *(__uint8_t *)data = UNM_NIC_PCI_READ_8((void *) (uptr_t)off);
828 break;
829 case 2:
830 *(__uint16_t *)data = UNM_NIC_PCI_READ_16((void *) (uptr_t)off);
831 break;
832 case 4:
833 *(__uint32_t *)data = UNM_NIC_PCI_READ_32((void *) (uptr_t)off);
834 break;
835 case 8:
836 *(__uint64_t *)data = UNM_NIC_PCI_READ_64((void *) (uptr_t)off);
837 break;
838 default:
839 #if !defined(NDEBUG)
840 if ((len & 0x7) != 0)
841 cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
842 unm_nic_driver_name, __FUNCTION__, len);
843 #endif
844 UNM_NIC_HW_BLOCK_READ_64(data, (void *) (uptr_t)off, (len>>3));
845 break;
848 if (rv == 1) {
849 crb_win_unlock(adapter);
850 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
853 return (0);
857 unm_nic_hw_read_wx_128M(unm_adapter *adapter, u64 off, void *data, int len)
859 void *addr;
861 if (ADDR_IN_WINDOW1(off)) {
862 // Window 1
863 addr = CRB_NORMALIZE(adapter, off);
864 UNM_READ_LOCK(&adapter->adapter_lock);
865 } else {// Window 0
866 addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
867 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
868 unm_nic_pci_change_crbwindow_128M(adapter, 0);
871 if (!addr) {
872 if (ADDR_IN_WINDOW1(off)) {// Window 1
873 UNM_READ_UNLOCK(&adapter->adapter_lock);
874 } else {// Window 0
875 unm_nic_pci_change_crbwindow_128M(adapter, 1);
876 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
878 return (1);
881 switch (len) {
882 case 1:
883 *(__uint8_t *)data = UNM_NIC_PCI_READ_8(addr);
884 break;
885 case 2:
886 *(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
887 break;
888 case 4:
889 *(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
890 break;
891 case 8:
892 *(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
893 break;
894 default:
895 #if !defined(NDEBUG)
896 if ((len & 0x7) != 0)
897 cmn_err(CE_WARN,
898 "%s: %s len(%d) not multiple of 8.\n",
899 unm_nic_driver_name, __FUNCTION__, len);
900 #endif
901 UNM_NIC_HW_BLOCK_READ_64(data, addr, (len>>3));
902 break;
905 if (ADDR_IN_WINDOW1(off)) {// Window 1
906 UNM_READ_UNLOCK(&adapter->adapter_lock);
907 } else {// Window 0
908 unm_nic_pci_change_crbwindow_128M(adapter, 1);
909 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
912 return (0);
915 /* PCI Windowing for DDR regions. */
916 #define ADDR_IN_RANGE(addr, low, high) \
917 (((addr) <= (high)) && ((low) ? ((addr) >= (low)) : 1))
920 * check memory access boundary.
921 * used by test agent. support ddr access only for now
923 /* ARGSUSED */
924 static unsigned long
925 unm_nic_pci_mem_bound_check(struct unm_adapter_s *adapter,
926 unsigned long long addr, int size)
928 if (!ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX) ||
929 !ADDR_IN_RANGE(addr + size -1, UNM_ADDR_DDR_NET,
930 UNM_ADDR_DDR_NET_MAX) || ((size != 1) && (size != 2) &&
931 (size != 4) && (size != 8)))
932 return (0);
934 return (1);
937 int unm_pci_set_window_warning_count = 0;
939 unsigned long long
940 unm_nic_pci_set_window_128M(struct unm_adapter_s *adapter,
941 unsigned long long addr)
943 int window;
944 unsigned long long qdr_max;
946 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
947 qdr_max = NX_P2_ADDR_QDR_NET_MAX;
948 } else {
949 qdr_max = NX_P3_ADDR_QDR_NET_MAX;
952 if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
953 /* DDR network side */
954 /* MN access should never come here */
955 cmn_err(CE_PANIC, "%s\n", __FUNCTION__);
956 addr = -1ULL;
957 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
958 addr -= UNM_ADDR_OCM0;
959 addr += UNM_PCI_OCM0;
960 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, UNM_ADDR_OCM1_MAX)) {
961 addr -= UNM_ADDR_OCM1;
962 addr += UNM_PCI_OCM1;
963 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
964 /* QDR network side */
965 addr -= UNM_ADDR_QDR_NET;
966 window = (addr >> 22) & 0x3f;
967 if (adapter->ahw.qdr_sn_window != window) {
968 adapter->ahw.qdr_sn_window = window;
969 UNM_NIC_PCI_WRITE_32((window << 22),
970 (void *) (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter,
971 UNM_PCIX_PH_REG(PCIE_SN_WINDOW_REG(
972 adapter->ahw.pci_func)))));
973 /* MUST make sure window is set before we forge on... */
974 (void) UNM_NIC_PCI_READ_32((void *)
975 (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter,
976 UNM_PCIX_PH_REG(PCIE_SN_WINDOW_REG(
977 adapter->ahw.pci_func)))));
979 addr -= (window * 0x400000);
980 addr += UNM_PCI_QDR_NET;
981 } else {
983 * peg gdb frequently accesses memory that doesn't exist,
984 * this limits the chit chat so debugging isn't slowed down.
986 if ((unm_pci_set_window_warning_count++ < 8) ||
987 (unm_pci_set_window_warning_count%64 == 0)) {
988 cmn_err(CE_WARN, "%s: Warning:unm_nic_pci_set_window() "
989 "Unknown address range!\n", unm_nic_driver_name);
991 addr = -1ULL;
993 return (addr);
996 unsigned long long
997 unm_nic_pci_set_window_2M(struct unm_adapter_s *adapter,
998 unsigned long long addr)
1000 int window;
1001 u32 win_read;
1003 if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
1004 /* DDR network side */
1005 window = MN_WIN(addr);
1006 adapter->ahw.ddr_mn_window = window;
1007 adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.mn_win_crb |
1008 UNM_PCI_CRBSPACE, &window, 4);
1009 adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.mn_win_crb |
1010 UNM_PCI_CRBSPACE, &win_read, 4);
1011 if ((win_read << 17) != window) {
1012 cmn_err(CE_WARN,
1013 "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",
1014 __FUNCTION__, window, win_read);
1016 addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
1017 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
1018 unsigned int temp1;
1019 // OCM: pci_addr[20:18] == 011 && pci_addr[17:11] != 7f
1020 if ((addr & 0x00ff800) == 0xff800) {
1021 // if bits 19:18&17:11 are on
1022 cmn_err(CE_WARN, "%s: QM access not handled.\n",
1023 __FUNCTION__);
1024 addr = -1ULL;
1027 window = OCM_WIN(addr);
1028 adapter->ahw.ddr_mn_window = window;
1029 adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.mn_win_crb |
1030 UNM_PCI_CRBSPACE, &window, 4);
1031 adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.mn_win_crb |
1032 UNM_PCI_CRBSPACE, &win_read, 4);
1033 temp1 = ((window & 0x1FF) << 7) |
1034 ((window & 0x0FFFE0000) >> 17);
1035 if (win_read != temp1) {
1036 cmn_err(CE_WARN,
1037 "%s: Written OCMwin(0x%x) != Read OCMwin(0x%x)\n",
1038 __FUNCTION__, temp1, win_read);
1040 addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
1042 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
1043 NX_P3_ADDR_QDR_NET_MAX)) {
1044 /* QDR network side */
1045 window = MS_WIN(addr);
1046 adapter->ahw.qdr_sn_window = window;
1047 adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.ms_win_crb |
1048 UNM_PCI_CRBSPACE, &window, 4);
1049 adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.ms_win_crb |
1050 UNM_PCI_CRBSPACE, &win_read, 4);
1051 if (win_read != window) {
1052 cmn_err(CE_WARN,
1053 "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n",
1054 __FUNCTION__, window, win_read);
1056 addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
1058 } else {
1060 * peg gdb frequently accesses memory that doesn't exist,
1061 * this limits the chit chat so debugging isn't slowed down.
1063 if ((unm_pci_set_window_warning_count++ < 8) ||
1064 (unm_pci_set_window_warning_count%64 == 0)) {
1065 cmn_err(CE_WARN, "%s%d: %s Unknown address range!\n",
1066 adapter->name, adapter->instance, __FUNCTION__);
1068 addr = -1ULL;
1070 return (addr);
1073 /* check if address is in the same windows as the previous access */
1074 static unsigned long
1075 unm_nic_pci_is_same_window(struct unm_adapter_s *adapter,
1076 unsigned long long addr)
1078 int window;
1079 unsigned long long qdr_max;
1081 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1082 qdr_max = NX_P2_ADDR_QDR_NET_MAX;
1083 } else {
1084 qdr_max = NX_P3_ADDR_QDR_NET_MAX;
1087 if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
1088 /* DDR network side */
1089 /* MN access can not come here */
1090 cmn_err(CE_PANIC, "%s\n", __FUNCTION__);
1091 #if 0
1092 window = ((addr - UNM_ADDR_DDR_NET) >> 25) & 0x3ff;
1093 if (adapter->ahw.ddr_mn_window == window) {
1094 return (1);
1096 #endif
1097 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
1098 return (1);
1099 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, UNM_ADDR_OCM1_MAX)) {
1100 return (1);
1101 } else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
1102 /* QDR network side */
1103 window = ((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f;
1104 if (adapter->ahw.qdr_sn_window == window) {
1105 return (1);
1109 return (0);
1112 static int
1113 unm_nic_pci_mem_read_direct(struct unm_adapter_s *adapter,
1114 u64 off, void *data, int size)
1116 void *addr;
1117 int ret = 0;
1118 u64 start;
1120 #if 0
1122 * This check can not be currently executed, since phanmon findq
1123 * command breaks this check whereby 8 byte reads are being attempted
1124 * on "aligned-by-4" addresses on x86. Reason this works is our version
1125 * breaks up the access into 2 consecutive 4 byte writes; on other
1126 * architectures, this might require "aligned-by-8" addresses and we
1127 * will run into trouble.
1129 * Check alignment for expected sizes of 1, 2, 4, 8. Other size
1130 * values will not trigger access.
1132 if ((off & (size - 1)) != 0)
1133 return (-1);
1134 #endif
1136 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1139 * If attempting to access unknown address or straddle hw windows,
1140 * do not access.
1142 if (((start = adapter->unm_nic_pci_set_window(adapter, off)) == -1UL) ||
1143 (unm_nic_pci_is_same_window(adapter, off + size -1) == 0)) {
1144 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1145 cmn_err(CE_WARN, "%s out of bound pci memory access. "
1146 "offset is 0x%llx\n", unm_nic_driver_name, off);
1147 return (-1);
1150 addr = (void *) (uptr_t)(pci_base_offset(adapter, start));
1151 if (!addr)
1152 addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 + start);
1154 switch (size) {
1155 case 1:
1156 *(__uint8_t *)data = UNM_NIC_PCI_READ_8(addr);
1157 break;
1158 case 2:
1159 *(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
1160 break;
1161 case 4:
1162 *(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
1163 break;
1164 case 8:
1165 *(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
1166 break;
1167 default:
1168 ret = -1;
1169 break;
1172 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1173 return (ret);
1176 static int
1177 unm_nic_pci_mem_write_direct(struct unm_adapter_s *adapter, u64 off,
1178 void *data, int size)
1180 void *addr;
1181 int ret = 0;
1182 u64 start;
1184 #if 0
1186 * This check can not be currently executed, since firmware load
1187 * breaks this check whereby 8 byte writes are being attempted on
1188 * "aligned-by-4" addresses on x86. Reason this works is our version
1189 * breaks up the access into 2 consecutive 4 byte writes; on other
1190 * architectures, this might require "aligned-by-8" addresses and we
1191 * will run into trouble.
1193 * Check alignment for expected sizes of 1, 2, 4, 8. Other size
1194 * values will not trigger access.
1196 if ((off & (size - 1)) != 0)
1197 return (-1);
1198 #endif
1200 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1203 * If attempting to access unknown address or straddle hw windows,
1204 * do not access.
1206 if (((start = adapter->unm_nic_pci_set_window(adapter, off)) == -1UL) ||
1207 (unm_nic_pci_is_same_window(adapter, off + size -1) == 0)) {
1208 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1209 cmn_err(CE_WARN, "%s out of bound pci memory access. "
1210 "offset is 0x%llx\n", unm_nic_driver_name, off);
1211 return (-1);
1214 addr = (void *) (uptr_t)(pci_base_offset(adapter, start));
1215 if (!addr)
1216 addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 + start);
1218 switch (size) {
1219 case 1:
1220 UNM_NIC_PCI_WRITE_8(*(__uint8_t *)data, addr);
1221 break;
1222 case 2:
1223 UNM_NIC_PCI_WRITE_16(*(__uint16_t *)data, addr);
1224 break;
1225 case 4:
1226 UNM_NIC_PCI_WRITE_32(*(__uint32_t *)data, addr);
1227 break;
1228 case 8:
1229 UNM_NIC_PCI_WRITE_64(*(__uint64_t *)data, addr);
1230 break;
1231 default:
1232 ret = -1;
1233 break;
1235 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1236 return (ret);
1241 unm_nic_pci_mem_write_128M(struct unm_adapter_s *adapter, u64 off, void *data,
1242 int size)
1244 int i, j, ret = 0, loop, sz[2], off0;
1245 __uint32_t temp;
1246 __uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
1247 #define MAX_CTL_CHECK 1000
1250 * If not MN, go check for MS or invalid.
1252 if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1253 return (unm_nic_pci_mem_write_direct(adapter, off, data, size));
1255 off8 = off & 0xfffffff8;
1256 off0 = off & 0x7;
1257 sz[0] = (size < (8 - off0)) ? size : (8 - off0);
1258 sz[1] = size - sz[0];
1259 loop = ((off0 + size - 1) >> 3) + 1;
1260 /* LINTED: E_FALSE_LOGICAL_EXPR */
1261 mem_crb = (uptr_t)(pci_base_offset(adapter, UNM_CRB_DDR_NET));
1263 if ((size != 8) || (off0 != 0)) {
1264 for (i = 0; i < loop; i++) {
1265 if (adapter->unm_nic_pci_mem_read(adapter,
1266 off8 + (i << 3), &word[i], 8))
1267 return (-1);
1271 switch (size) {
1272 case 1:
1273 tmpw = *((__uint8_t *)data);
1274 break;
1275 case 2:
1276 tmpw = *((__uint16_t *)data);
1277 break;
1278 case 4:
1279 tmpw = *((__uint32_t *)data);
1280 break;
1281 case 8:
1282 default:
1283 tmpw = *((__uint64_t *)data);
1284 break;
1286 word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
1287 word[0] |= tmpw << (off0 * 8);
1289 if (loop == 2) {
1290 word[1] &= ~(~0ULL << (sz[1] * 8));
1291 word[1] |= tmpw >> (sz[0] * 8);
1294 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1295 unm_nic_pci_change_crbwindow_128M(adapter, 0);
1297 for (i = 0; i < loop; i++) {
1298 UNM_NIC_PCI_WRITE_32((__uint32_t)(off8 + (i << 3)),
1299 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_LO));
1300 UNM_NIC_PCI_WRITE_32(0,
1301 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_HI));
1302 UNM_NIC_PCI_WRITE_32(word[i] & 0xffffffff,
1303 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
1304 UNM_NIC_PCI_WRITE_32((word[i] >> 32) & 0xffffffff,
1305 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
1306 UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
1307 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1308 UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE |
1309 MIU_TA_CTL_WRITE,
1310 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1312 for (j = 0; j < MAX_CTL_CHECK; j++) {
1313 temp = UNM_NIC_PCI_READ_32((void *)
1314 (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1315 if ((temp & MIU_TA_CTL_BUSY) == 0) {
1316 break;
1320 if (j >= MAX_CTL_CHECK) {
1321 cmn_err(CE_WARN, "%s: %s Fail to write thru agent\n",
1322 __FUNCTION__, unm_nic_driver_name);
1323 ret = -1;
1324 break;
1328 unm_nic_pci_change_crbwindow_128M(adapter, 1);
1329 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1330 return (ret);
1334 unm_nic_pci_mem_read_128M(struct unm_adapter_s *adapter, u64 off, void *data,
1335 int size)
1337 int i, j = 0, k, start, end, loop, sz[2], off0[2];
1338 __uint32_t temp;
1339 __uint64_t off8, val, mem_crb, word[2] = {0, 0};
1340 #define MAX_CTL_CHECK 1000
1343 * If not MN, go check for MS or invalid.
1345 if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1346 return (unm_nic_pci_mem_read_direct(adapter, off, data, size));
1348 off8 = off & 0xfffffff8;
1349 off0[0] = off & 0x7;
1350 off0[1] = 0;
1351 sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
1352 sz[1] = size - sz[0];
1353 loop = ((off0[0] + size - 1) >> 3) + 1;
1354 /* LINTED: E_FALSE_LOGICAL_EXPR */
1355 mem_crb = (uptr_t)(pci_base_offset(adapter, UNM_CRB_DDR_NET));
1357 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1358 unm_nic_pci_change_crbwindow_128M(adapter, 0);
1360 for (i = 0; i < loop; i++) {
1361 UNM_NIC_PCI_WRITE_32((__uint32_t)(off8 + (i << 3)),
1362 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_LO));
1363 UNM_NIC_PCI_WRITE_32(0,
1364 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_HI));
1365 UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_ENABLE,
1366 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1367 UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
1368 (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1370 for (j = 0; j < MAX_CTL_CHECK; j++) {
1371 temp = UNM_NIC_PCI_READ_32((void *)
1372 (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
1373 if ((temp & MIU_TA_CTL_BUSY) == 0) {
1374 break;
1378 if (j >= MAX_CTL_CHECK) {
1379 cmn_err(CE_WARN, "%s: %s Fail to read through agent\n",
1380 __FUNCTION__, unm_nic_driver_name);
1381 break;
1384 start = off0[i] >> 2;
1385 end = (off0[i] + sz[i] - 1) >> 2;
1386 word[i] = 0;
1387 for (k = start; k <= end; k++) {
1388 word[i] |= ((__uint64_t)UNM_NIC_PCI_READ_32(
1389 (void *) (uptr_t)(mem_crb +
1390 MIU_TEST_AGT_RDDATA(k))) << (32*k));
1394 unm_nic_pci_change_crbwindow_128M(adapter, 1);
1395 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1397 if (j >= MAX_CTL_CHECK)
1398 return (-1);
1400 if (sz[0] == 8) {
1401 val = word[0];
1402 } else {
1403 val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
1404 ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
1407 switch (size) {
1408 case 1:
1409 *(__uint8_t *)data = val;
1410 break;
1411 case 2:
1412 *(__uint16_t *)data = val;
1413 break;
1414 case 4:
1415 *(__uint32_t *)data = val;
1416 break;
1417 case 8:
1418 *(__uint64_t *)data = val;
1419 break;
1421 return (0);
1427 unm_nic_pci_mem_write_2M(struct unm_adapter_s *adapter, u64 off, void *data,
1428 int size)
1430 int i, j, ret = 0, loop, sz[2], off0;
1431 __uint32_t temp;
1432 __uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
1433 #define MAX_CTL_CHECK 1000
1436 * If not MN, go check for MS or invalid.
1438 if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
1439 mem_crb = UNM_CRB_QDR_NET;
1440 } else {
1441 mem_crb = UNM_CRB_DDR_NET;
1442 if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1443 return (unm_nic_pci_mem_write_direct(adapter,
1444 off, data, size));
1447 off8 = off & 0xfffffff8;
1448 off0 = off & 0x7;
1449 sz[0] = (size < (8 - off0)) ? size : (8 - off0);
1450 sz[1] = size - sz[0];
1451 loop = ((off0 + size - 1) >> 3) + 1;
1453 if ((size != 8) || (off0 != 0)) {
1454 for (i = 0; i < loop; i++) {
1455 if (adapter->unm_nic_pci_mem_read(adapter,
1456 off8 + (i << 3), &word[i], 8))
1457 return (-1);
1461 switch (size) {
1462 case 1:
1463 tmpw = *((__uint8_t *)data);
1464 break;
1465 case 2:
1466 tmpw = *((__uint16_t *)data);
1467 break;
1468 case 4:
1469 tmpw = *((__uint32_t *)data);
1470 break;
1471 case 8:
1472 default:
1473 tmpw = *((__uint64_t *)data);
1474 break;
1477 word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
1478 word[0] |= tmpw << (off0 * 8);
1480 if (loop == 2) {
1481 word[1] &= ~(~0ULL << (sz[1] * 8));
1482 word[1] |= tmpw >> (sz[0] * 8);
1485 // don't lock here - write_wx gets the lock if each time
1486 // UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1487 // unm_nic_pci_change_crbwindow_128M(adapter, 0);
1489 for (i = 0; i < loop; i++) {
1490 temp = off8 + (i << 3);
1491 adapter->unm_nic_hw_write_wx(adapter,
1492 mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
1493 temp = 0;
1494 adapter->unm_nic_hw_write_wx(adapter,
1495 mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
1496 temp = word[i] & 0xffffffff;
1497 adapter->unm_nic_hw_write_wx(adapter,
1498 mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
1499 temp = (word[i] >> 32) & 0xffffffff;
1500 adapter->unm_nic_hw_write_wx(adapter,
1501 mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
1502 temp = 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 temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
1506 adapter->unm_nic_hw_write_wx(adapter,
1507 mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
1509 for (j = 0; j < MAX_CTL_CHECK; j++) {
1510 adapter->unm_nic_hw_read_wx(adapter,
1511 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1512 if ((temp & MIU_TA_CTL_BUSY) == 0) {
1513 break;
1517 if (j >= MAX_CTL_CHECK) {
1518 cmn_err(CE_WARN, "%s: Fail to write through agent\n",
1519 unm_nic_driver_name);
1520 ret = -1;
1521 break;
1525 // unm_nic_pci_change_crbwindow_128M(adapter, 1);
1526 // UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1527 return (ret);
1531 unm_nic_pci_mem_read_2M(struct unm_adapter_s *adapter, u64 off, void *data,
1532 int size)
1534 // unsigned long flags;
1535 int i, j = 0, k, start, end, loop, sz[2], off0[2];
1536 __uint32_t temp;
1537 __uint64_t off8, val, mem_crb, word[2] = {0, 0};
1538 #define MAX_CTL_CHECK 1000
1541 * If not MN, go check for MS or invalid.
1544 if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
1545 mem_crb = UNM_CRB_QDR_NET;
1546 } else {
1547 mem_crb = UNM_CRB_DDR_NET;
1548 if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
1549 return (unm_nic_pci_mem_read_direct(adapter,
1550 off, data, size));
1553 off8 = off & 0xfffffff8;
1554 off0[0] = off & 0x7;
1555 off0[1] = 0;
1556 sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
1557 sz[1] = size - sz[0];
1558 loop = ((off0[0] + size - 1) >> 3) + 1;
1560 // don't get lock - write_wx will get it
1561 // UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1562 // unm_nic_pci_change_crbwindow_128M(adapter, 0);
1564 for (i = 0; i < loop; i++) {
1565 temp = off8 + (i << 3);
1566 adapter->unm_nic_hw_write_wx(adapter,
1567 mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
1568 temp = 0;
1569 adapter->unm_nic_hw_write_wx(adapter,
1570 mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
1571 temp = MIU_TA_CTL_ENABLE;
1572 adapter->unm_nic_hw_write_wx(adapter,
1573 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1574 temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
1575 adapter->unm_nic_hw_write_wx(adapter,
1576 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1578 for (j = 0; j < MAX_CTL_CHECK; j++) {
1579 adapter->unm_nic_hw_read_wx(adapter,
1580 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1581 if ((temp & MIU_TA_CTL_BUSY) == 0) {
1582 break;
1586 if (j >= MAX_CTL_CHECK) {
1587 cmn_err(CE_WARN, "%s: Fail to read through agent\n",
1588 unm_nic_driver_name);
1589 break;
1592 start = off0[i] >> 2;
1593 end = (off0[i] + sz[i] - 1) >> 2;
1594 for (k = start; k <= end; k++) {
1595 adapter->unm_nic_hw_read_wx(adapter,
1596 mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
1597 word[i] |= ((__uint64_t)temp << (32 * k));
1601 // unm_nic_pci_change_crbwindow_128M(adapter, 1);
1602 // UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1604 if (j >= MAX_CTL_CHECK)
1605 return (-1);
1607 if (sz[0] == 8) {
1608 val = word[0];
1609 } else {
1610 val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
1611 ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
1614 switch (size) {
1615 case 1:
1616 *(__uint8_t *)data = val;
1617 break;
1618 case 2:
1619 *(__uint16_t *)data = val;
1620 break;
1621 case 4:
1622 *(__uint32_t *)data = val;
1623 break;
1624 case 8:
1625 *(__uint64_t *)data = val;
1626 break;
1628 return (0);
1632 unm_crb_writelit_adapter_2M(struct unm_adapter_s *adapter, unsigned long off,
1633 int data)
1635 return (unm_nic_hw_write_wx_2M(adapter, off, &data, 4));
1639 unm_crb_writelit_adapter_128M(struct unm_adapter_s *adapter, unsigned long off,
1640 int data)
1642 void *addr;
1644 if (ADDR_IN_WINDOW1(off)) {
1645 UNM_READ_LOCK(&adapter->adapter_lock);
1646 UNM_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off));
1647 UNM_READ_UNLOCK(&adapter->adapter_lock);
1648 } else {
1649 // unm_nic_write_w0 (adapter, off, data);
1650 UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1651 unm_nic_pci_change_crbwindow_128M(adapter, 0);
1652 addr = (void *) (pci_base_offset(adapter, off));
1653 UNM_NIC_PCI_WRITE_32(data, addr);
1654 unm_nic_pci_change_crbwindow_128M(adapter, 1);
1655 UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
1658 return (0);
1662 unm_nic_get_board_info(struct unm_adapter_s *adapter)
1664 int rv = 0;
1665 unm_board_info_t *boardinfo;
1666 int i;
1667 int addr = BRDCFG_START;
1668 uint32_t *ptr32;
1669 uint32_t gpioval;
1671 boardinfo = &adapter->ahw.boardcfg;
1672 ptr32 = (uint32_t *)boardinfo;
1674 for (i = 0; i < sizeof (unm_board_info_t) / sizeof (uint32_t); i++) {
1675 if (rom_fast_read(adapter, addr, (int *)ptr32) == -1) {
1676 return (-1);
1678 DPRINTF(1, (CE_WARN, "ROM(%d): %x\n", i, *ptr32));
1679 ptr32++;
1680 addr += sizeof (uint32_t);
1683 if (boardinfo->magic != UNM_BDINFO_MAGIC) {
1684 DPRINTF(1, (CE_WARN, "%s: ERROR reading board config."
1685 " Read %x, expected %x\n", unm_nic_driver_name,
1686 boardinfo->magic, UNM_BDINFO_MAGIC));
1687 rv = -1;
1690 if (boardinfo->header_version != UNM_BDINFO_VERSION) {
1691 DPRINTF(1, (CE_WARN, "%s: Unknown board config version."
1692 " Read %x, expected %x\n", unm_nic_driver_name,
1693 boardinfo->header_version, UNM_BDINFO_VERSION));
1694 rv = -1;
1697 if (boardinfo->board_type == UNM_BRDTYPE_P3_4_GB_MM) {
1698 gpioval = UNM_CRB_READ_VAL_ADAPTER(UNM_ROMUSB_GLB_PAD_GPIO_I,
1699 adapter);
1700 if ((gpioval & 0x8000) == 0)
1701 boardinfo->board_type = UNM_BRDTYPE_P3_10G_TRP;
1704 DPRINTF(0, (CE_WARN, "Discovered board type:0x%x ",
1705 boardinfo->board_type));
1707 switch ((unm_brdtype_t)boardinfo->board_type) {
1708 case UNM_BRDTYPE_P2_SB35_4G:
1709 adapter->ahw.board_type = UNM_NIC_GBE;
1710 break;
1711 case UNM_BRDTYPE_P2_SB31_10G:
1712 case UNM_BRDTYPE_P2_SB31_10G_IMEZ:
1713 case UNM_BRDTYPE_P2_SB31_10G_HMEZ:
1714 case UNM_BRDTYPE_P2_SB31_10G_CX4:
1715 case UNM_BRDTYPE_P3_HMEZ:
1716 case UNM_BRDTYPE_P3_XG_LOM:
1717 case UNM_BRDTYPE_P3_10G_CX4:
1718 case UNM_BRDTYPE_P3_10G_CX4_LP:
1719 case UNM_BRDTYPE_P3_IMEZ:
1720 case UNM_BRDTYPE_P3_10G_SFP_PLUS:
1721 case UNM_BRDTYPE_P3_10G_XFP:
1722 case UNM_BRDTYPE_P3_10000_BASE_T:
1723 adapter->ahw.board_type = UNM_NIC_XGBE;
1724 break;
1725 case UNM_BRDTYPE_P3_REF_QG:
1726 case UNM_BRDTYPE_P3_4_GB:
1727 case UNM_BRDTYPE_P3_4_GB_MM:
1728 adapter->ahw.board_type = UNM_NIC_GBE;
1729 break;
1730 case UNM_BRDTYPE_P1_BD:
1731 case UNM_BRDTYPE_P1_SB:
1732 case UNM_BRDTYPE_P1_SMAX:
1733 case UNM_BRDTYPE_P1_SOCK:
1734 adapter->ahw.board_type = UNM_NIC_GBE;
1735 break;
1736 case UNM_BRDTYPE_P3_10G_TRP:
1737 if (adapter->portnum < 2)
1738 adapter->ahw.board_type = UNM_NIC_XGBE;
1739 else
1740 adapter->ahw.board_type = UNM_NIC_GBE;
1741 break;
1742 default:
1743 DPRINTF(1, (CE_WARN, "%s: Unknown(%x)\n", unm_nic_driver_name,
1744 boardinfo->board_type));
1745 break;
1748 return (rv);
1751 /* NIU access sections */
1754 unm_nic_macaddr_set(struct unm_adapter_s *adapter, __uint8_t *addr)
1756 int ret = 0, i, retry_count = 10;
1757 unsigned char mac_addr[MAX_ADDR_LEN];
1759 /* For P3, we should not set MAC in HW any more */
1760 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1761 return (0);
1763 switch (adapter->ahw.board_type) {
1764 case UNM_NIC_GBE:
1766 * Flaky Mac address registers on qgig require several writes.
1768 for (i = 0; i < retry_count; ++i) {
1769 if (unm_niu_macaddr_set(adapter, addr) != 0)
1770 return (-1);
1772 (void) unm_niu_macaddr_get(adapter,
1773 (unsigned char *)mac_addr);
1774 if (memcmp(mac_addr, addr, 6) == 0)
1775 return (0);
1777 cmn_err(CE_WARN, "%s: Flaky MAC addr registers\n",
1778 unm_nic_driver_name);
1779 break;
1781 case UNM_NIC_XGBE:
1782 ret = unm_niu_xg_macaddr_set(adapter, addr);
1783 break;
1785 default:
1786 cmn_err(CE_WARN, "\r\nUnknown board type encountered"
1787 " while setting the MAC address.\n");
1788 return (-1);
1790 return (ret);
1793 #define MTU_FUDGE_FACTOR 100
1795 unm_nic_set_mtu(struct unm_adapter_s *adapter, int new_mtu)
1797 long port = adapter->physical_port;
1798 int ret = 0;
1799 u32 port_mode = 0;
1801 if (adapter->ahw.revision_id >= NX_P3_A2)
1802 return (nx_fw_cmd_set_mtu(adapter, new_mtu));
1804 new_mtu += MTU_FUDGE_FACTOR; /* so that MAC accepts frames > MTU */
1805 switch (adapter->ahw.board_type) {
1806 case UNM_NIC_GBE:
1807 unm_nic_write_w0(adapter,
1808 UNM_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
1809 new_mtu);
1811 break;
1813 case UNM_NIC_XGBE:
1814 adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
1815 &port_mode, 4);
1816 if (port_mode == UNM_PORT_MODE_802_3_AP) {
1817 unm_nic_write_w0(adapter,
1818 UNM_NIU_AP_MAX_FRAME_SIZE(port), new_mtu);
1819 } else {
1820 if (adapter->physical_port == 0) {
1821 unm_nic_write_w0(adapter,
1822 UNM_NIU_XGE_MAX_FRAME_SIZE,
1823 new_mtu);
1824 } else {
1825 unm_nic_write_w0(adapter,
1826 UNM_NIU_XG1_MAX_FRAME_SIZE,
1827 new_mtu);
1830 break;
1832 default:
1833 cmn_err(CE_WARN, "%s: Unknown brdtype\n",
1834 unm_nic_driver_name);
1837 return (ret);
1841 unm_nic_set_promisc_mode(struct unm_adapter_s *adapter)
1843 int ret;
1845 if (adapter->promisc)
1846 return (0);
1848 switch (adapter->ahw.board_type) {
1849 case UNM_NIC_GBE:
1850 ret = unm_niu_set_promiscuous_mode(adapter,
1851 UNM_NIU_PROMISCOUS_MODE);
1852 break;
1854 case UNM_NIC_XGBE:
1855 ret = unm_niu_xg_set_promiscuous_mode(adapter,
1856 UNM_NIU_PROMISCOUS_MODE);
1857 break;
1859 default:
1860 cmn_err(CE_WARN, "%s: Unknown brdtype\n",
1861 unm_nic_driver_name);
1862 ret = -1;
1863 break;
1866 if (!ret)
1867 adapter->promisc = 1;
1869 return (ret);
1873 unm_nic_unset_promisc_mode(struct unm_adapter_s *adapter)
1875 int ret = 0;
1878 * P3 does not unset promiscous mode. Why?
1880 if (adapter->ahw.revision_id >= NX_P3_A2) {
1881 return (0);
1884 if (!adapter->promisc)
1885 return (0);
1887 switch (adapter->ahw.board_type) {
1888 case UNM_NIC_GBE:
1889 ret = unm_niu_set_promiscuous_mode(adapter,
1890 UNM_NIU_NON_PROMISCOUS_MODE);
1891 break;
1893 case UNM_NIC_XGBE:
1894 ret = unm_niu_xg_set_promiscuous_mode(adapter,
1895 UNM_NIU_NON_PROMISCOUS_MODE);
1896 break;
1898 default:
1899 cmn_err(CE_WARN, "%s: Unknown brdtype\n",
1900 unm_nic_driver_name);
1901 ret = -1;
1902 break;
1905 if (!ret)
1906 adapter->promisc = 0;
1908 return (ret);
1911 long
1912 unm_nic_phy_read(unm_adapter *adapter, long reg, __uint32_t *readval)
1914 long ret = 0;
1916 switch (adapter->ahw.board_type) {
1917 case UNM_NIC_GBE:
1918 ret = unm_niu_gbe_phy_read(adapter, reg, readval);
1919 break;
1921 case UNM_NIC_XGBE:
1922 DPRINTF(1, (CE_WARN,
1923 "%s: Function %s is not implemented for XG\n",
1924 unm_nic_driver_name, __FUNCTION__));
1925 break;
1927 default:
1928 DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
1929 unm_nic_driver_name));
1932 return (ret);
1935 long
1936 unm_nic_init_port(struct unm_adapter_s *adapter)
1938 long portnum = adapter->physical_port;
1939 long ret = 0;
1940 long reg = 0;
1941 u32 port_mode = 0;
1943 unm_nic_set_link_parameters(adapter);
1945 switch (adapter->ahw.board_type) {
1946 case UNM_NIC_GBE:
1947 ret = unm_niu_enable_gbe_port(adapter);
1948 break;
1950 case UNM_NIC_XGBE:
1951 adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
1952 &port_mode, 4);
1953 if (port_mode == UNM_PORT_MODE_802_3_AP) {
1954 ret = unm_niu_enable_gbe_port(adapter);
1955 } else {
1956 adapter->unm_crb_writelit_adapter(adapter,
1957 UNM_NIU_XGE_CONFIG_0 + (0x10000 * portnum), 0x5);
1958 UNM_CRB_READ_CHECK_ADAPTER(UNM_NIU_XGE_CONFIG_1 +
1959 (0x10000 * portnum), &reg, adapter);
1960 if (adapter->ahw.revision_id < NX_P3_A2)
1961 reg = (reg & ~0x2000UL);
1962 adapter->unm_crb_writelit_adapter(adapter,
1963 UNM_NIU_XGE_CONFIG_1 + (0x10000 * portnum), reg);
1965 break;
1967 default:
1968 DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
1969 unm_nic_driver_name));
1972 return (ret);
1975 void
1976 unm_nic_stop_port(struct unm_adapter_s *adapter)
1979 (void) mac_unregister(adapter->mach);
1981 switch (adapter->ahw.board_type) {
1982 case UNM_NIC_GBE:
1983 (void) unm_niu_disable_gbe_port(adapter);
1984 break;
1986 case UNM_NIC_XGBE:
1987 (void) unm_niu_disable_xg_port(adapter);
1988 break;
1990 default:
1991 DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
1992 unm_nic_driver_name));
1996 void
1997 unm_crb_write_adapter(unsigned long off, void *data,
1998 struct unm_adapter_s *adapter)
2000 (void) adapter->unm_nic_hw_write_wx(adapter, off, data, 4);
2004 unm_crb_read_adapter(unsigned long off, void *data,
2005 struct unm_adapter_s *adapter)
2007 return (adapter->unm_nic_hw_read_wx(adapter, off, data, 4));
2011 unm_crb_read_val_adapter(unsigned long off, struct unm_adapter_s *adapter)
2013 int data;
2015 adapter->unm_nic_hw_read_wx(adapter, off, &data, 4);
2016 return (data);
2019 void
2020 unm_nic_set_link_parameters(struct unm_adapter_s *adapter)
2022 unm_niu_phy_status_t status;
2023 uint16_t defval = (uint16_t)-1;
2024 unm_niu_control_t mode;
2025 u32 port_mode = 0;
2027 unm_nic_read_w0(adapter, UNM_NIU_MODE, (uint32_t *)&mode);
2028 if (mode.enable_ge) { // Gb 10/100/1000 Mbps mode
2029 adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
2030 &port_mode, 4);
2031 if (port_mode == UNM_PORT_MODE_802_3_AP) {
2032 adapter->link_speed = MBPS_1000;
2033 adapter->link_duplex = LINK_DUPLEX_FULL;
2034 } else {
2035 if (unm_nic_phy_read(adapter,
2036 UNM_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
2037 (unm_crbword_t *)&status) == 0) {
2038 if (status.link) {
2039 switch (status.speed) {
2040 case 0: adapter->link_speed = MBPS_10;
2041 break;
2042 case 1: adapter->link_speed = MBPS_100;
2043 break;
2044 case 2: adapter->link_speed = MBPS_1000;
2045 break;
2046 default:
2047 adapter->link_speed = defval;
2048 break;
2050 switch (status.duplex) {
2051 case 0: adapter->link_duplex = LINK_DUPLEX_HALF;
2052 break;
2053 case 1: adapter->link_duplex = LINK_DUPLEX_FULL;
2054 break;
2055 default:
2056 adapter->link_duplex = defval;
2057 break;
2059 } else {
2060 adapter->link_speed = defval;
2061 adapter->link_duplex = defval;
2063 } else {
2064 adapter->link_speed = defval;
2065 adapter->link_duplex = defval;
2071 void
2072 unm_nic_flash_print(struct unm_adapter_s *adapter)
2074 int valid = 1;
2075 unm_board_info_t *board_info = &(adapter->ahw.boardcfg);
2077 if (board_info->magic != UNM_BDINFO_MAGIC) {
2078 cmn_err(CE_WARN, "%s UNM Unknown board config, Read 0x%x "
2079 "expected as 0x%x\n", unm_nic_driver_name,
2080 board_info->magic, UNM_BDINFO_MAGIC);
2081 valid = 0;
2083 if (board_info->header_version != UNM_BDINFO_VERSION) {
2084 cmn_err(CE_WARN, "%s UNM Unknown board config version."
2085 " Read %x, expected %x\n", unm_nic_driver_name,
2086 board_info->header_version, UNM_BDINFO_VERSION);
2087 valid = 0;
2089 if (valid) {
2090 unm_user_info_t user_info;
2091 int i;
2092 int addr = USER_START;
2093 int *ptr32;
2095 ptr32 = (int *)&user_info;
2096 for (i = 0; i < sizeof (unm_user_info_t) / sizeof (uint32_t);
2097 i++) {
2098 if (rom_fast_read(adapter, addr, ptr32) == -1) {
2099 cmn_err(CE_WARN,
2100 "%s: ERROR reading %s board userarea.\n",
2101 unm_nic_driver_name, unm_nic_driver_name);
2102 return;
2104 ptr32++;
2105 addr += sizeof (uint32_t);
2107 if (verbmsg != 0) {
2108 char *brd_name;
2109 GET_BRD_NAME_BY_TYPE(board_info->board_type, brd_name);
2110 cmn_err(CE_NOTE, "%s %s Board S/N %s Chip id 0x%x\n",
2111 unm_nic_driver_name, brd_name, user_info.serial_num,
2112 board_info->chip_id);
2117 static int
2118 nx_nic_send_cmd_descs(unm_adapter *adapter, cmdDescType0_t *cmd_desc_arr,
2119 int nr_elements)
2121 struct unm_cmd_buffer *pbuf;
2122 unsigned int i = 0, producer;
2125 * We need to check if space is available.
2127 UNM_SPIN_LOCK(&adapter->tx_lock);
2128 producer = adapter->cmdProducer;
2130 do {
2131 pbuf = &adapter->cmd_buf_arr[producer];
2132 pbuf->head = pbuf->tail = NULL;
2133 pbuf->msg = NULL;
2134 (void) memcpy(&adapter->ahw.cmdDescHead[producer],
2135 &cmd_desc_arr[i], sizeof (cmdDescType0_t));
2136 unm_desc_dma_sync(adapter->ahw.cmd_desc_dma_handle, producer,
2137 1, adapter->MaxTxDescCount, sizeof (cmdDescType0_t),
2138 DDI_DMA_SYNC_FORDEV);
2139 producer = get_next_index(producer, adapter->MaxTxDescCount);
2140 i++;
2141 } while (i != nr_elements);
2143 adapter->cmdProducer = adapter->ahw.cmdProducer = producer;
2144 adapter->freecmds -= i;
2146 unm_nic_update_cmd_producer(adapter, producer);
2148 UNM_SPIN_UNLOCK(&adapter->tx_lock);
2149 return (0);
2152 typedef struct {
2153 u64 qhdr, req_hdr, words[6];
2154 } nx_nic_req_t;
2156 typedef struct {
2157 u8 op, tag, mac_addr[6];
2158 } nx_mac_req_t;
2160 static void
2161 nx_p3_sre_macaddr_change(unm_adapter *adapter, u8 *addr, u8 op)
2163 nx_nic_req_t req;
2164 nx_mac_req_t mac_req;
2165 int rv;
2167 (void) memset(&req, 0, sizeof (nx_nic_req_t));
2168 req.qhdr |= (NX_NIC_REQUEST << 23);
2169 req.req_hdr |= NX_MAC_EVENT;
2170 req.req_hdr |= ((u64)adapter->portnum << 16);
2171 mac_req.op = op;
2172 (void) memcpy(&mac_req.mac_addr, addr, 6);
2173 req.words[0] = HOST_TO_LE_64(*(u64 *)(uintptr_t)&mac_req);
2175 rv = nx_nic_send_cmd_descs(adapter, (cmdDescType0_t *)&req, 1);
2176 if (rv != 0)
2177 cmn_err(CE_WARN, "%s%d: Could not send mac update\n",
2178 adapter->name, adapter->instance);
2181 static int
2182 nx_p3_nic_set_promisc(unm_adapter *adapter, u32 mode)
2184 nx_nic_req_t req;
2186 (void) memset(&req, 0, sizeof (nx_nic_req_t));
2188 req.qhdr |= (NX_HOST_REQUEST << 23);
2189 req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE;
2190 req.req_hdr |= ((u64)adapter->portnum << 16);
2191 req.words[0] = HOST_TO_LE_64(mode);
2193 return (nx_nic_send_cmd_descs(adapter, (cmdDescType0_t *)&req, 1));
2197 * Currently only invoked at interface initialization time
2199 void
2200 nx_p3_nic_set_multi(unm_adapter *adapter)
2202 u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2204 if (nx_p3_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL))
2205 cmn_err(CE_WARN, "Could not set promisc mode\n");
2207 nx_p3_sre_macaddr_change(adapter, adapter->mac_addr, NETXEN_MAC_ADD);
2208 nx_p3_sre_macaddr_change(adapter, bcast_addr, NETXEN_MAC_ADD);