netxen: ethtool fixes
[safe/jmp/linux-2.6] / drivers / net / netxen / netxen_nic_ethtool.c
1 /*
2  * Copyright (C) 2003 - 2006 NetXen, Inc.
3  * All rights reserved.
4  *
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.
9  *
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.
14  *
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.
19  *
20  * The full GNU General Public License is included in this distribution
21  * in the file called LICENSE.
22  *
23  * Contact Information:
24  *    info@netxen.com
25  * NetXen,
26  * 3965 Freedom Circle, Fourth floor,
27  * Santa Clara, CA 95054
28  *
29  *
30  * ethtool support for netxen nic
31  *
32  */
33
34 #include <linux/types.h>
35 #include <linux/delay.h>
36 #include <asm/uaccess.h>
37 #include <linux/pci.h>
38 #include <asm/io.h>
39 #include <linux/netdevice.h>
40 #include <linux/ethtool.h>
41 #include <linux/version.h>
42
43 #include "netxen_nic.h"
44 #include "netxen_nic_hw.h"
45 #include "netxen_nic_phan_reg.h"
46
47 struct netxen_nic_stats {
48         char stat_string[ETH_GSTRING_LEN];
49         int sizeof_stat;
50         int stat_offset;
51 };
52
53 #define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \
54                         offsetof(struct netxen_adapter, m)
55
56 #define NETXEN_NIC_PORT_WINDOW 0x10000
57 #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
58
59 static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
60         {"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)},
61         {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
62         {"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)},
63         {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
64         {"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)},
65         {"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)},
66         {"polled", NETXEN_NIC_STAT(stats.polled)},
67         {"uphappy", NETXEN_NIC_STAT(stats.uphappy)},
68         {"updropped", NETXEN_NIC_STAT(stats.updropped)},
69         {"uplcong", NETXEN_NIC_STAT(stats.uplcong)},
70         {"uphcong", NETXEN_NIC_STAT(stats.uphcong)},
71         {"upmcong", NETXEN_NIC_STAT(stats.upmcong)},
72         {"updunno", NETXEN_NIC_STAT(stats.updunno)},
73         {"skb_freed", NETXEN_NIC_STAT(stats.skbfreed)},
74         {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
75         {"tx_null_skb", NETXEN_NIC_STAT(stats.txnullskb)},
76         {"csummed", NETXEN_NIC_STAT(stats.csummed)},
77         {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)},
78         {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
79         {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
80 };
81
82 #define NETXEN_NIC_STATS_LEN    ARRAY_SIZE(netxen_nic_gstrings_stats)
83
84 static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
85         "Register_Test_on_offline",
86         "Link_Test_on_offline"
87 };
88
89 #define NETXEN_NIC_TEST_LEN sizeof(netxen_nic_gstrings_test) / ETH_GSTRING_LEN
90
91 #define NETXEN_NIC_REGS_COUNT 42
92 #define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
93 #define NETXEN_MAX_EEPROM_LEN   1024
94
95 static int netxen_nic_get_eeprom_len(struct net_device *dev)
96 {
97         return NETXEN_FLASH_TOTAL_SIZE;
98 }
99
100 static void
101 netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
102 {
103         struct netxen_adapter *adapter = netdev_priv(dev);
104         u32 fw_major = 0;
105         u32 fw_minor = 0;
106         u32 fw_build = 0;
107
108         strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
109         strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
110         fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
111                                               NETXEN_FW_VERSION_MAJOR));
112         fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
113                                               NETXEN_FW_VERSION_MINOR));
114         fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
115         sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
116
117         strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
118         drvinfo->regdump_len = NETXEN_NIC_REGS_LEN;
119         drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev);
120 }
121
122 static int
123 netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
124 {
125         struct netxen_adapter *adapter = netdev_priv(dev);
126         struct netxen_board_info *boardinfo = &adapter->ahw.boardcfg;
127
128         /* read which mode */
129         if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
130                 ecmd->supported = (SUPPORTED_10baseT_Half |
131                                    SUPPORTED_10baseT_Full |
132                                    SUPPORTED_100baseT_Half |
133                                    SUPPORTED_100baseT_Full |
134                                    SUPPORTED_1000baseT_Half |
135                                    SUPPORTED_1000baseT_Full);
136
137                 ecmd->advertising = (ADVERTISED_100baseT_Half |
138                                      ADVERTISED_100baseT_Full |
139                                      ADVERTISED_1000baseT_Half |
140                                      ADVERTISED_1000baseT_Full);
141
142                 ecmd->port = PORT_TP;
143
144                 if (netif_running(dev)) {
145                         ecmd->speed = adapter->link_speed;
146                         ecmd->duplex = adapter->link_duplex;
147                 } else
148                         return -EIO;    /* link absent */
149         } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
150                 ecmd->supported = (SUPPORTED_TP |
151                                    SUPPORTED_1000baseT_Full |
152                                    SUPPORTED_10000baseT_Full);
153                 ecmd->advertising = (ADVERTISED_TP |
154                                      ADVERTISED_1000baseT_Full |
155                                      ADVERTISED_10000baseT_Full);
156                 ecmd->port = PORT_TP;
157
158                 ecmd->speed = SPEED_10000;
159                 ecmd->duplex = DUPLEX_FULL;
160                 ecmd->autoneg = AUTONEG_DISABLE;
161         } else
162                 return -EIO;
163
164         ecmd->phy_address = adapter->portnum;
165         ecmd->transceiver = XCVR_EXTERNAL;
166
167         switch ((netxen_brdtype_t) boardinfo->board_type) {
168         case NETXEN_BRDTYPE_P2_SB35_4G:
169         case NETXEN_BRDTYPE_P2_SB31_2G:
170                 ecmd->supported |= SUPPORTED_Autoneg;
171                 ecmd->advertising |= ADVERTISED_Autoneg;
172         case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
173                 ecmd->supported |= SUPPORTED_TP;
174                 ecmd->advertising |= ADVERTISED_TP;
175                 ecmd->port = PORT_TP;
176                 ecmd->autoneg = (boardinfo->board_type ==
177                                  NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
178                     (AUTONEG_DISABLE) : (adapter->link_autoneg);
179                 break;
180         case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
181         case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
182                 ecmd->supported |= SUPPORTED_MII;
183                 ecmd->advertising |= ADVERTISED_MII;
184                 ecmd->port = PORT_FIBRE;
185                 ecmd->autoneg = AUTONEG_DISABLE;
186                 break;
187         case NETXEN_BRDTYPE_P2_SB31_10G:
188                 ecmd->supported |= SUPPORTED_FIBRE;
189                 ecmd->advertising |= ADVERTISED_FIBRE;
190                 ecmd->port = PORT_FIBRE;
191                 ecmd->autoneg = AUTONEG_DISABLE;
192                 break;
193         default:
194                 printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
195                        (netxen_brdtype_t) boardinfo->board_type);
196                 return -EIO;
197         }
198
199         return 0;
200 }
201
202 static int
203 netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
204 {
205         struct netxen_adapter *adapter = netdev_priv(dev);
206         __u32 status;
207
208         /* read which mode */
209         if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
210                 /* autonegotiation */
211                 if (adapter->phy_write
212                     && adapter->phy_write(adapter,
213                                           NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
214                                           ecmd->autoneg) != 0)
215                         return -EIO;
216                 else
217                         adapter->link_autoneg = ecmd->autoneg;
218
219                 if (adapter->phy_read
220                     && adapter->phy_read(adapter,
221                                          NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
222                                          &status) != 0)
223                         return -EIO;
224
225                 /* speed */
226                 switch (ecmd->speed) {
227                 case SPEED_10:
228                         netxen_set_phy_speed(status, 0);
229                         break;
230                 case SPEED_100:
231                         netxen_set_phy_speed(status, 1);
232                         break;
233                 case SPEED_1000:
234                         netxen_set_phy_speed(status, 2);
235                         break;
236                 }
237                 /* set duplex mode */
238                 if (ecmd->duplex == DUPLEX_HALF)
239                         netxen_clear_phy_duplex(status);
240                 if (ecmd->duplex == DUPLEX_FULL)
241                         netxen_set_phy_duplex(status);
242                 if (adapter->phy_write
243                     && adapter->phy_write(adapter,
244                                           NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
245                                           *((int *)&status)) != 0)
246                         return -EIO;
247                 else {
248                         adapter->link_speed = ecmd->speed;
249                         adapter->link_duplex = ecmd->duplex;
250                 }
251         } else
252                 return -EOPNOTSUPP;
253
254         if (netif_running(dev)) {
255                 dev->stop(dev);
256                 dev->open(dev);
257         }
258         return 0;
259 }
260
261 static int netxen_nic_get_regs_len(struct net_device *dev)
262 {
263         return NETXEN_NIC_REGS_LEN;
264 }
265
266 struct netxen_niu_regs {
267         __u32 reg[NETXEN_NIC_REGS_COUNT];
268 };
269
270 static struct netxen_niu_regs niu_registers[] = {
271         {
272          /* GB Mode */
273          {
274           NETXEN_NIU_GB_SERDES_RESET,
275           NETXEN_NIU_GB0_MII_MODE,
276           NETXEN_NIU_GB1_MII_MODE,
277           NETXEN_NIU_GB2_MII_MODE,
278           NETXEN_NIU_GB3_MII_MODE,
279           NETXEN_NIU_GB0_GMII_MODE,
280           NETXEN_NIU_GB1_GMII_MODE,
281           NETXEN_NIU_GB2_GMII_MODE,
282           NETXEN_NIU_GB3_GMII_MODE,
283           NETXEN_NIU_REMOTE_LOOPBACK,
284           NETXEN_NIU_GB0_HALF_DUPLEX,
285           NETXEN_NIU_GB1_HALF_DUPLEX,
286           NETXEN_NIU_RESET_SYS_FIFOS,
287           NETXEN_NIU_GB_CRC_DROP,
288           NETXEN_NIU_GB_DROP_WRONGADDR,
289           NETXEN_NIU_TEST_MUX_CTL,
290
291           NETXEN_NIU_GB_MAC_CONFIG_0(0),
292           NETXEN_NIU_GB_MAC_CONFIG_1(0),
293           NETXEN_NIU_GB_HALF_DUPLEX_CTRL(0),
294           NETXEN_NIU_GB_MAX_FRAME_SIZE(0),
295           NETXEN_NIU_GB_TEST_REG(0),
296           NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
297           NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
298           NETXEN_NIU_GB_MII_MGMT_ADDR(0),
299           NETXEN_NIU_GB_MII_MGMT_CTRL(0),
300           NETXEN_NIU_GB_MII_MGMT_STATUS(0),
301           NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
302           NETXEN_NIU_GB_INTERFACE_CTRL(0),
303           NETXEN_NIU_GB_INTERFACE_STATUS(0),
304           NETXEN_NIU_GB_STATION_ADDR_0(0),
305           NETXEN_NIU_GB_STATION_ADDR_1(0),
306           -1,
307           }
308          },
309         {
310          /* XG Mode */
311          {
312           NETXEN_NIU_XG_SINGLE_TERM,
313           NETXEN_NIU_XG_DRIVE_HI,
314           NETXEN_NIU_XG_DRIVE_LO,
315           NETXEN_NIU_XG_DTX,
316           NETXEN_NIU_XG_DEQ,
317           NETXEN_NIU_XG_WORD_ALIGN,
318           NETXEN_NIU_XG_RESET,
319           NETXEN_NIU_XG_POWER_DOWN,
320           NETXEN_NIU_XG_RESET_PLL,
321           NETXEN_NIU_XG_SERDES_LOOPBACK,
322           NETXEN_NIU_XG_DO_BYTE_ALIGN,
323           NETXEN_NIU_XG_TX_ENABLE,
324           NETXEN_NIU_XG_RX_ENABLE,
325           NETXEN_NIU_XG_STATUS,
326           NETXEN_NIU_XG_PAUSE_THRESHOLD,
327           NETXEN_NIU_XGE_CONFIG_0,
328           NETXEN_NIU_XGE_CONFIG_1,
329           NETXEN_NIU_XGE_IPG,
330           NETXEN_NIU_XGE_STATION_ADDR_0_HI,
331           NETXEN_NIU_XGE_STATION_ADDR_0_1,
332           NETXEN_NIU_XGE_STATION_ADDR_1_LO,
333           NETXEN_NIU_XGE_STATUS,
334           NETXEN_NIU_XGE_MAX_FRAME_SIZE,
335           NETXEN_NIU_XGE_PAUSE_FRAME_VALUE,
336           NETXEN_NIU_XGE_TX_BYTE_CNT,
337           NETXEN_NIU_XGE_TX_FRAME_CNT,
338           NETXEN_NIU_XGE_RX_BYTE_CNT,
339           NETXEN_NIU_XGE_RX_FRAME_CNT,
340           NETXEN_NIU_XGE_AGGR_ERROR_CNT,
341           NETXEN_NIU_XGE_MULTICAST_FRAME_CNT,
342           NETXEN_NIU_XGE_UNICAST_FRAME_CNT,
343           NETXEN_NIU_XGE_CRC_ERROR_CNT,
344           NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
345           NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
346           NETXEN_NIU_XGE_LOCAL_ERROR_CNT,
347           NETXEN_NIU_XGE_REMOTE_ERROR_CNT,
348           NETXEN_NIU_XGE_CONTROL_CHAR_CNT,
349           NETXEN_NIU_XGE_PAUSE_FRAME_CNT,
350           -1,
351           }
352          }
353 };
354
355 static void
356 netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
357 {
358         struct netxen_adapter *adapter = netdev_priv(dev);
359         __u32 mode, *regs_buff = p;
360         void __iomem *addr;
361         int i, window;
362
363         memset(p, 0, NETXEN_NIC_REGS_LEN);
364         regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
365             (adapter->pdev)->device;
366         /* which mode */
367         NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
368         mode = regs_buff[0];
369
370         /* Common registers to all the modes */
371         NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
372                                    &regs_buff[2]);
373         /* GB/XGB Mode */
374         mode = (mode / 2) - 1;
375         window = 0;
376         if (mode <= 1) {
377                 for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) {
378                         /* GB: port specific registers */
379                         if (mode == 0 && i >= 19)
380                                 window = physical_port[adapter->portnum] *
381                                         NETXEN_NIC_PORT_WINDOW;
382
383                         NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
384                                                    reg[i - 3] + window,
385                                                    &regs_buff[i]);
386                 }
387
388         }
389 }
390
391 static u32 netxen_nic_test_link(struct net_device *dev)
392 {
393         struct netxen_adapter *adapter = netdev_priv(dev);
394         __u32 status;
395         int val;
396
397         /* read which mode */
398         if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
399                 if (adapter->phy_read
400                     && adapter->phy_read(adapter,
401                                          NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
402                                          &status) != 0)
403                         return -EIO;
404                 else {
405                         val = netxen_get_phy_link(status);
406                         return !val;
407                 }
408         } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
409                 val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
410                 return (val == XG_LINK_UP) ? 0 : 1;
411         }
412         return -EIO;
413 }
414
415 static int
416 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
417                       u8 * bytes)
418 {
419         struct netxen_adapter *adapter = netdev_priv(dev);
420         int offset;
421         int ret;
422
423         if (eeprom->len == 0)
424                 return -EINVAL;
425
426         eeprom->magic = (adapter->pdev)->vendor | 
427                         ((adapter->pdev)->device << 16);
428         offset = eeprom->offset;
429
430         ret = netxen_rom_fast_read_words(adapter, offset, bytes, 
431                                                 eeprom->len);
432         if (ret < 0)
433                 return ret;
434
435         return 0;
436 }
437
438 static int
439 netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
440                         u8 * bytes)
441 {
442         struct netxen_adapter *adapter = netdev_priv(dev);
443         int offset = eeprom->offset;
444         static int flash_start;
445         static int ready_to_flash;
446         int ret;
447
448         if (flash_start == 0) {
449                 netxen_halt_pegs(adapter);
450                 ret = netxen_flash_unlock(adapter);
451                 if (ret < 0) {
452                         printk(KERN_ERR "%s: Flash unlock failed.\n",
453                                 netxen_nic_driver_name);
454                         return ret;
455                 }
456                 printk(KERN_INFO "%s: flash unlocked. \n", 
457                         netxen_nic_driver_name);
458                 last_schedule_time = jiffies;
459                 ret = netxen_flash_erase_secondary(adapter);
460                 if (ret != FLASH_SUCCESS) {
461                         printk(KERN_ERR "%s: Flash erase failed.\n", 
462                                 netxen_nic_driver_name);
463                         return ret;
464                 }
465                 printk(KERN_INFO "%s: secondary flash erased successfully.\n", 
466                         netxen_nic_driver_name);
467                 flash_start = 1;
468                 return 0;
469         }
470
471         if (offset == NETXEN_BOOTLD_START) {
472                 ret = netxen_flash_erase_primary(adapter);
473                 if (ret != FLASH_SUCCESS) {
474                         printk(KERN_ERR "%s: Flash erase failed.\n", 
475                                 netxen_nic_driver_name);
476                         return ret;
477                 }
478
479                 ret = netxen_rom_se(adapter, NETXEN_USER_START);
480                 if (ret != FLASH_SUCCESS)
481                         return ret;
482                 ret = netxen_rom_se(adapter, NETXEN_FIXED_START);
483                 if (ret != FLASH_SUCCESS)
484                         return ret;
485
486                 printk(KERN_INFO "%s: primary flash erased successfully\n", 
487                         netxen_nic_driver_name);
488
489                 ret = netxen_backup_crbinit(adapter);
490                 if (ret != FLASH_SUCCESS) {
491                         printk(KERN_ERR "%s: CRBinit backup failed.\n", 
492                                 netxen_nic_driver_name);
493                         return ret;
494                 }
495                 printk(KERN_INFO "%s: CRBinit backup done.\n", 
496                         netxen_nic_driver_name);
497                 ready_to_flash = 1;
498         }
499
500         if (!ready_to_flash) {
501                 printk(KERN_ERR "%s: Invalid write sequence, returning...\n",
502                         netxen_nic_driver_name);
503                 return -EINVAL;
504         }
505
506         return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
507 }
508
509 static void
510 netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
511 {
512         struct netxen_adapter *adapter = netdev_priv(dev);
513         int i;
514
515         ring->rx_pending = 0;
516         ring->rx_jumbo_pending = 0;
517         for (i = 0; i < MAX_RCV_CTX; ++i) {
518                 ring->rx_pending += adapter->recv_ctx[i].
519                     rcv_desc[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
520                 ring->rx_jumbo_pending += adapter->recv_ctx[i].
521                     rcv_desc[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
522         }
523         ring->tx_pending = adapter->max_tx_desc_count;
524
525         ring->rx_max_pending = MAX_RCV_DESCRIPTORS;
526         ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST;
527         ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS;
528         ring->rx_mini_max_pending = 0;
529         ring->rx_mini_pending = 0;
530 }
531
532 static void
533 netxen_nic_get_pauseparam(struct net_device *dev,
534                           struct ethtool_pauseparam *pause)
535 {
536         struct netxen_adapter *adapter = netdev_priv(dev);
537         __u32 val;
538         int port = physical_port[adapter->portnum];
539
540         if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
541                 if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
542                         return;
543                 /* get flow control settings */
544                 netxen_nic_read_w0(adapter,NETXEN_NIU_GB_MAC_CONFIG_0(port),
545                                 &val);
546                 pause->rx_pause = netxen_gb_get_rx_flowctl(val);
547                 netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
548                 switch (port) {
549                         case 0:
550                                 pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
551                                 break;
552                         case 1:
553                                 pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
554                                 break;
555                         case 2:
556                                 pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
557                                 break;
558                         case 3:
559                         default:
560                                 pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
561                                 break;
562                 }
563         } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
564                 if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
565                         return;
566                 pause->rx_pause = 1;
567                 netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
568                 if (port == 0)
569                         pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
570                 else
571                         pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
572         } else {
573                 printk(KERN_ERR"%s: Unknown board type: %x\n", 
574                                 netxen_nic_driver_name, adapter->ahw.board_type);
575         }
576 }
577
578 static int
579 netxen_nic_set_pauseparam(struct net_device *dev,
580                           struct ethtool_pauseparam *pause)
581 {
582         struct netxen_adapter *adapter = netdev_priv(dev);
583         __u32 val;
584         int port = physical_port[adapter->portnum];
585         /* read mode */
586         if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
587                 if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
588                         return -EIO;
589                 /* set flow control */
590                 netxen_nic_read_w0(adapter,
591                                         NETXEN_NIU_GB_MAC_CONFIG_0(port), &val);
592                 
593                 if (pause->rx_pause)
594                         netxen_gb_rx_flowctl(val);
595                 else
596                         netxen_gb_unset_rx_flowctl(val);
597
598                 netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
599                                 val);
600                 /* set autoneg */
601                 netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
602                 switch (port) {
603                         case 0:
604                                 if (pause->tx_pause)
605                                         netxen_gb_unset_gb0_mask(val);
606                                 else
607                                         netxen_gb_set_gb0_mask(val);
608                                 break;
609                         case 1:
610                                 if (pause->tx_pause)
611                                         netxen_gb_unset_gb1_mask(val);
612                                 else
613                                         netxen_gb_set_gb1_mask(val);
614                                 break;
615                         case 2:
616                                 if (pause->tx_pause)
617                                         netxen_gb_unset_gb2_mask(val);
618                                 else
619                                         netxen_gb_set_gb2_mask(val);
620                                 break;
621                         case 3:
622                         default:
623                                 if (pause->tx_pause)
624                                         netxen_gb_unset_gb3_mask(val);
625                                 else
626                                         netxen_gb_set_gb3_mask(val);
627                                 break;
628                 }
629                 netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
630         } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
631                 if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
632                         return -EIO;
633                 netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
634                 if (port == 0) {
635                         if (pause->tx_pause)
636                                 netxen_xg_unset_xg0_mask(val);
637                         else
638                                 netxen_xg_set_xg0_mask(val);
639                 } else {
640                         if (pause->tx_pause)
641                                 netxen_xg_unset_xg1_mask(val);
642                         else
643                                 netxen_xg_set_xg1_mask(val);
644                 }
645                 netxen_nic_write_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);                     
646         } else {
647                 printk(KERN_ERR "%s: Unknown board type: %x\n",
648                                 netxen_nic_driver_name, 
649                                 adapter->ahw.board_type);
650         }
651         return 0;
652 }
653
654 static int netxen_nic_reg_test(struct net_device *dev)
655 {
656         struct netxen_adapter *adapter = netdev_priv(dev);
657         u32 data_read, data_written;
658
659         netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read);
660         if ((data_read & 0xffff) != PHAN_VENDOR_ID)
661         return 1;
662
663         data_written = (u32)0xa5a5a5a5;
664
665         netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
666         data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
667         if (data_written != data_read)
668                 return 1;
669
670         return 0;
671 }
672
673 static int netxen_get_sset_count(struct net_device *dev, int sset)
674 {
675         switch (sset) {
676         case ETH_SS_TEST:
677                 return NETXEN_NIC_TEST_LEN;
678         case ETH_SS_STATS:
679                 return NETXEN_NIC_STATS_LEN;
680         default:
681                 return -EOPNOTSUPP;
682         }
683 }
684
685 static void
686 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
687                      u64 * data)
688 {
689         memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
690         if ((data[0] = netxen_nic_reg_test(dev)))
691                 eth_test->flags |= ETH_TEST_FL_FAILED;
692         /* link test */
693         if ((data[1] = (u64) netxen_nic_test_link(dev)))
694                 eth_test->flags |= ETH_TEST_FL_FAILED;
695 }
696
697 static void
698 netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
699 {
700         int index;
701
702         switch (stringset) {
703         case ETH_SS_TEST:
704                 memcpy(data, *netxen_nic_gstrings_test,
705                        NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
706                 break;
707         case ETH_SS_STATS:
708                 for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
709                         memcpy(data + index * ETH_GSTRING_LEN,
710                                netxen_nic_gstrings_stats[index].stat_string,
711                                ETH_GSTRING_LEN);
712                 }
713                 break;
714         }
715 }
716
717 static void
718 netxen_nic_get_ethtool_stats(struct net_device *dev,
719                              struct ethtool_stats *stats, u64 * data)
720 {
721         struct netxen_adapter *adapter = netdev_priv(dev);
722         int index;
723
724         for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
725                 char *p =
726                     (char *)adapter +
727                     netxen_nic_gstrings_stats[index].stat_offset;
728                 data[index] =
729                     (netxen_nic_gstrings_stats[index].sizeof_stat ==
730                      sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
731         }
732 }
733
734 static u32 netxen_nic_get_rx_csum(struct net_device *dev)
735 {
736         struct netxen_adapter *adapter = netdev_priv(dev);
737         return adapter->rx_csum;
738 }
739
740 static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
741 {
742         struct netxen_adapter *adapter = netdev_priv(dev);
743         adapter->rx_csum = !!data;
744         return 0;
745 }
746
747 struct ethtool_ops netxen_nic_ethtool_ops = {
748         .get_settings = netxen_nic_get_settings,
749         .set_settings = netxen_nic_set_settings,
750         .get_drvinfo = netxen_nic_get_drvinfo,
751         .get_regs_len = netxen_nic_get_regs_len,
752         .get_regs = netxen_nic_get_regs,
753         .get_link = ethtool_op_get_link,
754         .get_eeprom_len = netxen_nic_get_eeprom_len,
755         .get_eeprom = netxen_nic_get_eeprom,
756         .set_eeprom = netxen_nic_set_eeprom,
757         .get_ringparam = netxen_nic_get_ringparam,
758         .get_pauseparam = netxen_nic_get_pauseparam,
759         .set_pauseparam = netxen_nic_set_pauseparam,
760         .set_tx_csum = ethtool_op_set_tx_csum,
761         .set_sg = ethtool_op_set_sg,
762         .set_tso = ethtool_op_set_tso,
763         .self_test = netxen_nic_diag_test,
764         .get_strings = netxen_nic_get_strings,
765         .get_ethtool_stats = netxen_nic_get_ethtool_stats,
766         .get_sset_count = netxen_get_sset_count,
767         .get_rx_csum = netxen_nic_get_rx_csum,
768         .set_rx_csum = netxen_nic_set_rx_csum,
769 };