blob: 33444a20e4f72cae37a27e10659a8bf89ec2c687 [file] [log] [blame]
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001/*
Dhananjay Phadke5d242f12009-02-25 15:57:56 +00002 * Copyright (C) 2003 - 2009 NetXen, Inc.
Amit S. Kale3d396eb2006-10-21 15:33:03 -04003 * All rights reserved.
Amit S. Kale80922fb2006-12-04 09:18:00 -08004 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -04005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
Amit S. Kalecb8011a2006-11-29 09:00:10 -08009 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040010 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Amit S. Kalecb8011a2006-11-29 09:00:10 -080014 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040015 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA 02111-1307, USA.
Amit S. Kale80922fb2006-12-04 09:18:00 -080019 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040020 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
Amit S. Kale80922fb2006-12-04 09:18:00 -080022 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040023 * Contact Information:
24 * info@netxen.com
Dhananjay Phadke5d242f12009-02-25 15:57:56 +000025 * NetXen Inc,
26 * 18922 Forge Drive
27 * Cupertino, CA 95014-0701
Amit S. Kale3d396eb2006-10-21 15:33:03 -040028 *
29 */
30
31#include "netxen_nic.h"
32#include "netxen_nic_hw.h"
33#include "netxen_nic_phan_reg.h"
34
Dhananjay Phadkeba599d42009-02-24 16:38:22 -080035#include <linux/firmware.h>
Arnaldo Carvalho de Meloc9bdd4b2007-03-12 20:09:15 -030036#include <net/ip.h>
37
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -070038#define MASK(n) ((1ULL<<(n))-1)
39#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
40#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
41#define MS_WIN(addr) (addr & 0x0ffc0000)
42
43#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
44
45#define CRB_BLK(off) ((off >> 20) & 0x3f)
46#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
47#define CRB_WINDOW_2M (0x130060)
48#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
49#define CRB_INDIRECT_2M (0x1e0000UL)
50
Dhananjay Phadkee98e3352009-04-07 22:50:38 +000051#ifndef readq
52static inline u64 readq(void __iomem *addr)
53{
54 return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
55}
56#endif
57
58#ifndef writeq
59static inline void writeq(u64 val, void __iomem *addr)
60{
61 writel(((u32) (val)), (addr));
62 writel(((u32) (val >> 32)), (addr + 4));
63}
64#endif
65
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -070066#define CRB_WIN_LOCK_TIMEOUT 100000000
67static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
68 {{{0, 0, 0, 0} } }, /* 0: PCI */
69 {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
70 {1, 0x0110000, 0x0120000, 0x130000},
71 {1, 0x0120000, 0x0122000, 0x124000},
72 {1, 0x0130000, 0x0132000, 0x126000},
73 {1, 0x0140000, 0x0142000, 0x128000},
74 {1, 0x0150000, 0x0152000, 0x12a000},
75 {1, 0x0160000, 0x0170000, 0x110000},
76 {1, 0x0170000, 0x0172000, 0x12e000},
77 {0, 0x0000000, 0x0000000, 0x000000},
78 {0, 0x0000000, 0x0000000, 0x000000},
79 {0, 0x0000000, 0x0000000, 0x000000},
80 {0, 0x0000000, 0x0000000, 0x000000},
81 {0, 0x0000000, 0x0000000, 0x000000},
82 {0, 0x0000000, 0x0000000, 0x000000},
83 {1, 0x01e0000, 0x01e0800, 0x122000},
84 {0, 0x0000000, 0x0000000, 0x000000} } },
85 {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
86 {{{0, 0, 0, 0} } }, /* 3: */
87 {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
88 {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */
89 {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */
90 {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */
91 {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
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 {0, 0x0000000, 0x0000000, 0x000000},
98 {0, 0x0000000, 0x0000000, 0x000000},
99 {0, 0x0000000, 0x0000000, 0x000000},
100 {0, 0x0000000, 0x0000000, 0x000000},
101 {0, 0x0000000, 0x0000000, 0x000000},
102 {0, 0x0000000, 0x0000000, 0x000000},
103 {0, 0x0000000, 0x0000000, 0x000000},
104 {0, 0x0000000, 0x0000000, 0x000000},
105 {0, 0x0000000, 0x0000000, 0x000000},
106 {1, 0x08f0000, 0x08f2000, 0x172000} } },
107 {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/
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 {0, 0x0000000, 0x0000000, 0x000000},
121 {0, 0x0000000, 0x0000000, 0x000000},
122 {1, 0x09f0000, 0x09f2000, 0x176000} } },
123 {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/
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 {0, 0x0000000, 0x0000000, 0x000000},
137 {0, 0x0000000, 0x0000000, 0x000000},
138 {1, 0x0af0000, 0x0af2000, 0x17a000} } },
139 {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/
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 {0, 0x0000000, 0x0000000, 0x000000},
153 {0, 0x0000000, 0x0000000, 0x000000},
154 {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
155 {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
156 {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
157 {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
158 {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
159 {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
160 {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
161 {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
162 {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
163 {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
164 {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
165 {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
166 {{{0, 0, 0, 0} } }, /* 23: */
167 {{{0, 0, 0, 0} } }, /* 24: */
168 {{{0, 0, 0, 0} } }, /* 25: */
169 {{{0, 0, 0, 0} } }, /* 26: */
170 {{{0, 0, 0, 0} } }, /* 27: */
171 {{{0, 0, 0, 0} } }, /* 28: */
172 {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
173 {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
174 {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
175 {{{0} } }, /* 32: PCI */
176 {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
177 {1, 0x2110000, 0x2120000, 0x130000},
178 {1, 0x2120000, 0x2122000, 0x124000},
179 {1, 0x2130000, 0x2132000, 0x126000},
180 {1, 0x2140000, 0x2142000, 0x128000},
181 {1, 0x2150000, 0x2152000, 0x12a000},
182 {1, 0x2160000, 0x2170000, 0x110000},
183 {1, 0x2170000, 0x2172000, 0x12e000},
184 {0, 0x0000000, 0x0000000, 0x000000},
185 {0, 0x0000000, 0x0000000, 0x000000},
186 {0, 0x0000000, 0x0000000, 0x000000},
187 {0, 0x0000000, 0x0000000, 0x000000},
188 {0, 0x0000000, 0x0000000, 0x000000},
189 {0, 0x0000000, 0x0000000, 0x000000},
190 {0, 0x0000000, 0x0000000, 0x000000},
191 {0, 0x0000000, 0x0000000, 0x000000} } },
192 {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
193 {{{0} } }, /* 35: */
194 {{{0} } }, /* 36: */
195 {{{0} } }, /* 37: */
196 {{{0} } }, /* 38: */
197 {{{0} } }, /* 39: */
198 {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
199 {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
200 {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
201 {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
202 {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
203 {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
204 {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
205 {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
206 {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
207 {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
208 {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
209 {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
210 {{{0} } }, /* 52: */
211 {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
212 {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
213 {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
214 {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
215 {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
216 {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
217 {{{0} } }, /* 59: I2C0 */
218 {{{0} } }, /* 60: I2C1 */
219 {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
220 {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
221 {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */
222};
223
224/*
225 * top 12 bits of crb internal address (hub, agent)
226 */
227static unsigned crb_hub_agt[64] =
228{
229 0,
230 NETXEN_HW_CRB_HUB_AGT_ADR_PS,
231 NETXEN_HW_CRB_HUB_AGT_ADR_MN,
232 NETXEN_HW_CRB_HUB_AGT_ADR_MS,
233 0,
234 NETXEN_HW_CRB_HUB_AGT_ADR_SRE,
235 NETXEN_HW_CRB_HUB_AGT_ADR_NIU,
236 NETXEN_HW_CRB_HUB_AGT_ADR_QMN,
237 NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,
238 NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,
239 NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,
240 NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,
241 NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
242 NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
243 NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
244 NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,
245 NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
246 NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,
247 NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,
248 NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,
249 NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,
250 NETXEN_HW_CRB_HUB_AGT_ADR_PGND,
251 NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,
252 NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,
253 NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,
254 NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,
255 NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,
256 0,
257 NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,
258 NETXEN_HW_CRB_HUB_AGT_ADR_SN,
259 0,
260 NETXEN_HW_CRB_HUB_AGT_ADR_EG,
261 0,
262 NETXEN_HW_CRB_HUB_AGT_ADR_PS,
263 NETXEN_HW_CRB_HUB_AGT_ADR_CAM,
264 0,
265 0,
266 0,
267 0,
268 0,
269 NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
270 0,
271 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,
272 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,
273 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,
274 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,
275 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,
276 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,
277 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,
278 NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
279 NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
280 NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
281 0,
282 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,
283 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,
284 NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,
285 NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,
286 0,
287 NETXEN_HW_CRB_HUB_AGT_ADR_SMB,
288 NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,
289 NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,
290 0,
291 NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,
292 0,
293};
294
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400295/* PCI Windowing for DDR regions. */
296
297#define ADDR_IN_RANGE(addr, low, high) \
298 (((addr) <= (high)) && ((addr) >= (low)))
299
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700300#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400301
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800302#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
303#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
304#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
305#define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL
306
307#define NETXEN_NIC_WINDOW_MARGIN 0x100000
308
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400309int netxen_nic_set_mac(struct net_device *netdev, void *p)
310{
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700311 struct netxen_adapter *adapter = netdev_priv(netdev);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400312 struct sockaddr *addr = p;
313
314 if (netif_running(netdev))
315 return -EBUSY;
316
317 if (!is_valid_ether_addr(addr->sa_data))
318 return -EADDRNOTAVAIL;
319
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400320 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
321
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700322 /* For P3, MAC addr is not set in NIU */
323 if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
324 if (adapter->macaddr_set)
325 adapter->macaddr_set(adapter, addr->sa_data);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400326
327 return 0;
328}
329
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700330#define NETXEN_UNICAST_ADDR(port, index) \
331 (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
332#define NETXEN_MCAST_ADDR(port, index) \
333 (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
334#define MAC_HI(addr) \
335 ((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
336#define MAC_LO(addr) \
337 ((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
338
339static int
340netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
341{
342 u32 val = 0;
343 u16 port = adapter->physical_port;
344 u8 *addr = adapter->netdev->dev_addr;
345
346 if (adapter->mc_enabled)
347 return 0;
348
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700349 adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700350 val |= (1UL << (28+port));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700351 adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700352
353 /* add broadcast addr to filter */
354 val = 0xffffff;
355 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
356 netxen_crb_writelit_adapter(adapter,
357 NETXEN_UNICAST_ADDR(port, 0)+4, val);
358
359 /* add station addr to filter */
360 val = MAC_HI(addr);
361 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
362 val = MAC_LO(addr);
363 netxen_crb_writelit_adapter(adapter,
364 NETXEN_UNICAST_ADDR(port, 1)+4, val);
365
366 adapter->mc_enabled = 1;
367 return 0;
368}
369
370static int
371netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
372{
373 u32 val = 0;
374 u16 port = adapter->physical_port;
375 u8 *addr = adapter->netdev->dev_addr;
376
377 if (!adapter->mc_enabled)
378 return 0;
379
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700380 adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700381 val &= ~(1UL << (28+port));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700382 adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700383
384 val = MAC_HI(addr);
385 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
386 val = MAC_LO(addr);
387 netxen_crb_writelit_adapter(adapter,
388 NETXEN_UNICAST_ADDR(port, 0)+4, val);
389
390 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
391 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
392
393 adapter->mc_enabled = 0;
394 return 0;
395}
396
397static int
398netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
399 int index, u8 *addr)
400{
401 u32 hi = 0, lo = 0;
402 u16 port = adapter->physical_port;
403
404 lo = MAC_LO(addr);
405 hi = MAC_HI(addr);
406
407 netxen_crb_writelit_adapter(adapter,
408 NETXEN_MCAST_ADDR(port, index), hi);
409 netxen_crb_writelit_adapter(adapter,
410 NETXEN_MCAST_ADDR(port, index)+4, lo);
411
412 return 0;
413}
414
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700415void netxen_p2_nic_set_multi(struct net_device *netdev)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400416{
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700417 struct netxen_adapter *adapter = netdev_priv(netdev);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400418 struct dev_mc_list *mc_ptr;
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700419 u8 null_addr[6];
420 int index = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400421
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700422 memset(null_addr, 0, 6);
423
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400424 if (netdev->flags & IFF_PROMISC) {
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700425
426 adapter->set_promisc(adapter,
427 NETXEN_NIU_PROMISC_MODE);
428
429 /* Full promiscuous mode */
430 netxen_nic_disable_mcast_filter(adapter);
431
432 return;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400433 }
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700434
435 if (netdev->mc_count == 0) {
436 adapter->set_promisc(adapter,
437 NETXEN_NIU_NON_PROMISC_MODE);
438 netxen_nic_disable_mcast_filter(adapter);
439 return;
440 }
441
442 adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
443 if (netdev->flags & IFF_ALLMULTI ||
444 netdev->mc_count > adapter->max_mc_count) {
445 netxen_nic_disable_mcast_filter(adapter);
446 return;
447 }
448
449 netxen_nic_enable_mcast_filter(adapter);
450
451 for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
452 netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
453
454 if (index != netdev->mc_count)
455 printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
456 netxen_nic_driver_name, netdev->name);
457
458 /* Clear out remaining addresses */
459 for (; index < adapter->max_mc_count; index++)
460 netxen_nic_set_mcast_addr(adapter, index, null_addr);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400461}
462
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700463static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
464 u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
465{
466 nx_mac_list_t *cur, *prev;
467
468 /* if in del_list, move it to adapter->mac_list */
469 for (cur = *del_list, prev = NULL; cur;) {
470 if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
471 if (prev == NULL)
472 *del_list = cur->next;
473 else
474 prev->next = cur->next;
475 cur->next = adapter->mac_list;
476 adapter->mac_list = cur;
477 return 0;
478 }
479 prev = cur;
480 cur = cur->next;
481 }
482
483 /* make sure to add each mac address only once */
484 for (cur = adapter->mac_list; cur; cur = cur->next) {
485 if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
486 return 0;
487 }
488 /* not in del_list, create new entry and add to add_list */
489 cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
490 if (cur == NULL) {
491 printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
492 "not work properly from now.\n", __func__);
493 return -1;
494 }
495
496 memcpy(cur->mac_addr, addr, ETH_ALEN);
497 cur->next = *add_list;
498 *add_list = cur;
499 return 0;
500}
501
502static int
503netxen_send_cmd_descs(struct netxen_adapter *adapter,
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000504 struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700505{
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000506 u32 i, producer, consumer;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700507 struct netxen_cmd_buffer *pbuf;
508 struct cmd_desc_type0 *cmd_desc;
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000509 struct nx_host_tx_ring *tx_ring;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700510
511 i = 0;
512
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000513 tx_ring = &adapter->tx_ring;
Dhananjay Phadke03e678e2009-01-14 20:49:43 -0800514 netif_tx_lock_bh(adapter->netdev);
515
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000516 producer = tx_ring->producer;
517 consumer = tx_ring->sw_consumer;
518
519 if (nr_desc > find_diff_among(producer, consumer, tx_ring->num_desc)) {
520 netif_tx_unlock_bh(adapter->netdev);
521 return -EBUSY;
522 }
523
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700524 do {
525 cmd_desc = &cmd_desc_arr[i];
526
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000527 pbuf = &tx_ring->cmd_buf_arr[producer];
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700528 pbuf->skb = NULL;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700529 pbuf->frag_count = 0;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700530
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000531 memcpy(&tx_ring->desc_head[producer],
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700532 &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
533
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000534 producer = get_next_index(producer, tx_ring->num_desc);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700535 i++;
536
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000537 } while (i != nr_desc);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700538
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000539 tx_ring->producer = producer;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700540
Dhananjay Phadked877f1e2009-04-07 22:50:40 +0000541 netxen_nic_update_cmd_producer(adapter, tx_ring, producer);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700542
Dhananjay Phadke03e678e2009-01-14 20:49:43 -0800543 netif_tx_unlock_bh(adapter->netdev);
544
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700545 return 0;
546}
547
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700548static int nx_p3_sre_macaddr_change(struct net_device *dev,
549 u8 *addr, unsigned op)
550{
Wang Chen4cf16532008-11-12 23:38:14 -0800551 struct netxen_adapter *adapter = netdev_priv(dev);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700552 nx_nic_req_t req;
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800553 nx_mac_req_t *mac_req;
554 u64 word;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700555 int rv;
556
557 memset(&req, 0, sizeof(nx_nic_req_t));
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800558 req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
559
560 word = NX_MAC_EVENT | ((u64)adapter->portnum << 16);
561 req.req_hdr = cpu_to_le64(word);
562
563 mac_req = (nx_mac_req_t *)&req.words[0];
564 mac_req->op = op;
565 memcpy(mac_req->mac_addr, addr, 6);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700566
567 rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
568 if (rv != 0) {
569 printk(KERN_ERR "ERROR. Could not send mac update\n");
570 return rv;
571 }
572
573 return 0;
574}
575
576void netxen_p3_nic_set_multi(struct net_device *netdev)
577{
578 struct netxen_adapter *adapter = netdev_priv(netdev);
579 nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
580 struct dev_mc_list *mc_ptr;
581 u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700582 u32 mode = VPORT_MISS_MODE_DROP;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700583
584 del_list = adapter->mac_list;
585 adapter->mac_list = NULL;
586
587 nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700588 nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
589
590 if (netdev->flags & IFF_PROMISC) {
591 mode = VPORT_MISS_MODE_ACCEPT_ALL;
592 goto send_fw_cmd;
593 }
594
595 if ((netdev->flags & IFF_ALLMULTI) ||
596 (netdev->mc_count > adapter->max_mc_count)) {
597 mode = VPORT_MISS_MODE_ACCEPT_MULTI;
598 goto send_fw_cmd;
599 }
600
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700601 if (netdev->mc_count > 0) {
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700602 for (mc_ptr = netdev->mc_list; mc_ptr;
603 mc_ptr = mc_ptr->next) {
604 nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
605 &add_list, &del_list);
606 }
607 }
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700608
609send_fw_cmd:
610 adapter->set_promisc(adapter, mode);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700611 for (cur = del_list; cur;) {
612 nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
613 next = cur->next;
614 kfree(cur);
615 cur = next;
616 }
617 for (cur = add_list; cur;) {
618 nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
619 next = cur->next;
620 cur->next = adapter->mac_list;
621 adapter->mac_list = cur;
622 cur = next;
623 }
624}
625
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700626int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
627{
628 nx_nic_req_t req;
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800629 u64 word;
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700630
631 memset(&req, 0, sizeof(nx_nic_req_t));
632
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800633 req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
634
635 word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE |
636 ((u64)adapter->portnum << 16);
637 req.req_hdr = cpu_to_le64(word);
638
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700639 req.words[0] = cpu_to_le64(mode);
640
641 return netxen_send_cmd_descs(adapter,
642 (struct cmd_desc_type0 *)&req, 1);
643}
644
Dhananjay Phadke06e9d9f2009-01-14 20:49:22 -0800645void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
646{
647 nx_mac_list_t *cur, *next;
648
649 cur = adapter->mac_list;
650
651 while (cur) {
652 next = cur->next;
653 kfree(cur);
654 cur = next;
655 }
656}
657
Dhananjay Phadkecd1f8162008-07-21 19:44:09 -0700658#define NETXEN_CONFIG_INTR_COALESCE 3
659
660/*
661 * Send the interrupt coalescing parameter set by ethtool to the card.
662 */
663int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
664{
665 nx_nic_req_t req;
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800666 u64 word;
Dhananjay Phadkecd1f8162008-07-21 19:44:09 -0700667 int rv;
668
669 memset(&req, 0, sizeof(nx_nic_req_t));
670
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800671 req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
672
673 word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16);
674 req.req_hdr = cpu_to_le64(word);
Dhananjay Phadkecd1f8162008-07-21 19:44:09 -0700675
676 memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
677
678 rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
679 if (rv != 0) {
680 printk(KERN_ERR "ERROR. Could not send "
681 "interrupt coalescing parameters\n");
682 }
683
684 return rv;
685}
686
Dhananjay Phadked8b100c2009-03-13 14:52:05 +0000687#define RSS_HASHTYPE_IP_TCP 0x3
688
689int netxen_config_rss(struct netxen_adapter *adapter, int enable)
690{
691 nx_nic_req_t req;
692 u64 word;
693 int i, rv;
694
695 u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
696 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
697 0x255b0ec26d5a56daULL };
698
699
700 memset(&req, 0, sizeof(nx_nic_req_t));
701 req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
702
703 word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16);
704 req.req_hdr = cpu_to_le64(word);
705
706 /*
707 * RSS request:
708 * bits 3-0: hash_method
709 * 5-4: hash_type_ipv4
710 * 7-6: hash_type_ipv6
711 * 8: enable
712 * 9: use indirection table
713 * 47-10: reserved
714 * 63-48: indirection table mask
715 */
716 word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
717 ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
718 ((u64)(enable & 0x1) << 8) |
719 ((0x7ULL) << 48);
720 req.words[0] = cpu_to_le64(word);
721 for (i = 0; i < 5; i++)
722 req.words[i+1] = cpu_to_le64(key[i]);
723
724
725 rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
726 if (rv != 0) {
727 printk(KERN_ERR "%s: could not configure RSS\n",
728 adapter->netdev->name);
729 }
730
731 return rv;
732}
733
Dhananjay Phadke3bf26ce2009-04-07 22:50:42 +0000734int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
735{
736 nx_nic_req_t req;
737 u64 word;
738 int rv;
739
740 memset(&req, 0, sizeof(nx_nic_req_t));
741 req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
742
743 word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
744 req.req_hdr = cpu_to_le64(word);
745 req.words[0] = cpu_to_le64(enable);
746
747 rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
748 if (rv != 0) {
749 printk(KERN_ERR "%s: could not configure link notification\n",
750 adapter->netdev->name);
751 }
752
753 return rv;
754}
755
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400756/*
757 * netxen_nic_change_mtu - Change the Maximum Transfer Unit
758 * @returns 0 on success, negative on failure
759 */
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700760
761#define MTU_FUDGE_FACTOR 100
762
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400763int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
764{
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700765 struct netxen_adapter *adapter = netdev_priv(netdev);
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700766 int max_mtu;
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700767 int rc = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400768
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700769 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
770 max_mtu = P3_MAX_MTU;
771 else
772 max_mtu = P2_MAX_MTU;
773
774 if (mtu > max_mtu) {
775 printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
776 netdev->name, max_mtu);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400777 return -EINVAL;
778 }
779
Amit S. Kale80922fb2006-12-04 09:18:00 -0800780 if (adapter->set_mtu)
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700781 rc = adapter->set_mtu(adapter, mtu);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400782
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700783 if (!rc)
784 netdev->mtu = mtu;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700785
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700786 return rc;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400787}
788
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400789static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
Al Virof305f782007-12-22 19:44:00 +0000790 int size, __le32 * buf)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400791{
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +0000792 int i, v, addr;
Al Virof305f782007-12-22 19:44:00 +0000793 __le32 *ptr32;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400794
795 addr = base;
796 ptr32 = buf;
797 for (i = 0; i < size / sizeof(u32); i++) {
Al Virof305f782007-12-22 19:44:00 +0000798 if (netxen_rom_fast_read(adapter, addr, &v) == -1)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400799 return -1;
Al Virof305f782007-12-22 19:44:00 +0000800 *ptr32 = cpu_to_le32(v);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400801 ptr32++;
802 addr += sizeof(u32);
803 }
804 if ((char *)buf + size > (char *)ptr32) {
Al Virof305f782007-12-22 19:44:00 +0000805 __le32 local;
806 if (netxen_rom_fast_read(adapter, addr, &v) == -1)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400807 return -1;
Al Virof305f782007-12-22 19:44:00 +0000808 local = cpu_to_le32(v);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400809 memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
810 }
811
812 return 0;
813}
814
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700815int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400816{
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700817 __le32 *pmac = (__le32 *) mac;
818 u32 offset;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400819
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700820 offset = NETXEN_USER_START +
821 offsetof(struct netxen_new_user_info, mac_addr) +
822 adapter->portnum * sizeof(u64);
823
824 if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400825 return -1;
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700826
Al Virof305f782007-12-22 19:44:00 +0000827 if (*mac == cpu_to_le64(~0ULL)) {
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700828
829 offset = NETXEN_USER_START_OLD +
830 offsetof(struct netxen_user_old_info, mac_addr) +
831 adapter->portnum * sizeof(u64);
832
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400833 if (netxen_get_flash_block(adapter,
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700834 offset, sizeof(u64), pmac) == -1)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400835 return -1;
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700836
Al Virof305f782007-12-22 19:44:00 +0000837 if (*mac == cpu_to_le64(~0ULL))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400838 return -1;
839 }
840 return 0;
841}
842
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700843int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
844{
845 uint32_t crbaddr, mac_hi, mac_lo;
846 int pci_func = adapter->ahw.pci_func;
847
848 crbaddr = CRB_MAC_BLOCK_START +
849 (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
850
851 adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4);
852 adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4);
853
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700854 if (pci_func & 1)
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800855 *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700856 else
Dhananjay Phadke2edbb452009-01-14 20:47:30 -0800857 *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32));
Dhananjay Phadke9dc28ef2008-08-08 00:08:39 -0700858
859 return 0;
860}
861
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700862#define CRB_WIN_LOCK_TIMEOUT 100000000
863
864static int crb_win_lock(struct netxen_adapter *adapter)
865{
866 int done = 0, timeout = 0;
867
868 while (!done) {
869 /* acquire semaphore3 from PCI HW block */
870 adapter->hw_read_wx(adapter,
871 NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
872 if (done == 1)
873 break;
874 if (timeout >= CRB_WIN_LOCK_TIMEOUT)
875 return -1;
876 timeout++;
877 udelay(1);
878 }
879 netxen_crb_writelit_adapter(adapter,
880 NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
881 return 0;
882}
883
884static void crb_win_unlock(struct netxen_adapter *adapter)
885{
886 int val;
887
888 adapter->hw_read_wx(adapter,
889 NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
890}
891
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400892/*
893 * Changes the CRB window to the specified window.
894 */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700895void
896netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400897{
898 void __iomem *offset;
899 u32 tmp;
900 int count = 0;
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -0700901 uint8_t func = adapter->ahw.pci_func;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400902
903 if (adapter->curr_window == wndw)
904 return;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400905 /*
906 * Move the CRB window.
907 * We need to write to the "direct access" region of PCI
908 * to avoid a race condition where the window register has
909 * not been successfully written across CRB before the target
910 * register address is received by PCI. The direct region bypasses
911 * the CRB bus.
912 */
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -0700913 offset = PCI_OFFSET_SECOND_RANGE(adapter,
914 NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400915
916 if (wndw & 0x1)
917 wndw = NETXEN_WINDOW_ONE;
918
919 writel(wndw, offset);
920
921 /* MUST make sure window is set before we forge on... */
922 while ((tmp = readl(offset)) != wndw) {
923 printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
924 "registered properly: 0x%08x.\n",
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700925 netxen_nic_driver_name, __func__, tmp);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400926 mdelay(1);
927 if (count >= 10)
928 break;
929 count++;
930 }
931
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700932 if (wndw == NETXEN_WINDOW_ONE)
933 adapter->curr_window = 1;
934 else
935 adapter->curr_window = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400936}
937
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700938/*
939 * Return -1 if off is not valid,
940 * 1 if window access is needed. 'off' is set to offset from
941 * CRB space in 128M pci map
942 * 0 if no window access is needed. 'off' is set to 2M addr
943 * In: 'off' is offset from base in 128M pci map
944 */
945static int
946netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
947 ulong *off, int len)
948{
949 unsigned long end = *off + len;
950 crb_128M_2M_sub_block_map_t *m;
951
952
953 if (*off >= NETXEN_CRB_MAX)
954 return -1;
955
956 if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
957 *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
958 (ulong)adapter->ahw.pci_base0;
959 return 0;
960 }
961
962 if (*off < NETXEN_PCI_CRBSPACE)
963 return -1;
964
965 *off -= NETXEN_PCI_CRBSPACE;
966 end = *off + len;
967
968 /*
969 * Try direct map
970 */
971 m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
972
973 if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
974 *off = *off + m->start_2M - m->start_128M +
975 (ulong)adapter->ahw.pci_base0;
976 return 0;
977 }
978
979 /*
980 * Not in direct map, use crb window
981 */
982 return 1;
983}
984
985/*
986 * In: 'off' is offset from CRB space in 128M pci map
987 * Out: 'off' is 2M pci map addr
988 * side effect: lock crb window
989 */
990static void
991netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
992{
993 u32 win_read;
994
995 adapter->crb_win = CRB_HI(*off);
Dhananjay Phadked8313ce2009-02-17 20:26:44 -0800996 writel(adapter->crb_win, (adapter->ahw.pci_base0 + CRB_WINDOW_2M));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700997 /*
998 * Read back value to make sure write has gone through before trying
999 * to use it.
1000 */
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001001 win_read = readl(adapter->ahw.pci_base0 + CRB_WINDOW_2M);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001002 if (win_read != adapter->crb_win) {
1003 printk(KERN_ERR "%s: Written crbwin (0x%x) != "
1004 "Read crbwin (0x%x), off=0x%lx\n",
1005 __func__, adapter->crb_win, win_read, *off);
1006 }
1007 *off = (*off & MASK(16)) + CRB_INDIRECT_2M +
1008 (ulong)adapter->ahw.pci_base0;
1009}
1010
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001011static int
1012netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname,
1013 const struct firmware *fw)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001014{
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001015 u64 *ptr64;
1016 u32 i, flashaddr, size;
1017 struct pci_dev *pdev = adapter->pdev;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001018
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001019 if (fw)
1020 dev_info(&pdev->dev, "loading firmware from file %s\n", fwname);
1021 else
1022 dev_info(&pdev->dev, "loading firmware from flash\n");
Dhananjay Phadke29566402008-07-21 19:44:04 -07001023
1024 if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
1025 adapter->pci_write_normalize(adapter,
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001026 NETXEN_ROMUSB_GLB_CAS_RST, 1);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001027
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001028 if (fw) {
1029 __le64 data;
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +05301030
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001031 size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;
1032
1033 ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
1034 flashaddr = NETXEN_BOOTLD_START;
1035
1036 for (i = 0; i < size; i++) {
1037 data = cpu_to_le64(ptr64[i]);
1038 adapter->pci_mem_write(adapter, flashaddr, &data, 8);
1039 flashaddr += 8;
1040 }
1041
1042 size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
1043 size = (__force u32)cpu_to_le32(size) / 8;
1044
1045 ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
1046 flashaddr = NETXEN_IMAGE_START;
1047
1048 for (i = 0; i < size; i++) {
1049 data = cpu_to_le64(ptr64[i]);
1050
1051 if (adapter->pci_mem_write(adapter,
1052 flashaddr, &data, 8))
1053 return -EIO;
1054
1055 flashaddr += 8;
1056 }
1057 } else {
1058 u32 data;
1059
1060 size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
1061 flashaddr = NETXEN_BOOTLD_START;
1062
1063 for (i = 0; i < size; i++) {
1064 if (netxen_rom_fast_read(adapter,
1065 flashaddr, (int *)&data) != 0)
1066 return -EIO;
1067
1068 if (adapter->pci_mem_write(adapter,
1069 flashaddr, &data, 4))
1070 return -EIO;
1071
1072 flashaddr += 4;
1073 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001074 }
Dhananjay Phadke29566402008-07-21 19:44:04 -07001075 msleep(1);
1076
1077 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1078 adapter->pci_write_normalize(adapter,
1079 NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
1080 else {
1081 adapter->pci_write_normalize(adapter,
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001082 NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
Dhananjay Phadke29566402008-07-21 19:44:04 -07001083 adapter->pci_write_normalize(adapter,
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001084 NETXEN_ROMUSB_GLB_CAS_RST, 0);
Dhananjay Phadke29566402008-07-21 19:44:04 -07001085 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001086
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +05301087 return 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001088}
1089
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001090static int
1091netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname,
1092 const struct firmware *fw)
1093{
1094 __le32 val;
1095 u32 major, minor, build, ver, min_ver, bios;
1096 struct pci_dev *pdev = adapter->pdev;
1097
1098 if (fw->size < NX_FW_MIN_SIZE)
1099 return -EINVAL;
1100
1101 val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
1102 if ((__force u32)val != NETXEN_BDINFO_MAGIC)
1103 return -EINVAL;
1104
1105 val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
1106 major = (__force u32)val & 0xff;
1107 minor = ((__force u32)val >> 8) & 0xff;
1108 build = (__force u32)val >> 16;
1109
1110 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1111 min_ver = NETXEN_VERSION_CODE(4, 0, 216);
1112 else
1113 min_ver = NETXEN_VERSION_CODE(3, 4, 216);
1114
1115 ver = NETXEN_VERSION_CODE(major, minor, build);
1116
1117 if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
1118 dev_err(&pdev->dev,
1119 "%s: firmware version %d.%d.%d unsupported\n",
1120 fwname, major, minor, build);
1121 return -EINVAL;
1122 }
1123
1124 val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
1125 netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
1126 if ((__force u32)val != bios) {
1127 dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
1128 fwname);
1129 return -EINVAL;
1130 }
1131
Dhananjay Phadke567c6c42009-03-02 16:02:17 +00001132 /* check if flashed firmware is newer */
1133 if (netxen_rom_fast_read(adapter,
1134 NX_FW_VERSION_OFFSET, (int *)&val))
1135 return -EIO;
1136 major = (__force u32)val & 0xff;
1137 minor = ((__force u32)val >> 8) & 0xff;
1138 build = (__force u32)val >> 16;
1139 if (NETXEN_VERSION_CODE(major, minor, build) > ver)
1140 return -EINVAL;
1141
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001142 netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc),
1143 NETXEN_BDINFO_MAGIC);
1144 return 0;
1145}
1146
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001147static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" };
1148
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001149int netxen_load_firmware(struct netxen_adapter *adapter)
1150{
1151 u32 capability, flashed_ver;
1152 const struct firmware *fw;
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001153 int fw_type;
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001154 struct pci_dev *pdev = adapter->pdev;
1155 int rc = 0;
1156
1157 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001158 fw_type = NX_P2_MN_ROMIMAGE;
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001159 goto request_fw;
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001160 } else {
1161 fw_type = NX_P3_CT_ROMIMAGE;
Dhananjay Phadke567c6c42009-03-02 16:02:17 +00001162 goto request_fw;
1163 }
1164
1165request_mn:
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001166 capability = 0;
1167
1168 netxen_rom_fast_read(adapter,
1169 NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
1170 if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
1171 adapter->hw_read_wx(adapter,
1172 NX_PEG_TUNE_CAPABILITY, &capability, 4);
1173 if (capability & NX_PEG_TUNE_MN_PRESENT) {
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001174 fw_type = NX_P3_MN_ROMIMAGE;
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001175 goto request_fw;
1176 }
1177 }
1178
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001179request_fw:
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001180 rc = request_firmware(&fw, fw_name[fw_type], &pdev->dev);
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001181 if (rc != 0) {
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001182 if (fw_type == NX_P3_CT_ROMIMAGE) {
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001183 msleep(1);
Dhananjay Phadke567c6c42009-03-02 16:02:17 +00001184 goto request_mn;
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001185 }
1186
1187 fw = NULL;
1188 goto load_fw;
1189 }
1190
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001191 rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw);
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001192 if (rc != 0) {
1193 release_firmware(fw);
1194
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001195 if (fw_type == NX_P3_CT_ROMIMAGE) {
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001196 msleep(1);
Dhananjay Phadke567c6c42009-03-02 16:02:17 +00001197 goto request_mn;
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001198 }
1199
1200 fw = NULL;
1201 }
1202
1203load_fw:
Dhananjay Phadkebd257ed2009-03-17 13:14:22 -07001204 rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw);
Dhananjay Phadkeba599d42009-02-24 16:38:22 -08001205
1206 if (fw)
1207 release_firmware(fw);
1208 return rc;
1209}
1210
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001211int
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001212netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
1213 ulong off, void *data, int len)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001214{
1215 void __iomem *addr;
1216
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001217 BUG_ON(len != 4);
1218
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001219 if (ADDR_IN_WINDOW1(off)) {
1220 addr = NETXEN_CRB_NORMALIZE(adapter, off);
1221 } else { /* Window 0 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001222 addr = pci_base_offset(adapter, off);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001223 netxen_nic_pci_change_crbwindow_128M(adapter, 0);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001224 }
1225
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001226 if (!addr) {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001227 netxen_nic_pci_change_crbwindow_128M(adapter, 1);
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001228 return 1;
1229 }
1230
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001231 writel(*(u32 *) data, addr);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001232
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001233 if (!ADDR_IN_WINDOW1(off))
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001234 netxen_nic_pci_change_crbwindow_128M(adapter, 1);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001235
1236 return 0;
1237}
1238
1239int
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001240netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
1241 ulong off, void *data, int len)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001242{
1243 void __iomem *addr;
1244
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001245 BUG_ON(len != 4);
1246
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001247 if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
1248 addr = NETXEN_CRB_NORMALIZE(adapter, off);
1249 } else { /* Window 0 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001250 addr = pci_base_offset(adapter, off);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001251 netxen_nic_pci_change_crbwindow_128M(adapter, 0);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001252 }
1253
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001254 if (!addr) {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001255 netxen_nic_pci_change_crbwindow_128M(adapter, 1);
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001256 return 1;
1257 }
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001258
1259 *(u32 *)data = readl(addr);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001260
1261 if (!ADDR_IN_WINDOW1(off))
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001262 netxen_nic_pci_change_crbwindow_128M(adapter, 1);
1263
1264 return 0;
1265}
1266
1267int
1268netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
1269 ulong off, void *data, int len)
1270{
1271 unsigned long flags = 0;
1272 int rv;
1273
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001274 BUG_ON(len != 4);
1275
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001276 rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
1277
1278 if (rv == -1) {
1279 printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
1280 __func__, off);
1281 dump_stack();
1282 return -1;
1283 }
1284
1285 if (rv == 1) {
1286 write_lock_irqsave(&adapter->adapter_lock, flags);
1287 crb_win_lock(adapter);
1288 netxen_nic_pci_set_crbwindow_2M(adapter, &off);
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001289 writel(*(uint32_t *)data, (void __iomem *)off);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001290 crb_win_unlock(adapter);
1291 write_unlock_irqrestore(&adapter->adapter_lock, flags);
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001292 } else
1293 writel(*(uint32_t *)data, (void __iomem *)off);
1294
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001295
1296 return 0;
1297}
1298
1299int
1300netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
1301 ulong off, void *data, int len)
1302{
1303 unsigned long flags = 0;
1304 int rv;
1305
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001306 BUG_ON(len != 4);
1307
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001308 rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
1309
1310 if (rv == -1) {
1311 printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
1312 __func__, off);
1313 dump_stack();
1314 return -1;
1315 }
1316
1317 if (rv == 1) {
1318 write_lock_irqsave(&adapter->adapter_lock, flags);
1319 crb_win_lock(adapter);
1320 netxen_nic_pci_set_crbwindow_2M(adapter, &off);
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001321 *(uint32_t *)data = readl((void __iomem *)off);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001322 crb_win_unlock(adapter);
1323 write_unlock_irqrestore(&adapter->adapter_lock, flags);
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001324 } else
1325 *(uint32_t *)data = readl((void __iomem *)off);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001326
1327 return 0;
1328}
1329
1330void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001331{
1332 adapter->hw_write_wx(adapter, off, &val, 4);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001333}
1334
1335int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001336{
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001337 int val;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001338 adapter->hw_read_wx(adapter, off, &val, 4);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001339 return val;
1340}
1341
1342/* Change the window to 0, write and change back to window 1. */
1343void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
1344{
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001345 adapter->hw_write_wx(adapter, index, &value, 4);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001346}
1347
1348/* Change the window to 0, read and change back to window 1. */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001349void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001350{
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001351 adapter->hw_read_wx(adapter, index, value, 4);
1352}
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001353
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001354void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
1355{
1356 adapter->hw_write_wx(adapter, index, &value, 4);
1357}
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001358
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001359void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
1360{
1361 adapter->hw_read_wx(adapter, index, value, 4);
1362}
1363
1364/*
1365 * check memory access boundary.
1366 * used by test agent. support ddr access only for now
1367 */
1368static unsigned long
1369netxen_nic_pci_mem_bound_check(struct netxen_adapter *adapter,
1370 unsigned long long addr, int size)
1371{
1372 if (!ADDR_IN_RANGE(addr,
1373 NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
1374 !ADDR_IN_RANGE(addr+size-1,
1375 NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
1376 ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
1377 return 0;
1378 }
1379
1380 return 1;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001381}
1382
Jeff Garzik47906542007-11-23 21:23:36 -05001383static int netxen_pci_set_window_warning_count;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001384
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001385unsigned long
1386netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
1387 unsigned long long addr)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001388{
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07001389 void __iomem *offset;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001390 int window;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001391 unsigned long long qdr_max;
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07001392 uint8_t func = adapter->ahw.pci_func;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001393
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001394 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1395 qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
1396 } else {
1397 qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
1398 }
1399
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001400 if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1401 /* DDR network side */
1402 addr -= NETXEN_ADDR_DDR_NET;
1403 window = (addr >> 25) & 0x3ff;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001404 if (adapter->ahw.ddr_mn_window != window) {
1405 adapter->ahw.ddr_mn_window = window;
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07001406 offset = PCI_OFFSET_SECOND_RANGE(adapter,
1407 NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func)));
1408 writel(window, offset);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001409 /* MUST make sure window is set before we forge on... */
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07001410 readl(offset);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001411 }
Amit S. Kalecb8011a2006-11-29 09:00:10 -08001412 addr -= (window * NETXEN_WINDOW_ONE);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001413 addr += NETXEN_PCI_DDR_NET;
1414 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
1415 addr -= NETXEN_ADDR_OCM0;
1416 addr += NETXEN_PCI_OCM0;
1417 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
1418 addr -= NETXEN_ADDR_OCM1;
1419 addr += NETXEN_PCI_OCM1;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001420 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001421 /* QDR network side */
1422 addr -= NETXEN_ADDR_QDR_NET;
1423 window = (addr >> 22) & 0x3f;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001424 if (adapter->ahw.qdr_sn_window != window) {
1425 adapter->ahw.qdr_sn_window = window;
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07001426 offset = PCI_OFFSET_SECOND_RANGE(adapter,
1427 NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func)));
1428 writel((window << 22), offset);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001429 /* MUST make sure window is set before we forge on... */
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07001430 readl(offset);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001431 }
1432 addr -= (window * 0x400000);
1433 addr += NETXEN_PCI_QDR_NET;
1434 } else {
1435 /*
1436 * peg gdb frequently accesses memory that doesn't exist,
1437 * this limits the chit chat so debugging isn't slowed down.
1438 */
1439 if ((netxen_pci_set_window_warning_count++ < 8)
1440 || (netxen_pci_set_window_warning_count % 64 == 0))
1441 printk("%s: Warning:netxen_nic_pci_set_window()"
1442 " Unknown address range!\n",
1443 netxen_nic_driver_name);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001444 addr = -1UL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001445 }
1446 return addr;
1447}
1448
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001449/*
1450 * Note : only 32-bit writes!
1451 */
1452int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
1453 u64 off, u32 data)
1454{
1455 writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
1456 return 0;
1457}
1458
1459u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off)
1460{
1461 return readl((void __iomem *)(pci_base_offset(adapter, off)));
1462}
1463
1464void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
1465 u64 off, u32 data)
1466{
1467 writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
1468}
1469
1470u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
1471{
1472 return readl(NETXEN_CRB_NORMALIZE(adapter, off));
1473}
1474
1475unsigned long
1476netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
1477 unsigned long long addr)
1478{
1479 int window;
1480 u32 win_read;
1481
1482 if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1483 /* DDR network side */
1484 window = MN_WIN(addr);
1485 adapter->ahw.ddr_mn_window = window;
1486 adapter->hw_write_wx(adapter,
1487 adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
1488 &window, 4);
1489 adapter->hw_read_wx(adapter,
1490 adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
1491 &win_read, 4);
1492 if ((win_read << 17) != window) {
1493 printk(KERN_INFO "Written MNwin (0x%x) != "
1494 "Read MNwin (0x%x)\n", window, win_read);
1495 }
1496 addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET;
1497 } else if (ADDR_IN_RANGE(addr,
1498 NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
1499 if ((addr & 0x00ff800) == 0xff800) {
1500 printk("%s: QM access not handled.\n", __func__);
1501 addr = -1UL;
1502 }
1503
1504 window = OCM_WIN(addr);
1505 adapter->ahw.ddr_mn_window = window;
1506 adapter->hw_write_wx(adapter,
1507 adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
1508 &window, 4);
1509 adapter->hw_read_wx(adapter,
1510 adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
1511 &win_read, 4);
1512 if ((win_read >> 7) != window) {
1513 printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
1514 "Read OCMwin (0x%x)\n",
1515 __func__, window, win_read);
1516 }
1517 addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M;
1518
1519 } else if (ADDR_IN_RANGE(addr,
1520 NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) {
1521 /* QDR network side */
1522 window = MS_WIN(addr);
1523 adapter->ahw.qdr_sn_window = window;
1524 adapter->hw_write_wx(adapter,
1525 adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
1526 &window, 4);
1527 adapter->hw_read_wx(adapter,
1528 adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
1529 &win_read, 4);
1530 if (win_read != window) {
1531 printk(KERN_INFO "%s: Written MSwin (0x%x) != "
1532 "Read MSwin (0x%x)\n",
1533 __func__, window, win_read);
1534 }
1535 addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET;
1536
1537 } else {
1538 /*
1539 * peg gdb frequently accesses memory that doesn't exist,
1540 * this limits the chit chat so debugging isn't slowed down.
1541 */
1542 if ((netxen_pci_set_window_warning_count++ < 8)
1543 || (netxen_pci_set_window_warning_count%64 == 0)) {
1544 printk("%s: Warning:%s Unknown address range!\n",
1545 __func__, netxen_nic_driver_name);
1546}
1547 addr = -1UL;
1548 }
1549 return addr;
1550}
1551
1552static int netxen_nic_pci_is_same_window(struct netxen_adapter *adapter,
1553 unsigned long long addr)
1554{
1555 int window;
1556 unsigned long long qdr_max;
1557
1558 if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
1559 qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
1560 else
1561 qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
1562
1563 if (ADDR_IN_RANGE(addr,
1564 NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1565 /* DDR network side */
1566 BUG(); /* MN access can not come here */
1567 } else if (ADDR_IN_RANGE(addr,
1568 NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
1569 return 1;
1570 } else if (ADDR_IN_RANGE(addr,
1571 NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
1572 return 1;
1573 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
1574 /* QDR network side */
1575 window = ((addr - NETXEN_ADDR_QDR_NET) >> 22) & 0x3f;
1576 if (adapter->ahw.qdr_sn_window == window)
1577 return 1;
1578 }
1579
1580 return 0;
1581}
1582
1583static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
1584 u64 off, void *data, int size)
1585{
1586 unsigned long flags;
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001587 void __iomem *addr, *mem_ptr = NULL;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001588 int ret = 0;
1589 u64 start;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001590 unsigned long mem_base;
1591 unsigned long mem_page;
1592
1593 write_lock_irqsave(&adapter->adapter_lock, flags);
1594
1595 /*
1596 * If attempting to access unknown address or straddle hw windows,
1597 * do not access.
1598 */
1599 start = adapter->pci_set_window(adapter, off);
1600 if ((start == -1UL) ||
1601 (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
1602 write_unlock_irqrestore(&adapter->adapter_lock, flags);
1603 printk(KERN_ERR "%s out of bound pci memory access. "
Andrew Morton11a859e2008-07-30 12:50:12 -07001604 "offset is 0x%llx\n", netxen_nic_driver_name,
1605 (unsigned long long)off);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001606 return -1;
1607 }
1608
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001609 addr = pci_base_offset(adapter, start);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001610 if (!addr) {
1611 write_unlock_irqrestore(&adapter->adapter_lock, flags);
1612 mem_base = pci_resource_start(adapter->pdev, 0);
1613 mem_page = start & PAGE_MASK;
1614 /* Map two pages whenever user tries to access addresses in two
1615 consecutive pages.
1616 */
1617 if (mem_page != ((start + size - 1) & PAGE_MASK))
1618 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1619 else
1620 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
Hannes Ederf8057b72008-12-26 00:04:26 -08001621 if (mem_ptr == NULL) {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001622 *(uint8_t *)data = 0;
1623 return -1;
1624 }
1625 addr = mem_ptr;
1626 addr += start & (PAGE_SIZE - 1);
1627 write_lock_irqsave(&adapter->adapter_lock, flags);
1628 }
1629
1630 switch (size) {
1631 case 1:
1632 *(uint8_t *)data = readb(addr);
1633 break;
1634 case 2:
1635 *(uint16_t *)data = readw(addr);
1636 break;
1637 case 4:
1638 *(uint32_t *)data = readl(addr);
1639 break;
1640 case 8:
1641 *(uint64_t *)data = readq(addr);
1642 break;
1643 default:
1644 ret = -1;
1645 break;
1646 }
1647 write_unlock_irqrestore(&adapter->adapter_lock, flags);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001648
1649 if (mem_ptr)
1650 iounmap(mem_ptr);
1651 return ret;
1652}
1653
1654static int
1655netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
1656 void *data, int size)
1657{
1658 unsigned long flags;
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001659 void __iomem *addr, *mem_ptr = NULL;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001660 int ret = 0;
1661 u64 start;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001662 unsigned long mem_base;
1663 unsigned long mem_page;
1664
1665 write_lock_irqsave(&adapter->adapter_lock, flags);
1666
1667 /*
1668 * If attempting to access unknown address or straddle hw windows,
1669 * do not access.
1670 */
1671 start = adapter->pci_set_window(adapter, off);
1672 if ((start == -1UL) ||
1673 (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
1674 write_unlock_irqrestore(&adapter->adapter_lock, flags);
1675 printk(KERN_ERR "%s out of bound pci memory access. "
Andrew Morton11a859e2008-07-30 12:50:12 -07001676 "offset is 0x%llx\n", netxen_nic_driver_name,
1677 (unsigned long long)off);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001678 return -1;
1679 }
1680
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001681 addr = pci_base_offset(adapter, start);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001682 if (!addr) {
1683 write_unlock_irqrestore(&adapter->adapter_lock, flags);
1684 mem_base = pci_resource_start(adapter->pdev, 0);
1685 mem_page = start & PAGE_MASK;
1686 /* Map two pages whenever user tries to access addresses in two
1687 * consecutive pages.
1688 */
1689 if (mem_page != ((start + size - 1) & PAGE_MASK))
1690 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
1691 else
1692 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
Hannes Ederf8057b72008-12-26 00:04:26 -08001693 if (mem_ptr == NULL)
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001694 return -1;
1695 addr = mem_ptr;
1696 addr += start & (PAGE_SIZE - 1);
1697 write_lock_irqsave(&adapter->adapter_lock, flags);
1698 }
1699
1700 switch (size) {
1701 case 1:
1702 writeb(*(uint8_t *)data, addr);
1703 break;
1704 case 2:
1705 writew(*(uint16_t *)data, addr);
1706 break;
1707 case 4:
1708 writel(*(uint32_t *)data, addr);
1709 break;
1710 case 8:
1711 writeq(*(uint64_t *)data, addr);
1712 break;
1713 default:
1714 ret = -1;
1715 break;
1716 }
1717 write_unlock_irqrestore(&adapter->adapter_lock, flags);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001718 if (mem_ptr)
1719 iounmap(mem_ptr);
1720 return ret;
1721}
1722
1723#define MAX_CTL_CHECK 1000
1724
1725int
1726netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
1727 u64 off, void *data, int size)
1728{
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001729 unsigned long flags;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001730 int i, j, ret = 0, loop, sz[2], off0;
1731 uint32_t temp;
1732 uint64_t off8, tmpw, word[2] = {0, 0};
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001733 void __iomem *mem_crb;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001734
1735 /*
1736 * If not MN, go check for MS or invalid.
1737 */
1738 if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
1739 return netxen_nic_pci_mem_write_direct(adapter,
1740 off, data, size);
1741
1742 off8 = off & 0xfffffff8;
1743 off0 = off & 0x7;
1744 sz[0] = (size < (8 - off0)) ? size : (8 - off0);
1745 sz[1] = size - sz[0];
1746 loop = ((off0 + size - 1) >> 3) + 1;
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001747 mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001748
1749 if ((size != 8) || (off0 != 0)) {
1750 for (i = 0; i < loop; i++) {
1751 if (adapter->pci_mem_read(adapter,
1752 off8 + (i << 3), &word[i], 8))
1753 return -1;
1754 }
1755 }
1756
1757 switch (size) {
1758 case 1:
1759 tmpw = *((uint8_t *)data);
1760 break;
1761 case 2:
1762 tmpw = *((uint16_t *)data);
1763 break;
1764 case 4:
1765 tmpw = *((uint32_t *)data);
1766 break;
1767 case 8:
1768 default:
1769 tmpw = *((uint64_t *)data);
1770 break;
1771 }
1772 word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
1773 word[0] |= tmpw << (off0 * 8);
1774
1775 if (loop == 2) {
1776 word[1] &= ~(~0ULL << (sz[1] * 8));
1777 word[1] |= tmpw >> (sz[0] * 8);
1778 }
1779
1780 write_lock_irqsave(&adapter->adapter_lock, flags);
1781 netxen_nic_pci_change_crbwindow_128M(adapter, 0);
1782
1783 for (i = 0; i < loop; i++) {
1784 writel((uint32_t)(off8 + (i << 3)),
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001785 (mem_crb+MIU_TEST_AGT_ADDR_LO));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001786 writel(0,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001787 (mem_crb+MIU_TEST_AGT_ADDR_HI));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001788 writel(word[i] & 0xffffffff,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001789 (mem_crb+MIU_TEST_AGT_WRDATA_LO));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001790 writel((word[i] >> 32) & 0xffffffff,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001791 (mem_crb+MIU_TEST_AGT_WRDATA_HI));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001792 writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001793 (mem_crb+MIU_TEST_AGT_CTRL));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001794 writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001795 (mem_crb+MIU_TEST_AGT_CTRL));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001796
1797 for (j = 0; j < MAX_CTL_CHECK; j++) {
1798 temp = readl(
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001799 (mem_crb+MIU_TEST_AGT_CTRL));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001800 if ((temp & MIU_TA_CTL_BUSY) == 0)
1801 break;
1802 }
1803
1804 if (j >= MAX_CTL_CHECK) {
Dhananjay Phadke39754f42009-02-17 20:27:02 -08001805 if (printk_ratelimit())
1806 dev_err(&adapter->pdev->dev,
1807 "failed to write through agent\n");
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001808 ret = -1;
1809 break;
1810 }
1811 }
1812
1813 netxen_nic_pci_change_crbwindow_128M(adapter, 1);
1814 write_unlock_irqrestore(&adapter->adapter_lock, flags);
1815 return ret;
1816}
1817
1818int
1819netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
1820 u64 off, void *data, int size)
1821{
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001822 unsigned long flags;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001823 int i, j = 0, k, start, end, loop, sz[2], off0[2];
1824 uint32_t temp;
1825 uint64_t off8, val, word[2] = {0, 0};
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001826 void __iomem *mem_crb;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001827
1828
1829 /*
1830 * If not MN, go check for MS or invalid.
1831 */
1832 if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
1833 return netxen_nic_pci_mem_read_direct(adapter, off, data, size);
1834
1835 off8 = off & 0xfffffff8;
1836 off0[0] = off & 0x7;
1837 off0[1] = 0;
1838 sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
1839 sz[1] = size - sz[0];
1840 loop = ((off0[0] + size - 1) >> 3) + 1;
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001841 mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001842
1843 write_lock_irqsave(&adapter->adapter_lock, flags);
1844 netxen_nic_pci_change_crbwindow_128M(adapter, 0);
1845
1846 for (i = 0; i < loop; i++) {
1847 writel((uint32_t)(off8 + (i << 3)),
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001848 (mem_crb+MIU_TEST_AGT_ADDR_LO));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001849 writel(0,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001850 (mem_crb+MIU_TEST_AGT_ADDR_HI));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001851 writel(MIU_TA_CTL_ENABLE,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001852 (mem_crb+MIU_TEST_AGT_CTRL));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001853 writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001854 (mem_crb+MIU_TEST_AGT_CTRL));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001855
1856 for (j = 0; j < MAX_CTL_CHECK; j++) {
1857 temp = readl(
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001858 (mem_crb+MIU_TEST_AGT_CTRL));
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001859 if ((temp & MIU_TA_CTL_BUSY) == 0)
1860 break;
1861 }
1862
1863 if (j >= MAX_CTL_CHECK) {
Dhananjay Phadke39754f42009-02-17 20:27:02 -08001864 if (printk_ratelimit())
1865 dev_err(&adapter->pdev->dev,
1866 "failed to read through agent\n");
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001867 break;
1868 }
1869
1870 start = off0[i] >> 2;
1871 end = (off0[i] + sz[i] - 1) >> 2;
1872 for (k = start; k <= end; k++) {
1873 word[i] |= ((uint64_t) readl(
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08001874 (mem_crb +
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001875 MIU_TEST_AGT_RDDATA(k))) << (32*k));
1876 }
1877 }
1878
1879 netxen_nic_pci_change_crbwindow_128M(adapter, 1);
1880 write_unlock_irqrestore(&adapter->adapter_lock, flags);
1881
1882 if (j >= MAX_CTL_CHECK)
1883 return -1;
1884
1885 if (sz[0] == 8) {
1886 val = word[0];
1887 } else {
1888 val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
1889 ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
1890 }
1891
1892 switch (size) {
1893 case 1:
1894 *(uint8_t *)data = val;
1895 break;
1896 case 2:
1897 *(uint16_t *)data = val;
1898 break;
1899 case 4:
1900 *(uint32_t *)data = val;
1901 break;
1902 case 8:
1903 *(uint64_t *)data = val;
1904 break;
1905 }
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001906 return 0;
1907}
1908
1909int
1910netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
1911 u64 off, void *data, int size)
1912{
1913 int i, j, ret = 0, loop, sz[2], off0;
1914 uint32_t temp;
1915 uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
1916
1917 /*
1918 * If not MN, go check for MS or invalid.
1919 */
1920 if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
1921 mem_crb = NETXEN_CRB_QDR_NET;
1922 else {
1923 mem_crb = NETXEN_CRB_DDR_NET;
1924 if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
1925 return netxen_nic_pci_mem_write_direct(adapter,
1926 off, data, size);
1927 }
1928
1929 off8 = off & 0xfffffff8;
1930 off0 = off & 0x7;
1931 sz[0] = (size < (8 - off0)) ? size : (8 - off0);
1932 sz[1] = size - sz[0];
1933 loop = ((off0 + size - 1) >> 3) + 1;
1934
1935 if ((size != 8) || (off0 != 0)) {
1936 for (i = 0; i < loop; i++) {
1937 if (adapter->pci_mem_read(adapter, off8 + (i << 3),
1938 &word[i], 8))
1939 return -1;
1940 }
1941 }
1942
1943 switch (size) {
1944 case 1:
1945 tmpw = *((uint8_t *)data);
1946 break;
1947 case 2:
1948 tmpw = *((uint16_t *)data);
1949 break;
1950 case 4:
1951 tmpw = *((uint32_t *)data);
1952 break;
1953 case 8:
1954 default:
1955 tmpw = *((uint64_t *)data);
1956 break;
1957 }
1958
1959 word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
1960 word[0] |= tmpw << (off0 * 8);
1961
1962 if (loop == 2) {
1963 word[1] &= ~(~0ULL << (sz[1] * 8));
1964 word[1] |= tmpw >> (sz[0] * 8);
1965 }
1966
1967 /*
1968 * don't lock here - write_wx gets the lock if each time
1969 * write_lock_irqsave(&adapter->adapter_lock, flags);
1970 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
1971 */
1972
1973 for (i = 0; i < loop; i++) {
1974 temp = off8 + (i << 3);
1975 adapter->hw_write_wx(adapter,
1976 mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
1977 temp = 0;
1978 adapter->hw_write_wx(adapter,
1979 mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
1980 temp = word[i] & 0xffffffff;
1981 adapter->hw_write_wx(adapter,
1982 mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
1983 temp = (word[i] >> 32) & 0xffffffff;
1984 adapter->hw_write_wx(adapter,
1985 mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
1986 temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
1987 adapter->hw_write_wx(adapter,
1988 mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
1989 temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
1990 adapter->hw_write_wx(adapter,
1991 mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
1992
1993 for (j = 0; j < MAX_CTL_CHECK; j++) {
1994 adapter->hw_read_wx(adapter,
1995 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
1996 if ((temp & MIU_TA_CTL_BUSY) == 0)
1997 break;
1998 }
1999
2000 if (j >= MAX_CTL_CHECK) {
Dhananjay Phadke39754f42009-02-17 20:27:02 -08002001 if (printk_ratelimit())
2002 dev_err(&adapter->pdev->dev,
2003 "failed to write through agent\n");
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07002004 ret = -1;
2005 break;
2006 }
2007 }
2008
2009 /*
2010 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
2011 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
2012 */
2013 return ret;
2014}
2015
2016int
2017netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
2018 u64 off, void *data, int size)
2019{
2020 int i, j = 0, k, start, end, loop, sz[2], off0[2];
2021 uint32_t temp;
2022 uint64_t off8, val, mem_crb, word[2] = {0, 0};
2023
2024 /*
2025 * If not MN, go check for MS or invalid.
2026 */
2027
2028 if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
2029 mem_crb = NETXEN_CRB_QDR_NET;
2030 else {
2031 mem_crb = NETXEN_CRB_DDR_NET;
2032 if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
2033 return netxen_nic_pci_mem_read_direct(adapter,
2034 off, data, size);
2035 }
2036
2037 off8 = off & 0xfffffff8;
2038 off0[0] = off & 0x7;
2039 off0[1] = 0;
2040 sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
2041 sz[1] = size - sz[0];
2042 loop = ((off0[0] + size - 1) >> 3) + 1;
2043
2044 /*
2045 * don't lock here - write_wx gets the lock if each time
2046 * write_lock_irqsave(&adapter->adapter_lock, flags);
2047 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
2048 */
2049
2050 for (i = 0; i < loop; i++) {
2051 temp = off8 + (i << 3);
2052 adapter->hw_write_wx(adapter,
2053 mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
2054 temp = 0;
2055 adapter->hw_write_wx(adapter,
2056 mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
2057 temp = MIU_TA_CTL_ENABLE;
2058 adapter->hw_write_wx(adapter,
2059 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
2060 temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
2061 adapter->hw_write_wx(adapter,
2062 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
2063
2064 for (j = 0; j < MAX_CTL_CHECK; j++) {
2065 adapter->hw_read_wx(adapter,
2066 mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
2067 if ((temp & MIU_TA_CTL_BUSY) == 0)
2068 break;
2069 }
2070
2071 if (j >= MAX_CTL_CHECK) {
Dhananjay Phadke39754f42009-02-17 20:27:02 -08002072 if (printk_ratelimit())
2073 dev_err(&adapter->pdev->dev,
2074 "failed to read through agent\n");
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07002075 break;
2076 }
2077
2078 start = off0[i] >> 2;
2079 end = (off0[i] + sz[i] - 1) >> 2;
2080 for (k = start; k <= end; k++) {
2081 adapter->hw_read_wx(adapter,
2082 mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
2083 word[i] |= ((uint64_t)temp << (32 * k));
2084 }
2085 }
2086
2087 /*
2088 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
2089 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
2090 */
2091
2092 if (j >= MAX_CTL_CHECK)
2093 return -1;
2094
2095 if (sz[0] == 8) {
2096 val = word[0];
2097 } else {
2098 val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
2099 ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
2100 }
2101
2102 switch (size) {
2103 case 1:
2104 *(uint8_t *)data = val;
2105 break;
2106 case 2:
2107 *(uint16_t *)data = val;
2108 break;
2109 case 4:
2110 *(uint32_t *)data = val;
2111 break;
2112 case 8:
2113 *(uint64_t *)data = val;
2114 break;
2115 }
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07002116 return 0;
2117}
2118
2119/*
2120 * Note : only 32-bit writes!
2121 */
2122int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
2123 u64 off, u32 data)
2124{
2125 adapter->hw_write_wx(adapter, off, &data, 4);
2126
2127 return 0;
2128}
2129
2130u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
2131{
2132 u32 temp;
2133 adapter->hw_read_wx(adapter, off, &temp, 4);
2134 return temp;
2135}
2136
2137void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
2138 u64 off, u32 data)
2139{
2140 adapter->hw_write_wx(adapter, off, &data, 4);
2141}
2142
2143u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
2144{
2145 u32 temp;
2146 adapter->hw_read_wx(adapter, off, &temp, 4);
2147 return temp;
2148}
2149
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002150int netxen_nic_get_board_info(struct netxen_adapter *adapter)
2151{
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002152 int offset, board_type, magic, header_version;
2153 struct pci_dev *pdev = adapter->pdev;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002154
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002155 offset = NETXEN_BRDCFG_START +
2156 offsetof(struct netxen_board_info, magic);
2157 if (netxen_rom_fast_read(adapter, offset, &magic))
2158 return -EIO;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002159
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002160 offset = NETXEN_BRDCFG_START +
2161 offsetof(struct netxen_board_info, header_version);
2162 if (netxen_rom_fast_read(adapter, offset, &header_version))
2163 return -EIO;
2164
2165 if (magic != NETXEN_BDINFO_MAGIC ||
2166 header_version != NETXEN_BDINFO_VERSION) {
2167 dev_err(&pdev->dev,
2168 "invalid board config, magic=%08x, version=%08x\n",
2169 magic, header_version);
2170 return -EIO;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002171 }
2172
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002173 offset = NETXEN_BRDCFG_START +
2174 offsetof(struct netxen_board_info, board_type);
2175 if (netxen_rom_fast_read(adapter, offset, &board_type))
2176 return -EIO;
2177
2178 adapter->ahw.board_type = board_type;
2179
2180 if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002181 u32 gpio = netxen_nic_reg_read(adapter,
2182 NETXEN_ROMUSB_GLB_PAD_GPIO_I);
2183 if ((gpio & 0x8000) == 0)
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002184 board_type = NETXEN_BRDTYPE_P3_10G_TP;
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002185 }
2186
Dhananjay Phadkee98e3352009-04-07 22:50:38 +00002187 switch (board_type) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002188 case NETXEN_BRDTYPE_P2_SB35_4G:
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002189 adapter->ahw.port_type = NETXEN_NIC_GBE;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002190 break;
2191 case NETXEN_BRDTYPE_P2_SB31_10G:
2192 case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
2193 case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
2194 case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07002195 case NETXEN_BRDTYPE_P3_HMEZ:
2196 case NETXEN_BRDTYPE_P3_XG_LOM:
2197 case NETXEN_BRDTYPE_P3_10G_CX4:
2198 case NETXEN_BRDTYPE_P3_10G_CX4_LP:
2199 case NETXEN_BRDTYPE_P3_IMEZ:
2200 case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
Dhananjay Phadkea70f9392008-08-01 03:14:56 -07002201 case NETXEN_BRDTYPE_P3_10G_SFP_CT:
2202 case NETXEN_BRDTYPE_P3_10G_SFP_QT:
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07002203 case NETXEN_BRDTYPE_P3_10G_XFP:
2204 case NETXEN_BRDTYPE_P3_10000_BASE_T:
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002205 adapter->ahw.port_type = NETXEN_NIC_XGBE;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002206 break;
2207 case NETXEN_BRDTYPE_P1_BD:
2208 case NETXEN_BRDTYPE_P1_SB:
2209 case NETXEN_BRDTYPE_P1_SMAX:
2210 case NETXEN_BRDTYPE_P1_SOCK:
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -07002211 case NETXEN_BRDTYPE_P3_REF_QG:
2212 case NETXEN_BRDTYPE_P3_4_GB:
2213 case NETXEN_BRDTYPE_P3_4_GB_MM:
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002214 adapter->ahw.port_type = NETXEN_NIC_GBE;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002215 break;
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002216 case NETXEN_BRDTYPE_P3_10G_TP:
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002217 adapter->ahw.port_type = (adapter->portnum < 2) ?
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002218 NETXEN_NIC_XGBE : NETXEN_NIC_GBE;
2219 break;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002220 default:
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002221 dev_err(&pdev->dev, "unknown board type %x\n", board_type);
2222 adapter->ahw.port_type = NETXEN_NIC_XGBE;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002223 break;
2224 }
2225
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002226 return 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002227}
2228
2229/* NIU access sections */
2230
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002231int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002232{
Dhananjay Phadke9ad27642008-08-01 03:14:59 -07002233 new_mtu += MTU_FUDGE_FACTOR;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002234 netxen_nic_write_w0(adapter,
Dhananjay Phadke3276fba2008-06-15 22:59:44 -07002235 NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
2236 new_mtu);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002237 return 0;
2238}
2239
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002240int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002241{
Dhananjay Phadke9ad27642008-08-01 03:14:59 -07002242 new_mtu += MTU_FUDGE_FACTOR;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -07002243 if (adapter->physical_port == 0)
Jeff Garzik47906542007-11-23 21:23:36 -05002244 netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE,
Mithlesh Thukral595e3fb2007-04-20 07:53:52 -07002245 new_mtu);
Jeff Garzik47906542007-11-23 21:23:36 -05002246 else
Mithlesh Thukral595e3fb2007-04-20 07:53:52 -07002247 netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE,
2248 new_mtu);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002249 return 0;
2250}
2251
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002252void
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07002253netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
2254 unsigned long off, int data)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002255{
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07002256 adapter->hw_write_wx(adapter, off, &data, 4);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002257}
2258
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002259void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002260{
Al Viroa608ab9c2007-01-02 10:39:10 +00002261 __u32 status;
2262 __u32 autoneg;
Dhananjay Phadke24a7a452008-08-01 03:14:55 -07002263 __u32 port_mode;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002264
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002265 if (!netif_carrier_ok(adapter->netdev)) {
2266 adapter->link_speed = 0;
2267 adapter->link_duplex = -1;
2268 adapter->link_autoneg = AUTONEG_ENABLE;
2269 return;
2270 }
Dhananjay Phadke24a7a452008-08-01 03:14:55 -07002271
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002272 if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
Dhananjay Phadke24a7a452008-08-01 03:14:55 -07002273 adapter->hw_read_wx(adapter,
2274 NETXEN_PORT_MODE_ADDR, &port_mode, 4);
2275 if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
2276 adapter->link_speed = SPEED_1000;
2277 adapter->link_duplex = DUPLEX_FULL;
2278 adapter->link_autoneg = AUTONEG_DISABLE;
2279 return;
2280 }
2281
Amit S. Kale80922fb2006-12-04 09:18:00 -08002282 if (adapter->phy_read
Dhananjay Phadke24a7a452008-08-01 03:14:55 -07002283 && adapter->phy_read(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002284 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
2285 &status) == 0) {
2286 if (netxen_get_phy_link(status)) {
2287 switch (netxen_get_phy_speed(status)) {
2288 case 0:
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002289 adapter->link_speed = SPEED_10;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002290 break;
2291 case 1:
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002292 adapter->link_speed = SPEED_100;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002293 break;
2294 case 2:
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002295 adapter->link_speed = SPEED_1000;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002296 break;
2297 default:
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002298 adapter->link_speed = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002299 break;
2300 }
2301 switch (netxen_get_phy_duplex(status)) {
2302 case 0:
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002303 adapter->link_duplex = DUPLEX_HALF;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002304 break;
2305 case 1:
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002306 adapter->link_duplex = DUPLEX_FULL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002307 break;
2308 default:
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002309 adapter->link_duplex = -1;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002310 break;
2311 }
Amit S. Kale80922fb2006-12-04 09:18:00 -08002312 if (adapter->phy_read
Dhananjay Phadke24a7a452008-08-01 03:14:55 -07002313 && adapter->phy_read(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002314 NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08002315 &autoneg) != 0)
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002316 adapter->link_autoneg = autoneg;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002317 } else
2318 goto link_down;
2319 } else {
2320 link_down:
Dhananjay Phadkec7860a22009-01-14 20:48:32 -08002321 adapter->link_speed = 0;
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07002322 adapter->link_duplex = -1;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002323 }
2324 }
2325}
2326
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002327void netxen_nic_get_firmware_info(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002328{
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002329 u32 fw_major, fw_minor, fw_build;
Amit S. Kalecb8011a2006-11-29 09:00:10 -08002330 char brd_name[NETXEN_MAX_SHORT_NAME];
Harvey Harrison8d748492008-04-22 11:48:35 -07002331 char serial_num[32];
Dhananjay Phadkefbb52f22009-03-13 14:52:01 +00002332 int i, addr, val;
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08002333 int *ptr32;
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002334 struct pci_dev *pdev = adapter->pdev;
Harvey Harrison8d748492008-04-22 11:48:35 -07002335
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002336 adapter->driver_mismatch = 0;
2337
Dhananjay Phadked8313ce2009-02-17 20:26:44 -08002338 ptr32 = (int *)&serial_num;
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002339 addr = NETXEN_USER_START +
2340 offsetof(struct netxen_new_user_info, serial_num);
2341 for (i = 0; i < 8; i++) {
Dhananjay Phadkefbb52f22009-03-13 14:52:01 +00002342 if (netxen_rom_fast_read(adapter, addr, &val) == -1) {
2343 dev_err(&pdev->dev, "error reading board info\n");
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002344 adapter->driver_mismatch = 1;
2345 return;
2346 }
Dhananjay Phadkefbb52f22009-03-13 14:52:01 +00002347 ptr32[i] = cpu_to_le32(val);
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002348 addr += sizeof(u32);
2349 }
2350
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07002351 adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
2352 adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
2353 adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002354
Dhananjay Phadke29566402008-07-21 19:44:04 -07002355 adapter->fw_major = fw_major;
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002356 adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
Dhananjay Phadke29566402008-07-21 19:44:04 -07002357
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002358 if (adapter->portnum == 0) {
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002359 get_brd_name_by_type(adapter->ahw.board_type, brd_name);
Amit S. Kalecb8011a2006-11-29 09:00:10 -08002360
Dhananjay Phadke11d89d62008-08-08 00:08:45 -07002361 printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n",
2362 brd_name, serial_num, adapter->ahw.revision_id);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002363 }
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002364
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002365 if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002366 adapter->driver_mismatch = 1;
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002367 dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n",
Dhananjay Phadke58735562008-07-21 19:44:10 -07002368 fw_major, fw_minor, fw_build);
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -07002369 return;
2370 }
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +00002371
2372 dev_info(&pdev->dev, "firmware version %d.%d.%d\n",
2373 fw_major, fw_minor, fw_build);
2374
2375 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
2376 adapter->hw_read_wx(adapter,
2377 NETXEN_MIU_MN_CONTROL, &i, 4);
2378 adapter->ahw.cut_through = (i & 0x4) ? 1 : 0;
2379 dev_info(&pdev->dev, "firmware running in %s mode\n",
2380 adapter->ahw.cut_through ? "cut-through" : "legacy");
2381 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -04002382}
2383
Dhananjay Phadke0b72e652009-03-13 14:52:02 +00002384int
2385netxen_nic_wol_supported(struct netxen_adapter *adapter)
2386{
2387 u32 wol_cfg;
2388
2389 if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
2390 return 0;
2391
2392 wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV);
2393 if (wol_cfg & (1UL << adapter->portnum)) {
2394 wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG);
2395 if (wol_cfg & (1 << adapter->portnum))
2396 return 1;
2397 }
2398
2399 return 0;
2400}