blob: 3851a677fd551dad604a4e6b6450ce4ecb99f087 [file] [log] [blame]
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001/*
2 * Copyright (C) 2003 - 2006 NetXen, Inc.
3 * 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
25 * NetXen,
26 * 3965 Freedom Circle, Fourth floor,
27 * Santa Clara, CA 95054
28 *
29 *
30 * Provides access to the Network Interface Unit h/w block.
31 *
32 */
33
34#include "netxen_nic.h"
Amit S. Kalecb8011a2006-11-29 09:00:10 -080035
36#define NETXEN_GB_MAC_SOFT_RESET 0x80000000
37#define NETXEN_GB_MAC_RESET_PROT_BLK 0x000F0000
38#define NETXEN_GB_MAC_ENABLE_TX_RX 0x00000005
39#define NETXEN_GB_MAC_PAUSED_FRMS 0x00000020
40
41static long phy_lock_timeout = 100000000;
42
Adrian Bunk993fb902007-11-05 18:07:31 +010043static int phy_lock(struct netxen_adapter *adapter)
Amit S. Kalecb8011a2006-11-29 09:00:10 -080044{
45 int i;
46 int done = 0, timeout = 0;
47
48 while (!done) {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -070049 done = netxen_nic_reg_read(adapter,
50 NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
Amit S. Kalecb8011a2006-11-29 09:00:10 -080051 if (done == 1)
52 break;
53 if (timeout >= phy_lock_timeout) {
54 return -1;
55 }
56 timeout++;
57 if (!in_atomic())
58 schedule();
59 else {
60 for (i = 0; i < 20; i++)
61 cpu_relax();
62 }
63 }
64
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -070065 netxen_crb_writelit_adapter(adapter,
66 NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
Amit S. Kalecb8011a2006-11-29 09:00:10 -080067 return 0;
68}
69
Adrian Bunk993fb902007-11-05 18:07:31 +010070static int phy_unlock(struct netxen_adapter *adapter)
Amit S. Kalecb8011a2006-11-29 09:00:10 -080071{
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -070072 adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
Amit S. Kaleed25ffa2006-12-04 09:23:25 -080073
Amit S. Kalecb8011a2006-11-29 09:00:10 -080074 return 0;
75}
Amit S. Kale3d396eb2006-10-21 15:33:03 -040076
Jeff Garzik47906542007-11-23 21:23:36 -050077/*
Amit S. Kale3d396eb2006-10-21 15:33:03 -040078 * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
79 * mii management interface.
80 *
81 * Note: The MII management interface goes through port 0.
Amit S. Kalecb8011a2006-11-29 09:00:10 -080082 * Individual phys are addressed as follows:
Amit S. Kale3d396eb2006-10-21 15:33:03 -040083 * @param phy [15:8] phy id
84 * @param reg [7:0] register number
85 *
86 * @returns 0 on success
Amit S. Kalecb8011a2006-11-29 09:00:10 -080087 * -1 on error
Amit S. Kale3d396eb2006-10-21 15:33:03 -040088 *
89 */
Jeff Garzik47906542007-11-23 21:23:36 -050090int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -070091 __u32 * readval)
Amit S. Kale3d396eb2006-10-21 15:33:03 -040092{
93 long timeout = 0;
94 long result = 0;
95 long restore = 0;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -070096 long phy = adapter->physical_port;
Al Viroa608ab92007-01-02 10:39:10 +000097 __u32 address;
98 __u32 command;
99 __u32 status;
100 __u32 mac_cfg0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400101
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800102 if (phy_lock(adapter) != 0) {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800103 return -1;
104 }
105
106 /*
107 * MII mgmt all goes through port 0 MAC interface,
108 * so it cannot be in reset
109 */
110
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700111 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400112 &mac_cfg0, 4))
113 return -EIO;
114 if (netxen_gb_get_soft_reset(mac_cfg0)) {
Al Viroa608ab92007-01-02 10:39:10 +0000115 __u32 temp;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400116 temp = 0;
117 netxen_gb_tx_reset_pb(temp);
118 netxen_gb_rx_reset_pb(temp);
119 netxen_gb_tx_reset_mac(temp);
120 netxen_gb_rx_reset_mac(temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700121 if (adapter->hw_write_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400122 NETXEN_NIU_GB_MAC_CONFIG_0(0),
123 &temp, 4))
124 return -EIO;
125 restore = 1;
126 }
127
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400128 address = 0;
129 netxen_gb_mii_mgmt_reg_addr(address, reg);
130 netxen_gb_mii_mgmt_phy_addr(address, phy);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700131 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400132 &address, 4))
133 return -EIO;
134 command = 0; /* turn off any prior activity */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700135 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400136 &command, 4))
137 return -EIO;
138 /* send read command */
139 netxen_gb_mii_mgmt_set_read_cycle(command);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700140 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400141 &command, 4))
142 return -EIO;
143
144 status = 0;
145 do {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700146 if (adapter->hw_read_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400147 NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
148 &status, 4))
149 return -EIO;
150 timeout++;
151 } while ((netxen_get_gb_mii_mgmt_busy(status)
152 || netxen_get_gb_mii_mgmt_notvalid(status))
153 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
154
155 if (timeout < NETXEN_NIU_PHY_WAITMAX) {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700156 if (adapter->hw_read_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400157 NETXEN_NIU_GB_MII_MGMT_STATUS(0),
158 readval, 4))
159 return -EIO;
160 result = 0;
161 } else
162 result = -1;
163
164 if (restore)
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700165 if (adapter->hw_write_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400166 NETXEN_NIU_GB_MAC_CONFIG_0(0),
167 &mac_cfg0, 4))
168 return -EIO;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800169 phy_unlock(adapter);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400170 return result;
171}
172
Jeff Garzik47906542007-11-23 21:23:36 -0500173/*
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400174 * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
175 * mii management interface.
176 *
177 * Note: The MII management interface goes through port 0.
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800178 * Individual phys are addressed as follows:
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400179 * @param phy [15:8] phy id
180 * @param reg [7:0] register number
181 *
182 * @returns 0 on success
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800183 * -1 on error
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400184 *
185 */
Jeff Garzik47906542007-11-23 21:23:36 -0500186int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700187 __u32 val)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400188{
189 long timeout = 0;
190 long result = 0;
191 long restore = 0;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700192 long phy = adapter->physical_port;
Al Viroa608ab92007-01-02 10:39:10 +0000193 __u32 address;
194 __u32 command;
195 __u32 status;
196 __u32 mac_cfg0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400197
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800198 /*
199 * MII mgmt all goes through port 0 MAC interface, so it
200 * cannot be in reset
201 */
202
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700203 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400204 &mac_cfg0, 4))
205 return -EIO;
206 if (netxen_gb_get_soft_reset(mac_cfg0)) {
Al Viroa608ab92007-01-02 10:39:10 +0000207 __u32 temp;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400208 temp = 0;
209 netxen_gb_tx_reset_pb(temp);
210 netxen_gb_rx_reset_pb(temp);
211 netxen_gb_tx_reset_mac(temp);
212 netxen_gb_rx_reset_mac(temp);
213
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700214 if (adapter->hw_write_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400215 NETXEN_NIU_GB_MAC_CONFIG_0(0),
216 &temp, 4))
217 return -EIO;
218 restore = 1;
219 }
220
221 command = 0; /* turn off any prior activity */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700222 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400223 &command, 4))
224 return -EIO;
225
226 address = 0;
227 netxen_gb_mii_mgmt_reg_addr(address, reg);
228 netxen_gb_mii_mgmt_phy_addr(address, phy);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700229 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400230 &address, 4))
231 return -EIO;
232
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700233 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400234 &val, 4))
235 return -EIO;
236
237 status = 0;
238 do {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700239 if (adapter->hw_read_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400240 NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
241 &status, 4))
242 return -EIO;
243 timeout++;
244 } while ((netxen_get_gb_mii_mgmt_busy(status))
245 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
246
247 if (timeout < NETXEN_NIU_PHY_WAITMAX)
248 result = 0;
249 else
250 result = -EIO;
251
252 /* restore the state of port 0 MAC in case we tampered with it */
253 if (restore)
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700254 if (adapter->hw_write_wx(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400255 NETXEN_NIU_GB_MAC_CONFIG_0(0),
256 &mac_cfg0, 4))
257 return -EIO;
258
259 return result;
260}
261
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700262int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400263{
264 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
265 return 0;
266}
267
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700268int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400269{
270 int result = 0;
Al Viroa608ab92007-01-02 10:39:10 +0000271 __u32 enable = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400272 netxen_set_phy_int_link_status_changed(enable);
273 netxen_set_phy_int_autoneg_completed(enable);
274 netxen_set_phy_int_speed_changed(enable);
275
276 if (0 !=
Jeff Garzik47906542007-11-23 21:23:36 -0500277 netxen_niu_gbe_phy_write(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400278 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,
279 enable))
280 result = -EIO;
281
282 return result;
283}
284
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700285int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400286{
287 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
288 return 0;
289}
290
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700291int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400292{
293 int result = 0;
294 if (0 !=
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700295 netxen_niu_gbe_phy_write(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400296 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0))
297 result = -EIO;
298
299 return result;
300}
301
Adrian Bunk993fb902007-11-05 18:07:31 +0100302static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400303{
304 int result = 0;
305 if (0 !=
Jeff Garzik47906542007-11-23 21:23:36 -0500306 netxen_niu_gbe_phy_write(adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400307 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
308 -EIO))
309 result = -EIO;
310
311 return result;
312}
313
Jeff Garzik47906542007-11-23 21:23:36 -0500314/*
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400315 * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
316 *
317 */
Adrian Bunk993fb902007-11-05 18:07:31 +0100318static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
319 int port, long enable)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400320{
321 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
322 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
323 0x80000000);
324 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
325 0x0000f0025);
326 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
327 0xf1ff);
328 netxen_crb_writelit_adapter(adapter,
329 NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
330 netxen_crb_writelit_adapter(adapter,
331 NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
332 netxen_crb_writelit_adapter(adapter,
333 (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
334 netxen_crb_writelit_adapter(adapter,
335 NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
336
337 if (enable) {
Jeff Garzik47906542007-11-23 21:23:36 -0500338 /*
339 * Do NOT enable flow control until a suitable solution for
340 * shutting down pause frames is found.
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400341 */
342 netxen_crb_writelit_adapter(adapter,
343 NETXEN_NIU_GB_MAC_CONFIG_0(port),
344 0x5);
345 }
346
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700347 if (netxen_niu_gbe_enable_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400348 printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700349 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400350 printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
351}
352
Jeff Garzik47906542007-11-23 21:23:36 -0500353/*
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400354 * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC
355 */
Adrian Bunk993fb902007-11-05 18:07:31 +0100356static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
357 int port, long enable)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400358{
359 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
360 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
361 0x80000000);
362 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
363 0x0000f0025);
364 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
365 0xf2ff);
366 netxen_crb_writelit_adapter(adapter,
367 NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
368 netxen_crb_writelit_adapter(adapter,
369 NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
370 netxen_crb_writelit_adapter(adapter,
371 (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
372 netxen_crb_writelit_adapter(adapter,
373 NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
374
375 if (enable) {
Jeff Garzik47906542007-11-23 21:23:36 -0500376 /*
377 * Do NOT enable flow control until a suitable solution for
378 * shutting down pause frames is found.
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400379 */
380 netxen_crb_writelit_adapter(adapter,
381 NETXEN_NIU_GB_MAC_CONFIG_0(port),
382 0x5);
383 }
384
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700385 if (netxen_niu_gbe_enable_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400386 printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700387 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400388 printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
389}
390
391int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
392{
393 int result = 0;
Al Viroa608ab92007-01-02 10:39:10 +0000394 __u32 status;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700395
396 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
397 return 0;
398
Amit S. Kale80922fb2006-12-04 09:18:00 -0800399 if (adapter->disable_phy_interrupts)
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700400 adapter->disable_phy_interrupts(adapter);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400401 mdelay(2);
402
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700403 if (0 == netxen_niu_gbe_phy_read(adapter,
404 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400405 if (netxen_get_phy_link(status)) {
406 if (netxen_get_phy_speed(status) == 2) {
407 netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
408 } else if ((netxen_get_phy_speed(status) == 1)
409 || (netxen_get_phy_speed(status) == 0)) {
410 netxen_niu_gbe_set_mii_mode(adapter, port, 1);
411 } else {
412 result = -1;
413 }
414
415 } else {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800416 /*
417 * We don't have link. Cable must be unconnected.
418 * Enable phy interrupts so we take action when
419 * plugged in.
420 */
421
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400422 netxen_crb_writelit_adapter(adapter,
423 NETXEN_NIU_GB_MAC_CONFIG_0
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800424 (port),
425 NETXEN_GB_MAC_SOFT_RESET);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400426 netxen_crb_writelit_adapter(adapter,
427 NETXEN_NIU_GB_MAC_CONFIG_0
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800428 (port),
429 NETXEN_GB_MAC_RESET_PROT_BLK
430 | NETXEN_GB_MAC_ENABLE_TX_RX
431 |
432 NETXEN_GB_MAC_PAUSED_FRMS);
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700433 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400434 printk(KERN_ERR PFX
435 "ERROR clearing PHY interrupts\n");
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700436 if (netxen_niu_gbe_enable_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400437 printk(KERN_ERR PFX
438 "ERROR enabling PHY interrupts\n");
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700439 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400440 printk(KERN_ERR PFX
441 "ERROR clearing PHY interrupts\n");
442 result = -1;
443 }
444 } else {
445 result = -EIO;
446 }
447 return result;
448}
449
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800450int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
451{
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700452 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
453 netxen_crb_writelit_adapter(adapter,
454 NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
455 netxen_crb_writelit_adapter(adapter,
456 NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
457 }
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700458
459 return 0;
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800460}
461
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400462/*
463 * Return the current station MAC address.
464 * Note that the passed-in value must already be in network byte order.
465 */
Adrian Bunk993fb902007-11-05 18:07:31 +0100466static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
467 netxen_ethernet_macaddr_t * addr)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400468{
Al Viroa608ab92007-01-02 10:39:10 +0000469 u32 stationhigh;
470 u32 stationlow;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700471 int phy = adapter->physical_port;
Al Viroa608ab92007-01-02 10:39:10 +0000472 u8 val[8];
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400473
474 if (addr == NULL)
475 return -EINVAL;
476 if ((phy < 0) || (phy > 3))
477 return -EINVAL;
478
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700479 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400480 &stationhigh, 4))
481 return -EIO;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700482 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400483 &stationlow, 4))
484 return -EIO;
Al Viroa608ab92007-01-02 10:39:10 +0000485 ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
486 ((__le32 *)val)[0] = cpu_to_le32(stationlow);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400487
Al Viroa608ab92007-01-02 10:39:10 +0000488 memcpy(addr, val + 2, 6);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400489
490 return 0;
491}
492
493/*
494 * Set the station MAC address.
495 * Note that the passed-in value must already be in network byte order.
496 */
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700497int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400498 netxen_ethernet_macaddr_t addr)
499{
Al Viroa608ab92007-01-02 10:39:10 +0000500 u8 temp[4];
501 u32 val;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700502 int phy = adapter->physical_port;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800503 unsigned char mac_addr[6];
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800504 int i;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400505
Dhananjay Phadke24a7a452008-08-01 03:14:55 -0700506 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
507 return 0;
508
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800509 for (i = 0; i < 10; i++) {
Al Viroa608ab92007-01-02 10:39:10 +0000510 temp[0] = temp[1] = 0;
511 memcpy(temp + 2, addr, 2);
512 val = le32_to_cpu(*(__le32 *)temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700513 if (adapter->hw_write_wx(adapter,
514 NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800515 return -EIO;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400516
Al Viroa608ab92007-01-02 10:39:10 +0000517 memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
518 val = le32_to_cpu(*(__le32 *)temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700519 if (adapter->hw_write_wx(adapter,
520 NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800521 return -2;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400522
Jeff Garzik47906542007-11-23 21:23:36 -0500523 netxen_niu_macaddr_get(adapter,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800524 (netxen_ethernet_macaddr_t *) mac_addr);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800525 if (memcmp(mac_addr, addr, 6) == 0)
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800526 break;
527 }
528
529 if (i == 10) {
530 printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700531 netxen_nic_driver_name, adapter->netdev->name);
Johannes Berge1749612008-10-27 15:59:26 -0700532 printk(KERN_ERR "MAC address set: %pM.\n", addr);
533 printk(KERN_ERR "MAC address get: %pM.\n", mac_addr);
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800534 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400535 return 0;
536}
537
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400538/* Disable a GbE interface */
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700539int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400540{
Al Viroa608ab92007-01-02 10:39:10 +0000541 __u32 mac_cfg0;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700542 u32 port = adapter->physical_port;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400543
Dhananjay Phadke24a7a452008-08-01 03:14:55 -0700544 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
545 return 0;
546
Bill Nottingham287aa832007-05-30 03:59:02 -0400547 if (port > NETXEN_NIU_MAX_GBE_PORTS)
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700548 return -EINVAL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400549 mac_cfg0 = 0;
550 netxen_gb_soft_reset(mac_cfg0);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700551 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400552 &mac_cfg0, 4))
553 return -EIO;
554 return 0;
555}
556
557/* Disable an XG interface */
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700558int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400559{
Al Viroa608ab92007-01-02 10:39:10 +0000560 __u32 mac_cfg;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700561 u32 port = adapter->physical_port;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400562
Dhananjay Phadke24a7a452008-08-01 03:14:55 -0700563 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
564 return 0;
565
dhananjay@netxen.com72b0a7a2007-12-26 10:23:56 -0800566 if (port > NETXEN_NIU_MAX_XG_PORTS)
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700567 return -EINVAL;
dhananjay@netxen.com72b0a7a2007-12-26 10:23:56 -0800568
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400569 mac_cfg = 0;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700570 if (adapter->hw_write_wx(adapter,
dhananjay@netxen.com72b0a7a2007-12-26 10:23:56 -0800571 NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400572 return -EIO;
573 return 0;
574}
575
576/* Set promiscuous mode for a GbE interface */
Jeff Garzik47906542007-11-23 21:23:36 -0500577int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700578 u32 mode)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400579{
Al Viroa608ab92007-01-02 10:39:10 +0000580 __u32 reg;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700581 u32 port = adapter->physical_port;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400582
Bill Nottingham287aa832007-05-30 03:59:02 -0400583 if (port > NETXEN_NIU_MAX_GBE_PORTS)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400584 return -EINVAL;
585
586 /* save previous contents */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700587 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400588 &reg, 4))
589 return -EIO;
590 if (mode == NETXEN_NIU_PROMISC_MODE) {
591 switch (port) {
592 case 0:
593 netxen_clear_gb_drop_gb0(reg);
594 break;
595 case 1:
596 netxen_clear_gb_drop_gb1(reg);
597 break;
598 case 2:
599 netxen_clear_gb_drop_gb2(reg);
600 break;
601 case 3:
602 netxen_clear_gb_drop_gb3(reg);
603 break;
604 default:
605 return -EIO;
606 }
607 } else {
608 switch (port) {
609 case 0:
610 netxen_set_gb_drop_gb0(reg);
611 break;
612 case 1:
613 netxen_set_gb_drop_gb1(reg);
614 break;
615 case 2:
616 netxen_set_gb_drop_gb2(reg);
617 break;
618 case 3:
619 netxen_set_gb_drop_gb3(reg);
620 break;
621 default:
622 return -EIO;
623 }
624 }
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700625 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400626 &reg, 4))
627 return -EIO;
628 return 0;
629}
630
631/*
632 * Set the MAC address for an XG port
633 * Note that the passed-in value must already be in network byte order.
634 */
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700635int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400636 netxen_ethernet_macaddr_t addr)
637{
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700638 int phy = adapter->physical_port;
Al Viroa608ab92007-01-02 10:39:10 +0000639 u8 temp[4];
640 u32 val;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400641
Dhananjay Phadke24a7a452008-08-01 03:14:55 -0700642 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
643 return 0;
644
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700645 if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400646 return -EIO;
647
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700648 temp[0] = temp[1] = 0;
649 switch (phy) {
650 case 0:
651 memcpy(temp + 2, addr, 2);
652 val = le32_to_cpu(*(__le32 *)temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700653 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700654 &val, 4))
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400655 return -EIO;
656
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700657 memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
658 val = le32_to_cpu(*(__le32 *)temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700659 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700660 &val, 4))
661 return -EIO;
662 break;
663
664 case 1:
665 memcpy(temp + 2, addr, 2);
666 val = le32_to_cpu(*(__le32 *)temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700667 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700668 &val, 4))
669 return -EIO;
670
671 memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
672 val = le32_to_cpu(*(__le32 *)temp);
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700673 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700674 &val, 4))
675 return -EIO;
676 break;
677
678 default:
679 printk(KERN_ERR "Unknown port %d\n", phy);
680 break;
681 }
682
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400683 return 0;
684}
685
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400686int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700687 u32 mode)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400688{
Al Viroa608ab92007-01-02 10:39:10 +0000689 __u32 reg;
Dhananjay Phadke3276fba2008-06-15 22:59:44 -0700690 u32 port = adapter->physical_port;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400691
Bill Nottingham287aa832007-05-30 03:59:02 -0400692 if (port > NETXEN_NIU_MAX_XG_PORTS)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400693 return -EINVAL;
694
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700695 if (adapter->hw_read_wx(adapter,
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700696 NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
697 return -EIO;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400698 if (mode == NETXEN_NIU_PROMISC_MODE)
699 reg = (reg | 0x2000UL);
700 else
701 reg = (reg & ~0x2000UL);
702
Dhananjay Phadke623621b2008-07-21 19:44:01 -0700703 if (mode == NETXEN_NIU_ALLMULTI_MODE)
704 reg = (reg | 0x1000UL);
705 else
706 reg = (reg & ~0x1000UL);
707
Mithlesh Thukral6c80b182007-04-20 07:55:26 -0700708 netxen_crb_writelit_adapter(adapter,
709 NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400710
711 return 0;
712}