Commit | Line | Data |
---|---|---|
3d396eb1 | 1 | /* |
5d242f1c | 2 | * Copyright (C) 2003 - 2009 NetXen, Inc. |
3d396eb1 | 3 | * All rights reserved. |
80922fbc | 4 | * |
3d396eb1 AK |
5 | * 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. | |
cb8011ad | 9 | * |
3d396eb1 AK |
10 | * 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. | |
cb8011ad | 14 | * |
3d396eb1 AK |
15 | * 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. | |
80922fbc | 19 | * |
3d396eb1 AK |
20 | * The full GNU General Public License is included in this distribution |
21 | * in the file called LICENSE. | |
80922fbc | 22 | * |
3d396eb1 AK |
23 | * Contact Information: |
24 | * info@netxen.com | |
5d242f1c DP |
25 | * NetXen Inc, |
26 | * 18922 Forge Drive | |
27 | * Cupertino, CA 95014-0701 | |
3d396eb1 AK |
28 | * |
29 | */ | |
30 | ||
31 | #include "netxen_nic.h" | |
cb8011ad AK |
32 | |
33 | #define NETXEN_GB_MAC_SOFT_RESET 0x80000000 | |
34 | #define NETXEN_GB_MAC_RESET_PROT_BLK 0x000F0000 | |
35 | #define NETXEN_GB_MAC_ENABLE_TX_RX 0x00000005 | |
36 | #define NETXEN_GB_MAC_PAUSED_FRMS 0x00000020 | |
37 | ||
38 | static long phy_lock_timeout = 100000000; | |
39 | ||
993fb90c | 40 | static int phy_lock(struct netxen_adapter *adapter) |
cb8011ad AK |
41 | { |
42 | int i; | |
43 | int done = 0, timeout = 0; | |
44 | ||
45 | while (!done) { | |
f98a9f69 | 46 | done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); |
cb8011ad AK |
47 | if (done == 1) |
48 | break; | |
49 | if (timeout >= phy_lock_timeout) { | |
50 | return -1; | |
51 | } | |
52 | timeout++; | |
53 | if (!in_atomic()) | |
54 | schedule(); | |
55 | else { | |
56 | for (i = 0; i < 20; i++) | |
57 | cpu_relax(); | |
58 | } | |
59 | } | |
60 | ||
f98a9f69 | 61 | NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER); |
cb8011ad AK |
62 | return 0; |
63 | } | |
64 | ||
993fb90c | 65 | static int phy_unlock(struct netxen_adapter *adapter) |
cb8011ad | 66 | { |
3ce06a32 | 67 | adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)); |
ed25ffa1 | 68 | |
cb8011ad AK |
69 | return 0; |
70 | } | |
3d396eb1 | 71 | |
4790654c | 72 | /* |
3d396eb1 AK |
73 | * netxen_niu_gbe_phy_read - read a register from the GbE PHY via |
74 | * mii management interface. | |
75 | * | |
76 | * Note: The MII management interface goes through port 0. | |
cb8011ad | 77 | * Individual phys are addressed as follows: |
3d396eb1 AK |
78 | * @param phy [15:8] phy id |
79 | * @param reg [7:0] register number | |
80 | * | |
81 | * @returns 0 on success | |
cb8011ad | 82 | * -1 on error |
3d396eb1 AK |
83 | * |
84 | */ | |
4790654c | 85 | int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, |
13ba9c77 | 86 | __u32 * readval) |
3d396eb1 AK |
87 | { |
88 | long timeout = 0; | |
89 | long result = 0; | |
90 | long restore = 0; | |
3276fbad | 91 | long phy = adapter->physical_port; |
a608ab9c AV |
92 | __u32 address; |
93 | __u32 command; | |
94 | __u32 status; | |
95 | __u32 mac_cfg0; | |
3d396eb1 | 96 | |
ed25ffa1 | 97 | if (phy_lock(adapter) != 0) { |
cb8011ad AK |
98 | return -1; |
99 | } | |
100 | ||
101 | /* | |
102 | * MII mgmt all goes through port 0 MAC interface, | |
103 | * so it cannot be in reset | |
104 | */ | |
105 | ||
f98a9f69 | 106 | mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); |
3d396eb1 | 107 | if (netxen_gb_get_soft_reset(mac_cfg0)) { |
a608ab9c | 108 | __u32 temp; |
3d396eb1 AK |
109 | temp = 0; |
110 | netxen_gb_tx_reset_pb(temp); | |
111 | netxen_gb_rx_reset_pb(temp); | |
112 | netxen_gb_tx_reset_mac(temp); | |
113 | netxen_gb_rx_reset_mac(temp); | |
f98a9f69 | 114 | if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) |
3d396eb1 AK |
115 | return -EIO; |
116 | restore = 1; | |
117 | } | |
118 | ||
3d396eb1 AK |
119 | address = 0; |
120 | netxen_gb_mii_mgmt_reg_addr(address, reg); | |
121 | netxen_gb_mii_mgmt_phy_addr(address, phy); | |
f98a9f69 | 122 | if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) |
3d396eb1 AK |
123 | return -EIO; |
124 | command = 0; /* turn off any prior activity */ | |
f98a9f69 | 125 | if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) |
3d396eb1 AK |
126 | return -EIO; |
127 | /* send read command */ | |
128 | netxen_gb_mii_mgmt_set_read_cycle(command); | |
f98a9f69 | 129 | if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) |
3d396eb1 AK |
130 | return -EIO; |
131 | ||
132 | status = 0; | |
133 | do { | |
f98a9f69 | 134 | status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); |
3d396eb1 AK |
135 | timeout++; |
136 | } while ((netxen_get_gb_mii_mgmt_busy(status) | |
137 | || netxen_get_gb_mii_mgmt_notvalid(status)) | |
138 | && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); | |
139 | ||
140 | if (timeout < NETXEN_NIU_PHY_WAITMAX) { | |
f98a9f69 | 141 | *readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0)); |
3d396eb1 AK |
142 | result = 0; |
143 | } else | |
144 | result = -1; | |
145 | ||
146 | if (restore) | |
f98a9f69 | 147 | if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) |
3d396eb1 | 148 | return -EIO; |
ed25ffa1 | 149 | phy_unlock(adapter); |
3d396eb1 AK |
150 | return result; |
151 | } | |
152 | ||
4790654c | 153 | /* |
3d396eb1 AK |
154 | * netxen_niu_gbe_phy_write - write a register to the GbE PHY via |
155 | * mii management interface. | |
156 | * | |
157 | * Note: The MII management interface goes through port 0. | |
cb8011ad | 158 | * Individual phys are addressed as follows: |
3d396eb1 AK |
159 | * @param phy [15:8] phy id |
160 | * @param reg [7:0] register number | |
161 | * | |
162 | * @returns 0 on success | |
cb8011ad | 163 | * -1 on error |
3d396eb1 AK |
164 | * |
165 | */ | |
4790654c | 166 | int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, |
13ba9c77 | 167 | __u32 val) |
3d396eb1 AK |
168 | { |
169 | long timeout = 0; | |
170 | long result = 0; | |
171 | long restore = 0; | |
3276fbad | 172 | long phy = adapter->physical_port; |
a608ab9c AV |
173 | __u32 address; |
174 | __u32 command; | |
175 | __u32 status; | |
176 | __u32 mac_cfg0; | |
3d396eb1 | 177 | |
cb8011ad AK |
178 | /* |
179 | * MII mgmt all goes through port 0 MAC interface, so it | |
180 | * cannot be in reset | |
181 | */ | |
182 | ||
f98a9f69 | 183 | mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); |
3d396eb1 | 184 | if (netxen_gb_get_soft_reset(mac_cfg0)) { |
a608ab9c | 185 | __u32 temp; |
3d396eb1 AK |
186 | temp = 0; |
187 | netxen_gb_tx_reset_pb(temp); | |
188 | netxen_gb_rx_reset_pb(temp); | |
189 | netxen_gb_tx_reset_mac(temp); | |
190 | netxen_gb_rx_reset_mac(temp); | |
191 | ||
f98a9f69 | 192 | if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) |
3d396eb1 AK |
193 | return -EIO; |
194 | restore = 1; | |
195 | } | |
196 | ||
197 | command = 0; /* turn off any prior activity */ | |
f98a9f69 | 198 | if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) |
3d396eb1 AK |
199 | return -EIO; |
200 | ||
201 | address = 0; | |
202 | netxen_gb_mii_mgmt_reg_addr(address, reg); | |
203 | netxen_gb_mii_mgmt_phy_addr(address, phy); | |
f98a9f69 | 204 | if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) |
3d396eb1 AK |
205 | return -EIO; |
206 | ||
f98a9f69 | 207 | if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val)) |
3d396eb1 AK |
208 | return -EIO; |
209 | ||
210 | status = 0; | |
211 | do { | |
f98a9f69 | 212 | status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); |
3d396eb1 AK |
213 | timeout++; |
214 | } while ((netxen_get_gb_mii_mgmt_busy(status)) | |
215 | && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); | |
216 | ||
217 | if (timeout < NETXEN_NIU_PHY_WAITMAX) | |
218 | result = 0; | |
219 | else | |
220 | result = -EIO; | |
221 | ||
222 | /* restore the state of port 0 MAC in case we tampered with it */ | |
223 | if (restore) | |
f98a9f69 | 224 | if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) |
3d396eb1 AK |
225 | return -EIO; |
226 | ||
227 | return result; | |
228 | } | |
229 | ||
13ba9c77 | 230 | int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter) |
3d396eb1 | 231 | { |
f98a9f69 | 232 | NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x3f); |
3d396eb1 AK |
233 | return 0; |
234 | } | |
235 | ||
13ba9c77 | 236 | int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter) |
3d396eb1 AK |
237 | { |
238 | int result = 0; | |
a608ab9c | 239 | __u32 enable = 0; |
3d396eb1 AK |
240 | netxen_set_phy_int_link_status_changed(enable); |
241 | netxen_set_phy_int_autoneg_completed(enable); | |
242 | netxen_set_phy_int_speed_changed(enable); | |
243 | ||
244 | if (0 != | |
4790654c | 245 | netxen_niu_gbe_phy_write(adapter, |
3d396eb1 AK |
246 | NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, |
247 | enable)) | |
248 | result = -EIO; | |
249 | ||
250 | return result; | |
251 | } | |
252 | ||
13ba9c77 | 253 | int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter) |
3d396eb1 | 254 | { |
f98a9f69 | 255 | NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x7f); |
3d396eb1 AK |
256 | return 0; |
257 | } | |
258 | ||
13ba9c77 | 259 | int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter) |
3d396eb1 AK |
260 | { |
261 | int result = 0; | |
262 | if (0 != | |
13ba9c77 | 263 | netxen_niu_gbe_phy_write(adapter, |
3d396eb1 AK |
264 | NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0)) |
265 | result = -EIO; | |
266 | ||
267 | return result; | |
268 | } | |
269 | ||
993fb90c | 270 | static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter) |
3d396eb1 AK |
271 | { |
272 | int result = 0; | |
273 | if (0 != | |
4790654c | 274 | netxen_niu_gbe_phy_write(adapter, |
3d396eb1 AK |
275 | NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, |
276 | -EIO)) | |
277 | result = -EIO; | |
278 | ||
279 | return result; | |
280 | } | |
281 | ||
4790654c | 282 | /* |
3d396eb1 AK |
283 | * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC |
284 | * | |
285 | */ | |
993fb90c AB |
286 | static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, |
287 | int port, long enable) | |
3d396eb1 | 288 | { |
f98a9f69 DP |
289 | NXWR32(adapter, NETXEN_NIU_MODE, 0x2); |
290 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); | |
291 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); | |
292 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf1ff); | |
293 | NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); | |
294 | NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); | |
295 | NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); | |
296 | NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); | |
3d396eb1 AK |
297 | |
298 | if (enable) { | |
4790654c JG |
299 | /* |
300 | * Do NOT enable flow control until a suitable solution for | |
301 | * shutting down pause frames is found. | |
3d396eb1 | 302 | */ |
f98a9f69 | 303 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); |
3d396eb1 AK |
304 | } |
305 | ||
13ba9c77 | 306 | if (netxen_niu_gbe_enable_phy_interrupts(adapter)) |
e98e3350 | 307 | printk(KERN_ERR "ERROR enabling PHY interrupts\n"); |
13ba9c77 | 308 | if (netxen_niu_gbe_clear_phy_interrupts(adapter)) |
e98e3350 | 309 | printk(KERN_ERR "ERROR clearing PHY interrupts\n"); |
3d396eb1 AK |
310 | } |
311 | ||
4790654c | 312 | /* |
3d396eb1 AK |
313 | * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC |
314 | */ | |
993fb90c AB |
315 | static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, |
316 | int port, long enable) | |
3d396eb1 | 317 | { |
f98a9f69 DP |
318 | NXWR32(adapter, NETXEN_NIU_MODE, 0x2); |
319 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); | |
320 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); | |
321 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf2ff); | |
322 | NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); | |
323 | NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); | |
324 | NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); | |
325 | NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); | |
3d396eb1 AK |
326 | |
327 | if (enable) { | |
4790654c JG |
328 | /* |
329 | * Do NOT enable flow control until a suitable solution for | |
330 | * shutting down pause frames is found. | |
3d396eb1 | 331 | */ |
f98a9f69 | 332 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); |
3d396eb1 AK |
333 | } |
334 | ||
13ba9c77 | 335 | if (netxen_niu_gbe_enable_phy_interrupts(adapter)) |
e98e3350 | 336 | printk(KERN_ERR "ERROR enabling PHY interrupts\n"); |
13ba9c77 | 337 | if (netxen_niu_gbe_clear_phy_interrupts(adapter)) |
e98e3350 | 338 | printk(KERN_ERR "ERROR clearing PHY interrupts\n"); |
3d396eb1 AK |
339 | } |
340 | ||
341 | int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) | |
342 | { | |
343 | int result = 0; | |
a608ab9c | 344 | __u32 status; |
c9fc891f DP |
345 | |
346 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | |
347 | return 0; | |
348 | ||
80922fbc | 349 | if (adapter->disable_phy_interrupts) |
13ba9c77 | 350 | adapter->disable_phy_interrupts(adapter); |
3d396eb1 AK |
351 | mdelay(2); |
352 | ||
c9fc891f DP |
353 | if (0 == netxen_niu_gbe_phy_read(adapter, |
354 | NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) { | |
3d396eb1 AK |
355 | if (netxen_get_phy_link(status)) { |
356 | if (netxen_get_phy_speed(status) == 2) { | |
357 | netxen_niu_gbe_set_gmii_mode(adapter, port, 1); | |
358 | } else if ((netxen_get_phy_speed(status) == 1) | |
359 | || (netxen_get_phy_speed(status) == 0)) { | |
360 | netxen_niu_gbe_set_mii_mode(adapter, port, 1); | |
361 | } else { | |
362 | result = -1; | |
363 | } | |
364 | ||
365 | } else { | |
cb8011ad AK |
366 | /* |
367 | * We don't have link. Cable must be unconnected. | |
368 | * Enable phy interrupts so we take action when | |
369 | * plugged in. | |
370 | */ | |
371 | ||
f98a9f69 | 372 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), |
cb8011ad | 373 | NETXEN_GB_MAC_SOFT_RESET); |
f98a9f69 DP |
374 | NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), |
375 | NETXEN_GB_MAC_RESET_PROT_BLK | | |
376 | NETXEN_GB_MAC_ENABLE_TX_RX | | |
377 | NETXEN_GB_MAC_PAUSED_FRMS); | |
13ba9c77 | 378 | if (netxen_niu_gbe_clear_phy_interrupts(adapter)) |
e98e3350 | 379 | printk(KERN_ERR |
3d396eb1 | 380 | "ERROR clearing PHY interrupts\n"); |
13ba9c77 | 381 | if (netxen_niu_gbe_enable_phy_interrupts(adapter)) |
e98e3350 | 382 | printk(KERN_ERR |
3d396eb1 | 383 | "ERROR enabling PHY interrupts\n"); |
13ba9c77 | 384 | if (netxen_niu_gbe_clear_phy_interrupts(adapter)) |
e98e3350 | 385 | printk(KERN_ERR |
3d396eb1 AK |
386 | "ERROR clearing PHY interrupts\n"); |
387 | result = -1; | |
388 | } | |
389 | } else { | |
390 | result = -EIO; | |
391 | } | |
392 | return result; | |
393 | } | |
394 | ||
cb8011ad AK |
395 | int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) |
396 | { | |
c9fc891f | 397 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { |
f98a9f69 DP |
398 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); |
399 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); | |
c9fc891f | 400 | } |
cb8011ad | 401 | |
6c80b18d | 402 | return 0; |
cb8011ad AK |
403 | } |
404 | ||
3d396eb1 | 405 | /* Disable a GbE interface */ |
3176ff3e | 406 | int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) |
3d396eb1 | 407 | { |
a608ab9c | 408 | __u32 mac_cfg0; |
3276fbad | 409 | u32 port = adapter->physical_port; |
3d396eb1 | 410 | |
24a7a455 DP |
411 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
412 | return 0; | |
413 | ||
287aa83d | 414 | if (port > NETXEN_NIU_MAX_GBE_PORTS) |
6c80b18d | 415 | return -EINVAL; |
3d396eb1 AK |
416 | mac_cfg0 = 0; |
417 | netxen_gb_soft_reset(mac_cfg0); | |
f98a9f69 | 418 | if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0)) |
3d396eb1 AK |
419 | return -EIO; |
420 | return 0; | |
421 | } | |
422 | ||
423 | /* Disable an XG interface */ | |
3176ff3e | 424 | int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) |
3d396eb1 | 425 | { |
a608ab9c | 426 | __u32 mac_cfg; |
3276fbad | 427 | u32 port = adapter->physical_port; |
3d396eb1 | 428 | |
24a7a455 DP |
429 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
430 | return 0; | |
431 | ||
72b0a7a8 | 432 | if (port > NETXEN_NIU_MAX_XG_PORTS) |
6c80b18d | 433 | return -EINVAL; |
72b0a7a8 | 434 | |
3d396eb1 | 435 | mac_cfg = 0; |
f98a9f69 DP |
436 | if (NXWR32(adapter, |
437 | NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) | |
3d396eb1 AK |
438 | return -EIO; |
439 | return 0; | |
440 | } | |
441 | ||
442 | /* Set promiscuous mode for a GbE interface */ | |
4790654c | 443 | int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, |
9ad27643 | 444 | u32 mode) |
3d396eb1 | 445 | { |
a608ab9c | 446 | __u32 reg; |
3276fbad | 447 | u32 port = adapter->physical_port; |
3d396eb1 | 448 | |
287aa83d | 449 | if (port > NETXEN_NIU_MAX_GBE_PORTS) |
3d396eb1 AK |
450 | return -EINVAL; |
451 | ||
452 | /* save previous contents */ | |
f98a9f69 | 453 | reg = NXRD32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR); |
3d396eb1 AK |
454 | if (mode == NETXEN_NIU_PROMISC_MODE) { |
455 | switch (port) { | |
456 | case 0: | |
457 | netxen_clear_gb_drop_gb0(reg); | |
458 | break; | |
459 | case 1: | |
460 | netxen_clear_gb_drop_gb1(reg); | |
461 | break; | |
462 | case 2: | |
463 | netxen_clear_gb_drop_gb2(reg); | |
464 | break; | |
465 | case 3: | |
466 | netxen_clear_gb_drop_gb3(reg); | |
467 | break; | |
468 | default: | |
469 | return -EIO; | |
470 | } | |
471 | } else { | |
472 | switch (port) { | |
473 | case 0: | |
474 | netxen_set_gb_drop_gb0(reg); | |
475 | break; | |
476 | case 1: | |
477 | netxen_set_gb_drop_gb1(reg); | |
478 | break; | |
479 | case 2: | |
480 | netxen_set_gb_drop_gb2(reg); | |
481 | break; | |
482 | case 3: | |
483 | netxen_set_gb_drop_gb3(reg); | |
484 | break; | |
485 | default: | |
486 | return -EIO; | |
487 | } | |
488 | } | |
f98a9f69 | 489 | if (NXWR32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg)) |
3d396eb1 AK |
490 | return -EIO; |
491 | return 0; | |
492 | } | |
493 | ||
3d396eb1 | 494 | int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, |
9ad27643 | 495 | u32 mode) |
3d396eb1 | 496 | { |
a608ab9c | 497 | __u32 reg; |
3276fbad | 498 | u32 port = adapter->physical_port; |
3d396eb1 | 499 | |
287aa83d | 500 | if (port > NETXEN_NIU_MAX_XG_PORTS) |
3d396eb1 AK |
501 | return -EINVAL; |
502 | ||
f98a9f69 | 503 | reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); |
3d396eb1 AK |
504 | if (mode == NETXEN_NIU_PROMISC_MODE) |
505 | reg = (reg | 0x2000UL); | |
506 | else | |
507 | reg = (reg & ~0x2000UL); | |
508 | ||
623621b0 DP |
509 | if (mode == NETXEN_NIU_ALLMULTI_MODE) |
510 | reg = (reg | 0x1000UL); | |
511 | else | |
512 | reg = (reg & ~0x1000UL); | |
513 | ||
f98a9f69 | 514 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); |
3d396eb1 AK |
515 | |
516 | return 0; | |
517 | } | |
3d0a3cc9 DP |
518 | |
519 | int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) | |
520 | { | |
521 | u32 mac_hi, mac_lo; | |
522 | u32 reg_hi, reg_lo; | |
523 | ||
524 | u8 phy = adapter->physical_port; | |
525 | u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ? | |
526 | NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS; | |
527 | ||
528 | if (phy >= phy_count) | |
529 | return -EINVAL; | |
530 | ||
531 | mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24); | |
532 | mac_hi = addr[2] | ((u32)addr[3] << 8) | | |
533 | ((u32)addr[4] << 16) | ((u32)addr[5] << 24); | |
534 | ||
535 | if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { | |
536 | reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy); | |
537 | reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy); | |
538 | } else { | |
539 | reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy); | |
540 | reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy); | |
541 | } | |
542 | ||
543 | /* write twice to flush */ | |
544 | if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) | |
545 | return -EIO; | |
546 | if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) | |
547 | return -EIO; | |
548 | ||
549 | return 0; | |
550 | } |