netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6.17 0/9] NetXen: ethernet nic driver
@ 2006-07-05 13:15 Linsys Contractor Amit S. Kale
  2006-07-05 13:20 ` [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface Linsys Contractor Amit S. Kale
                   ` (8 more replies)
  0 siblings, 9 replies; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:15 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

Hi,

I'll be sending a NetXen 1G/10G ethernet driver patch in subsequent 
emails. We have made changes as per the feedback received. We would like 
this driver to be included in mainline kernel.

Kindly review it and feel free to send feedback.

Thanks,
-Amit

Signed-off-by: Amit S. Kale <amitkale@unminc.com>

  Kconfig                      |    5
  Makefile                     |    1
  netxen/Makefile              |   35 +
  netxen/netxen_nic.h          |  998 ++++++++++++++++++++++++++++++++
  netxen/netxen_nic_ethtool.c  |  707 +++++++++++++++++++++++
  netxen/netxen_nic_hdr.h      |  684 ++++++++++++++++++++++
  netxen/netxen_nic_hw.c       | 1308 +++++++++++++++++++++++++++++++++++++++++++
  netxen/netxen_nic_hw.h       |  346 +++++++++++
  netxen/netxen_nic_init.c     | 1263 +++++++++++++++++++++++++++++++++++++++++
  netxen/netxen_nic_ioctl.h    |   75 ++
  netxen/netxen_nic_isr.c      |  430 ++++++++++++++
  netxen/netxen_nic_main.c     | 1228 ++++++++++++++++++++++++++++++++++++++++
  netxen/netxen_nic_niu.c      |  761 +++++++++++++++++++++++++
  netxen/netxen_nic_phan_reg.h |  293 +++++++++
  14 files changed, 8134 insertions(+)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
@ 2006-07-05 13:20 ` Linsys Contractor Amit S. Kale
  2006-07-05 15:34   ` Jeff Garzik
  2006-07-05 13:29 ` [PATCH 2.6.17 2/9] NetXen: Main header file Linsys Contractor Amit S. Kale
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:20 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/Kconfig linux-2.6.17/drivers/net/Kconfig
--- linux-2.6.17.orig/drivers/net/Kconfig	2006-07-05 01:15:38.740111318 -0700
+++ linux-2.6.17/drivers/net/Kconfig	2006-07-05 01:18:13.066500584 -0700
@@ -2311,6 +2311,11 @@

  	  If in doubt, say N.

+config NETXEN_NIC
+	tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
+	help
+	  This enables the support for NetXen's Gigabit Ethernet card.
+
  endmenu

  source "drivers/net/tokenring/Kconfig"
diff -Naru linux-2.6.17.orig/drivers/net/Makefile linux-2.6.17/drivers/net/Makefile
--- linux-2.6.17.orig/drivers/net/Makefile	2006-07-05 01:15:39.197017758 -0700
+++ linux-2.6.17/drivers/net/Makefile	2006-07-05 01:18:40.408898046 -0700
@@ -213,3 +213,4 @@

  obj-$(CONFIG_FS_ENET) += fs_enet/

+obj-$(CONFIG_NETXEN_NIC) += netxen/
diff -Naru linux-2.6.17.orig/drivers/net/netxen/Makefile linux-2.6.17/drivers/net/netxen/Makefile
--- linux-2.6.17.orig/drivers/net/netxen/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/Makefile	2006-07-05 01:18:40.410897637 -0700
@@ -0,0 +1,35 @@
+# Copyright (C) 2003 - 2006 NetXen, Inc.
+# All rights reserved.
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA  02111-1307, USA.
+# 
+# The full GNU General Public License is included in this distribution
+# in the file called LICENSE.
+# 
+# Contact Information:
+#    info@netxen.com
+# NetXen,
+# 3965 Freedom Circle, Fourth floor,
+# Santa Clara, CA 95054
+#
+# Makefile for the NetXen NIC Driver
+#
+
+
+obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o
+
+netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \
+	netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o
diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_ethtool.c linux-2.6.17/drivers/net/netxen/netxen_nic_ethtool.c
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_ethtool.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_ethtool.c	2006-07-05 01:18:40.363907266 -0700
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * ethtool support for netxen nic
+ *
+ */
+
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/version.h>
+
+#include "netxen_nic_hw.h"
+#include "netxen_nic.h"
+#include "netxen_nic_phan_reg.h"
+#include "netxen_nic_ioctl.h"
+
+struct netxen_nic_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
+};
+
+#define NETXEN_NIC_STAT(m) sizeof(((struct netxen_port *)0)->m), \
+                    offsetof(struct netxen_port, m)
+
+static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
+	{"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)},
+	{"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
+	{"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)},
+	{"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
+	{"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)},
+	{"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)},
+	{"polled", NETXEN_NIC_STAT(stats.polled)},
+	{"uphappy", NETXEN_NIC_STAT(stats.uphappy)},
+	{"updropped", NETXEN_NIC_STAT(stats.updropped)},
+	{"uplcong", NETXEN_NIC_STAT(stats.uplcong)},
+	{"uphcong", NETXEN_NIC_STAT(stats.uphcong)},
+	{"upmcong", NETXEN_NIC_STAT(stats.upmcong)},
+	{"updunno", NETXEN_NIC_STAT(stats.updunno)},
+	{"skb_freed", NETXEN_NIC_STAT(stats.skbfreed)},
+	{"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
+	{"tx_null_skb", NETXEN_NIC_STAT(stats.txnullskb)},
+	{"csummed", NETXEN_NIC_STAT(stats.csummed)},
+	{"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)},
+	{"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
+	{"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
+};
+
+#define NETXEN_NIC_STATS_LEN        \
+        sizeof(netxen_nic_gstrings_stats) / sizeof(struct netxen_nic_stats)
+
+static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
+	"Register_Test  (offline)", "EEPROM_Test    (offline)",
+	"Interrupt_Test (offline)", "Loopback_Test  (offline)",
+	"Link_Test   (on/offline)"
+};
+
+#define NETXEN_NIC_TEST_LEN sizeof(netxen_nic_gstrings_test) / ETH_GSTRING_LEN
+
+#define NETXEN_NIC_REGS_COUNT 42
+#define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(netxen_crbword_t))
+
+static int netxen_nic_get_eeprom_len(struct net_device *dev)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	int n;
+
+	if ((netxen_rom_fast_read(adapter, 0, &n) == 0) && (n & 0x80000000)) {
+		n &= ~0x80000000;
+		if (n < 1024)
+			return n;
+	}
+	return 0;
+}
+
+static void
+netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
+{
+	struct netxen_port *port = netdev_priv(dev);
+
+	strncpy(drvinfo->driver, "NetXen NIC Driver", 32);
+	strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
+	strncpy(drvinfo->fw_version, NETXEN_NIC_FW_VERSIONID, 32);
+	strncpy(drvinfo->bus_info, pci_name(port->pdev), 32);
+	drvinfo->n_stats = NETXEN_NIC_STATS_LEN;
+	drvinfo->testinfo_len = NETXEN_NIC_TEST_LEN;
+	drvinfo->regdump_len = NETXEN_NIC_REGS_LEN;
+	drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev);
+}
+
+static int
+netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+
+	/* read which mode */
+	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+		ecmd->supported = (SUPPORTED_10baseT_Half |
+				   SUPPORTED_10baseT_Full |
+				   SUPPORTED_100baseT_Half |
+				   SUPPORTED_100baseT_Full |
+				   SUPPORTED_1000baseT_Half |
+				   SUPPORTED_1000baseT_Full |
+				   SUPPORTED_TP |
+				   SUPPORTED_MII | SUPPORTED_Autoneg);
+
+		ecmd->advertising = (ADVERTISED_100baseT_Half |
+				     ADVERTISED_100baseT_Full |
+				     ADVERTISED_1000baseT_Half |
+				     ADVERTISED_1000baseT_Full |
+				     ADVERTISED_TP |
+				     ADVERTISED_MII | ADVERTISED_Autoneg);
+
+		ecmd->port = PORT_TP;
+
+		if (netif_running(dev)) {
+			ecmd->speed = port->link_speed;
+			ecmd->duplex = port->link_duplex;
+		} else
+			return -EIO;	/* link absent */
+
+		ecmd->phy_address = port->portnum;
+		ecmd->transceiver = XCVR_EXTERNAL;
+
+		/* get autoneg settings */
+		ecmd->autoneg = port->link_autoneg;
+		return 0;
+	}
+
+	if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+		ecmd->supported = (SUPPORTED_TP |
+				   SUPPORTED_1000baseT_Full |
+				   SUPPORTED_10000baseT_Full);
+		ecmd->advertising = (ADVERTISED_TP |
+				     ADVERTISED_1000baseT_Full |
+				     ADVERTISED_10000baseT_Full);
+		ecmd->port = PORT_TP;
+
+		ecmd->speed = SPEED_10000;
+		ecmd->duplex = DUPLEX_FULL;
+		ecmd->phy_address = port->portnum;
+		ecmd->transceiver = XCVR_EXTERNAL;
+		ecmd->autoneg = AUTONEG_DISABLE;
+		return 0;
+	}
+
+	return -EIO;
+}
+
+static int
+netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	struct netxen_niu_phy_status status;
+
+	/* read which mode */
+	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+		/* autonegotiation */
+		if (netxen_nic_phy_write(port->adapter, port->portnum,
+					 NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+					 (netxen_crbword_t) ecmd->autoneg) != 0)
+			return -EIO;
+		else
+			port->link_autoneg = ecmd->autoneg;
+
+		if (netxen_nic_phy_read(port->adapter, port->portnum,
+					NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+					(netxen_crbword_t *) & status) != 0)
+			return -EIO;
+
+		/* speed */
+		switch (ecmd->speed) {
+		case SPEED_10:
+			status.speed = 0;
+			break;
+		case SPEED_100:
+			status.speed = 1;
+			break;
+		case SPEED_1000:
+			status.speed = 2;
+			break;
+		}
+		/* set duplex mode */
+		if (ecmd->duplex == DUPLEX_HALF)
+			status.duplex = 0;
+		if (ecmd->duplex == DUPLEX_FULL)
+			status.duplex = 1;
+
+		if (netxen_nic_phy_write(port->adapter, port->portnum,
+					 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+					 *((int *)&status)) != 0)
+			return -EIO;
+		else {
+			port->link_speed = ecmd->speed;
+			port->link_duplex = ecmd->duplex;
+		}
+	}
+	if (netif_running(dev)) {
+		dev->stop(dev);
+		dev->open(dev);
+	}
+	return 0;
+}
+
+static int netxen_nic_get_regs_len(struct net_device *dev)
+{
+	return NETXEN_NIC_REGS_LEN;
+}
+
+struct netxen_niu_regs {
+	netxen_crbword_t	reg[NETXEN_NIC_REGS_COUNT];
+};
+
+static struct netxen_niu_regs niu_registers[] = {
+	{
+	 /* GB Mode */
+	 {
+	  NETXEN_NIU_GB_SERDES_RESET,
+	  NETXEN_NIU_GB0_MII_MODE,
+	  NETXEN_NIU_GB1_MII_MODE,
+	  NETXEN_NIU_GB2_MII_MODE,
+	  NETXEN_NIU_GB3_MII_MODE,
+	  NETXEN_NIU_GB0_GMII_MODE,
+	  NETXEN_NIU_GB1_GMII_MODE,
+	  NETXEN_NIU_GB2_GMII_MODE,
+	  NETXEN_NIU_GB3_GMII_MODE,
+	  NETXEN_NIU_REMOTE_LOOPBACK,
+	  NETXEN_NIU_GB0_HALF_DUPLEX,
+	  NETXEN_NIU_GB1_HALF_DUPLEX,
+	  NETXEN_NIU_RESET_SYS_FIFOS,
+	  NETXEN_NIU_GB_CRC_DROP,
+	  NETXEN_NIU_GB_DROP_WRONGADDR,
+	  NETXEN_NIU_TEST_MUX_CTL,
+ 
+	  NETXEN_NIU_GB_MAC_CONFIG_0(0),
+	  NETXEN_NIU_GB_MAC_CONFIG_1(0),
+	  NETXEN_NIU_GB_HALF_DUPLEX_CTRL(0),
+	  NETXEN_NIU_GB_MAX_FRAME_SIZE(0),
+	  NETXEN_NIU_GB_TEST_REG(0),
+	  NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
+	  NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+	  NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+	  NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+	  NETXEN_NIU_GB_MII_MGMT_STATUS(0),
+	  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
+	  NETXEN_NIU_GB_INTERFACE_CTRL(0),
+	  NETXEN_NIU_GB_INTERFACE_STATUS(0),
+	  NETXEN_NIU_GB_STATION_ADDR_0(0),
+	  NETXEN_NIU_GB_STATION_ADDR_1(0),
+	  -1,
+	 }
+	},
+	{
+	 /* XG Mode */
+	 {
+	  NETXEN_NIU_XG_SINGLE_TERM,
+	  NETXEN_NIU_XG_DRIVE_HI,
+	  NETXEN_NIU_XG_DRIVE_LO,
+	  NETXEN_NIU_XG_DTX,
+	  NETXEN_NIU_XG_DEQ,
+	  NETXEN_NIU_XG_WORD_ALIGN,
+	  NETXEN_NIU_XG_RESET,
+	  NETXEN_NIU_XG_POWER_DOWN,
+	  NETXEN_NIU_XG_RESET_PLL,
+	  NETXEN_NIU_XG_SERDES_LOOPBACK,
+	  NETXEN_NIU_XG_DO_BYTE_ALIGN,
+	  NETXEN_NIU_XG_TX_ENABLE,
+	  NETXEN_NIU_XG_RX_ENABLE,
+	  NETXEN_NIU_XG_STATUS,
+	  NETXEN_NIU_XG_PAUSE_THRESHOLD,
+	  NETXEN_NIU_XGE_CONFIG_0,
+	  NETXEN_NIU_XGE_CONFIG_1,
+	  NETXEN_NIU_XGE_IPG,
+	  NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+	  NETXEN_NIU_XGE_STATION_ADDR_0_1,
+	  NETXEN_NIU_XGE_STATION_ADDR_1_LO,
+	  NETXEN_NIU_XGE_STATUS,
+	  NETXEN_NIU_XGE_MAX_FRAME_SIZE,
+	  NETXEN_NIU_XGE_PAUSE_FRAME_VALUE,
+	  NETXEN_NIU_XGE_TX_BYTE_CNT,
+	  NETXEN_NIU_XGE_TX_FRAME_CNT,
+	  NETXEN_NIU_XGE_RX_BYTE_CNT,
+	  NETXEN_NIU_XGE_RX_FRAME_CNT,
+	  NETXEN_NIU_XGE_AGGR_ERROR_CNT,
+	  NETXEN_NIU_XGE_MULTICAST_FRAME_CNT,
+	  NETXEN_NIU_XGE_UNICAST_FRAME_CNT,
+	  NETXEN_NIU_XGE_CRC_ERROR_CNT,
+	  NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
+	  NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
+	  NETXEN_NIU_XGE_LOCAL_ERROR_CNT,
+	  NETXEN_NIU_XGE_REMOTE_ERROR_CNT,
+	  NETXEN_NIU_XGE_CONTROL_CHAR_CNT,
+	  NETXEN_NIU_XGE_PAUSE_FRAME_CNT,
+	  -1,
+	 }
+	}
+};
+
+static void
+netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	netxen_crbword_t mode, *regs_buff = p;
+	unsigned long flags;
+	void *addr;
+	int i, window;
+
+	memset(p, 0, NETXEN_NIC_REGS_LEN);
+	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
+	    adapter->ahw.device_id;
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	/* which mode */
+	NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
+	mode = regs_buff[0];
+
+	/* Common registers to all the modes */
+	NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
+				   &regs_buff[2]);
+	/* GB/XGB Mode */
+	mode = (mode/2) - 1;
+	window = 0;
+	if(mode <= 1) {
+		for ( i = 3; niu_registers[mode].reg[i - 3] != -1; i++) {
+			/* GB: port specific registers */
+			if(mode == 0 && i >= 19)
+				window = port->portnum * 0x10000;
+
+			NETXEN_NIC_LOCKED_READ_REG
+			    (niu_registers[mode].reg[i - 3] + window,
+			    &regs_buff[i]);
+		}
+	}
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+}
+
+static void
+netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+	wol->wolopts = 0;	/* options can be added depending upon the mode */
+}
+
+/* Restart Link Process */
+static int netxen_nic_nway_reset(struct net_device *dev)
+{
+	if (netif_running(dev)) {
+		dev->stop(dev);	/* verify */
+		dev->open(dev);
+	}
+	return 0;
+}
+
+static u32 netxen_nic_get_link(struct net_device *dev)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	struct netxen_niu_phy_status status;
+
+	/* read which mode */
+	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+		if (netxen_nic_phy_read(port->adapter, port->portnum,
+					NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+					(netxen_crbword_t *) & status) != 0)
+			return -EIO;
+		else
+			return status.link;
+	}
+	return -EIO;
+}
+
+static int
+netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+		      u8 * bytes)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	int offset;
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	eeprom->magic = adapter->ahw.vendor_id | (adapter->ahw.device_id << 16);
+	for (offset = 0; offset < eeprom->len; offset++)
+		if (netxen_rom_fast_read
+		    (adapter, (8 * offset) + 8, (int *)eeprom->data) == -1)
+			return -1;
+	return 0;
+}
+
+static void
+netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	int i, j;
+	struct netxen_ring_context *ctx;
+
+	ring->rx_pending = 0;
+	ring->rx_max_pending = 0;
+	ring->tx_max_pending = 0;
+	for (i = 0; i < MAX_RING_CTX; ++i) {
+		ctx = &adapter->ring_ctx[i];
+		for (j = 0; j < NUM_RCV_DESC_RINGS; j++)
+			ring->rx_pending +=
+			    ctx->recv_ctx.rcv_desc[j].rcv_pending;
+		ring->tx_pending += ctx->pending_cmd_count;
+		ring->rx_max_pending += ctx->max_rx_desc_count;
+		ring->tx_max_pending += ctx->max_tx_desc_count;
+	}
+
+	ring->rx_mini_max_pending = 0;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static void
+netxen_nic_get_pauseparam(struct net_device *dev,
+			  struct ethtool_pauseparam *pause)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	struct netxen_niu_gb_mac_config_0_t val;
+
+	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+		/* get flow control settings */
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
+				   (u32 *) & val);
+		pause->rx_pause = val.rx_flowctl;
+		pause->tx_pause = val.tx_flowctl;
+		/* get autoneg settings */
+		pause->autoneg = port->link_autoneg;
+	}
+}
+
+static int
+netxen_nic_set_pauseparam(struct net_device *dev,
+			  struct ethtool_pauseparam *pause)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	struct netxen_niu_gb_mac_config_0_t val;
+	unsigned int autoneg;
+
+	/* read mode */
+	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+		/* set flow control */
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
+				   (u32 *) & val);
+		val.rx_flowctl = pause->rx_pause;
+		val.tx_flowctl = pause->tx_pause;
+		netxen_nic_write_w0(adapter,
+				    NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
+				    *(u32 *) (&val));
+		/* set autoneg */
+		autoneg = pause->autoneg;
+		if (netxen_nic_phy_write(port->adapter, port->portnum,
+					 NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+					 (netxen_crbword_t) autoneg) != 0)
+			return -EIO;
+		else {
+			port->link_autoneg = pause->autoneg;
+			return 0;
+		}
+	} else
+		return -EIO;
+}
+
+static int netxen_nic_reg_test(struct net_device *dev)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	struct netxen_adapter *adapter = port->adapter;
+	int data_read, data_written, save;
+	struct netxen_niu_control mode;
+
+	/* 
+	 * first test the "Read Only" registers by writing which mode
+	 */
+	netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, (u32 *) & mode);
+	if (mode.enable_ge) {	/* GB Mode */
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
+				   &data_read);
+
+		save = data_read;
+		if (data_read)
+			data_written = data_read & 0xDEADBEEF;
+		else
+			data_written = 0xDEADBEEF;
+		netxen_nic_write_w0(adapter,
+				    NETXEN_NIU_GB_MII_MGMT_STATUS(port->
+								  portnum),
+				    data_written);
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
+				   &data_read);
+
+		if (data_written == data_read) {
+			netxen_nic_write_w0(adapter,
+					    NETXEN_NIU_GB_MII_MGMT_STATUS(port->
+									  portnum),
+					    save);
+
+			return 0;
+		}
+
+		/* netxen_niu_gb_mii_mgmt_indicators_t is read only */
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
+								   portnum),
+				   &data_read);
+
+		save = data_read;
+		if (data_read)
+			data_written = data_read & 0xDEADBEEF;
+		else
+			data_written = 0xDEADBEEF;
+		netxen_nic_write_w0(adapter,
+				    NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
+								    portnum),
+				    data_written);
+
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
+								   portnum),
+				   &data_read);
+
+		if (data_written == data_read) {
+			netxen_nic_write_w0(adapter,
+					    NETXEN_NIU_GB_MII_MGMT_INDICATE
+					    (port->portnum), save);
+			return 0;
+		}
+
+		/* netxen_niu_gb_interface_status_t is read only */
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_INTERFACE_STATUS(port->
+								  portnum),
+				   &data_read);
+
+		save = data_read;
+		if (data_read)
+			data_written = data_read & 0xDEADBEEF;
+		else
+			data_written = 0xDEADBEEF;
+		netxen_nic_write_w0(adapter,
+				    NETXEN_NIU_GB_INTERFACE_STATUS(port->
+								   portnum),
+				    data_written);
+
+		netxen_nic_read_w0(adapter,
+				   NETXEN_NIU_GB_INTERFACE_STATUS(port->
+								  portnum),
+				   &data_read);
+
+		if (data_written == data_read) {
+			netxen_nic_write_w0(adapter,
+					    NETXEN_NIU_GB_INTERFACE_STATUS
+					    (port->portnum), save);
+
+			return 0;
+		}
+	}			/* GB Mode */
+	return 1;
+}
+
+static int netxen_nic_diag_test_count(struct net_device *dev)
+{
+	return NETXEN_NIC_TEST_LEN;
+}
+
+static void
+netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
+		     u64 * data)
+{
+	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {	/* offline tests */
+		/* link test */
+		if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		if (netif_running(dev))
+			dev->stop(dev);
+
+		/* register tests */
+		if (!(data[0] = netxen_nic_reg_test(dev)))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+		/* other tests pass as of now */
+		data[1] = data[2] = data[3] = 1;
+		if (netif_running(dev))
+			dev->open(dev);
+	} else {		/* online tests */
+		/* link test */
+		if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		/* other tests pass by default */
+		data[0] = data[1] = data[2] = data[3] = 1;
+	}
+}
+
+static void
+netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+	int index;
+
+	switch (stringset) {
+	case ETH_SS_TEST:
+		memcpy(data, *netxen_nic_gstrings_test,
+		       NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
+		break;
+	case ETH_SS_STATS:
+		for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
+			memcpy(data + index * ETH_GSTRING_LEN,
+			       netxen_nic_gstrings_stats[index].stat_string,
+			       ETH_GSTRING_LEN);
+		}
+		break;
+	}
+}
+
+static int netxen_nic_get_stats_count(struct net_device *dev)
+{
+	return NETXEN_NIC_STATS_LEN;
+}
+
+static void
+netxen_nic_get_ethtool_stats(struct net_device *dev,
+			     struct ethtool_stats *stats, u64 * data)
+{
+	struct netxen_port *port = netdev_priv(dev);
+	int index;
+
+	for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
+		char *p =
+		    (char *)port + netxen_nic_gstrings_stats[index].stat_offset;
+		data[index] =
+		    (netxen_nic_gstrings_stats[index].sizeof_stat ==
+		     sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
+	}
+
+}
+
+struct ethtool_ops netxen_nic_ethtool_ops = {
+	.get_settings = netxen_nic_get_settings,
+	.set_settings = netxen_nic_set_settings,
+	.get_drvinfo = netxen_nic_get_drvinfo,
+	.get_regs_len = netxen_nic_get_regs_len,
+	.get_regs = netxen_nic_get_regs,
+	.get_wol = netxen_nic_get_wol,
+	.nway_reset = netxen_nic_nway_reset,
+	.get_link = netxen_nic_get_link,
+	.get_eeprom_len = netxen_nic_get_eeprom_len,
+	.get_eeprom = netxen_nic_get_eeprom,
+	.get_ringparam = netxen_nic_get_ringparam,
+	.get_pauseparam = netxen_nic_get_pauseparam,
+	.set_pauseparam = netxen_nic_set_pauseparam,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = ethtool_op_set_tso,
+#endif
+	.self_test_count = netxen_nic_diag_test_count,
+	.self_test = netxen_nic_diag_test,
+	.get_strings = netxen_nic_get_strings,
+	.get_stats_count = netxen_nic_get_stats_count,
+	.get_ethtool_stats = netxen_nic_get_ethtool_stats,
+	.get_perm_addr = ethtool_op_get_perm_addr,
+};

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 2/9] NetXen: Main header file.
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
  2006-07-05 13:20 ` [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface Linsys Contractor Amit S. Kale
@ 2006-07-05 13:29 ` Linsys Contractor Amit S. Kale
  2006-07-05 15:46   ` Jeff Garzik
  2006-07-05 13:31 ` [PATCH 2.6.17 3/9] NetXen: Registers info " Linsys Contractor Amit S. Kale
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:29 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic.h linux-2.6.17/drivers/net/netxen/netxen_nic.h
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic.h	2006-07-05 01:18:40.363907266 -0700
@@ -0,0 +1,998 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef _NETXEN_NIC_H_
+#define _NETXEN_NIC_H_
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/version.h>
+
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+#include <linux/skbuff.h>
+
+#include "netxen_nic_hw.h"
+#include "netxen_nic_hdr.h"
+
+#define NETXEN_NIC_BUILD_NO     "231"
+#define _NETXEN_NIC_LINUX_MAJOR 2
+#define _NETXEN_NIC_LINUX_MINOR 1
+#define _NETXEN_NIC_LINUX_SUBVERSION 39
+#define NETXEN_NIC_LINUX_VERSIONID  "2.1.39"
+#define NETXEN_NIC_FW_VERSIONID "2.1.39"
+#define NETXEN_NIC_TIMESTAMP "Mon May  1 01:34:07 PDT 2006"
+
+#define RCV_DESC_RINGSIZE(ctxid)	\
+	(sizeof(struct rcv_desc_t) * adapter->ring_ctx[ctxid].max_rx_desc_count)
+#define STATUS_DESC_RINGSIZE(i)	\
+	(sizeof(struct status_desc_t)* adapter->ring_ctx[i].max_rx_desc_count)
+#define TX_RINGSIZE(i)	(sizeof(struct netxen_cmd_buffer)	\
+	* adapter->ring_ctx[i].max_tx_desc_count)
+#define JUMBO_DESC_RINGSIZE	\
+	(sizeof(rcvDesc_t) * adapter->ring_ctx[i].MaxJumboRxDescCount)
+#define RCV_BUFFSIZE	\
+	(sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+
+#define DB_PAGE_SIZE    0x1000
+#define NETXEN_CMD_PRODUCER_OFFSET(ctx) \
+	((NETXEN_CMD_PRODUCER_DB_PAGE(ctx)) * DB_PAGE_SIZE)
+#define NETXEN_RCV_STATUS_CONSUMER_OFFSET(ctx) \
+	((NETXEN_RCV_STATUS_CONSUMER_DB_PAGE(ctx)) * DB_PAGE_SIZE)
+#define NETXEN_RCV_PRODUCER_OFFSET(ctx,ring) \
+	((NETXEN_RCV_PRODUCER_DB_PAGE(ctx,ring)) * DB_PAGE_SIZE)
+
+#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
+
+#define NETXEN_NETDEV_STATUS 0x1
+
+#define ADDR_IN_WINDOW1(off)	\
+	((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
+
+/* 
+ * normalize a 64MB crb address to 32MB PCI window 
+ * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1
+ */
+#define NETXEN_CRB_NORMALIZE(adapter, reg) \
+	(void *)(ptrdiff_t)(adapter->ahw.pci_base+ (reg)	\
+	- NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST)
+
+#define DB_NORMALIZE(adapter, off) \
+	(void *)(ptrdiff_t)(adapter->ahw.db_base + (off))
+
+#define MAX_RX_BUFFER_LENGTH		2000
+#define MAX_RX_JUMBO_BUFFER_LENGTH 	9046
+#define RX_DMA_MAP_LEN 		(MAX_RX_BUFFER_LENGTH - NET_IP_ALIGN)
+#define RX_JUMBO_DMA_MAP_LEN	\
+	(MAX_RX_JUMBO_BUFFER_LENGTH - NET_IP_ALIGN)
+
+/*
+ * Maximum number of ring contexts
+ */
+#define MAX_RING_CTX 1
+
+/* Opcodes to be used with the commands */
+#define	TX_ETHER_PKT 0x01
+/* The following opcodes are for IP checksum	*/
+#define	TX_TCP_PKT 	0x02
+#define	TX_UDP_PKT	0x03
+#define	TX_IP_PKT	0x04
+#define	TX_TCP_LSO	0x05
+#define	TX_IPSEC	0x06
+#define	TX_IPSEC_CMD	0x07
+
+/* The following opcodes are for internal consumption. */
+#define NETXEN_CONTROL_OP	0x10
+#define PEGNET_REQUEST		0x11
+
+#define	MAX_NUM_CARDS		4
+
+#define MAX_BUFFERS_PER_CMD	32
+
+/*
+ * Following are the states of the Phantom. Phantom will set them and
+ * Host will read to check if the fields are correct.
+ */
+#define PHAN_INITIALIZE_START		0xff00
+#define PHAN_INITIALIZE_FAILED		0xffff
+#define PHAN_INITIALIZE_COMPLETE	0xff01
+
+/* Host writes the following to notify that it has done the init-handshake */
+#define PHAN_INITIALIZE_ACK	0xf00f
+
+#define NUM_RCV_DESC_RINGS	2	/* No of Rcv Descriptor contexts */
+
+/* descriptor types */
+#define RCV_DESC_NORMAL		0x01
+#define RCV_DESC_JUMBO		0x02
+#define RCV_DESC_NORMAL_CTXID	0
+#define RCV_DESC_JUMBO_CTXID	1
+
+#define RCV_DESC_TYPE(ID) \
+	((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : RCV_DESC_NORMAL)
+
+#define MAX_CMD_DESCRIPTORS		1024
+#define MAX_RCV_DESCRIPTORS		32768
+#define MAX_JUMBO_RCV_DESCRIPTORS	1024
+#define MAX_RCVSTATUS_DESCRIPTORS	MAX_RCV_DESCRIPTORS
+#define MAX_JUMBO_RCV_DESC	MAX_JUMBO_RCV_DESCRIPTORS
+#define MAX_RCV_DESC		MAX_RCV_DESCRIPTORS
+#define MAX_RCVSTATUS_DESC	MAX_RCV_DESCRIPTORS
+#define NUM_RCV_DESC		(MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS)
+#define MAX_EPG_DESCRIPTORS	MAX_CMD_DESCRIPTORS * 8
+
+#define MIN_TX_COUNT	4096
+#define MIN_RX_COUNT	4096
+
+#define MAX_FRAME_SIZE	0x10000	/* 64K MAX size for LSO */
+
+#define PHAN_PEG_RCV_INITIALIZED	0xff01
+#define PHAN_PEG_RCV_START_INITIALIZE	0xff00
+
+#define get_next_index(index, length)	\
+	((((index) + 1) == length) ? \
+		0 : \
+		(index) +1)
+
+#define get_index_range(index,length,count)	\
+	((((index) + (count)) >= length) ?	\
+		(((index) + (count))-(length)) :	\
+		((index) + (count)))
+
+/**
+ * Following data structures describe the descriptors that will be used.
+ * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
+ * we are doing LSO (above the 1500 size packet) only.
+ **/
+
+/**
+ * The size of reference handle been changed to 16 bits to pass the MSS fields
+ * for the LSO packet
+ **/
+
+#define FLAGS_CHECKSUM_ENABLED	0x01
+#define FLAGS_LSO_ENABLED	0x02
+#define FLAGS_IPSEC_SA_ADD	0x04
+#define FLAGS_IPSEC_SA_DELETE	0x08
+#define FLAGS_VLAN_TAGGED	0x10
+
+struct cmd_desc_type0_t {
+	u64 netxen_next;	/* for fragments handled by Phantom */
+	union {
+		struct {
+			u32 addr_low_part2;
+			u32 addr_high_part2;
+		};
+		u64 addr_buffer2;
+	};
+
+	u64 total_length:24,	/* Total size of the packet */
+	 tcp_hdr_offset:8,	/* For LSO only */
+	 ip_hdr_offset:8,	/* For LSO only */
+	 num_of_buffers:8,	/* total number of segments */
+	 flags:8,		/* as defined above */
+	 opcode:8;
+
+	u64 reference_handle:16,	/* changed to u16 to add mss */
+	 mss:16,		/* passed by NDIS_PACKET for LSO */
+	 port:4,
+	 ctx_id:4,
+	 total_hdr_length:8,	/* LSO only : MAC+IP+TCP Hdr size */
+	 conn_id:16;		/* IPSec offoad only */
+
+	union {
+		struct {
+			u32 addr_low_part3;
+			u32 addr_high_part3;
+		};
+		u64 addr_buffer3;
+	};
+
+	union {
+		struct {
+			u32 addr_low_part1;
+			u32 addr_high_part1;
+		};
+		u64 addr_buffer1;
+	};
+
+	u64 buffer1_length:16,
+	    buffer2_length:16, buffer3_length:16, buffer4_length:16;
+
+	union {
+		struct {
+			u32 addr_low_part4;
+			u32 addr_high_part4;
+		};
+		u64 addr_buffer4;
+	};
+
+} __attribute__ ((aligned(64)));
+
+/* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
+struct rcv_desc_t {
+	u64 reference_handle:16,
+	 reserved:16,
+	 buffer_length:32;	/* allocated buffer length (usually 2K) */
+	u64 addr_buffer;
+};
+
+/* opcode field in status_desc_t */
+#define RCV_NIC_PKT	(0xA)
+#define STATUS_NIC_PKT	((RCV_NIC_PKT) << 12)
+
+/* for status field in status_desc_t */
+#define STATUS_NEED_CKSUM	(1)
+#define STATUS_CKSUM_OK		(2)
+
+/* owner bits of status_desc_t */
+#define STATUS_OWNER_HOST	(1ULL)
+#define STATUS_OWNER_PHANTOM	(2ULL)
+#define HOST_STATUS_DESC	((STATUS_OWNER_HOST) << 48)
+#define PHANTOM_STATUS_DESC	((STATUS_OWNER_PHANTOM) << 48)
+
+#define NETXEN_PROT_IP		(1)
+#define NETXEN_PROT_UNKNOWN	(0)
+
+/* Note: sizeof(status_desc) should always be a mutliple of 2 */
+struct status_desc_t {
+	u64 port:4,		/* initially to be used but noe now */
+	 status:4,		/* completion status may not have use */
+	 type:4,		/* type/index of descriptor ring */
+	 opcode:4,		/* Completion of receive or transmit */
+	 total_length:16,	/* NIC mode */
+	 reference_handle:16,	/* handle for the associated packet */
+	 owner:2,		/* Owner of the descriptor */
+	 prot:4;		/* protocol type for skb (Linux) */
+} __attribute__ ((aligned(8)));
+
+enum {
+	NETXEN_RCV_PEG_0 = 0,
+	NETXEN_RCV_PEG_1
+};
+
+/* The version of the main data structure */
+#define	NETXEN_BDINFO_VERSION 1
+
+/* Magic number to let user know flash is programmed */
+#define	NETXEN_BDINFO_MAGIC 0x12345678
+
+/* Max number of Gig ports on a Phantom board */
+#define NETXEN_MAX_PORTS 4
+
+typedef enum {
+	NETXEN_BRDTYPE_P1_BD = 0x0000,
+	NETXEN_BRDTYPE_P1_SB = 0x0001,
+	NETXEN_BRDTYPE_P1_SMAX = 0x0002,
+	NETXEN_BRDTYPE_P1_SOCK = 0x0003,
+
+	NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008,
+	NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009,
+	NETXEN_BRDTYPE_P2_SB35_4G = 0x000a,
+	NETXEN_BRDTYPE_P2_SB31_10G = 0x000b,
+	NETXEN_BRDTYPE_P2_SB31_2G = 0x000c,
+
+	NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
+	NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
+	NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f
+} netxen_brdtype_t;
+
+typedef enum {
+	NETXEN_BRDMFG_INVENTEC = 1
+} netxen_brdmfg;
+
+typedef enum {
+	MEM_ORG_128Mbx4 = 0x0,	/* DDR1 only */
+	MEM_ORG_128Mbx8 = 0x1,	/* DDR1 only */
+	MEM_ORG_128Mbx16 = 0x2,	/* DDR1 only */
+	MEM_ORG_256Mbx4 = 0x3,
+	MEM_ORG_256Mbx8 = 0x4,
+	MEM_ORG_256Mbx16 = 0x5,
+	MEM_ORG_512Mbx4 = 0x6,
+	MEM_ORG_512Mbx8 = 0x7,
+	MEM_ORG_512Mbx16 = 0x8,
+	MEM_ORG_1Gbx4 = 0x9,
+	MEM_ORG_1Gbx8 = 0xa,
+	MEM_ORG_1Gbx16 = 0xb,
+	MEM_ORG_2Gbx4 = 0xc,
+	MEM_ORG_2Gbx8 = 0xd,
+	MEM_ORG_2Gbx16 = 0xe,
+	MEM_ORG_128Mbx32 = 0x10002,	/* GDDR only */
+	MEM_ORG_256Mbx32 = 0x10005	/* GDDR only */
+} netxen_mn_mem_org_t;
+
+typedef enum {
+	MEM_ORG_512Kx36 = 0x0,
+	MEM_ORG_1Mx36 = 0x1,
+	MEM_ORG_2Mx36 = 0x2
+} netxen_sn_mem_org_t;
+
+typedef enum {
+	MEM_DEPTH_4MB = 0x1,
+	MEM_DEPTH_8MB = 0x2,
+	MEM_DEPTH_16MB = 0x3,
+	MEM_DEPTH_32MB = 0x4,
+	MEM_DEPTH_64MB = 0x5,
+	MEM_DEPTH_128MB = 0x6,
+	MEM_DEPTH_256MB = 0x7,
+	MEM_DEPTH_512MB = 0x8,
+	MEM_DEPTH_1GB = 0x9,
+	MEM_DEPTH_2GB = 0xa,
+	MEM_DEPTH_4GB = 0xb,
+	MEM_DEPTH_8GB = 0xc,
+	MEM_DEPTH_16GB = 0xd,
+	MEM_DEPTH_32GB = 0xe
+} netxen_mem_depth_t;
+
+struct netxen_board_info {
+	u32 header_version;
+
+	u32 board_mfg;
+	u32 board_type;
+	u32 board_num;
+	u32 chip_id;
+	u32 chip_minor;
+	u32 chip_major;
+	u32 chip_pkg;
+	u32 chip_lot;
+
+	u32 port_mask;		/* available niu ports */
+	u32 peg_mask;		/* available pegs */
+	u32 icache_ok;		/* can we run with icache? */
+	u32 dcache_ok;		/* can we run with dcache? */
+	u32 casper_ok;
+
+	u32 mac_addr_lo_0;
+	u32 mac_addr_lo_1;
+	u32 mac_addr_lo_2;
+	u32 mac_addr_lo_3;
+
+	/* MN-related config */
+	u32 mn_sync_mode;	/* enable/ sync shift cclk/ sync shift mclk */
+	u32 mn_sync_shift_cclk;
+	u32 mn_sync_shift_mclk;
+	u32 mn_wb_en;
+	u32 mn_crystal_freq;	/* in MHz */
+	u32 mn_speed;		/* in MHz */
+	u32 mn_org;
+	u32 mn_depth;
+	u32 mn_ranks_0;		/* ranks per slot */
+	u32 mn_ranks_1;		/* ranks per slot */
+	u32 mn_rd_latency_0;
+	u32 mn_rd_latency_1;
+	u32 mn_rd_latency_2;
+	u32 mn_rd_latency_3;
+	u32 mn_rd_latency_4;
+	u32 mn_rd_latency_5;
+	u32 mn_rd_latency_6;
+	u32 mn_rd_latency_7;
+	u32 mn_rd_latency_8;
+	u32 mn_dll_val[18];
+	u32 mn_mode_reg;	/* MIU DDR Mode Register */
+	u32 mn_ext_mode_reg;	/* MIU DDR Extended Mode Register */
+	u32 mn_timing_0;	/* MIU Memory Control Timing Rgister */
+	u32 mn_timing_1;	/* MIU Extended Memory Ctrl Timing Register */
+	u32 mn_timing_2;	/* MIU Extended Memory Ctrl Timing2 Register */
+
+	/* SN-related config */
+	u32 sn_sync_mode;	/* enable/ sync shift cclk / sync shift mclk */
+	u32 sn_pt_mode;		/* pass through mode */
+	u32 sn_ecc_en;
+	u32 sn_wb_en;
+	u32 sn_crystal_freq;
+	u32 sn_speed;
+	u32 sn_org;
+	u32 sn_depth;
+	u32 sn_dll_tap;
+	u32 sn_rd_latency;
+
+	u32 mac_addr_hi_0;
+	u32 mac_addr_hi_1;
+	u32 mac_addr_hi_2;
+	u32 mac_addr_hi_3;
+
+	u32 magic;		/* indicates flash has been initialized */
+
+	u32 mn_rdimm;
+	u32 mn_dll_override;
+
+};
+
+#define FLASH_NUM_PORTS		(4)
+
+struct netxen_flash_mac_addr {
+	u32 flash_addr[32];
+};
+
+#define FLASH_NUM_MAC_PER_PORT	32
+struct netxen_user_info {
+	u8 flash_md5[16 * 64];
+	/* bootloader */
+	u32 bootld_version;
+	u32 bootld_size;
+	/* image */
+	u32 image_version;
+	u32 image_size;
+	/* primary image status */
+	u32 primary_status;
+	u32 secondary_present;
+
+	/* MAC address , 4 ports, 32 address per port */
+	u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
+	u32 sub_sys_id;
+	u8 serial_num[32];
+
+	/* Any user defined data */
+};
+
+/*
+ * Flash Layout - new format.
+ */
+#define FLASH_NUM_MAC_PER_PORT	32
+struct netxen_new_user_info {
+	u8 flash_md5[16 * 64];
+	/* bootloader */
+	u32 bootld_version;
+	u32 bootld_size;
+	/* image */
+	u32 image_version;
+	u32 image_size;
+	/* primary image status */
+	u32 primary_status;
+	u32 secondary_present;
+
+	/* MAC address , 4 ports, 32 address per port */
+	u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
+	u32 sub_sys_id;
+	u8 serial_num[32];
+
+	/* Any user defined data */
+};
+
+#define SECONDARY_IMAGE_PRESENT 0xb3b4b5b6
+#define SECONDARY_IMAGE_ABSENT	0xffffffff
+#define PRIMARY_IMAGE_GOOD	0x5a5a5a5a
+#define PRIMARY_IMAGE_BAD	0xffffffff
+
+/* Flash memory map */
+typedef enum {
+	CRBINIT_START = 0,	/* Crbinit section */
+	BRDCFG_START = 0x4000,	/* board config */
+	INITCODE_START = 0x6000,	/* pegtune code */
+	BOOTLD_START = 0x10000,	/* bootld */
+	IMAGE_START = 0x43000,	/* compressed image */
+	SECONDARY_START = 0x200000,	/* backup images */
+	PXE_START = 0x3E0000,	/* user defined region */
+	USER_START = 0x3E8000,	/* User defined region for new boards */
+	FIXED_START = 0x3F0000	/* backup of crbinit */
+} netxen_flash_map_t;
+
+#define USER_START_OLD PXE_START	/* for backward compatibility */
+
+#define FLASH_START		(CRBINIT_START)
+#define INIT_SECTOR		(0)
+#define PRIMARY_START 		(BOOTLD_START)
+#define FLASH_CRBINIT_SIZE 	(0x4000)
+#define FLASH_BRDCFG_SIZE 	(sizeof(struct netxen_board_info))
+#define FLASH_USER_SIZE		(sizeof(netxen_user_info)/sizeof(u32))
+#define FLASH_SECONDARY_SIZE 	(USER_START-SECONDARY_START)
+#define NUM_PRIMARY_SECTORS	(0x20)
+#define NUM_CONFIG_SECTORS 	(1)
+int is_flash_supported(struct netxen_adapter *adapter);
+int get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
+extern char netxen_nic_driver_string[];
+extern void netxen_change_ringparam(struct netxen_adapter *adapter);
+extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
+				int *valp);
+
+extern struct ethtool_ops netxen_nic_ethtool_ops;
+
+/*
+ * The PCI VendorID and DeviceID for our board.
+ */
+#define PCI_VENDOR_ID_NX       0x4040
+#define PCI_DEVICE_ID_NX_XG    0x0001
+#define PCI_DEVICE_ID_NX_CX4   0x0002
+#define PCI_DEVICE_ID_NX_QG    0x0003
+#define PCI_DEVICE_ID_NX_IMEZ  0x0004
+#define PCI_DEVICE_ID_NX_HMEZ  0x0005
+
+#define NETXEN_PCI_ID(X) { PCI_DEVICE(PCI_VENDOR_ID_NX, (X)) }
+
+#define PFX "netxen: "
+
+/* Note: Make sure to not call this before adapter->port is valid */
+#if !defined(NETXEN_DEBUG)
+#define DPRINTK(klevel, fmt, args...)	do { \
+	} while (0)
+#else
+#define DPRINTK(klevel, fmt, args...)	do { \
+	printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
+		(adapter != NULL && adapter->port != NULL && \
+		adapter->port[0] != NULL && \
+		adapter->port[0]->netdev != NULL) ? \
+		adapter->port[0]->netdev->name : NULL, \
+		## args); } while(0)
+#endif
+
+/* Number of status descriptors to handle per interrupt */
+#define MAX_STATUS_HANDLE	(128)
+
+/*
+ * netxen_skb_frag{} is to contain mapping info for each SG list. This
+ * has to be freed when DMA is complete. This is part of netxen_tx_buffer{}.
+ */
+struct netxen_skb_frag {
+	u64 dma;
+	u32 length;
+};
+
+/*    Following defines are for the state of the buffers    */
+#define	NETXEN_BUFFER_FREE	0
+#define	NETXEN_BUFFER_BUSY	1
+
+/*
+ * There will be one netxen_buffer per skb packet.    These will be
+ * used to save the dma info for pci_unmap_page()
+ */
+struct netxen_cmd_buffer {
+	struct sk_buff *skb;
+	struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
+	u32 total_length;
+	u32 mss;
+	u32 port:16, cmd:8, frag_count:8;
+	unsigned long time_stamp;
+	u32 state;
+	u32 no_of_descriptors;
+};
+
+/* In rx_buffer, we do not need multiple fragments as is a single buffer */
+struct netxen_rx_buffer {
+	struct sk_buff *skb;
+	u64 dma;
+	u32 ref_handle:16, state:16;
+};
+
+/* Board types */
+#define	NETXEN_NIC_GBE	0x01
+#define	NETXEN_NIC_XGBE	0x02
+
+/*
+ * One hardware_context{} per adapter
+ * contains interrupt info as well shared hardware info.
+ */
+struct netxen_hardware_context {
+	struct pci_dev *pdev;
+	unsigned long pci_base;	/* base of mapped phantom memory */
+	unsigned long pci_len;	/* length of mapped phantom memory */
+	u16 vendor_id;
+	u16 device_id;
+	u8 revision_id;
+	u16 pci_cmd_word;
+	u16 board_type;
+	u16 max_ports;
+	struct netxen_board_info boardcfg;
+	u32 xg_linkup;
+	struct netxen_adapter *adapter;
+	u32 crb_base;
+	unsigned long db_base;	/* base of mapped db memory */
+	unsigned long db_len;	/* length of mapped db memory */
+};
+
+#define MINIMUM_ETHERNET_FRAME_SIZE	64	/* With FCS */
+#define ETHERNET_FCS_SIZE		4
+
+struct netxen_adapter_stats {
+	u64 ints;
+	u64 hostints;
+	u64 otherints;
+	u64 process_rcv;
+	u64 process_xmit;
+	u64 noxmitdone;
+	u64 xmitcsummed;
+	u64 post_called;
+	u64 posted;
+	u64 lastposted;
+	u64 goodskbposts;
+};
+
+/*
+ * Ring which will hold the skbs which can be fed to receive ring
+ */
+#define NETXEN_SKB_ARRAY_SIZE	1024
+
+struct netxen_recv_skb_ring {
+	struct sk_buff **skb_array;
+	u32 interrupt_index;
+	u32 tasklet_index;
+	u32 data_size;
+};
+
+/*
+ * Rcv Descriptor Context. One such per Rcv Descriptor. There may
+ * be one Rcv Descriptor for normal packets, one for jumbo and may be others.
+ */
+struct netxen_rcv_desc_ctx {
+	u32 flags;
+	u32 producer;
+	u32 rcv_pending;	/* Num of bufs posted in phantom */
+	u32 rcv_free;		/* Num of bufs in free list */
+	u32 phys_addr;
+	struct rcv_desc_t *desc_head;	/* address of rx ring in Phantom */
+	u32 max_rx_desc_count;
+	u32 dma_size;
+	u32 skb_size;
+	struct netxen_rx_buffer *rx_buf_arr;	/* rx buffers for receive   */
+	dma_addr_t rx_buf_phys;	/* physical address of above */
+	int begin_alloc;
+};
+
+/*
+ * Receive context. There is one such structure per instance of the
+ * receive processing. Any state information that is relevant to
+ * the receive, and is must be in this structure. The global data may be
+ * present elsewhere.
+ */
+struct netxen_recv_context {
+	struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
+	u32 status_rx_producer;
+	u32 status_rx_consumer;
+	u32 rcv_status_desc_phys_addr;
+	struct status_desc_t *rcv_status_desc_head;
+};
+
+#define NETXEN_NIC_MSI_ENABLED 0x02
+
+struct netxen_hardware_ring_context {
+	/* Address of cmd ring in Phantom */
+	struct cmd_desc_type0_t *cmd_desc_head;
+	u32 cmd_producer;
+	u32 cmd_consumer;
+	u32 status_rx_producer;
+	u32 status_rx_consumer;
+	u32 cmd_desc_phys_addr;
+};
+
+struct netxen_ring_context {
+	struct netxen_hardware_ring_context hw_ring_ctx;
+	u32 cmd_producer;
+	u32 *cmd_consumer;
+
+	u32 last_cmd_consumer;
+	/* Num of bufs posted in phantom */
+	u32 pending_cmd_count;
+	u32 free_cmd_count;	/* Num of bufs in free list */
+	u32 max_tx_desc_count;
+	u32 max_rx_desc_count;
+	u32 max_jumbo_rx_desc_count;
+	/* Num of instances active on cmd buffer ring */
+	u32 proc_cmd_buf_counter;
+	volatile u32 cmd_peg_consumer;
+
+	struct netxen_cmd_buffer *cmd_buf_arr;	/* Command buffers for xmit */
+	struct netxen_rx_buffer *rx_buf_arr;	/* rx buffers for receive   */
+
+	/*
+	 * Receive instance.
+	 */
+	struct netxen_recv_context recv_ctx;
+
+	/* context interface shared between card and host */
+	struct ring_context *ctx_desc;
+	u32 ctx_desc_phys_addr;
+
+};
+
+/* this structure by all ports on the adapter */
+struct netxen_adapter {
+	struct netxen_hardware_context ahw;
+	int port_count;		/* Number of configured ports  */
+	int active_ports;	/* Number of open ports */
+	struct netxen_port **port;	/* ptr to each port  */
+	spinlock_t tx_lock;
+	rwlock_t adapter_lock;
+	spinlock_t lock;
+	struct work_struct watchdog_task;
+	struct work_struct tx_timeout_task[4];
+	struct timer_list watchdog_timer;
+
+	u32 curr_window;
+
+	u32 num_threads, total_threads;	/*Use to keep track of xmit threads */
+
+	u32 flags;
+	u32 irq;
+	int driver_mismatch;
+
+	struct netxen_adapter_stats stats;
+
+	struct netxen_ring_context ring_ctx[MAX_RING_CTX];
+	int number;
+	int is_up;
+	int work_done;
+};				/* netxen_adapter structure */
+
+/* Max number of xmit producer threads that can run simultaneously */
+#define	MAX_XMIT_PRODUCERS		16
+
+struct netxen_port_stats {
+	u64 rcvdbadskb;
+	u64 xmitcalled;
+	u64 xmitedframes;
+	u64 xmitfinished;
+	u64 badskblen;
+	u64 nocmddescriptor;
+	u64 polled;
+	u64 uphappy;
+	u64 updropped;
+	u64 uplcong;
+	u64 uphcong;
+	u64 upmcong;
+	u64 updunno;
+	u64 skbfreed;
+	u64 txdropped;
+	u64 txnullskb;
+	u64 csummed;
+	u64 no_rcv;
+	u64 rxbytes;
+	u64 txbytes;
+};
+
+struct netxen_port {
+	struct netxen_adapter *adapter;
+
+	u16 portnum;		/* GBE port number */
+	u16 link_speed;
+	u16 link_duplex;
+	u16 link_autoneg;
+
+	int flags;
+	spinlock_t stats_lock;
+
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device_stats net_stats;
+	struct netxen_port_stats stats;
+};
+
+extern char netxen_nic_driver_name[];
+
+#define NETXEN_CTX_SIGNATURE	0xdee0
+#define MAX_PEG_RING_CTX	4
+
+#define RX_PRODUCER 0
+#define RX_PRODUCER_JUMBO 1
+#define TX_PRODUCER 2
+#define STS_PRODUCER 3
+
+#define NUM_DB_CODE 16
+
+#define NETXEN_RCV_PRODUCER(ringid)	(ringid)
+
+#define NETXEN_CMD_PRODUCER 2
+#define NETXEN_RCV_STATUS_CONSUMER 3
+
+struct ctx_msg {
+	u32 PegId:2, Count:16, CtxId:10, Opcode:4;
+};
+
+struct rcv_context {
+	u64 RcvRingAddrLo:32, RcvRingAddrHi:32;
+	u32 RcvRingSize;
+	u32 Rsrv;
+};
+
+struct ring_context {
+
+	u64 CMD_CONSUMER_OFFSET;
+	u64 CmdRingAddrLo:32, CmdRingAddrHi:32;
+	u32 CmdRingSize;
+	u32 Rsrv;
+	struct rcv_context RcvContext[2];
+	u64 StsRingAddrLo:32, StsRingAddrHi:32;
+	u32 StsRingSize;
+	u32 CtxId;
+} __attribute__ ((aligned(64)));
+
+#define NETXEN_RCV_PEG_DB_ID  1
+#define NETXEN_XMIT_PEG_DB_ID 2
+
+long netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
+					  long port);
+long netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter,
+					   long port);
+long netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter,
+					 long port);
+void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, long port,
+				 long enable);
+void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, long port,
+				  long enable);
+long netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, long reg,
+			     netxen_crbword_t * readval);
+long netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy,
+			      long reg, netxen_crbword_t val);
+
+/* Functions available from netxen_nic_hw.c */
+void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw);
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value);
+
+int netxen_nic_get_board_info(struct netxen_adapter *adapter);
+void netxen_nic_hw_block_write(struct netxen_adapter *adapter,
+			       u64 off, void *data, int num_words);
+int netxen_nic_pci_mem_write(struct netxen_adapter *adapter,
+			     u64 off, void *data, int size);
+int netxen_nic_pci_mem_read(struct netxen_adapter *adapter,
+			    u64 off, void *data, int size);
+void netxen_nic_mem_block_read(struct netxen_adapter *adapter, u64 off,
+			       void *data, int num_words);
+void netxen_nic_mem_block_write(struct netxen_adapter *adapter, u64 off,
+				void *data, int num_words);
+int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
+			  int len);
+int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
+			   int len);
+int netxen_nic_macaddr_set(struct netxen_port *port, u8 * addr);
+int netxen_nic_macaddr_get(struct netxen_port *port, u8 ** addr);
+int netxen_nic_macaddr_set(struct netxen_port *port, u8 * addr);
+int netxen_nic_macaddr_get(struct netxen_port *port, u8 ** addr);
+int netxen_nic_set_mtu(struct netxen_port *port, int new_mtu);
+long netxen_nic_phy_read(struct netxen_adapter *adapter, long phy, long, u32 *);
+long netxen_nic_phy_write(struct netxen_adapter *adapter, long phy, long reg,
+			  u32);
+long netxen_nic_init_port(struct netxen_port *port);
+void netxen_nic_init_niu(struct netxen_adapter *adapter);
+void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+				 unsigned long off, int data);
+
+/* Functions from netxen_nic_init.c */
+void phantom_init(struct netxen_adapter *adapter);
+void load_firmware(struct netxen_adapter *adapter);
+int pinit_from_rom(struct netxen_adapter *adapter, int verbose);
+int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
+
+/* Functions from netxen_nic_isr.c */
+void netxen_nic_isr_other(struct netxen_adapter *adapter);
+void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter);
+long netxen_nic_phy_read(struct netxen_adapter *adapter, long phy, long reg,
+			 u32 * readval);
+long netxen_nic_phy_write(struct netxen_adapter *adapter, long phy, long reg,
+			  u32 val);
+long netxen_nic_enable_phy_interrupts(struct netxen_adapter *adapter,
+				      long port);
+long netxen_nic_disable_phy_interrupts(struct netxen_adapter *adapter,
+				       long port);
+long netxen_nic_clear_phy_interrupts(struct netxen_adapter *adapter, long port);
+void netxen_nic_set_mii_mode(struct netxen_adapter *adapter, long port,
+			     long enable);
+void netxen_nic_set_gmii_mode(struct netxen_adapter *adapter, long port,
+			      long enable);
+void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 port,
+				 u32 link);
+void netxen_handle_port_int(struct netxen_adapter *adapter, u32 port,
+			    u32 enable);
+int netxen_nic_set_promisc_mode(struct netxen_port *port);
+int netxen_nic_unset_promisc_mode(struct netxen_port *port);
+void netxen_nic_stop_all_ports(struct netxen_adapter *adapter);
+void netxen_nic_stop_port(struct netxen_port *port);
+int netxen_nic_get_board_num(struct netxen_adapter *adapter);
+void initialize_adapter_sw(struct netxen_adapter *adapter);
+int initialize_adapter_hw(struct netxen_adapter *adapter);
+int init_firmware(struct netxen_adapter *adapter);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+void netxen_tso_check(struct netxen_adapter *adapter,
+		      struct cmd_desc_type0_t *desc, struct sk_buff *skb);
+int netxen_nic_hw_resources(struct netxen_adapter *adapter);
+void netxen_nic_clear_stats(struct netxen_adapter *adapter);
+int
+netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
+		    struct netxen_port *port);
+int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
+int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
+void netxen_watchdog_task(unsigned long v);
+void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
+			    u32 ringid);
+void netxen_process_cmd_ring(unsigned long data, int ctxid);
+u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
+void netxen_nic_set_multi(struct net_device *netdev);
+int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+int netxen_nic_set_mac(struct net_device *netdev, void *p);
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+int netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state);
+int netxen_nic_resume(struct pci_dev *pdev);
+void netxen_nic_down(struct netxen_port *port);
+void __devinit netxen_check_options(struct netxen_adapter *adapter);
+void netxen_check_cmdline_params(void);
+
+static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
+{
+	u32 mask;
+
+	mask = 0x7ff;
+
+	/*
+	 * ISR_INT_MASK: Can be read from window 0 or 1.
+	 */
+	writel(mask, (void *)(adapter->ahw.pci_base + ISR_INT_MASK));
+}
+
+static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
+{
+	u32 mask;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		mask = 0x77b;
+		break;
+	case NETXEN_NIC_XGBE:
+		mask = 0x77f;
+		break;
+	default:
+		mask = 0x7ff;
+		break;
+	}
+
+	writel(mask, (void *)(adapter->ahw.pci_base + ISR_INT_MASK));
+
+	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		mask = 0xbff;
+		writel(mask,
+		       (void *)(adapter->ahw.pci_base + ISR_INT_TARGET_MASK));
+	}
+}
+
+#endif				/* __NETXEN_NIC_H_ */


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 3/9] NetXen: Registers info header file.
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
  2006-07-05 13:20 ` [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface Linsys Contractor Amit S. Kale
  2006-07-05 13:29 ` [PATCH 2.6.17 2/9] NetXen: Main header file Linsys Contractor Amit S. Kale
@ 2006-07-05 13:31 ` Linsys Contractor Amit S. Kale
  2006-07-05 15:51   ` Jeff Garzik
  2006-07-05 13:34 ` [PATCH 2.6.17 4/9] NetXen: hardware access routines Linsys Contractor Amit S. Kale
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:31 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_hdr.h linux-2.6.17/drivers/net/netxen/netxen_nic_hdr.h
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_hdr.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_hdr.h	2006-07-05 01:18:40.359908085 -0700
@@ -0,0 +1,684 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef __NETXEN_NIC_HDR_H_
+#define __NETXEN_NIC_HDR_H_
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <asm/semaphore.h>
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/string.h>		/* for memset */
+
+extern struct netxen_adapter *g_adapter;
+
+/*
+ * The basic unit of access when reading/writing control registers.
+ */
+
+typedef u32 netxen_crbword_t;	/* single word in CRB space */
+
+#define NETXEN_HW_H0_CH_HUB_ADR	0x05
+#define NETXEN_HW_H1_CH_HUB_ADR	0x0E
+#define NETXEN_HW_H2_CH_HUB_ADR	0x03
+#define NETXEN_HW_H3_CH_HUB_ADR	0x01
+#define NETXEN_HW_H4_CH_HUB_ADR	0x06
+#define NETXEN_HW_H5_CH_HUB_ADR	0x07
+#define NETXEN_HW_H6_CH_HUB_ADR	0x08
+
+/*  Hub 0 */
+#define NETXEN_HW_MN_CRB_AGT_ADR	0x15
+#define NETXEN_HW_MS_CRB_AGT_ADR	0x25
+
+/*  Hub 1 */
+#define NETXEN_HW_PS_CRB_AGT_ADR	0x73
+#define NETXEN_HW_SS_CRB_AGT_ADR	0x20
+#define NETXEN_HW_RPMX3_CRB_AGT_ADR	0x0b
+#define NETXEN_HW_QMS_CRB_AGT_ADR	0x00
+#define NETXEN_HW_SQGS0_CRB_AGT_ADR	0x01
+#define NETXEN_HW_SQGS1_CRB_AGT_ADR	0x02
+#define NETXEN_HW_SQGS2_CRB_AGT_ADR	0x03
+#define NETXEN_HW_SQGS3_CRB_AGT_ADR	0x04
+#define NETXEN_HW_C2C0_CRB_AGT_ADR	0x58
+#define NETXEN_HW_C2C1_CRB_AGT_ADR	0x59
+#define NETXEN_HW_C2C2_CRB_AGT_ADR	0x5a
+#define NETXEN_HW_RPMX2_CRB_AGT_ADR	0x0a
+#define NETXEN_HW_RPMX4_CRB_AGT_ADR	0x0c
+#define NETXEN_HW_RPMX7_CRB_AGT_ADR	0x0f
+#define NETXEN_HW_RPMX9_CRB_AGT_ADR	0x12
+#define NETXEN_HW_SMB_CRB_AGT_ADR	0x18
+
+/*  Hub 2 */
+#define NETXEN_HW_NIU_CRB_AGT_ADR	0x31
+#define NETXEN_HW_I2C0_CRB_AGT_ADR	0x19
+#define NETXEN_HW_I2C1_CRB_AGT_ADR	0x29
+
+#define NETXEN_HW_SN_CRB_AGT_ADR	0x10
+#define NETXEN_HW_I2Q_CRB_AGT_ADR	0x20
+#define NETXEN_HW_LPC_CRB_AGT_ADR	0x22
+#define NETXEN_HW_ROMUSB_CRB_AGT_ADR	0x21
+#define NETXEN_HW_QM_CRB_AGT_ADR	0x66
+#define NETXEN_HW_SQG0_CRB_AGT_ADR	0x60
+#define NETXEN_HW_SQG1_CRB_AGT_ADR	0x61
+#define NETXEN_HW_SQG2_CRB_AGT_ADR	0x62
+#define NETXEN_HW_SQG3_CRB_AGT_ADR	0x63
+#define NETXEN_HW_RPMX1_CRB_AGT_ADR	0x09
+#define NETXEN_HW_RPMX5_CRB_AGT_ADR	0x0d
+#define NETXEN_HW_RPMX6_CRB_AGT_ADR	0x0e
+#define NETXEN_HW_RPMX8_CRB_AGT_ADR	0x11
+
+/*  Hub 3 */
+#define NETXEN_HW_PH_CRB_AGT_ADR	0x1A
+#define NETXEN_HW_SRE_CRB_AGT_ADR	0x50
+#define NETXEN_HW_EG_CRB_AGT_ADR	0x51
+#define NETXEN_HW_RPMX0_CRB_AGT_ADR	0x08
+
+/*  Hub 4 */
+#define NETXEN_HW_PEGN0_CRB_AGT_ADR	0x40
+#define NETXEN_HW_PEGN1_CRB_AGT_ADR	0x41
+#define NETXEN_HW_PEGN2_CRB_AGT_ADR	0x42
+#define NETXEN_HW_PEGN3_CRB_AGT_ADR	0x43
+#define NETXEN_HW_PEGNI_CRB_AGT_ADR	0x44
+#define NETXEN_HW_PEGND_CRB_AGT_ADR	0x45
+#define NETXEN_HW_PEGNC_CRB_AGT_ADR	0x46
+#define NETXEN_HW_PEGR0_CRB_AGT_ADR	0x47
+#define NETXEN_HW_PEGR1_CRB_AGT_ADR	0x48
+#define NETXEN_HW_PEGR2_CRB_AGT_ADR	0x49
+#define NETXEN_HW_PEGR3_CRB_AGT_ADR	0x4a
+
+/*  Hub 5 */
+#define NETXEN_HW_PEGS0_CRB_AGT_ADR	0x40
+#define NETXEN_HW_PEGS1_CRB_AGT_ADR	0x41
+#define NETXEN_HW_PEGS2_CRB_AGT_ADR	0x42
+#define NETXEN_HW_PEGS3_CRB_AGT_ADR	0x43
+#define NETXEN_HW_PEGSI_CRB_AGT_ADR	0x44
+#define NETXEN_HW_PEGSD_CRB_AGT_ADR	0x45
+#define NETXEN_HW_PEGSC_CRB_AGT_ADR	0x46
+
+/*  Hub 6 */
+#define NETXEN_HW_CAS0_CRB_AGT_ADR	0x46
+#define NETXEN_HW_CAS1_CRB_AGT_ADR	0x47
+#define NETXEN_HW_CAS2_CRB_AGT_ADR	0x48
+#define NETXEN_HW_CAS3_CRB_AGT_ADR	0x49
+#define NETXEN_HW_NCM_CRB_AGT_ADR	0x16
+#define NETXEN_HW_TMR_CRB_AGT_ADR	0x17
+#define NETXEN_HW_XDMA_CRB_AGT_ADR	0x05
+#define NETXEN_HW_OCM0_CRB_AGT_ADR	0x06
+#define NETXEN_HW_OCM1_CRB_AGT_ADR	0x07
+
+/*  Floaters - non existent modules */
+#define NETXEN_HW_EFC_RPMX0_CRB_AGT_ADR	0x67
+
+/*  This field defines PCI/X adr [25:20] of agents on the CRB */
+#define NETXEN_HW_PX_MAP_CRB_PH		0
+#define NETXEN_HW_PX_MAP_CRB_PS		1
+#define NETXEN_HW_PX_MAP_CRB_MN		2
+#define NETXEN_HW_PX_MAP_CRB_MS		3
+#define NETXEN_HW_PX_MAP_CRB_SRE	5
+#define NETXEN_HW_PX_MAP_CRB_NIU	6
+#define NETXEN_HW_PX_MAP_CRB_QMN	7
+#define NETXEN_HW_PX_MAP_CRB_SQN0	8
+#define NETXEN_HW_PX_MAP_CRB_SQN1	9
+#define NETXEN_HW_PX_MAP_CRB_SQN2	10
+#define NETXEN_HW_PX_MAP_CRB_SQN3	11
+#define NETXEN_HW_PX_MAP_CRB_QMS	12
+#define NETXEN_HW_PX_MAP_CRB_SQS0	13
+#define NETXEN_HW_PX_MAP_CRB_SQS1	14
+#define NETXEN_HW_PX_MAP_CRB_SQS2	15
+#define NETXEN_HW_PX_MAP_CRB_SQS3	16
+#define NETXEN_HW_PX_MAP_CRB_PGN0	17
+#define NETXEN_HW_PX_MAP_CRB_PGN1	18
+#define NETXEN_HW_PX_MAP_CRB_PGN2	19
+#define NETXEN_HW_PX_MAP_CRB_PGN3	20
+#define NETXEN_HW_PX_MAP_CRB_PGND	21
+#define NETXEN_HW_PX_MAP_CRB_PGNI	22
+#define NETXEN_HW_PX_MAP_CRB_PGS0	23
+#define NETXEN_HW_PX_MAP_CRB_PGS1	24
+#define NETXEN_HW_PX_MAP_CRB_PGS2	25
+#define NETXEN_HW_PX_MAP_CRB_PGS3	26
+#define NETXEN_HW_PX_MAP_CRB_PGSD	27
+#define NETXEN_HW_PX_MAP_CRB_PGSI	28
+#define NETXEN_HW_PX_MAP_CRB_SN		29
+#define NETXEN_HW_PX_MAP_CRB_EG		31
+#define NETXEN_HW_PX_MAP_CRB_PH2	32
+#define NETXEN_HW_PX_MAP_CRB_PS2	33
+#define NETXEN_HW_PX_MAP_CRB_CAM	34
+#define NETXEN_HW_PX_MAP_CRB_CAS0	35
+#define NETXEN_HW_PX_MAP_CRB_CAS1	36
+#define NETXEN_HW_PX_MAP_CRB_CAS2	37
+#define NETXEN_HW_PX_MAP_CRB_C2C0	38
+#define NETXEN_HW_PX_MAP_CRB_C2C1	39
+#define NETXEN_HW_PX_MAP_CRB_TIMR	40
+#define NETXEN_HW_PX_MAP_CRB_RPMX1	42
+#define NETXEN_HW_PX_MAP_CRB_RPMX2	43
+#define NETXEN_HW_PX_MAP_CRB_RPMX3	44
+#define NETXEN_HW_PX_MAP_CRB_RPMX4	45
+#define NETXEN_HW_PX_MAP_CRB_RPMX5	46
+#define NETXEN_HW_PX_MAP_CRB_RPMX6	47
+#define NETXEN_HW_PX_MAP_CRB_RPMX7	48
+#define NETXEN_HW_PX_MAP_CRB_XDMA	49
+#define NETXEN_HW_PX_MAP_CRB_I2Q	50
+#define NETXEN_HW_PX_MAP_CRB_ROMUSB	51
+#define NETXEN_HW_PX_MAP_CRB_CAS3	52
+#define NETXEN_HW_PX_MAP_CRB_RPMX0	53
+#define NETXEN_HW_PX_MAP_CRB_RPMX8	54
+#define NETXEN_HW_PX_MAP_CRB_RPMX9	55
+#define NETXEN_HW_PX_MAP_CRB_OCM0	56
+#define NETXEN_HW_PX_MAP_CRB_OCM1	57
+#define NETXEN_HW_PX_MAP_CRB_SMB	58
+#define NETXEN_HW_PX_MAP_CRB_I2C0	59
+#define NETXEN_HW_PX_MAP_CRB_I2C1	60
+#define NETXEN_HW_PX_MAP_CRB_LPC	61
+#define NETXEN_HW_PX_MAP_CRB_PGNC	62
+#define NETXEN_HW_PX_MAP_CRB_PGR0	63
+#define NETXEN_HW_PX_MAP_CRB_PGR1	4
+#define NETXEN_HW_PX_MAP_CRB_PGR2	30
+#define NETXEN_HW_PX_MAP_CRB_PGR3	41
+
+/*  This field defines CRB adr [31:20] of the agents */
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_MN	\
+	((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_MN_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PH	\
+	((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_PH_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_MS	\
+	((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_MS_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PS	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_PS_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SS	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SS_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_QMS	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_QMS_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS0	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS1	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS2	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS3	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_C2C0	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_C2C0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_C2C1	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_C2C1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX4_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX7_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX9_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SMB	\
+	((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SMB_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_NIU	\
+	((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_NIU_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_I2C0	\
+	((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_I2C0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_I2C1	\
+	((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_I2C1_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SRE	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SRE_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_EG	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_EG_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_QMN	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_QM_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN0	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN1	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN2	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN3	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX5_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX6_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX8_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS0	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS1	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS2	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS3	\
+	((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS3_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNI	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNI_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGND	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGND_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN0	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN1	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN2	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR1	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR2	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR3	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR3_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSI	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSI_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSD	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSD_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS0	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS1	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS2	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS2_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS3	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSC	\
+	((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSC_CRB_AGT_ADR)
+
+#define NETXEN_HW_CRB_HUB_AGT_ADR_CAM	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_NCM_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_TIMR	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_TMR_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_XDMA	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_XDMA_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_SN	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_SN_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_I2Q	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_I2Q_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_ROMUSB_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_OCM0	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_OCM0_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_OCM1	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_OCM1_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_LPC	\
+	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR)
+
+/* ------------------------------------------------------------------------ */
+/*  NCM IMBus Port Tag Defines */
+/* ------------------------------------------------------------------------ */
+#define NETXEN_HW_PH_CAM_TAG	0x3
+#define NETXEN_HW_CAS_CAM_TAG	0x4
+#define NETXEN_HW_PS_CAM_TAG	0x5
+#define NETXEN_HW_PEGN0_CAM_TAG	0x6
+#define NETXEN_HW_PEGN1_CAM_TAG	0x7
+#define NETXEN_HW_PEGN2_CAM_TAG	0x9
+#define NETXEN_HW_PEGN3_CAM_TAG	0xa
+#define NETXEN_HW_PEGS0_CAM_TAG	0xb
+#define NETXEN_HW_PEGS1_CAM_TAG	0xc
+#define NETXEN_HW_PEGS2_CAM_TAG	0xd
+#define NETXEN_HW_PEGS3_CAM_TAG	0xe
+
+/* ------------------------------------------------------------------------ */
+/*  Network QM IMBus Port Tag Defines */
+/* ------------------------------------------------------------------------ */
+#define NETXEN_HW_EG_QM_REQ_TAG		0x4
+#define NETXEN_HW_PEGN0_QM_REQ_TAG	0x5
+#define NETXEN_HW_PEGN1_QM_REQ_TAG	0x6
+#define NETXEN_HW_PEGN2_QM_REQ_TAG	0x7
+#define NETXEN_HW_PEGN3_QM_REQ_TAG	0xE
+#define NETXEN_HW_I2Q_QM_REQ_TAG	0x8
+#define NETXEN_HW_PS_DMA_QMN_REQ_TAG	0x9
+#define NETXEN_HW_PS_QMN_REQ_TAG	0xA
+#define NETXEN_HW_XDMA_QMN_REQ_TAG	0xB
+#define NETXEN_HW_PCIX_QM_REQ_TAG	0xC
+#define NETXEN_HW_CAS_QMN_REQ_TAG	0xD
+#define NETXEN_HW_TMR_QMN_REQ_TAG	0xF
+#define NETXEN_HW_QMS_QMN_REQ_TAG	0xB
+#define NETXEN_HW_C2C0_QM_REQ_TAG	0x9
+
+/* ------------------------------------------------------------------------ */
+/*  Storage QM IMBus Port Tag Defines */
+/* ------------------------------------------------------------------------ */
+#define NETXEN_HW_PEGS0_QMS_REQ_TAG	0x0
+#define NETXEN_HW_PEGS1_QMS_REQ_TAG	0x1
+#define NETXEN_HW_PEGS2_QMS_REQ_TAG	0x2
+#define NETXEN_HW_PEGS3_QMS_REQ_TAG	0xf
+#define NETXEN_HW_C2C1_QMS_REQ_TAG	0x4
+#define NETXEN_HW_PS_QMS_REQ_TAG	0x5
+#define NETXEN_HW_PH_QMS_REQ_TAG	0x6
+#define NETXEN_HW_XDMA_QMS_REQ_TAG	0x9
+#define NETXEN_HW_QMN_QMS_REQ_TAG	0xE
+
+/* ------------------------------------------------------------------------ */
+/*  OCM0 IMBus Port Tag Defines */
+/* ------------------------------------------------------------------------ */
+#define NETXEN_HW_MN_OCM0_PORT_TAG	0x00
+#define NETXEN_HW_SN_OCM0_PORT_TAG	0x01
+#define NETXEN_HW_P2D0_OCM0_PORT_TAG	0x02
+#define NETXEN_HW_P2D1_OCM0_PORT_TAG	0x03
+#define NETXEN_HW_XDMA_OCM0_PORT_TAG	0x04
+
+/* ------------------------------------------------------------------------ */
+/*  OCM0 IMBus Port Tag Defines */
+/* ------------------------------------------------------------------------ */
+#define NETXEN_HW_MN_OCM1_PORT_TAG	0x00
+#define NETXEN_HW_SN_OCM1_PORT_TAG	0x01
+#define NETXEN_HW_P2D0_OCM1_PORT_TAG	0x02
+#define NETXEN_HW_P2D1_OCM1_PORT_TAG	0x03
+#define NETXEN_HW_XDMA_OCM1_PORT_TAG	0x04
+
+/*  Q SubAgent Field for Locking */
+
+#define NETXEN_HW_NPEG0_VPEG0_SUB_AGNT	0x0
+#define NETXEN_HW_NPEG0_VPEG1_SUB_AGNT	0x1
+#define NETXEN_HW_NPEG1_VPEG0_SUB_AGNT	0x2
+#define NETXEN_HW_NPEG1_VPEG1_SUB_AGNT	0x3
+#define NETXEN_HW_NPEG2_VPEG0_SUB_AGNT	0x4
+#define NETXEN_HW_NPEG2_VPEG1_SUB_AGNT	0x5
+#define NETXEN_HW_CAS_SUB_AGNT		0x6
+#define NETXEN_HW_PCI_SUB_AGNT		0x7
+#define NETXEN_HW_SPEG0_VPEG0_SUB_AGNT	0x8
+#define NETXEN_HW_SPEG0_VPEG1_SUB_AGNT	0x9
+#define NETXEN_HW_SPEG1_VPEG0_SUB_AGNT	0xa
+#define NETXEN_HW_SPEG1_VPEG1_SUB_AGNT	0xb
+#define NETXEN_HW_SPEG2_VPEG0_SUB_AGNT	0xc
+#define NETXEN_HW_SPEG2_VPEG1_SUB_AGNT	0xd
+
+/*
+ * MAX_RCV_CTX : The number of receive contexts that are available on
+ * the phantom.
+ */
+#define MAX_RCV_CTX		1
+
+#define NETXEN_SRE_INT_STATUS		(NETXEN_CRB_SRE + 0x00034)
+#define NETXEN_SRE_PBI_ACTIVE_STATUS	(NETXEN_CRB_SRE + 0x01014)
+#define NETXEN_SRE_L1RE_CTL		(NETXEN_CRB_SRE + 0x03000)
+#define NETXEN_SRE_L2RE_CTL		(NETXEN_CRB_SRE + 0x05000)
+#define NETXEN_SRE_BUF_CTL		(NETXEN_CRB_SRE + 0x01000)
+
+#define	NETXEN_DMA_BASE(U)	(NETXEN_CRB_PCIX_MD + 0x20000 + ((U)<<16))
+#define	NETXEN_DMA_COMMAND(U)	(NETXEN_DMA_BASE(U) + 0x00008)
+
+#define NETXEN_I2Q_CLR_PCI_HI	(NETXEN_CRB_I2Q + 0x00034)
+
+#define PEG_NETWORK_BASE(N)	(NETXEN_CRB_PEG_NET_0 + (((N)&3) << 20))
+#define CRB_REG_EX_PC		0x3c
+
+#define ROMUSB_GLB	(NETXEN_CRB_ROMUSB + 0x00000)
+#define ROMUSB_ROM	(NETXEN_CRB_ROMUSB + 0x10000)
+
+#define NETXEN_ROMUSB_GLB_STATUS	(ROMUSB_GLB + 0x0004)
+#define NETXEN_ROMUSB_GLB_SW_RESET	(ROMUSB_GLB + 0x0008)
+#define NETXEN_ROMUSB_GLB_PAD_GPIO_I	(ROMUSB_GLB + 0x000c)
+#define NETXEN_ROMUSB_GLB_CAS_RST	(ROMUSB_GLB + 0x0038)
+#define NETXEN_ROMUSB_GLB_TEST_MUX_SEL	(ROMUSB_GLB + 0x0044)
+#define NETXEN_ROMUSB_GLB_PEGTUNE_DONE	(ROMUSB_GLB + 0x005c)
+#define NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL	(ROMUSB_GLB + 0x00A8)
+
+#define NETXEN_ROMUSB_GPIO(n)		(ROMUSB_GLB + 0x60 + (4 * (n)))
+
+#define NETXEN_ROMUSB_ROM_INSTR_OPCODE	(ROMUSB_ROM + 0x0004)
+#define NETXEN_ROMUSB_ROM_ADDRESS	(ROMUSB_ROM + 0x0008)
+#define NETXEN_ROMUSB_ROM_ABYTE_CNT	(ROMUSB_ROM + 0x0010)
+#define NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014)
+#define NETXEN_ROMUSB_ROM_RDATA		(ROMUSB_ROM + 0x0018)
+
+/* Lock IDs for ROM lock */
+#define ROM_LOCK_DRIVER	0x0d417340
+
+#define NETXEN_PCI_CRB_WINDOWSIZE	0x00100000	/* all are 1MB windows */
+#define NETXEN_PCI_CRB_WINDOW(A)	\
+	(NETXEN_PCI_CRBSPACE + (A)*NETXEN_PCI_CRB_WINDOWSIZE)
+
+#define NETXEN_CRB_NIU		NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_NIU)
+#define NETXEN_CRB_SRE		NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SRE)
+#define NETXEN_CRB_ROMUSB	\
+	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
+#define NETXEN_CRB_I2Q		NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_MAX		NETXEN_PCI_CRB_WINDOW(64)
+
+#define NETXEN_CRB_PCIX_HOST	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH)
+#define NETXEN_CRB_PCIX_HOST2	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH2)
+#define NETXEN_CRB_PEG_NET_0	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN0)
+#define NETXEN_CRB_PEG_NET_1	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN1)
+#define NETXEN_CRB_PEG_NET_2	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN2)
+#define NETXEN_CRB_PEG_NET_3	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN3)
+#define NETXEN_CRB_PEG_NET_D	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND)
+#define NETXEN_CRB_PEG_NET_I	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI)
+#define NETXEN_CRB_DDR_NET	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN)
+
+#define NETXEN_CRB_PCIX_MD	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS)
+#define NETXEN_CRB_PCIE		NETXEN_CRB_PCIX_MD
+
+#define ISR_INT_VECTOR		(NETXEN_PCIX_PS_REG(PCIX_INT_VECTOR))
+#define ISR_INT_MASK		(NETXEN_PCIX_PS_REG(PCIX_INT_MASK))
+#define ISR_INT_MASK_SLOW	(NETXEN_PCIX_PS_REG(PCIX_INT_MASK))
+#define ISR_INT_TARGET_STATUS	(NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS))
+#define ISR_INT_TARGET_MASK	(NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK))
+
+#define NETXEN_PCI_MAPSIZE	128
+#define NETXEN_PCI_DDR_NET	(unsigned long)0x00000000
+#define NETXEN_PCI_QDR_NET	(unsigned long)0x04000000
+#define NETXEN_PCI_DIRECT_CRB	(unsigned long)0x04400000
+#define NETXEN_PCI_CAMQM_MAX	(unsigned long)0x04ffffff
+#define NETXEN_PCI_OCM0		(unsigned long)0x05000000
+#define NETXEN_PCI_OCM0_MAX	(unsigned long)0x050fffff
+#define NETXEN_PCI_OCM1		(unsigned long)0x05100000
+#define NETXEN_PCI_OCM1_MAX	(unsigned long)0x051fffff
+#define NETXEN_PCI_CRBSPACE	(unsigned long)0x06000000
+
+#define NETXEN_CRB_CAM	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)
+
+#define NETXEN_ADDR_DDR_NET	(0x0000000000000000ULL)
+#define NETXEN_ADDR_DDR_NET_MAX (0x000000000fffffffULL)
+#define NETXEN_ADDR_OCM0	(0x0000000200000000ULL)
+#define NETXEN_ADDR_OCM0_MAX	(0x00000002000fffffULL)
+#define NETXEN_ADDR_OCM1	(0x0000000200400000ULL)
+#define NETXEN_ADDR_OCM1_MAX	(0x00000002004fffffULL)
+#define NETXEN_ADDR_QDR_NET	(0x0000000300000000ULL)
+#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL)
+
+	/* 200ms delay in each loop */
+#define	NETXEN_NIU_PHY_WAITLEN		200000
+	/* 10 seconds before we give up */
+#define	NETXEN_NIU_PHY_WAITMAX		50
+#define	NETXEN_NIU_MAX_GBE_PORTS	4
+
+#define	NETXEN_NIU_MODE			(NETXEN_CRB_NIU + 0x00000)
+
+#define	NETXEN_NIU_XG_SINGLE_TERM	(NETXEN_CRB_NIU + 0x00004)
+#define	NETXEN_NIU_XG_DRIVE_HI		(NETXEN_CRB_NIU + 0x00008)
+#define	NETXEN_NIU_XG_DRIVE_LO		(NETXEN_CRB_NIU + 0x0000c)
+#define	NETXEN_NIU_XG_DTX		(NETXEN_CRB_NIU + 0x00010)
+#define	NETXEN_NIU_XG_DEQ		(NETXEN_CRB_NIU + 0x00014)
+#define	NETXEN_NIU_XG_WORD_ALIGN	(NETXEN_CRB_NIU + 0x00018)
+#define	NETXEN_NIU_XG_RESET		(NETXEN_CRB_NIU + 0x0001c)
+#define	NETXEN_NIU_XG_POWER_DOWN	(NETXEN_CRB_NIU + 0x00020)
+#define	NETXEN_NIU_XG_RESET_PLL		(NETXEN_CRB_NIU + 0x00024)
+#define	NETXEN_NIU_XG_SERDES_LOOPBACK	(NETXEN_CRB_NIU + 0x00028)
+#define	NETXEN_NIU_XG_DO_BYTE_ALIGN	(NETXEN_CRB_NIU + 0x0002c)
+#define	NETXEN_NIU_XG_TX_ENABLE		(NETXEN_CRB_NIU + 0x00030)
+#define	NETXEN_NIU_XG_RX_ENABLE		(NETXEN_CRB_NIU + 0x00034)
+#define	NETXEN_NIU_XG_STATUS		(NETXEN_CRB_NIU + 0x00038)
+#define	NETXEN_NIU_XG_PAUSE_THRESHOLD	(NETXEN_CRB_NIU + 0x0003c)
+#define	NETXEN_NIU_INT_MASK		(NETXEN_CRB_NIU + 0x00040)
+#define	NETXEN_NIU_ACTIVE_INT		(NETXEN_CRB_NIU + 0x00044)
+#define	NETXEN_NIU_MASKABLE_INT		(NETXEN_CRB_NIU + 0x00048)
+
+#define NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER	(NETXEN_CRB_NIU + 0x0004c)
+
+#define	NETXEN_NIU_GB_SERDES_RESET	(NETXEN_CRB_NIU + 0x00050)
+#define	NETXEN_NIU_GB0_GMII_MODE	(NETXEN_CRB_NIU + 0x00054)
+#define	NETXEN_NIU_GB0_MII_MODE		(NETXEN_CRB_NIU + 0x00058)
+#define	NETXEN_NIU_GB1_GMII_MODE	(NETXEN_CRB_NIU + 0x0005c)
+#define	NETXEN_NIU_GB1_MII_MODE		(NETXEN_CRB_NIU + 0x00060)
+#define	NETXEN_NIU_GB2_GMII_MODE	(NETXEN_CRB_NIU + 0x00064)
+#define	NETXEN_NIU_GB2_MII_MODE		(NETXEN_CRB_NIU + 0x00068)
+#define	NETXEN_NIU_GB3_GMII_MODE	(NETXEN_CRB_NIU + 0x0006c)
+#define	NETXEN_NIU_GB3_MII_MODE		(NETXEN_CRB_NIU + 0x00070)
+#define	NETXEN_NIU_REMOTE_LOOPBACK	(NETXEN_CRB_NIU + 0x00074)
+#define	NETXEN_NIU_GB0_HALF_DUPLEX	(NETXEN_CRB_NIU + 0x00078)
+#define	NETXEN_NIU_GB1_HALF_DUPLEX	(NETXEN_CRB_NIU + 0x0007c)
+#define	NETXEN_NIU_RESET_SYS_FIFOS	(NETXEN_CRB_NIU + 0x00088)
+#define	NETXEN_NIU_GB_CRC_DROP		(NETXEN_CRB_NIU + 0x0008c)
+#define	NETXEN_NIU_GB_DROP_WRONGADDR	(NETXEN_CRB_NIU + 0x00090)
+#define	NETXEN_NIU_TEST_MUX_CTL		(NETXEN_CRB_NIU + 0x00094)
+#define	NETXEN_NIU_XG_PAUSE_CTL		(NETXEN_CRB_NIU + 0x00098)
+#define	NETXEN_NIU_XG_PAUSE_LEVEL	(NETXEN_CRB_NIU + 0x000dc)
+#define	NETXEN_NIU_XG_SEL		(NETXEN_CRB_NIU + 0x00128)
+
+#define	NETXEN_NIU_GB_MAC_CONFIG_0(I)		\
+	(NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
+#define	NETXEN_NIU_GB_MAC_CONFIG_1(I)		\
+	(NETXEN_CRB_NIU + 0x30004 + (I)*0x10000)
+#define	NETXEN_NIU_GB_MAC_IPG_IFG(I)		\
+	(NETXEN_CRB_NIU + 0x30008 + (I)*0x10000)
+#define	NETXEN_NIU_GB_HALF_DUPLEX_CTRL(I)	\
+	(NETXEN_CRB_NIU + 0x3000c + (I)*0x10000)
+#define	NETXEN_NIU_GB_MAX_FRAME_SIZE(I)		\
+	(NETXEN_CRB_NIU + 0x30010 + (I)*0x10000)
+#define	NETXEN_NIU_GB_TEST_REG(I)		\
+	(NETXEN_CRB_NIU + 0x3001c + (I)*0x10000)
+#define	NETXEN_NIU_GB_MII_MGMT_CONFIG(I)	\
+	(NETXEN_CRB_NIU + 0x30020 + (I)*0x10000)
+#define	NETXEN_NIU_GB_MII_MGMT_COMMAND(I)	\
+	(NETXEN_CRB_NIU + 0x30024 + (I)*0x10000)
+#define	NETXEN_NIU_GB_MII_MGMT_ADDR(I)		\
+	(NETXEN_CRB_NIU + 0x30028 + (I)*0x10000)
+#define	NETXEN_NIU_GB_MII_MGMT_CTRL(I)		\
+	(NETXEN_CRB_NIU + 0x3002c + (I)*0x10000)
+#define	NETXEN_NIU_GB_MII_MGMT_STATUS(I)	\
+	(NETXEN_CRB_NIU + 0x30030 + (I)*0x10000)
+#define	NETXEN_NIU_GB_MII_MGMT_INDICATE(I)	\
+	(NETXEN_CRB_NIU + 0x30034 + (I)*0x10000)
+#define	NETXEN_NIU_GB_INTERFACE_CTRL(I)		\
+	(NETXEN_CRB_NIU + 0x30038 + (I)*0x10000)
+#define	NETXEN_NIU_GB_INTERFACE_STATUS(I)	\
+	(NETXEN_CRB_NIU + 0x3003c + (I)*0x10000)
+#define	NETXEN_NIU_GB_STATION_ADDR_0(I)		\
+	(NETXEN_CRB_NIU + 0x30040 + (I)*0x10000)
+#define	NETXEN_NIU_GB_STATION_ADDR_1(I)		\
+	(NETXEN_CRB_NIU + 0x30044 + (I)*0x10000)
+
+#define	NETXEN_NIU_XGE_CONFIG_0			(NETXEN_CRB_NIU + 0x70000)
+#define	NETXEN_NIU_XGE_CONFIG_1			(NETXEN_CRB_NIU + 0x70004)
+#define	NETXEN_NIU_XGE_IPG			(NETXEN_CRB_NIU + 0x70008)
+#define	NETXEN_NIU_XGE_STATION_ADDR_0_HI	(NETXEN_CRB_NIU + 0x7000c)
+#define	NETXEN_NIU_XGE_STATION_ADDR_0_1		(NETXEN_CRB_NIU + 0x70010)
+#define	NETXEN_NIU_XGE_STATION_ADDR_1_LO	(NETXEN_CRB_NIU + 0x70014)
+#define	NETXEN_NIU_XGE_STATUS			(NETXEN_CRB_NIU + 0x70018)
+#define	NETXEN_NIU_XGE_MAX_FRAME_SIZE		(NETXEN_CRB_NIU + 0x7001c)
+#define	NETXEN_NIU_XGE_PAUSE_FRAME_VALUE	(NETXEN_CRB_NIU + 0x70020)
+#define	NETXEN_NIU_XGE_TX_BYTE_CNT		(NETXEN_CRB_NIU + 0x70024)
+#define	NETXEN_NIU_XGE_TX_FRAME_CNT		(NETXEN_CRB_NIU + 0x70028)
+#define	NETXEN_NIU_XGE_RX_BYTE_CNT		(NETXEN_CRB_NIU + 0x7002c)
+#define	NETXEN_NIU_XGE_RX_FRAME_CNT		(NETXEN_CRB_NIU + 0x70030)
+#define	NETXEN_NIU_XGE_AGGR_ERROR_CNT		(NETXEN_CRB_NIU + 0x70034)
+#define	NETXEN_NIU_XGE_MULTICAST_FRAME_CNT 	(NETXEN_CRB_NIU + 0x70038)
+#define	NETXEN_NIU_XGE_UNICAST_FRAME_CNT	(NETXEN_CRB_NIU + 0x7003c)
+#define	NETXEN_NIU_XGE_CRC_ERROR_CNT		(NETXEN_CRB_NIU + 0x70040)
+#define	NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR	(NETXEN_CRB_NIU + 0x70044)
+#define	NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR	(NETXEN_CRB_NIU + 0x70048)
+#define	NETXEN_NIU_XGE_LOCAL_ERROR_CNT		(NETXEN_CRB_NIU + 0x7004c)
+#define	NETXEN_NIU_XGE_REMOTE_ERROR_CNT		(NETXEN_CRB_NIU + 0x70050)
+#define	NETXEN_NIU_XGE_CONTROL_CHAR_CNT		(NETXEN_CRB_NIU + 0x70054)
+#define	NETXEN_NIU_XGE_PAUSE_FRAME_CNT		(NETXEN_CRB_NIU + 0x70058)
+
+/* XG Link status */
+#define XG_LINK_UP	0x10
+#define XG_LINK_DOWN	0x20
+
+#define NETXEN_CAM_RAM_BASE	(NETXEN_CRB_CAM + 0x02000)
+#define NETXEN_CAM_RAM(reg)	(NETXEN_CAM_RAM_BASE + (reg))
+#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
+#define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154))
+#define NETXEN_FW_VERSION_SUB	(NETXEN_CAM_RAM(0x158))
+#define NETXEN_ROM_LOCK_ID	(NETXEN_CAM_RAM(0x100))
+
+/*
+ * CRB window register.
+ */
+struct netxen_pcix_crb_window {
+	netxen_crbword_t rsvd1:25, addrbit:1,	/* bit 25 of CRB address */
+	 rsvd2:6;
+};
+
+#define PCIX_PS_OP_ADDR_LO	(0x10000) /* Used for PS PCI Memory access */
+#define PCIX_PS_OP_ADDR_HI	(0x10004) /*   via CRB  (PS side only)     */
+
+#define PCIX_INT_VECTOR		(0x10100)
+#define PCIX_INT_MASK		(0x10104)
+
+#define PCIX_MN_WINDOW		(0x10200)
+#define PCIX_MS_WINDOW		(0x10204)
+#define PCIX_SN_WINDOW		(0x10208)
+#define PCIX_CRB_WINDOW		(0x10210)
+
+#define PCIX_TARGET_STATUS	(0x10118)
+#define PCIX_TARGET_MASK	(0x10128)
+
+#define PCIX_MSI_F0		(0x13000)
+
+#define PCIX_PS_MEM_SPACE	(0x90000)
+
+#define NETXEN_PCIX_PH_REG(reg)	(NETXEN_CRB_PCIE + (reg))
+#define NETXEN_PCIX_PS_REG(reg)	(NETXEN_CRB_PCIX_MD + (reg))
+
+#define NETXEN_PCIE_REG(reg)	(NETXEN_CRB_PCIE + (reg))
+
+#define PCIE_MAX_DMA_XFER_SIZE	(0x1404c)
+
+#define PCIE_DCR		0x00d8
+
+#define PCIE_SEM2_LOCK		(0x1c010)	/* Flash lock   */
+#define PCIE_SEM2_UNLOCK	(0x1c014)	/* Flash unlock */
+
+#define PCIE_TGT_SPLIT_CHICKEN	(0x12080)
+
+#define PCIE_MAX_MASTER_SPLIT	(0x14048)
+
+#endif				/* __NETXEN_NIC_HDR_H_ */


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 4/9] NetXen: hardware access routines.
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
                   ` (2 preceding siblings ...)
  2006-07-05 13:31 ` [PATCH 2.6.17 3/9] NetXen: Registers info " Linsys Contractor Amit S. Kale
@ 2006-07-05 13:34 ` Linsys Contractor Amit S. Kale
  2006-07-05 16:00   ` Jeff Garzik
  2006-07-05 13:38 ` [PATCH 2.6.17 5/9] NetXen: hardware access header file Linsys Contractor Amit S. Kale
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:34 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_hw.c linux-2.6.17/drivers/net/netxen/netxen_nic_hw.c
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_hw.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_hw.c	2006-07-05 01:18:40.364907061 -0700
@@ -0,0 +1,1308 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Source file for NIC routines to access the Phantom hardware
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/version.h>
+#include "netxen_nic.h"
+#include "netxen_nic_hw.h"
+#include "netxen_nic_phan_reg.h"
+
+/*  PCI Windowing for DDR regions.  */
+
+#define ADDR_IN_RANGE(addr, low, high)	\
+	(((addr) <= (high)) && ((addr) >= (low)))
+
+static unsigned long netxen_nic_pci_set_window(unsigned long long pci_base,
+					       unsigned long long addr);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+
+int netxen_nic_set_mac(struct net_device *netdev, void *p)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+#ifdef NETXEN_DEBUG
+	struct netxen_adapter *adapter = port->adapter;
+#endif
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	DPRINTK(INFO, "valid ether addr\n");
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+	netxen_nic_macaddr_set(port, addr->sa_data);
+
+	return 0;
+}
+
+/**
+ * netxen_nic_set_multi - Multicast
+ **/
+void netxen_nic_set_multi(struct net_device *netdev)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+	struct dev_mc_list *mc_ptr;
+
+	mc_ptr = netdev->mc_list;
+	if (netdev->flags & IFF_PROMISC)
+		netxen_nic_set_promisc_mode(port);
+	else
+		netxen_nic_unset_promisc_mode(port);
+}
+
+/*
+ * netxen_nic_change_mtu - Change the Maximum Transfer Unit
+ * @returns 0 on success, negative on failure
+ */
+int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+
+	if (new_mtu & 0xffff0000)
+		return -EINVAL;
+
+	if (new_mtu > 8000) {
+		printk(KERN_ERR "%s: %s MTU > 8000 is not supported\n",
+		       netxen_nic_driver_name, netdev->name);
+		return -EINVAL;
+	}
+
+	netxen_nic_set_mtu(port, new_mtu);
+	netdev->mtu = new_mtu;
+
+	return 0;
+}
+
+/*
+ * check if the firmware has been downloaded and ready to run  and
+ * setup the address for the descriptors in the adapter
+ */
+int netxen_nic_hw_resources(struct netxen_adapter *adapter)
+{
+	int i;
+	u32 state = 0;
+	void *addr;
+	int loops = 0, err = 0;
+	int ring;
+	u32 card_cmdring = 0;
+	struct netxen_recv_context *recv_ctx;
+	struct netxen_rcv_desc_ctx *rcv_desc;
+	u32 ring_size;
+	struct netxen_ring_context *ctx;
+
+	DPRINTK(INFO, "pci_base: %lx\n", adapter->ahw.pci_base);
+	DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE,
+		adapter->ahw.pci_base + NETXEN_PCI_CRBSPACE);
+	DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM,
+		adapter->ahw.pci_base + NETXEN_CRB_CAM);
+	DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE,
+		adapter->ahw.pci_base + NETXEN_CAM_RAM_BASE);
+	DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1,
+		adapter->ahw.pci_base + NIC_CRB_BASE_PORT1);
+
+	/* Window 1 call */
+	read_lock(&adapter->adapter_lock);
+	card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));
+	read_unlock(&adapter->adapter_lock);
+
+	DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n",
+		card_cmdring);
+
+	DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
+	loops = 0;
+	do {
+		/* Window 1 call */
+		read_lock(&adapter->adapter_lock);
+		state = readl(NETXEN_CRB_NORMALIZE(adapter,
+						   recv_crb_registers[0].
+						   crb_rcvpeg_state));
+		read_unlock(&adapter->adapter_lock);
+
+		loops++;
+		udelay(100);
+	} while (state != PHAN_INITIALIZE_COMPLETE && loops < 21);
+	if (loops >= 21) {
+		DPRINTK(1, ERR, "Rcv Peg initialization not complete:"
+			"%x.\n", state);
+		return -EIO;
+	}
+	DPRINTK(1, INFO, "Recieve Peg ready too. starting stuff\n");
+	for (i = 0; i < MAX_RING_CTX; i++) {
+		ctx = &adapter->ring_ctx[i];
+		/*
+		 * Alloc command ring consumer location and ring context
+		 * which phanmon will dma to card
+		 */
+		addr = pci_alloc_consistent(adapter->ahw.pdev,
+					    sizeof(struct ring_context) +
+					    sizeof(u32),
+					    (dma_addr_t *) & ctx->
+					    ctx_desc_phys_addr);
+		DPRINTK(1, INFO, "ctx_desc_phys_addr: 0x%08x\n",
+			ctx->ctx_desc_phys_addr);
+		if (addr == NULL) {
+			DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
+			netxen_free_hw_resources(adapter);
+			err = -ENOMEM;
+			return err;
+		}
+		memset(addr, 0, sizeof(struct ring_context));
+		ctx->ctx_desc = (struct ring_context *)addr;
+		ctx->ctx_desc->CMD_CONSUMER_OFFSET = ctx->ctx_desc_phys_addr
+		    + sizeof(struct ring_context);
+		ctx->cmd_consumer =
+		    (u32 *) ((char *)addr) + sizeof(struct ring_context);
+		/*
+		 * Alloc command ring shared between host and phantom
+		 */
+		ring_size =
+		    sizeof(struct cmd_desc_type0_t) * ctx->max_tx_desc_count;
+		addr =
+		    pci_alloc_consistent(adapter->ahw.pdev, ring_size,
+					 (dma_addr_t *) & ctx->hw_ring_ctx.
+					 cmd_desc_phys_addr);
+		DPRINTK(1, INFO, "cmd_desc_phys_addr: 0x%08x, size 0x%08x\n",
+			ctx->hw_ring_ctx.cmd_desc_phys_addr, ring_size);
+		if (addr == NULL) {
+			DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
+			netxen_free_hw_resources(adapter);
+			err = -ENOMEM;
+			return err;
+		}
+		ctx->hw_ring_ctx.cmd_desc_head =
+		    (struct cmd_desc_type0_t *)addr;
+		ctx->ctx_desc->CmdRingAddrLo =
+		    ctx->hw_ring_ctx.cmd_desc_phys_addr;
+		ctx->ctx_desc->CmdRingSize = ctx->max_tx_desc_count;
+		DPRINTK(1, INFO, "CMD_RING, ctx %d, val 0x%x, virt%p,"
+			"size %d\n", i,
+			ctx->hw_ring_ctx.cmd_desc_phys_addr,
+			ctx->hw_ring_ctx.cmd_desc_head, ring_size);
+		/*
+		 * Alloc receive rings shared between host and phantom
+		 */
+		recv_ctx = &ctx->recv_ctx;
+
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			rcv_desc = &recv_ctx->rcv_desc[ring];
+			ring_size = (sizeof(struct rcv_desc_t) *
+					rcv_desc->max_rx_desc_count);
+			addr = pci_alloc_consistent(adapter->ahw.pdev,
+						    ring_size, (dma_addr_t *)
+						    & rcv_desc->phys_addr);
+			DPRINTK(1, INFO,
+				"rcv %d physAddr: 0x%08x, size 0x%08x\n", ring,
+				rcv_desc->phys_addr, ring_size);
+			if (addr == NULL) {
+				DPRINTK(ERR, "bad return from "
+					"pci_alloc_consistent\n");
+				netxen_free_hw_resources(adapter);
+				err = -ENOMEM;
+				return err;
+			}
+			rcv_desc->desc_head = (struct rcv_desc_t *)addr;
+			ctx->ctx_desc->RcvContext[ring].RcvRingAddrLo =
+			    rcv_desc->phys_addr;
+			ctx->ctx_desc->RcvContext[ring].RcvRingSize =
+			    rcv_desc->max_rx_desc_count;
+			DPRINTK(1, INFO, "GLOBAL_RCV_RING ctx %d, ring #%d,"
+				" val 0x%x, virt %p, size %d\n",
+				i, ring, rcv_desc->phys_addr,
+				rcv_desc->desc_head, ring_size);
+		}
+
+		addr = pci_alloc_consistent(adapter->ahw.pdev,
+					    ring_size, (dma_addr_t *)
+					    & recv_ctx->
+					    rcv_status_desc_phys_addr);
+		DPRINTK(1, INFO,
+			"rcvStatusDesc_physAddr: 0x%08x, size 0x%08x\n",
+			recv_ctx->rcvStatusDesc_physAddr, ring_size);
+		if (addr == NULL) {
+			DPRINTK(ERR, "bad return from"
+				" pci_alloc_consistent\n");
+			netxen_free_hw_resources(adapter);
+			err = -ENOMEM;
+			return err;
+		}
+		recv_ctx->rcv_status_desc_head = (struct status_desc_t *)addr;
+
+		ctx->ctx_desc->StsRingAddrLo =
+		    recv_ctx->rcv_status_desc_phys_addr;
+		ctx->ctx_desc->StsRingSize = ctx->max_rx_desc_count;
+		DPRINTK(1, INFO, "RCVSTATUS_RING, ctx %d,"
+			" val 0x%x, virt %p, size %d\n", i,
+			recv_ctx->rcvStatusDesc_physAddr,
+			recv_ctx->rcvStatusDescHead, ring_size);
+	}
+	/* Window = 1 */
+	read_lock(&adapter->adapter_lock);
+	writel(ctx->ctx_desc_phys_addr,
+	       NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG));
+	writel(NETXEN_CTX_SIGNATURE,
+	       NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG));
+
+	read_unlock(&adapter->adapter_lock);
+
+	return err;
+}
+
+void netxen_free_hw_resources(struct netxen_adapter *adapter)
+{
+	struct netxen_recv_context *recv_ctx;
+	struct netxen_rcv_desc_ctx *rcv_desc;
+	int ring, i;
+	struct netxen_ring_context *ctx;
+
+	for (i = 0; i < MAX_RING_CTX; i++) {
+		ctx = &adapter->ring_ctx[i];
+
+		if (ctx->ctx_desc != NULL) {
+			pci_free_consistent(adapter->ahw.pdev,
+					    sizeof(struct ring_context) +
+					    sizeof(u32),
+					    ctx->ctx_desc,
+					    ctx->ctx_desc_phys_addr);
+			ctx->ctx_desc = NULL;
+		}
+
+		if (ctx->hw_ring_ctx.cmd_desc_head != NULL) {
+			pci_free_consistent(adapter->ahw.pdev,
+					    sizeof(struct cmd_desc_type0_t) *
+					    ctx->max_tx_desc_count,
+					    ctx->hw_ring_ctx.cmd_desc_head,
+					    ctx->hw_ring_ctx.
+					    cmd_desc_phys_addr);
+			ctx->hw_ring_ctx.cmd_desc_head = NULL;
+		}
+		recv_ctx = &ctx->recv_ctx;
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			rcv_desc = &recv_ctx->rcv_desc[ring];
+
+			if (rcv_desc->desc_head != NULL) {
+				pci_free_consistent(adapter->ahw.pdev,
+						    RCV_DESC_RINGSIZE(i),
+						    rcv_desc->desc_head,
+						    rcv_desc->phys_addr);
+				rcv_desc->desc_head = NULL;
+			}
+		}
+
+		if (recv_ctx->rcv_status_desc_head != NULL) {
+			pci_free_consistent(adapter->ahw.pdev,
+					    STATUS_DESC_RINGSIZE(i),
+					    recv_ctx->rcv_status_desc_head,
+					    recv_ctx->
+					    rcv_status_desc_phys_addr);
+			recv_ctx->rcv_status_desc_head = NULL;
+		}
+	}
+}
+
+void netxen_tso_check(struct netxen_adapter *adapter,
+		      struct cmd_desc_type0_t *desc, struct sk_buff *skb)
+{
+	if (desc->mss) {
+		desc->total_hdr_length = sizeof(struct ethhdr) +
+		    ((skb->nh.iph)->ihl * sizeof(u32)) +
+		    ((skb->h.th)->doff * sizeof(u32));
+		desc->opcode = TX_TCP_LSO;
+	} else if (skb->ip_summed == CHECKSUM_HW) {
+		if (skb->nh.iph->protocol == IPPROTO_TCP) {
+			desc->opcode = TX_TCP_PKT;
+		} else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+			desc->opcode = TX_UDP_PKT;
+		} else {
+			return;
+		}
+	}
+	desc->tcp_hdr_offset = skb->h.raw - skb->data;
+	desc->ip_hdr_offset = skb->nh.raw - skb->data;
+	adapter->stats.xmitcsummed++;
+}
+
+int is_flash_supported(struct netxen_adapter *adapter)
+{
+	int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
+	int addr, val01, val02, i, j;
+
+	/* if the flash size less than 4Mb, make huge war cry and die */
+	for (j = 1; j < 4; j++) {
+		addr = j * 0x100000;
+		for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) {
+			if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0
+			    && netxen_rom_fast_read(adapter, (addr + locs[i]),
+						    &val02) == 0) {
+				if (val01 == val02)
+					return -1;
+			} else
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
+				  int size, u32 * buf)
+{
+	int i, addr;
+	u32 *ptr32;
+
+	addr = base;
+	ptr32 = buf;
+	for (i = 0; i < size / sizeof(u32); i++) {
+		if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
+			return -1;
+		ptr32++;
+		addr += sizeof(u32);
+	}
+	if ((char *)buf + size > (char *)ptr32) {
+		u32 local;
+
+		if (netxen_rom_fast_read(adapter, addr, &local) == -1)
+			return -1;
+		memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
+	}
+
+	return 0;
+}
+
+int get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
+{
+	u32 *pmac = (u32 *) & mac[0];
+
+	if (netxen_get_flash_block(adapter,
+				   USER_START +
+				   offsetof(struct netxen_new_user_info,
+					    mac_addr),
+				   FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
+		return -1;
+	}
+	if (*mac == ~0ULL) {
+		if (netxen_get_flash_block(adapter,
+					   USER_START_OLD +
+					   offsetof(struct netxen_user_info,
+						    mac_addr),
+					   FLASH_NUM_PORTS * sizeof(u64),
+					   pmac) == -1)
+			return -1;
+		if (*mac == ~0ULL)
+			return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Changes the CRB window to the specified window.
+ */
+void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
+{
+	struct netxen_pcix_crb_window window;
+	unsigned long offset;
+	u32 tmp;
+
+	if (adapter->curr_window == wndw)
+		return;
+
+	/*
+	 * Move the CRB window.
+	 * We need to write to the "direct access" region of PCI
+	 * to avoid a race condition where the window register has
+	 * not been successfully written across CRB before the target
+	 * register address is received by PCI. The direct region bypasses
+	 * the CRB bus.
+	 */
+	offset = adapter->ahw.pci_base + NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW);
+
+	*(netxen_crbword_t *) & window = 0;
+	window.addrbit = wndw;
+	writel(*(unsigned int *)&window, (void *)(offset));
+
+	/* MUST make sure window is set before we forge on... */
+	while ((tmp = readl((void *)offset)) != *(u32 *) & window)
+		printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
+		       "registered properly: 0x%08x.\n",
+		       netxen_nic_driver_name, __FUNCTION__, tmp);
+
+	adapter->curr_window = wndw;
+}
+
+/*
+ * Set the CRB window based on the offset.
+ */
+static inline unsigned long
+netxen_nic_pci_set_crbwindow(struct netxen_adapter *adapter, u64 off)
+{
+	/*
+	 * See if we are currently pointing to the region we want to use next.
+	 */
+
+	if ((off >= NETXEN_CRB_PCIX_HOST) && (off < NETXEN_CRB_DDR_NET)) {
+		/*
+		 * No need to change window. PCIX and PCIE regs are in both
+		 * windows.
+		 */
+		return off;
+	}
+
+	if ((off >= NETXEN_CRB_PCIX_HOST) && (off < NETXEN_CRB_PCIX_HOST2)) {
+		/* We are in first CRB window */
+		if (adapter->curr_window != 0)
+			netxen_nic_pci_change_crbwindow(adapter, 0);
+
+		return off;
+	}
+
+	if ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) {
+		/* We are in second CRB window */
+		off = off - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST;
+
+		if (adapter->curr_window != 1)
+			netxen_nic_pci_change_crbwindow(adapter, 1);
+
+		return off;
+	}
+
+	if ((off >= NETXEN_PCI_DIRECT_CRB) && (off < NETXEN_PCI_CAMQM_MAX)) {
+		/*
+		 * We are in the QM or direct access register region - do
+		 * nothing
+		 */
+		return off;
+	}
+
+	/* strange address given */
+	dump_stack();
+	printk(KERN_WARNING
+	       "%s: Warning: netxen_nic_pci_set_crbwindow called with"
+	       " an unknown address(%llx)\n", netxen_nic_driver_name, off);
+
+	return off;
+}
+
+int
+netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
+		       int len)
+{
+	void *addr;
+	unsigned long flags = 0;
+
+	if (ADDR_IN_WINDOW1(off)) {
+		addr = NETXEN_CRB_NORMALIZE(adapter, off);
+		read_lock(&adapter->adapter_lock);
+	} else {		/* Window 0 */
+		addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+		netxen_nic_pci_change_crbwindow(adapter, 0);
+	}
+
+	DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
+		" data %llx len %d\n",
+		adapter->ahw.pci_base, off, addr,
+		*(unsigned long long *)data, len);
+	switch (len) {
+	case 1:
+		writeb(*(u8 *) data, addr);
+		break;
+	case 2:
+		writew(*(u16 *) data, addr);
+		break;
+	case 4:
+		writel(*(u32 *) data, addr);
+		break;
+	case 8:
+		writeq(*(u64 *) data, addr);
+		break;
+	default:
+		DPRINTK(INFO,
+			"writing data %lx to offset %llx, num words=%d\n",
+			*(unsigned long *)data, off, (len >> 3));
+
+		NETXEN_NIC_HW_BLOCK_WRITE_64(data, addr, (len >> 3));
+		break;
+	}
+	if (ADDR_IN_WINDOW1(off))
+		read_unlock(&adapter->adapter_lock);
+	else {			/* Window 0 */
+		netxen_nic_pci_change_crbwindow(adapter, 1);
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	}
+
+	return 0;
+}
+
+int
+netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
+		      int len)
+{
+	void *addr;
+	unsigned long flags = 0;
+
+	if (ADDR_IN_WINDOW1(off)) {	/* Window 1 */
+		addr = NETXEN_CRB_NORMALIZE(adapter, off);
+		read_lock(&adapter->adapter_lock);
+	} else {		/* Window 0 */
+		addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+		netxen_nic_pci_change_crbwindow(adapter, 0);
+	}
+
+	DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
+		adapter->ahw.pci_base, off, addr);
+	switch (len) {
+	case 1:
+		*(u8 *) data = readb(addr);
+		break;
+	case 2:
+		*(u16 *) data = readw(addr);
+		break;
+	case 4:
+		*(u32 *) data = readl(addr);
+		break;
+	case 8:
+		*(u64 *) data = readq(addr);
+		break;
+	default:
+		NETXEN_NIC_HW_BLOCK_READ_64(data, addr, (len >> 3));
+		break;
+	}
+	DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
+
+	if (ADDR_IN_WINDOW1(off))
+		read_unlock(&adapter->adapter_lock);
+	else {			/* Window 0 */
+		netxen_nic_pci_change_crbwindow(adapter, 1);
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	}
+
+	return 0;
+}
+
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
+{				/* Only for window 1 */
+	void *addr;
+
+	read_lock(&adapter->adapter_lock);
+
+	if (adapter->curr_window != 1)
+		netxen_nic_pci_change_crbwindow(adapter, 1);
+	addr = NETXEN_CRB_NORMALIZE(adapter, off);
+	DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
+		adapter->ahw.pci_base, off, addr, val);
+	writel(val, addr);
+
+	read_unlock(&adapter->adapter_lock);
+}
+
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
+{				/* Only for window 1 */
+	void *addr;
+	int val;
+
+	read_lock(&adapter->adapter_lock);
+	addr = NETXEN_CRB_NORMALIZE(adapter, off);
+	DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
+		adapter->ahw.pci_base, off, addr);
+	val = readl(addr);
+	writel(val, addr);
+	read_unlock(&adapter->adapter_lock);
+
+	return val;
+}
+
+/* Change the window to 0, write and change back to window 1. */
+void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
+{
+	unsigned long flags;
+	void *addr;
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	netxen_nic_pci_change_crbwindow(adapter, 0);
+	addr = (void *)(adapter->ahw.pci_base + index);
+	writel(value, addr);
+	netxen_nic_pci_change_crbwindow(adapter, 1);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+}
+
+/* Change the window to 0, read and change back to window 1. */
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
+{
+	unsigned long flags;
+	void *addr;
+
+	addr = (void *)(adapter->ahw.pci_base + index);
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	netxen_nic_pci_change_crbwindow(adapter, 0);
+	*value = readl(addr);
+	netxen_nic_pci_change_crbwindow(adapter, 1);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+}
+
+int netxen_pci_set_window_warning_count = 0;
+
+static unsigned long
+netxen_nic_pci_set_window(unsigned long long pci_base, unsigned long long addr)
+{
+	static int ddr_mn_window = -1;
+	static int qdr_sn_window = -1;
+	int window;
+
+	if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+		/* DDR network side */
+		addr -= NETXEN_ADDR_DDR_NET;
+		window = (addr >> 25) & 0x3ff;
+		if (ddr_mn_window != window) {
+			ddr_mn_window = window;
+			writel(window, (void *)(ptrdiff_t) (pci_base +
+							    NETXEN_PCIX_PH_REG
+							    (PCIX_MN_WINDOW)));
+			/* MUST make sure window is set before we forge on... */
+			readl((void *)(ptrdiff_t) (pci_base +
+						   NETXEN_PCIX_PH_REG
+						   (PCIX_MN_WINDOW)));
+		}
+		addr -= (window * 0x2000000);
+		addr += NETXEN_PCI_DDR_NET;
+	} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+		addr -= NETXEN_ADDR_OCM0;
+		addr += NETXEN_PCI_OCM0;
+	} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
+		addr -= NETXEN_ADDR_OCM1;
+		addr += NETXEN_PCI_OCM1;
+	} else
+	    if (ADDR_IN_RANGE
+		(addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
+		/* QDR network side */
+		addr -= NETXEN_ADDR_QDR_NET;
+		window = (addr >> 22) & 0x3f;
+		if (qdr_sn_window != window) {
+			qdr_sn_window = window;
+			writel((window << 22),
+			       (void *)(ptrdiff_t) (pci_base +
+						    NETXEN_PCIX_PH_REG
+						    (PCIX_SN_WINDOW)));
+			/* MUST make sure window is set before we forge on... */
+			readl((void *)(ptrdiff_t) (pci_base +
+						   NETXEN_PCIX_PH_REG
+						   (PCIX_SN_WINDOW)));
+		}
+		addr -= (window * 0x400000);
+		addr += NETXEN_PCI_QDR_NET;
+	} else {
+		/*
+		 * peg gdb frequently accesses memory that doesn't exist,
+		 * this limits the chit chat so debugging isn't slowed down.
+		 */
+		if ((netxen_pci_set_window_warning_count++ < 8)
+		    || (netxen_pci_set_window_warning_count % 64 == 0))
+			printk("%s: Warning:netxen_nic_pci_set_window()"
+			       " Unknown address range!\n",
+			       netxen_nic_driver_name);
+
+	}
+	return addr;
+}
+
+/* read num_words from hardware (num_words in 64 bits    */
+void
+netxen_nic_mem_block_read(struct netxen_adapter *adapter, u64 off,
+			  void *data, int num_words)
+{
+	void *addr;
+	unsigned long flags;
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off);
+	addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
+	DPRINTK(INFO, "reading from base %lx offset %lx addr %p\n",
+		adapter->ahw.pci_base, (unsigned long)off, addr);
+	NETXEN_NIC_HW_BLOCK_READ_64(data, addr, num_words);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+}
+
+int
+netxen_nic_pci_mem_write(struct netxen_adapter *adapter, u64 off,
+			 void *data, int size)
+{
+	unsigned long flags;
+	void *addr;
+	int ret = 0;
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off);
+	addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
+	DPRINTK(INFO, "writing data %llx to offset %llx\n",
+		*(unsigned long long *)data, off);
+	switch (size) {
+	case 1:
+		writeb(*(u8 *) data, addr);
+		break;
+	case 2:
+		writew(*(u16 *) data, addr);
+		break;
+	case 4:
+		writel(*(u32 *) data, addr);
+		break;
+	case 8:
+		writeq(*(u64 *) data, addr);
+		break;
+	default:
+		ret = 1;
+		break;
+	}
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	DPRINTK(INFO, "wrote %llx\n", *(unsigned long long *)data);
+
+	return ret;
+}
+
+int
+netxen_nic_pci_mem_read(struct netxen_adapter *adapter,
+			u64 off, void *data, int size)
+{
+	unsigned long flags;
+	void *addr;
+	int ret = 0;
+
+	if (data == NULL || off > NETXEN_MEMADDR_MAX) {
+		printk(KERN_ERR "data: %p off:%llx\n", data, off);
+		return 1;
+	}
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off);
+	addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
+	switch (size) {
+	case 1:
+		*(u8 *) data = readb(addr);
+		break;
+	case 2:
+		*(u16 *) data = readw(addr);
+		break;
+	case 4:
+		*(u32 *) data = readl(addr);
+		break;
+	case 8:
+		*(u64 *) data = readq(addr);
+		break;
+	default:
+		ret = 1;
+		break;
+	}
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	DPRINTK(INFO, "read %llx\n", *(unsigned long long *)data);
+
+	return ret;
+}
+
+int netxen_nic_get_board_info(struct netxen_adapter *adapter)
+{
+	int rv = 0;
+	int addr = BRDCFG_START;
+	struct netxen_board_info *boardinfo;
+	int index;
+	u32 *ptr32;
+
+	boardinfo = &adapter->ahw.boardcfg;
+	ptr32 = (u32 *) boardinfo;
+
+	for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32);
+	     index++) {
+		if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
+			rv = -1;
+			return rv;
+		}
+		ptr32++;
+		addr += sizeof(u32);
+	}
+	if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
+		printk("%s: ERROR reading %s board config."
+		       " Read %x, expected %x\n", netxen_nic_driver_name,
+		       netxen_nic_driver_name,
+		       boardinfo->magic, NETXEN_BDINFO_MAGIC);
+		rv = -1;
+	}
+	if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
+		printk("%s: Unknown board config version."
+		       " Read %x, expected %x\n", netxen_nic_driver_name,
+		       boardinfo->header_version, NETXEN_BDINFO_VERSION);
+		rv = -1;
+	}
+
+	DPRINTK(INFO, "Discovered board type:0x%x  ", boardinfo->board_type);
+	switch ((netxen_brdtype_t) boardinfo->board_type) {
+	case NETXEN_BRDTYPE_P2_SB35_4G:
+		adapter->ahw.board_type = NETXEN_NIC_GBE;
+		break;
+	case NETXEN_BRDTYPE_P2_SB31_10G:
+	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+		adapter->ahw.board_type = NETXEN_NIC_XGBE;
+		break;
+	case NETXEN_BRDTYPE_P1_BD:
+	case NETXEN_BRDTYPE_P1_SB:
+	case NETXEN_BRDTYPE_P1_SMAX:
+	case NETXEN_BRDTYPE_P1_SOCK:
+		adapter->ahw.board_type = NETXEN_NIC_GBE;
+		break;
+	default:
+		printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
+		       boardinfo->board_type);
+		break;
+	}
+
+	return rv;
+}
+
+inline int netxen_nic_get_board_num(struct netxen_adapter *adapter)
+{
+	return adapter->ahw.boardcfg.board_num;
+}
+
+/* NIU access sections */
+
+/* Set the MAC address for a port */
+int netxen_nic_macaddr_set(struct netxen_port *port, u8 * addr)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	int phy = port->portnum, ret = 0;
+
+	if ((phy < 0) || (phy > 3))
+		return -1;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		ret = netxen_niu_macaddr_set(adapter, phy, addr);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		ret = netxen_niu_xg_macaddr_set(adapter, phy, addr);
+		break;
+
+	default:
+		dump_stack();
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+/* Return the current MAC address of the given port. */
+int netxen_nic_macaddr_get(struct netxen_port *port, u8 ** addr)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	int phy = port->portnum;
+	int ret = 0;
+
+	if (addr == NULL)
+		return -1;
+	if ((phy < 0) || (phy > 3))
+		return -1;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		ret = netxen_niu_macaddr_get(adapter, phy,
+					     (netxen_ethernet_macaddr_t *) *
+					     addr);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
+		       netxen_nic_driver_name, __FUNCTION__);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int netxen_nic_set_mtu(struct netxen_port *port, int new_mtu)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	int ret = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		netxen_nic_write_w0(adapter,
+				    NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum),
+				    new_mtu);
+
+		break;
+
+	case NETXEN_NIC_XGBE:
+		new_mtu += 100;	/* so that MAC accepts frames > MTU */
+		netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE,
+				    new_mtu);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int netxen_nic_set_promisc_mode(struct netxen_port *port)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	int phy = port->portnum;
+	int ret = 0;
+
+	if ((phy < 0) || (phy > 3))
+		return -1;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		ret = netxen_niu_set_promiscuous_mode(adapter, phy,
+						      NETXEN_NIU_PROMISCOUS_MODE);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		ret = netxen_niu_xg_set_promiscuous_mode(adapter, phy,
+							 NETXEN_NIU_PROMISCOUS_MODE);
+
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int netxen_nic_unset_promisc_mode(struct netxen_port *port)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	int phy = port->portnum;
+	int ret = 0;
+
+	if ((phy < 0) || (phy > 3))
+		return -1;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		ret = netxen_niu_set_promiscuous_mode(adapter, phy,
+						      NETXEN_NIU_NON_PROMISCOUS_MODE);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		ret = netxen_niu_xg_set_promiscuous_mode(adapter, phy,
+							 NETXEN_NIU_NON_PROMISCOUS_MODE);
+
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+long
+netxen_nic_phy_read(struct netxen_adapter *adapter, long phy, long reg,
+		    u32 * readval)
+{
+	long ret = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		ret = netxen_niu_gbe_phy_read(adapter, phy, reg, readval);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
+		       netxen_nic_driver_name, __FUNCTION__);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+long netxen_nic_phy_write(struct netxen_adapter *adapter, long phy, long reg,
+			  u32 val)
+{
+	long ret = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		ret = netxen_niu_gbe_phy_write(adapter, phy, reg, val);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
+		       netxen_nic_driver_name, __FUNCTION__);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+long netxen_nic_init_port(struct netxen_port *port)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	long portnum = port->portnum;
+	long ret = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		netxen_nic_disable_phy_interrupts(adapter, portnum);
+		udelay(20000);
+		netxen_niu_gbe_init_port(adapter, portnum);
+
+		break;
+
+	case NETXEN_NIC_XGBE:
+		/* Nothing to be done for XG */
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+void netxen_nic_init_niu(struct netxen_adapter *adapter)
+{
+	int portno;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++)
+			netxen_niu_gbe_init_port(adapter, portno);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		/* Do nothing */
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+	}
+}
+
+void netxen_nic_stop_port(struct netxen_port *port)
+{
+	long portnum = port->portnum;
+	struct netxen_adapter *adapter = port->adapter;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		netxen_niu_disable_gbe_port(adapter, portnum);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		netxen_niu_disable_xg_port(adapter, portnum);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+	}
+}
+
+void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
+{
+	int port_nr;
+	struct netxen_port *port;
+
+	for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
+		port = adapter->port[port_nr];
+		netxen_nic_stop_port(port);
+	}
+}
+
+void
+netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
+			    int data)
+{
+	unsigned long flags;
+	void *addr;
+
+	if (ADDR_IN_WINDOW1(off)) {
+		read_lock(&adapter->adapter_lock);
+		writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
+		read_unlock(&adapter->adapter_lock);
+	} else {
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+		netxen_nic_pci_change_crbwindow(adapter, 0);
+		addr = (void *)(adapter->ahw.pci_base + off);
+		writel(data, addr);
+		netxen_nic_pci_change_crbwindow(adapter, 1);
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	}
+}
+
+void netxen_nic_set_link_parameters(struct netxen_port *port)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	struct netxen_niu_phy_status status;
+	u16 autoneg;
+	struct netxen_niu_control mode;
+
+	netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, (u32 *) & mode);
+	if (mode.enable_ge) {	/* Gb 10/100/1000 Mbps mode */
+		if (netxen_nic_phy_read(port->adapter, port->portnum,
+					NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+					(netxen_crbword_t *) & status) == 0) {
+			if (status.link) {
+				switch (status.speed) {
+				case 0:
+					port->link_speed = SPEED_10;
+					break;
+				case 1:
+					port->link_speed = SPEED_100;
+					break;
+				case 2:
+					port->link_speed = SPEED_1000;
+					break;
+				default:
+					port->link_speed = -1;	/* unknown speed */
+					break;
+				}
+				switch (status.duplex) {
+				case 0:
+					port->link_duplex = DUPLEX_HALF;
+					break;
+				case 1:
+					port->link_duplex = DUPLEX_FULL;
+					break;
+				default:
+					port->link_duplex = -1;	/* unknown mode */
+					break;
+				}
+				if (netxen_nic_phy_read(port->adapter,
+							port->portnum,
+							NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+							(netxen_crbword_t *) &
+							autoneg) != 0)
+					port->link_autoneg = autoneg;
+			} else
+				goto link_down;
+		} else {
+		      link_down:
+			port->link_speed = -1;
+			port->link_duplex = -1;
+		}
+	}
+}
+
+void netxen_nic_flash_print(struct netxen_adapter *adapter)
+{
+	int valid = 1;
+	u32 fw_major = 0;
+	u32 fw_minor = 0;
+	u32 fw_build = 0;
+
+	struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
+	if (board_info->magic != NETXEN_BDINFO_MAGIC) {
+		printk
+		    ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n",
+		     board_info->magic, NETXEN_BDINFO_MAGIC);
+		valid = 0;
+	}
+	if (board_info->header_version != NETXEN_BDINFO_VERSION) {
+		printk("NetXen Unknown board config version."
+		       " Read %x, expected %x\n",
+		       board_info->header_version, NETXEN_BDINFO_VERSION);
+		valid = 0;
+	}
+	if (valid) {
+		printk("NetXen %s Board #%d, Chip id 0x%x\n",
+		       board_info->board_type == 0x0b ? "XGB" : "GBE",
+		       board_info->board_num, board_info->chip_id);
+		read_lock(&adapter->adapter_lock);
+		fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
+						      NETXEN_FW_VERSION_MAJOR));
+		fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
+						      NETXEN_FW_VERSION_MINOR));
+		fw_build =
+		    readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+		read_unlock(&adapter->adapter_lock);
+
+		printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor,
+		       fw_build);
+	}
+	if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
+		printk(KERN_ERR "The mismatch in driver version and firmware "
+		       "version major number\n"
+		       "Driver version major number = %d \t"
+		       "Firmware version major number = %d \n",
+		       _NETXEN_NIC_LINUX_MAJOR, fw_major);
+		adapter->driver_mismatch = 1;
+	}
+	if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
+		printk(KERN_ERR "The mismatch in driver version and firmware "
+		       "version minor number\n"
+		       "Driver version minor number = %d \t"
+		       "Firmware version minor number = %d \n",
+		       _NETXEN_NIC_LINUX_MINOR, fw_minor);
+		adapter->driver_mismatch = 1;
+	}
+	if (adapter->driver_mismatch)
+		printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n",
+		       fw_major, fw_minor);
+}


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 5/9] NetXen: hardware access header file
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
                   ` (3 preceding siblings ...)
  2006-07-05 13:34 ` [PATCH 2.6.17 4/9] NetXen: hardware access routines Linsys Contractor Amit S. Kale
@ 2006-07-05 13:38 ` Linsys Contractor Amit S. Kale
  2006-07-05 16:04   ` Jeff Garzik
  2006-07-05 13:40 ` [PATCH 2.6.17 6/9] NetXen: hw initialization routines Linsys Contractor Amit S. Kale
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:38 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_hw.h linux-2.6.17/drivers/net/netxen/netxen_nic_hw.h
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_hw.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_hw.h	2006-07-05 01:18:40.364907061 -0700
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Structures, enums, and macros for the MAC
+ *
+ */
+
+#ifndef __NETXEN_NIC_HW_H_
+#define __NETXEN_NIC_HW_H_
+
+#include "netxen_nic_hdr.h"
+
+/* Hardware memory size of 128 meg */
+#define NETXEN_MEMADDR_MAX (128 * 1024 * 1024)
+
+#ifndef readq
+static inline u64 readq(void __iomem * addr)
+{
+	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem * addr)
+{
+	writel(((u32) (val)), (addr));
+	writel(((u32) (val >> 32)), (addr + 4));
+}
+#endif
+
+#define NETXEN_NIC_HW_BLOCK_WRITE_64(DATA_PTR, ADDR, NUM_WORDS)     \
+        do {                                                        \
+                int num;                                            \
+                u64 *a = (u64 *) (DATA_PTR);                        \
+                u64 *b = (u64 *) (ADDR);                            \
+                for (num = 0; num < (NUM_WORDS); num++) {           \
+                        writeq(readq(a), b);                        \
+                        b++;                                        \
+                        a++;                                        \
+                }                                                   \
+        } while (0)
+
+#define NETXEN_NIC_HW_BLOCK_READ_64(DATA_PTR, ADDR, NUM_WORDS)        \
+        do {                                                          \
+                int num;                                              \
+                u64 *a = (u64 *) (DATA_PTR);                          \
+                u64 *b = (u64 *) (ADDR);                              \
+                for (num = 0; num < (NUM_WORDS); num++) {             \
+                        writeq(readq(b), a);                          \
+                        b++;                                          \
+                        a++;                                          \
+                }                                                     \
+        } while (0)
+
+#define NETXEN_PCI_MAPSIZE_BYTES  (NETXEN_PCI_MAPSIZE << 20)
+#define NETXEN_DB_MAPSIZE_BYTES    0x4000
+
+#define NETXEN_NIC_LOCKED_READ_REG(X, Y)   		\
+        addr = (void *)(adapter->ahw.pci_base + X);     \
+        *(u32 *)Y = readl(addr);
+
+#define NETXEN_NIC_LOCKED_WRITE_REG(X, Y)   		\
+	addr = (void *)(adapter->ahw.pci_base + X); 	\
+	writel(*(u32 *)Y, addr);
+
+struct netxen_port;
+void netxen_nic_set_link_parameters(struct netxen_port *port);
+struct netxen_adapter;
+void netxen_nic_flash_print(struct netxen_adapter *adapter);
+
+int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off,
+			   void *data, int len);
+void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+				 unsigned long off, int data);
+int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off,
+			  void *data, int len);
+
+typedef u8 netxen_ethernet_macaddr_t[6];
+
+/* Nibble or Byte mode for phy interface (GbE mode only) */
+typedef enum {
+	NETXEN_NIU_10_100_MB = 0,
+	NETXEN_NIU_1000_MB
+} netxen_niu_gbe_ifmode_t;
+
+/*
+ * NIU GB MAC Config Register 0 (applies to GB0, GB1, GB2, GB3)
+ */
+struct netxen_niu_gb_mac_config_0_t {
+	netxen_crbword_t tx_enable:1,	/* 1:enable frame xmit, 0:disable */
+	 tx_synched:1,		/* R/O: xmit enable synched to xmit stream */
+	 rx_enable:1,		/* 1:enable frame recv, 0:disable */
+	 rx_synched:1,		/* R/O: recv enable synched to recv stream */
+	 tx_flowctl:1,		/* 1:enable pause frame generation, 0:disable*/
+	 rx_flowctl:1,		/* 1:act on recv'd pause frames, 0:ignore */
+	 rsvd1:2,
+	 loopback:1,		/* 1:loop MAC xmits to MAC recvs, 0:normal */
+	 rsvd2:7,
+	 tx_reset_pb:1,		/* 1:reset frame xmit protocol blk, 0:no-op */
+	 rx_reset_pb:1,		/* 1:reset frame recv protocol blk, 0:no-op */
+	 tx_reset_mac:1,	/* 1:reset data/ctl multiplexer blk, 0:no-op */
+	 rx_reset_mac:1,	/* 1:reset ctl frames & timers blk, 0:no-op */
+	 rsvd3:11,
+	 soft_reset:1;	/* 1:reset the MAC and the SERDES, 0:no-op */
+};
+
+/*
+ * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3)
+ */
+struct netxen_niu_gb_mac_config_1_t {
+	netxen_crbword_t duplex:1,	/* 1:full duplex mode, 0:half duplex */
+	 crc_enable:1,	/* 1:append CRC to xmit frames, 0:dont append */
+	 padshort:1,	/* 1:pad short frames and add CRC, 0:dont pad */
+	 rsvd1:1,
+	 checklength:1,	/* 1:check framelen with actual, 0:dont check */
+	 hugeframes:1,	/* 1:allow oversize xmit frames, 0:dont allow */
+	 rsvd2:2,
+	 intfmode:2,	/* 01:nibble (10/100), 10:byte (1000) */
+	 rsvd3:2,
+	 preamblelen:4,	/* preamble field length in bytes, default 7 */
+	 rsvd4:16;
+};
+
+/*
+ * NIU GB Station Address High Register
+ * NOTE: this value is in network byte order.
+ */
+struct netxen_niu_gb_station_address_high {
+	netxen_crbword_t address:32;	/* station address [47:16] */
+};
+
+/*
+ * NIU GB Station Address Low Register
+ * NOTE: this value is in network byte order.
+ */
+struct netxen_niu_gb_station_address_low {
+	netxen_crbword_t rsvd:16, address:16;	/* station address [15:0] */
+};
+
+/*
+ * NIU GB MII Mgmt Config Register (applies to GB0, GB1, GB2, GB3)
+ */
+struct netxen_niu_gb_mii_mgmt_config {
+	netxen_crbword_t clockselect:3,
+	    /* 0:clk/4,  1:clk/4,  2:clk/6,  3:clk/8 */
+	    /* 4:clk/10, 5:clk/14, 6:clk/20, 7:clk/28 */
+	 rsvd1:1, nopreamble:1,	/* 1:suppress preamble generation, 0:normal */
+	 scanauto:1, rsvd2:25, reset:1;	/* 1:reset MII mgmt, 0:no-op */
+};
+
+/*
+ * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
+ */
+struct netxen_niu_gb_mii_mgmt_command {
+	/* 1:perform single read cycle, 0:no-op */
+	netxen_crbword_t read_cycle:1,
+	 scan_cycle:1,		/* 1:perform continuous read cycles, 0:no-op */
+	 rsvd:30;
+};
+
+/*
+ * NIU GB MII Mgmt Address Register (applies to GB0, GB1, GB2, GB3)
+ */
+struct netxen_niu_gb_mii_mgmt_address {
+	/* which mgmt register we want to talk to */
+	netxen_crbword_t reg_addr:5,
+	 rsvd1:3, phy_addr:5,	/* which PHY to talk to (0 is reserved) */
+	 rsvd:19;
+};
+
+/*
+ * NIU GB MII Mgmt Indicators Register (applies to GB0, GB1, GB2, GB3)
+ * Read-only register.
+ */
+struct netxen_niu_gb_mii_mgmt_indicators {
+	/* 1:performing an MII mgmt cycle, 0:idle */
+	netxen_crbword_t busy:1,
+	 scanning:1,		/* 1:scan operation in progress, 0:idle */
+	 notvalid:1,		/* 1:mgmt result data not yet valid, 0:idle */
+	 rsvd:29;
+};
+
+/*
+ * PHY-Specific MII control/status registers.
+ */
+typedef enum {
+	NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26,
+	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27
+} netxen_niu_phy_register_t;
+
+/*
+ * PHY-Specific Status Register (reg 17).
+ */
+struct netxen_niu_phy_status {
+	netxen_crbword_t jabber:1,	/* 1:jabber detected, 0:not */
+	 polarity:1,		/* 1:polarity reversed, 0:normal */
+	 recvpause:1,		/* 1:receive pause enabled, 0:disabled */
+	 xmitpause:1,		/* 1:transmit pause enabled, 0:disabled */
+	 energydetect:1,	/* 1:sleep, 0:active */
+	 downshift:1,		/* 1:downshift, 0:no downshift */
+	 crossover:1,		/* 1:MDIX (crossover), 0:MDI (no crossover) */
+	 cablelen:3,		/* not valid in 10Mb/s mode */
+	    /* 0:<50m, 1:50-80m, 2:80-110m, 3:110-140m, 4:>140m */
+	 link:1,		/* 1:link up, 0:link down */
+	 resolved:1,		/* 1:speed and duplex resolved, 0:not yet */
+	 pagercvd:1,		/* 1:page received, 0:page not received */
+	 duplex:1,		/* 1:full duplex, 0:half duplex */
+	 speed:2,		/* 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd */
+	 rsvd:16;
+};
+
+/*
+ * Interrupt Register definition
+ * This definition applies to registers 18 and 19 (int enable and int status).
+ */
+struct netxen_niu_phy_interrupt {
+	netxen_crbword_t
+	    jabber:1,
+	    polarity_changed:1,
+	    reserved:2,
+	    energy_detect:1,
+	    downshift:1,
+	    mdi_xover_changed:1,
+	    fifo_over_underflow:1,
+	    false_carrier:1,
+	    symbol_error:1,
+	    link_status_changed:1,
+	    autoneg_completed:1,
+	    page_received:1,
+	    duplex_changed:1, speed_changed:1, autoneg_error:1, rsvd:16;
+};
+
+/*
+ * NIU Mode Register.
+ */
+struct netxen_niu_control {
+	netxen_crbword_t enable_fc:1,	/* enable FibreChannel */
+	 enable_ge:1,		/* enable 10/100/1000 Ethernet */
+	 enable_xgb:1,		/* enable 10Gb Ethernet */
+	 rsvd:29;
+};
+
+/* Promiscous mode options (GbE mode only) */
+typedef enum {
+	NETXEN_NIU_PROMISCOUS_MODE = 0,
+	NETXEN_NIU_NON_PROMISCOUS_MODE
+} netxen_niu_prom_mode_t;
+
+/*
+ * NIU GB Drop CRC Register
+ */
+struct netxen_niu_gb_drop_crc {
+	/* 1:drop pkts with bad CRCs, 0:pass them on */
+	netxen_crbword_t drop_gb0:1,
+	 drop_gb1:1,		/* 1:drop pkts with bad CRCs, 0:pass them on */
+	 drop_gb2:1,		/* 1:drop pkts with bad CRCs, 0:pass them on */
+	 drop_gb3:1,		/* 1:drop pkts with bad CRCs, 0:pass them on */
+	 rsvd:28;
+};
+
+/*
+ * NIU XG MAC Config Register
+ */
+struct netxen_niu_xg_mac_config_0_t {
+	netxen_crbword_t tx_enable:1,	/* 1:enable frame xmit, 0:disable */
+	 rsvd1:1, rx_enable:1,	/* 1:enable frame recv, 0:disable */
+	 rsvd2:1, soft_reset:1,	/* 1:reset the MAC , 0:no-op */
+	 rsvd3:22,
+	    xaui_framer_reset:1,
+	    xaui_rx_reset:1,
+	    xaui_tx_reset:1, xg_ingress_afifo_reset:1, xg_egress_afifo_reset:1;
+};
+
+/* Set promiscuous mode for a GbE interface */
+long netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, long port,
+				     netxen_niu_prom_mode_t mode);
+long netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
+					long port, netxen_niu_prom_mode_t mode);
+
+/* get/set the MAC address for a given MAC */
+int netxen_niu_macaddr_get(struct netxen_adapter *adapter, int port,
+			   netxen_ethernet_macaddr_t * addr);
+int netxen_niu_macaddr_set(struct netxen_adapter *adapter, int port,
+			   netxen_ethernet_macaddr_t addr);
+
+/* XG versons */
+int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int port,
+			      netxen_ethernet_macaddr_t * addr);
+int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, int port,
+			      netxen_ethernet_macaddr_t addr);
+
+/* Generic enable for GbE ports. Will detect the speed of the link. */
+long netxen_niu_gbe_init_port(struct netxen_adapter *adapter, long port);
+
+/* Disable a GbE interface */
+long netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, long port);
+
+long netxen_niu_disable_xg_port(struct netxen_adapter *adapter, long port);
+
+#endif				/* __NETXEN_NIC_HW_H_ */


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 6/9] NetXen: hw initialization routines
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
                   ` (4 preceding siblings ...)
  2006-07-05 13:38 ` [PATCH 2.6.17 5/9] NetXen: hardware access header file Linsys Contractor Amit S. Kale
@ 2006-07-05 13:40 ` Linsys Contractor Amit S. Kale
  2006-07-05 16:12   ` Jeff Garzik
  2006-07-05 13:42 ` [PATCH 2.6.17 7/9] NetXen: ioctl interface and intr routines Linsys Contractor Amit S. Kale
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:40 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_init.c linux-2.6.17/drivers/net/netxen/netxen_nic_init.c
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_init.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_init.c	2006-07-05 01:18:40.366906651 -0700
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Source file for NIC routines to initialize the Phantom Hardware
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include "netxen_nic.h"
+#include "netxen_nic_hw.h"
+#include "netxen_nic_ioctl.h"
+#include "netxen_nic_phan_reg.h"
+
+struct crb_addr_pair {
+	long addr;
+	long data;
+};
+
+#define NETXEN_MAX_CRB_XFORM 60
+static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
+#define NETXEN_ADDR_ERROR ((unsigned long ) 0xffffffff )
+
+#define crb_addr_transform(name) \
+        crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \
+        NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20
+
+#define NETXEN_FLASH_BASE	(BOOTLD_START)
+#define NETXEN_PHANTOM_MEM_BASE	(NETXEN_FLASH_BASE)
+
+static void crb_addr_transform_setup(void)
+{
+	crb_addr_transform(XDMA);
+	crb_addr_transform(TIMR);
+	crb_addr_transform(SRE);
+	crb_addr_transform(SQN3);
+	crb_addr_transform(SQN2);
+	crb_addr_transform(SQN1);
+	crb_addr_transform(SQN0);
+	crb_addr_transform(SQS3);
+	crb_addr_transform(SQS2);
+	crb_addr_transform(SQS1);
+	crb_addr_transform(SQS0);
+	crb_addr_transform(RPMX7);
+	crb_addr_transform(RPMX6);
+	crb_addr_transform(RPMX5);
+	crb_addr_transform(RPMX4);
+	crb_addr_transform(RPMX3);
+	crb_addr_transform(RPMX2);
+	crb_addr_transform(RPMX1);
+	crb_addr_transform(RPMX0);
+	crb_addr_transform(ROMUSB);
+	crb_addr_transform(SN);
+	crb_addr_transform(QMN);
+	crb_addr_transform(QMS);
+	crb_addr_transform(PGNI);
+	crb_addr_transform(PGND);
+	crb_addr_transform(PGN3);
+	crb_addr_transform(PGN2);
+	crb_addr_transform(PGN1);
+	crb_addr_transform(PGN0);
+	crb_addr_transform(PGSI);
+	crb_addr_transform(PGSD);
+	crb_addr_transform(PGS3);
+	crb_addr_transform(PGS2);
+	crb_addr_transform(PGS1);
+	crb_addr_transform(PGS0);
+	crb_addr_transform(PS);
+	crb_addr_transform(PH);
+	crb_addr_transform(NIU);
+	crb_addr_transform(I2Q);
+	crb_addr_transform(EG);
+	crb_addr_transform(MN);
+	crb_addr_transform(MS);
+	crb_addr_transform(CAS2);
+	crb_addr_transform(CAS1);
+	crb_addr_transform(CAS0);
+	crb_addr_transform(CAM);
+	crb_addr_transform(C2C1);
+	crb_addr_transform(C2C0);
+}
+
+static int cmdline_max_cmd_desc = 1024;
+static int cmdline_max_rcv_desc = 16384;
+static int cmdline_max_jumbo_rcv_desc = 512;
+
+module_param(cmdline_max_cmd_desc, int, S_IRUGO);
+module_param(cmdline_max_rcv_desc, int, S_IRUGO);
+module_param(cmdline_max_jumbo_rcv_desc, int, S_IRUGO);
+
+void inline netxen_check_cmdline_params(void)
+{
+	if (cmdline_max_cmd_desc < 1024)
+		cmdline_max_cmd_desc = MAX_CMD_DESCRIPTORS;
+	if (cmdline_max_rcv_desc < 16384)
+		cmdline_max_rcv_desc = MAX_RCV_DESCRIPTORS;
+	if (cmdline_max_jumbo_rcv_desc < 512)
+		cmdline_max_jumbo_rcv_desc = MAX_JUMBO_RCV_DESCRIPTORS;
+}
+
+void __devinit netxen_check_options(struct netxen_adapter *adapter)
+{
+	struct netxen_ring_context *ctx;
+	int i;
+
+	for (i = 0; i < MAX_RING_CTX; i++) {
+		ctx = &adapter->ring_ctx[i];
+		ctx->max_tx_desc_count = cmdline_max_cmd_desc;
+		ctx->max_rx_desc_count = cmdline_max_rcv_desc;
+		ctx->max_jumbo_rx_desc_count = cmdline_max_jumbo_rcv_desc;
+	}
+}
+
+int init_firmware(struct netxen_adapter *adapter)
+{
+	u32 state = 0, loops = 0, err = 0;
+
+	/* Window 1 call */
+	read_lock(&adapter->adapter_lock);
+	state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+	read_unlock(&adapter->adapter_lock);
+
+	while (state != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
+		udelay(100);
+		/* Window 1 call */
+		read_lock(&adapter->adapter_lock);
+		state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+		read_unlock(&adapter->adapter_lock);
+
+		loops++;
+	}
+	if (loops >= 200000) {
+		printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
+		       state);
+		err = -EIO;
+		return err;
+	}
+	/* Window 1 call */
+	read_lock(&adapter->adapter_lock);
+	writel(PHAN_INITIALIZE_ACK,
+	       NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+	read_unlock(&adapter->adapter_lock);
+
+	return err;
+}
+
+void initialize_adapter_sw(struct netxen_adapter *adapter)
+{
+	int ctxid, ring;
+	u32 i;
+	u32 num_rx_bufs = 0;
+	struct netxen_rcv_desc_ctx *rcv_desc;
+	struct netxen_ring_context *ctx;
+
+	DPRINTK(INFO, "initializing some queues: %p\n", adapter);
+	for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+		ctx = &adapter->ring_ctx[ctxid];
+		ctx->free_cmd_count = ctx->max_tx_desc_count;
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			struct netxen_rx_buffer *rx_buf;
+			rcv_desc = &ctx->recv_ctx.rcv_desc[ring];
+			rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
+			rcv_desc->begin_alloc = 0;
+			rx_buf = rcv_desc->rx_buf_arr;
+			num_rx_bufs = rcv_desc->max_rx_desc_count;
+			/*
+			 * Now go through all of them, set reference handles
+			 * and put them in the queues.
+			 */
+			for (i = 0; i < num_rx_bufs; i++) {
+				rx_buf->ref_handle = i;
+				rx_buf->state = NETXEN_BUFFER_FREE;
+
+				DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
+					"%p\n", ctxid, i, rx_buf);
+				rx_buf++;
+			}
+		}
+	}
+	DPRINTK(INFO, "initialized buffers for %s and %s\n",
+		"adapter->free_cmd_buf_list", "adapter->free_rxbuf");
+}
+
+int initialize_adapter_hw(struct netxen_adapter *adapter)
+{
+	u32 value = 0;
+
+	if (netxen_nic_get_board_info(adapter) != 0)
+		printk("%s: Error getting board config info.\n",
+			netxen_nic_driver_name);
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		adapter->ahw.max_ports = 4;
+		break;
+
+	case NETXEN_NIC_XGBE:
+		adapter->ahw.max_ports = 1;
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+			netxen_nic_driver_name);
+	}
+
+	return value;
+}
+
+/*
+ * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB
+ * address to external PCI CRB address.
+ */
+unsigned long netxen_decode_crb_addr(unsigned long addr)
+{
+	int i;
+	unsigned long base_addr, offset, pci_base;
+
+	crb_addr_transform_setup();
+
+	pci_base = NETXEN_ADDR_ERROR;
+	base_addr = addr & 0xfff00000;
+	offset = addr & 0x000fffff;
+
+	for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) {
+		if (crb_addr_xform[i] == base_addr) {
+			pci_base = i << 20;
+			break;
+		}
+	}
+	if (pci_base == NETXEN_ADDR_ERROR)
+		return pci_base;
+	else
+		return (pci_base + offset);
+}
+
+static long rom_max_timeout = 10000;
+static long rom_lock_timeout = 100000000;
+
+int rom_lock(struct netxen_adapter *adapter)
+{
+	int iter;
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore2 from PCI HW block */
+		netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
+				   &done);
+		if (done == 1)
+			break;
+		if (timeout >= rom_lock_timeout)
+			return -1;
+
+		timeout++;
+		/*
+		 * Yield CPU
+		 */
+		if (!in_atomic())
+			schedule();
+		else {
+			for (iter = 0; iter < 20; iter++)
+				cpu_relax();	/*This a nop instr on i386 */
+		}
+	}
+	netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+	return 0;
+}
+
+void rom_unlock(struct netxen_adapter *adapter)
+{
+	int val;
+
+	/* release semaphore2 */
+	netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
+
+}
+
+int netxen_wait_rom_done(struct netxen_adapter *adapter)
+{
+	long timeout = 0;
+	long done = 0;
+
+	while (done == 0) {
+		done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
+		done &= 2;
+		timeout++;
+		if (timeout >= rom_max_timeout) {
+			printk("Timeout reached  waiting for rom done");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
+{
+	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+	udelay(100);		/* prevent bursting on CRB */
+	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+	if (netxen_wait_rom_done(adapter)) {
+		printk("Error waiting for rom done\n");
+		return -1;
+	}
+	/* reset abyte_cnt and dummy_byte_cnt */
+	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+	udelay(100);		/* prevent bursting on CRB */
+	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+
+	*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
+	return 0;
+}
+
+int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
+{
+	int ret;
+
+	if (rom_lock(adapter) != 0)
+		return -1;
+
+	ret = do_rom_fast_read(adapter, addr, valp);
+	rom_unlock(adapter);
+	return ret;
+}
+
+int pinit_from_rom(struct netxen_adapter *adapter, int verbose)
+{
+	int addr, val, status;
+	int n, i;
+	int init_delay = 0;
+	struct crb_addr_pair *buf;
+	unsigned long off;
+	unsigned long flags;
+
+	/* resetall */
+	status = netxen_nic_get_board_info(adapter);
+	if (status)
+		printk("%s: pinit_from_rom: Error getting board info\n",
+		       netxen_nic_driver_name);
+
+	netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
+				    0xffffffff);
+
+	if (verbose) {
+		int val;
+		if (netxen_rom_fast_read(adapter, 0x4008, &val) == 0)
+			printk("P2 ROM board type: 0x%08x\n", val);
+		else
+			printk("Could not read board type\n");
+		if (netxen_rom_fast_read(adapter, 0x400c, &val) == 0)
+			printk("P2 ROM board  num: 0x%08x\n", val);
+		else
+			printk("Could not read board number\n");
+		if (netxen_rom_fast_read(adapter, 0x4010, &val) == 0)
+			printk("P2 ROM chip   num: 0x%08x\n", val);
+		else
+			printk("Could not read chip number\n");
+	}
+
+	if (netxen_rom_fast_read(adapter, 0, &n) == 0 && (n & 0x800000000ULL)) {
+		n &= ~0x80000000ULL;
+		if (n < 1024) {
+			if (verbose)
+				printk("%s: %d CRB init values found"
+				       " in ROM.\n", netxen_nic_driver_name, n);
+		} else {
+			printk("%s:n=0x%x Error! NetXen card flash not"
+			       " initialized.\n", __FUNCTION__, n);
+			return -1;
+		}
+		buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+		if (buf == NULL) {
+			printk("%s: pinit_from_rom: Unable to calloc memory.\n",
+			       netxen_nic_driver_name);
+			return -1;
+		}
+		for (i = 0; i < n; i++) {
+			if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
+			    || netxen_rom_fast_read(adapter, 8 * i + 8,
+						    &addr) != 0)
+				goto error_ret;
+
+			buf[i].addr = addr;
+			buf[i].data = val;
+
+			if (verbose)
+				printk("%s: PCI:     0x%08x == 0x%08x\n",
+				       netxen_nic_driver_name, (unsigned int)
+				       netxen_decode_crb_addr((unsigned long)
+							      addr), val);
+		}
+		for (i = 0; i < n; i++) {
+
+			off =
+			    netxen_decode_crb_addr((unsigned long)buf[i].addr) +
+			    NETXEN_PCI_CRBSPACE;
+			/* skipping cold reboot MAGIC */
+			if (off == NETXEN_CAM_RAM(0x1fc))
+				continue;
+
+			/* After writing this register, HW needs time for CRB */
+			/* to quiet down (else crb_window returns 0xffffffff) */
+			if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+				init_delay = 1;
+				/* hold xdma in reset also */
+				buf[i].data = 0x8000ff;
+			}
+
+			if (ADDR_IN_WINDOW1(off)) {
+				read_lock(&adapter->adapter_lock);
+				writel(buf[i].data,
+				       NETXEN_CRB_NORMALIZE(adapter, off));
+				read_unlock(&adapter->adapter_lock);
+			} else {
+				write_lock_irqsave(&adapter->adapter_lock,
+						   flags);
+				netxen_nic_pci_change_crbwindow(adapter, 0);
+				off = adapter->ahw.pci_base + off;
+				writel(buf[i].data, (void *)off);
+				netxen_nic_pci_change_crbwindow(adapter, 1);
+				write_unlock_irqrestore(&adapter->adapter_lock,
+							flags);
+			}
+			if (init_delay == 1) {
+				msleep(1000);
+				init_delay = 0;
+			}
+			msleep(1);
+		}
+		kfree(buf);
+
+		/* disable_peg_cache_all */
+
+		/* unreset_net_cache */
+		netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
+				      4);
+		netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
+					    (val & 0xffffff0f));
+		/* p2dn replyCount */
+		netxen_crb_writelit_adapter(adapter,
+					    NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+		/* disable_peg_cache 0 */
+		netxen_crb_writelit_adapter(adapter,
+					    NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+		/* disable_peg_cache 1 */
+		netxen_crb_writelit_adapter(adapter,
+					    NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+		/* peg_clr_all */
+
+		/* peg_clr 0 */
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
+					    0);
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
+					    0);
+		/* peg_clr 1 */
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
+					    0);
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
+					    0);
+		/* peg_clr 2 */
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
+					    0);
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
+					    0);
+		/* peg_clr 3 */
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
+					    0);
+		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
+					    0);
+	}
+	return 0;
+      error_ret:
+	return -1;
+}
+
+void phantom_init(struct netxen_adapter *adapter)
+{
+	u32 val = 0;
+	int loops = 0;
+
+	read_lock(&adapter->adapter_lock);
+	netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, &val, 4);
+	writel(1,
+	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+
+	if (0 == val) {
+		while (val != PHAN_INITIALIZE_COMPLETE && loops < 2000000) {
+			udelay(100);
+			val =
+			    readl(NETXEN_CRB_NORMALIZE
+				  (adapter, CRB_CMDPEG_STATE));
+			loops++;
+		}
+		if (val != PHAN_INITIALIZE_COMPLETE)
+			printk("WARNING: Initial boot wait loop failed...\n");
+	}
+	read_unlock(&adapter->adapter_lock);
+}
+
+void load_firmware(struct netxen_adapter *adapter)
+{
+	int i;
+	long data, size = 0;
+	long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
+
+	size = (16 * 1024) / 4;
+	read_lock(&adapter->adapter_lock);
+	writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+	read_unlock(&adapter->adapter_lock);
+
+	for (i = 0; i < size; i++) {
+		if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
+			DPRINTK(ERR,
+				"Error in netxen_rom_fast_read(). Will skip"
+				"loading flash image\n");
+			return;
+		}
+		netxen_nic_pci_mem_write(adapter, memaddr, &data, 4);
+		flashaddr += 4;
+		memaddr += 4;
+	}
+	udelay(100);
+	read_lock(&adapter->adapter_lock);
+	/* make sure Casper is powered on */
+	writel(0x3fff,
+	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
+	writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+	read_unlock(&adapter->adapter_lock);
+
+	udelay(10000);
+}
+
+int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
+{
+	int ctxid;
+
+	for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+		struct netxen_ring_context *ctx = &adapter->ring_ctx[ctxid];
+		struct netxen_recv_context *recv_ctx = &(ctx->recv_ctx);
+		u32 consumer;
+		struct status_desc_t *desc_head;
+		struct status_desc_t *desc;	/* used to read status desc here */
+
+		consumer = recv_ctx->status_rx_consumer;
+		desc_head = recv_ctx->rcv_status_desc_head;
+		desc = &desc_head[consumer];
+
+		if ((desc->owner & STATUS_OWNER_HOST))
+			return 1;
+	}
+
+	return 0;
+}
+
+void netxen_watchdog_task(unsigned long v)
+{
+	int port_num;
+	struct netxen_port *port;
+	struct net_device *netdev;
+	struct netxen_adapter *adapter = (struct netxen_adapter *)v;
+	unsigned long flags;
+
+	if (adapter->driver_mismatch) {
+		/* We return without turning on the netdev queue as there
+		 * was a mismatch in driver and firmware version
+		 */
+		return;
+	}
+	for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
+		port = adapter->port[port_num];
+		netdev = port->netdev;
+
+		if ((netdev->flags & IFF_UP) && !netif_carrier_ok(netdev)) {
+			printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
+			       netxen_nic_driver_name, port_num, netdev->name);
+			netif_carrier_on(netdev);
+		}
+
+		if (netif_queue_stopped(netdev))
+			netif_wake_queue(netdev);
+	}
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	netxen_nic_pci_change_crbwindow(adapter, 1);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+
+	netxen_nic_handle_phy_intr(adapter);
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+/*
+ * netxen_process_rcv() send the received packet to the protocol stack.
+ * and if the number of receives exceeds RX_BUFFERS_REFILL, then we
+ * invoke the routine to send more rx buffers to the Phantom...
+ */
+inline void
+netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
+		   struct status_desc_t *desc)
+{
+	struct netxen_port *port = adapter->port[desc->port];
+	struct pci_dev *pdev = port->pdev;
+	struct net_device *netdev = port->netdev;
+	int index = desc->reference_handle;
+	struct netxen_recv_context *recv_ctx =
+	    &(adapter->ring_ctx[ctxid].recv_ctx);
+	struct netxen_rx_buffer *buffer;
+	struct sk_buff *skb;
+	u32 length = desc->total_length;
+	u32 desc_ctx;
+	struct netxen_rcv_desc_ctx *rcv_desc;
+	int ret;
+
+	desc_ctx = desc->type;
+	if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
+		printk("%s: %s Bad Rcv descriptor ring\n",
+		       netxen_nic_driver_name, netdev->name);
+		return;
+	}
+
+	rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
+	buffer = &rcv_desc->rx_buf_arr[index];
+
+	pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
+			 PCI_DMA_FROMDEVICE);
+
+	skb = (struct sk_buff *)buffer->skb;
+
+	if (unlikely(skb == NULL)) {
+		/*
+		 * This should not happen and if it does, it is serious,
+		 * catch it
+		 */
+		u32 temp1, temp2;
+		/* Window = 0 or 1 */
+		read_lock(&adapter->adapter_lock);
+		temp1 = readl((void *)(adapter->ahw.pci_base
+				       + (NETXEN_CRB_PCIE + 0x20000)));
+		temp2 = readl((void *)(adapter->ahw.pci_base
+				       + (NETXEN_CRB_PCIE + 0x20008)));
+
+		read_unlock(&adapter->adapter_lock);
+
+		/* Window = 0 */
+		netxen_nic_write_w0(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c, 1);
+		netxen_nic_write_w0(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c, 1);
+		netxen_nic_write_w0(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c, 1);
+		netxen_nic_write_w0(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c, 1);
+		netxen_nic_write_w0(adapter, NETXEN_CRB_NIU + 0x70000, 0);
+
+		printk("%s: %s Halted the pegs and stopped the NIU consumer\n",
+		       netxen_nic_driver_name, netdev->name);
+		printk("Curr DMA Addr: 0x%x, status:0x%x\n", temp1, temp2);
+		printk("got NULL skb for index %d  desc %p\n", index, desc);
+		printk("prev desc %p: refh:%x\n", desc - 1,
+		       (desc - 1)->reference_handle);
+		printk("next desc %p: refh:%x\n", desc + 1,
+		       (desc + 1)->reference_handle);
+		printk("next desc %p: refh:%x\n", desc + 2,
+		       (desc + 2)->reference_handle);
+		printk("and mine again %p: refh:%x\n", desc,
+		       (desc)->reference_handle);
+
+		port->stats.rcvdbadskb++;
+		return;
+	}
+
+	if (likely(desc->status == STATUS_CKSUM_OK)) {
+		port->stats.csummed++;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	} else
+		skb->ip_summed = CHECKSUM_NONE;
+	skb->dev = netdev;
+	skb_put(skb, length);
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	ret = netif_receive_skb(skb);
+
+	/*
+	 * RH: Do we need these stats on a regular basis. Can we get it from
+	 * Linux stats.
+	 */
+	switch (ret) {
+	case NET_RX_SUCCESS:
+		port->stats.uphappy++;
+		break;
+
+	case NET_RX_CN_LOW:
+		port->stats.uplcong++;
+		break;
+
+	case NET_RX_CN_MOD:
+		port->stats.upmcong++;
+		break;
+
+	case NET_RX_CN_HIGH:
+		port->stats.uphcong++;
+		break;
+
+	case NET_RX_DROP:
+		port->stats.updropped++;
+		break;
+
+	default:
+		port->stats.updunno++;
+		break;
+	}
+
+	netdev->last_rx = jiffies;
+
+	rcv_desc->rcv_free++;
+	rcv_desc->rcv_pending--;
+
+	/*
+	 * We just consumed one buffer so post a buffer.
+	 */
+	adapter->stats.post_called++;
+	buffer->skb = NULL;
+	buffer->state = NETXEN_BUFFER_FREE;
+
+	port->stats.no_rcv++;
+	port->stats.rxbytes += length;
+}
+
+/* Process Receive status ring */
+u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+{
+	struct netxen_ring_context *ctx = &adapter->ring_ctx[ctxid];
+	struct netxen_recv_context *recv_ctx = &(ctx->recv_ctx);
+	struct status_desc_t *desc_head = recv_ctx->rcv_status_desc_head;
+	struct status_desc_t *desc;	/* used to read status desc here */
+	u32 producer = 0;	/* will be read from phantom */
+	u32 consumer = recv_ctx->status_rx_consumer;
+	int count = 0, ring;
+	DPRINTK(INFO, "procesing receive\n");
+	/*
+	 * we assume in this case that there is only one port and that is
+	 * port #1...changes need to be done in firmware to indicate port
+	 * number as part of the descriptor. This way we will be able to get
+	 * the netdev which is associated with that device.
+	 */
+	while (count < max) {
+		desc = &desc_head[consumer];
+		if (!(desc->owner & STATUS_OWNER_HOST)) {
+			DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner);
+			break;
+		}
+		netxen_process_rcv(adapter, ctxid, desc);
+		consumer = (consumer + 1) & (ctx->max_rx_desc_count - 1);
+		count++;
+	}
+	if (count) {
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			netxen_post_rx_buffers(adapter, ctxid, ring);
+		}
+	}
+
+	/* update the consumer index in phantom */
+	if (count) {
+		struct ctx_msg msg = { 0 };
+		adapter->stats.process_rcv++;
+		recv_ctx->status_rx_consumer = consumer;
+		recv_ctx->status_rx_producer = producer;
+
+		msg.PegId = NETXEN_RCV_PEG_DB_ID;
+		msg.Count = consumer;
+		msg.CtxId = ctxid;
+		msg.Opcode = NETXEN_RCV_STATUS_CONSUMER;
+
+		/* Window = 1 */
+		read_lock(&adapter->adapter_lock);
+		writel(*((u32 *) & msg),
+		       DB_NORMALIZE(adapter, recv_crb_registers[ctxid].
+				    crb_rcv_status_consumer));
+		read_unlock(&adapter->adapter_lock);
+	}
+
+	return count;
+}
+
+/* Process Command status ring */
+void netxen_process_cmd_ring(unsigned long data, int ctxid)
+{
+	u32 last_consumer;
+	u32 consumer;
+	struct netxen_adapter *adapter = (struct netxen_adapter *)data;
+	int count = 0;
+	struct netxen_cmd_buffer *buffer;
+	struct netxen_port *port;	/* port #1 */
+	struct netxen_port *nport;
+	struct pci_dev *pdev;
+	struct netxen_skb_frag *frag;
+	u32 i;
+	struct sk_buff *skb = NULL;
+	int p;
+	struct netxen_ring_context *ctx = &adapter->ring_ctx[ctxid];
+
+	spin_lock(&adapter->tx_lock);
+	last_consumer = ctx->last_cmd_consumer;
+	DPRINTK(INFO, "procesing xmit complete\n");
+	/* we assume in this case that there is only one port and that is
+	 * port #1...changes need to be done in firmware to indicate port
+	 * number as part of the descriptor. This way we will be able to get
+	 * the netdev which is associated with that device.
+	 */
+	/* Window = 1 */
+	consumer = *(ctx->cmd_consumer);
+
+	if (last_consumer == consumer) {	/* Ring is empty    */
+		DPRINTK(INFO, "last_consumer %d == consumer %d\n",
+			last_consumer, consumer);
+		spin_unlock(&adapter->tx_lock);
+		return;
+	}
+
+	ctx->proc_cmd_buf_counter++;
+	adapter->stats.process_xmit++;
+	/*
+	 * Not needed - does not seem to be used anywhere.
+	 * adapter->cmd_consumer = consumer;
+	 */
+	spin_unlock(&adapter->tx_lock);
+
+	while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) {
+		buffer = &ctx->cmd_buf_arr[last_consumer];
+		port = adapter->port[buffer->port];
+		pdev = port->pdev;
+		frag = &buffer->frag_array[0];
+		skb = buffer->skb;
+		if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
+			pci_unmap_single(pdev, frag->dma, frag->length,
+					 PCI_DMA_TODEVICE);
+			for (i = 1; i < buffer->frag_count; i++) {
+				DPRINTK(INFO, "getting fragment no %d\n", i);
+				frag++;	/* Get the next frag */
+				pci_unmap_page(pdev, frag->dma, frag->length,
+					       PCI_DMA_TODEVICE);
+			}
+
+			port->stats.skbfreed++;
+			dev_kfree_skb_any(skb);
+			skb = NULL;
+		} else if (ctx->proc_cmd_buf_counter == 1) {
+			port->stats.txnullskb++;
+		}
+		if (unlikely(netif_queue_stopped(port->netdev)
+			     && netif_carrier_ok(port->netdev))
+		    && ((jiffies - port->netdev->trans_start) >
+			port->netdev->watchdog_timeo)) {
+			schedule_work(port->adapter->tx_timeout_task +
+				      port->portnum);
+		}
+
+		last_consumer = get_next_index(last_consumer,
+					       ctx->max_tx_desc_count);
+		count++;
+	}
+	adapter->stats.noxmitdone += count;
+
+	count = 0;
+	spin_lock(&adapter->tx_lock);
+	if ((--ctx->proc_cmd_buf_counter) == 0) {
+		ctx->last_cmd_consumer = last_consumer;
+		while ((ctx->last_cmd_consumer != consumer)
+		       && (count < MAX_STATUS_HANDLE)) {
+			buffer = &ctx->cmd_buf_arr[ctx->last_cmd_consumer];
+			count++;
+			if (buffer->skb)
+				break;
+			else
+				ctx->last_cmd_consumer =
+				    get_next_index(ctx->last_cmd_consumer,
+						   ctx->max_tx_desc_count);
+		}
+	}
+	if (count) {
+		for (p = 0; p < adapter->ahw.max_ports; p++) {
+			nport = adapter->port[p];
+			if (netif_queue_stopped(nport->netdev)
+			    && (nport->flags & NETXEN_NETDEV_STATUS)) {
+				netif_wake_queue(nport->netdev);
+				nport->flags &= ~NETXEN_NETDEV_STATUS;
+			}
+		}
+	}
+
+	spin_unlock(&adapter->tx_lock);
+	DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer,
+		__FUNCTION__);
+}
+
+/**
+ * netxen_post_rx_buffers puts buffer in the Phantom memory
+ **/
+void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctxid,
+			    u32 ringid)
+{
+	struct pci_dev *pdev = adapter->ahw.pdev;
+	struct sk_buff *skb;
+	struct netxen_recv_context *recv_ctx =
+	    &(adapter->ring_ctx[ctxid].recv_ctx);
+	struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+	u32 producer;
+	struct rcv_desc_t *pdesc;
+	struct netxen_rx_buffer *buffer;
+	int count = 0;
+	int index = 0;
+	struct ctx_msg msg = { 0 };
+
+	adapter->stats.post_called++;
+	rcv_desc = &recv_ctx->rcv_desc[ringid];
+
+	producer = rcv_desc->producer;
+	buffer = &rcv_desc->rx_buf_arr[index];
+	/* We can start writing rx descriptors into the phantom memory. */
+	while (buffer->state == NETXEN_BUFFER_FREE) {
+		skb = dev_alloc_skb(rcv_desc->skb_size);
+		if (unlikely(!skb)) {
+			/*
+			 * We need to schedule the posting of buffers to the pegs.
+			 */
+			rcv_desc->begin_alloc = index;
+			DPRINTK(ERR, "netxen_post_rx_buffers: "
+				" allocated only %d buffers\n", count);
+			break;
+		}
+		count++;	/* now there should be no failure */
+		pdesc = &rcv_desc->desc_head[producer];
+		skb_reserve(skb, NET_IP_ALIGN);
+		/* 
+		 * This will be setup when we receive the
+		 * buffer after it has been filled
+		 * skb->dev = netdev;
+		 */
+		buffer->skb = skb;
+		buffer->state = NETXEN_BUFFER_BUSY;
+		buffer->dma = pci_map_single(pdev, skb->data,
+					     rcv_desc->dma_size,
+					     PCI_DMA_FROMDEVICE);
+		/* make a rcv descriptor  */
+		pdesc->reference_handle = buffer->ref_handle;
+		pdesc->buffer_length = rcv_desc->dma_size;
+		pdesc->addr_buffer = buffer->dma;
+		DPRINTK(INFO, "done writing descripter\n");
+		producer =
+		    get_next_index(producer, rcv_desc->max_rx_desc_count);
+		index = get_next_index(index, rcv_desc->max_rx_desc_count);
+		buffer = &rcv_desc->rx_buf_arr[index];
+	}
+	rcv_desc->begin_alloc = index;
+
+	/* if we did allocate buffers, then write the count to Phantom */
+	if (count) {
+		rcv_desc->begin_alloc = index;
+		rcv_desc->rcv_pending += count;
+		adapter->stats.lastposted = count;
+		adapter->stats.posted += count;
+		rcv_desc->producer = producer;
+		if (rcv_desc->rcv_free >= 32) {
+			rcv_desc->rcv_free = 0;
+			/*
+			 * Write a doorbell msg to tell phanmon of change in
+			 * receive ring producer
+			 */
+			msg.PegId = NETXEN_RCV_PEG_DB_ID;
+			msg.Count =
+			    (producer - 1) & (rcv_desc->max_rx_desc_count - 1);
+			msg.CtxId = ctxid;
+			msg.Opcode = NETXEN_RCV_PRODUCER(ringid);
+			/* Window = 1 */
+			read_lock(&adapter->adapter_lock);
+			writel(*((u32 *) & msg),
+			       DB_NORMALIZE(adapter,
+					    NETXEN_RCV_PRODUCER_OFFSET(ctxid,
+								       ringid)));
+			read_unlock(&adapter->adapter_lock);
+
+		}
+	}
+}
+
+int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
+{
+	int ctxid;
+	struct netxen_ring_context *ctx;
+	for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+		ctx = &adapter->ring_ctx[ctxid];
+		if (find_diff_among(ctx->last_cmd_consumer,
+				    ctx->cmd_producer,
+				    ctx->max_tx_desc_count) > 0)
+			return 1;
+	}
+	return 0;
+}
+
+int
+netxen_nic_fill_statistics(struct netxen_adapter *adapter,
+			   struct netxen_port *port,
+			   struct netxen_statistics *netxen_stats)
+{
+	unsigned long flags;
+	void *addr;
+
+	if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+		netxen_nic_pci_change_crbwindow(adapter, 0);
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_BYTE_CNT,
+					   &(netxen_stats->tx_bytes));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_FRAME_CNT,
+					   &(netxen_stats->tx_packets));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_BYTE_CNT,
+					   &(netxen_stats->rx_bytes));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_FRAME_CNT,
+					   &(netxen_stats->rx_packets));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_AGGR_ERROR_CNT,
+					   &(netxen_stats->rx_errors));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_CRC_ERROR_CNT,
+					   &(netxen_stats->rx_crc_errors));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
+					   &(netxen_stats->
+					     rx_long_length_error));
+		NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
+					   &(netxen_stats->
+					     rx_short_length_error));
+
+		netxen_nic_pci_change_crbwindow(adapter, 1);
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	} else {
+		spin_lock_bh(&adapter->tx_lock);
+		netxen_stats->tx_bytes = port->stats.txbytes;
+		netxen_stats->tx_packets = port->stats.xmitedframes +
+		    port->stats.xmitfinished;
+		netxen_stats->rx_bytes = port->stats.rxbytes;
+		netxen_stats->rx_packets = port->stats.no_rcv;
+		netxen_stats->rx_errors = port->stats.rcvdbadskb;
+		netxen_stats->tx_errors = port->stats.nocmddescriptor;
+		netxen_stats->rx_short_length_error = port->stats.uplcong;
+		netxen_stats->rx_long_length_error = port->stats.uphcong;
+		netxen_stats->rx_crc_errors = 0;
+		netxen_stats->rx_mac_errors = 0;
+		spin_unlock_bh(&adapter->tx_lock);
+	}
+	return 0;
+}
+
+void netxen_nic_clear_stats(struct netxen_adapter *adapter)
+{
+	struct netxen_port *port;
+	int port_num;
+
+	memset(&adapter->stats, 0, sizeof(adapter->stats));
+	for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
+		port = adapter->port[port_num];
+		memset(&port->stats, 0, sizeof(port->stats));
+	}
+}
+
+int
+netxen_nic_clear_statistics(struct netxen_adapter *adapter,
+			    struct netxen_port *port)
+{
+	unsigned long flags;
+	void *addr;
+	int data = 0;
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	netxen_nic_pci_change_crbwindow(adapter, 0);
+
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_TX_BYTE_CNT, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_TX_FRAME_CNT, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_RX_BYTE_CNT, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_RX_FRAME_CNT, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_AGGR_ERROR_CNT, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_CRC_ERROR_CNT, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR, &data);
+	NETXEN_NIC_LOCKED_WRITE_REG(NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR, &data);
+
+	netxen_nic_pci_change_crbwindow(adapter, 1);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	netxen_nic_clear_stats(adapter);
+	return 0;
+}
+
+int
+netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
+		    struct netxen_port *port)
+{
+	struct netxen_nic_ioctl_data data;
+	struct netxen_nic_ioctl_data *up_data;
+	int retval = 0;
+	struct netxen_statistics netxen_stats;
+
+	up_data = (void *)u_data;
+
+	DPRINTK(INFO, "doing ioctl for %p\n", adapter);
+	if (copy_from_user(&data, up_data, sizeof(data))) {
+		/* evil user tried to crash the kernel */
+		DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data));
+		retval = -EFAULT;
+		goto error_out;
+	}
+
+	/* Shouldn't access beyond legal limits of  "char u[64];" member */
+	if (!data.ptr && (data.size > sizeof(data.u))) {
+		/* evil user tried to crash the kernel */
+		DPRINTK(ERR, "bad size: %d\n", data.size);
+		retval = -EFAULT;
+		goto error_out;
+	}
+
+	switch (data.cmd) {
+	case netxen_nic_cmd_pci_read:
+		if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
+						    &(data.u), data.size)))
+			goto error_out;
+		if (copy_to_user((void *)&(up_data->u), &(data.u), data.size)) {
+			DPRINTK(ERR, "bad copy to userland: %d\n",
+				(int)sizeof(data));
+			retval = -EFAULT;
+			goto error_out;
+		}
+		data.rv = 0;
+		break;
+
+	case netxen_nic_cmd_pci_write:
+		data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u),
+						 data.size);
+		break;
+
+	case netxen_nic_cmd_pci_mem_read:
+		DPRINTK(INFO, "doing %s for %p\n",
+			"netxen_nic_cmd_pci_mm_rd", adapter);
+		netxen_nic_pci_mem_read(adapter, data.off, &(data.u),
+					data.size);
+		if (copy_to_user((void *)&(up_data->u), &(data.u), data.size)) {
+			DPRINTK(ERR, "bad copy to userland: %d\n",
+				(int)sizeof(data));
+			retval = -EFAULT;
+			goto error_out;
+		}
+		data.rv = 0;
+		DPRINTK(INFO, "read %lx\n", (unsigned long)data.u);
+		break;
+
+	case netxen_nic_cmd_pci_mem_write:
+		netxen_nic_pci_mem_write(adapter, data.off, &(data.u),
+					 data.size);
+		data.rv = 0;	/* write always succeeds */
+		break;
+
+	case netxen_nic_cmd_pci_config_read:
+		switch (data.size) {
+		case 1:
+			data.rv = pci_read_config_byte(adapter->ahw.pdev,
+						       data.off,
+						       (char *)&(data.u));
+			break;
+		case 2:
+			data.rv = pci_read_config_word(adapter->ahw.pdev,
+						       data.off,
+						       (short *)&(data.u));
+			break;
+		case 4:
+			data.rv = pci_read_config_dword(adapter->ahw.pdev,
+							data.off,
+							(u32 *) & (data.u));
+			break;
+		}
+		if (copy_to_user((void *)&(up_data->u), &(data.u), data.size)) {
+			DPRINTK(ERR, "bad copy to userland: %d\n",
+				(int)sizeof(data));
+			retval = -EFAULT;
+			goto error_out;
+		}
+		break;
+
+	case netxen_nic_cmd_pci_config_write:
+		switch (data.size) {
+		case 1:
+			data.rv = pci_write_config_byte(adapter->ahw.pdev,
+							data.off,
+							*(char *)&(data.u));
+			break;
+		case 2:
+			data.rv = pci_write_config_word(adapter->ahw.pdev,
+							data.off,
+							*(short *)&(data.u));
+			break;
+		case 4:
+			data.rv = pci_write_config_dword(adapter->ahw.pdev,
+							 data.off,
+							 *(u32 *) & (data.u));
+			break;
+		}
+		break;
+
+	case netxen_nic_cmd_get_stats:
+		data.rv =
+		    netxen_nic_fill_statistics(adapter, port, &netxen_stats);
+		if (copy_to_user
+		    ((void *)(up_data->ptr), (void *)&netxen_stats,
+		     sizeof(struct netxen_statistics))) {
+			DPRINTK(ERR, "bad copy to userland: %d\n",
+				(int)sizeof(netxen_stats));
+			retval = -EFAULT;
+			goto error_out;
+		}
+		up_data->rv = data.rv;
+		break;
+
+	case netxen_nic_cmd_clear_stats:
+		data.rv = netxen_nic_clear_statistics(adapter, port);
+		up_data->rv = data.rv;
+		break;
+
+	case netxen_nic_cmd_get_version:
+		if (copy_to_user
+		    ((void *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID,
+		     sizeof(NETXEN_NIC_LINUX_VERSIONID))) {
+			DPRINTK(ERR, "bad copy to userland: %d\n",
+				(int)sizeof(data));
+			retval = -EFAULT;
+			goto error_out;
+		}
+		break;
+
+	default:
+		DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter);
+		retval = -EOPNOTSUPP;
+		goto error_out;
+	}
+	put_user(data.rv, &(up_data->rv));
+	DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
+
+      error_out:
+	return retval;
+}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 7/9] NetXen: ioctl interface and intr routines
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
                   ` (5 preceding siblings ...)
  2006-07-05 13:40 ` [PATCH 2.6.17 6/9] NetXen: hw initialization routines Linsys Contractor Amit S. Kale
@ 2006-07-05 13:42 ` Linsys Contractor Amit S. Kale
  2006-07-05 13:44 ` [PATCH 2.6.17 8/9] NetXen: Driver main file Linsys Contractor Amit S. Kale
  2006-07-05 13:47 ` [PATCH 2.6.17 9/9] NetXen: niu handling and CRB reg definitions Linsys Contractor Amit S. Kale
  8 siblings, 0 replies; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:42 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_ioctl.h linux-2.6.17/drivers/net/netxen/netxen_nic_ioctl.h
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_ioctl.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_ioctl.h	2006-07-05 01:18:40.360907880 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef __NETXEN_NIC_IOCTL_H__
+#define __NETXEN_NIC_IOCTL_H__
+
+#include <linux/sockios.h>
+
+#define NETXEN_CMD_START        SIOCDEVPRIVATE
+#define NETXEN_NIC_CMD          (NETXEN_CMD_START + 1)
+#define NETXEN_NIC_NAME         (NETXEN_CMD_START + 2)
+
+typedef enum {
+	netxen_nic_cmd_none = 0,
+	netxen_nic_cmd_pci_read,
+	netxen_nic_cmd_pci_write,
+	netxen_nic_cmd_pci_mem_read,
+	netxen_nic_cmd_pci_mem_write,
+	netxen_nic_cmd_pci_config_read,
+	netxen_nic_cmd_pci_config_write,
+	netxen_nic_cmd_get_stats,
+	netxen_nic_cmd_clear_stats,
+	netxen_nic_cmd_get_version
+} netxen_nic_ioctl_cmd_t;
+
+struct netxen_nic_ioctl_data {
+	u32 cmd;
+	u32 unused1;
+	u64 off;
+	u32 size;
+	u32 rv;
+	char u[64];
+	void *ptr;
+};
+
+struct netxen_statistics {
+	u64 rx_packets;
+	u64 tx_packets;
+	u64 rx_bytes;
+	u64 rx_errors;
+	u64 tx_bytes;
+	u64 tx_errors;
+	u64 rx_crc_errors;
+	u64 rx_short_length_error;
+	u64 rx_long_length_error;
+	u64 rx_mac_errors;
+};
+
+#endif				/* __NETXEN_NIC_IOCTL_H_ */
diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_isr.c linux-2.6.17/drivers/net/netxen/netxen_nic_isr.c
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_isr.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_isr.c	2006-07-05 01:18:40.367906446 -0700
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+
+#include "netxen_nic.h"
+#include "netxen_nic_hw.h"
+#include "netxen_nic_phan_reg.h"
+
+/*
+ * This will be called when all the ports of the adapter are removed.
+ * This will cleanup and disable interrupts and irq.
+ */
+void netxen_nic_down(struct netxen_port *port)
+{
+	struct netxen_adapter *adapter = port->adapter;
+	int i, j, ctxid;
+	struct netxen_cmd_buffer *cmd_buff;
+	struct netxen_skb_frag *buffrag;
+	struct netxen_ring_context *ctx;
+
+	/* disable phy_ints */
+	netxen_nic_disable_phy_interrupts(adapter, (long)port->portnum);
+
+	adapter->active_ports--;
+
+	if (!adapter->active_ports) {
+		read_lock(&adapter->adapter_lock);
+		netxen_nic_disable_int(adapter);
+		read_unlock(&adapter->adapter_lock);
+
+		for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+			ctx = &adapter->ring_ctx[ctxid];
+			cmd_buff = ctx->cmd_buf_arr;
+
+			for (i = 0; i < ctx->max_tx_desc_count; i++) {
+				buffrag = cmd_buff->frag_array;
+				if (buffrag->dma) {
+					pci_unmap_single(port->pdev,
+							 buffrag->dma,
+							 buffrag->length,
+							 PCI_DMA_TODEVICE);
+					buffrag->dma = (u64) NULL;
+				}
+				for (j = 1; j < cmd_buff->frag_count; j++) {
+					buffrag++;
+					if (buffrag->dma) {
+						pci_unmap_page(port->pdev,
+							       buffrag->dma,
+							       buffrag->length,
+							       PCI_DMA_TODEVICE);
+						buffrag->dma = (u64) NULL;
+					}
+				}
+				/* Free the skb we received in
+				   netxen_nic_xmit_frame */
+				if (cmd_buff->skb) {
+					dev_kfree_skb_any(cmd_buff->skb);
+					cmd_buff->skb = NULL;
+				}
+				cmd_buff++;
+			}
+		}
+	}
+	del_timer_sync(&adapter->watchdog_timer);
+}
+
+int netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct netxen_port *port = netdev_priv(netdev);
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev)) {
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+		netxen_nic_down(port);
+	}
+
+	return 0;
+}
+
+int netxen_nic_resume(struct pci_dev *pdev)
+{
+	u32 ret;
+	struct net_device *netdev = pci_get_drvdata(pdev);
+
+	ret = pci_enable_device(pdev);
+	netif_device_attach(netdev);
+	return ret;
+}
+
+/*
+ * netxen_nic_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ */
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+	struct net_device_stats *stats = &port->net_stats;
+
+	memset(stats, 0, sizeof(*stats));
+
+	/* total packets received   */
+	stats->rx_packets = port->stats.no_rcv;
+	/* total packets transmitted    */
+	stats->tx_packets = port->stats.xmitedframes + port->stats.xmitfinished;
+	/* total bytes received     */
+	stats->rx_bytes = port->stats.rxbytes;
+	/* total bytes transmitted  */
+	stats->tx_bytes = port->stats.txbytes;
+	/* bad packets received     */
+	stats->rx_errors = port->stats.rcvdbadskb;
+	/* packet transmit problems */
+	stats->tx_errors = port->stats.nocmddescriptor;
+	/* no space in linux buffers    */
+	stats->rx_dropped = port->stats.updropped;
+	/* no space available in linux  */
+	stats->tx_dropped = port->stats.txdropped;
+
+	return stats;
+}
+
+long netxen_nic_enable_phy_interrupts(struct netxen_adapter *adapter,
+				      long portno)
+{
+	long result = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		result = netxen_niu_gbe_enable_phy_interrupts(adapter, portno);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		result = -1;
+	}
+
+	return result;
+}
+
+long netxen_nic_disable_phy_interrupts(struct netxen_adapter *adapter,
+				       long portno)
+{
+	long result = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		result = netxen_niu_gbe_disable_phy_interrupts(adapter, portno);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		result = -1;
+	}
+
+	return result;
+}
+
+long netxen_nic_clear_phy_interrupts(struct netxen_adapter *adapter,
+				     long portno)
+{
+	long result = 0;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		result = netxen_niu_gbe_clear_phy_interrupts(adapter, portno);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_ACTIVE_INT, -1);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+		result = -1;
+	}
+
+	return result;
+}
+
+void netxen_nic_set_mii_mode(struct netxen_adapter *adapter, long portno,
+			     long enable)
+{
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		netxen_niu_gbe_set_mii_mode(adapter, portno, enable);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
+		       netxen_nic_driver_name, __FUNCTION__);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+	}
+}
+
+void
+netxen_nic_set_gmii_mode(struct netxen_adapter *adapter, long portno,
+			 long enable)
+{
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		netxen_niu_gbe_set_gmii_mode(adapter, portno, enable);
+		break;
+
+	case NETXEN_NIC_XGBE:
+		printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
+		       netxen_nic_driver_name, __FUNCTION__);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: Unknown board type\n",
+		       netxen_nic_driver_name);
+	}
+}
+
+void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno,
+				 u32 link)
+{
+	struct netxen_port *pport = adapter->port[portno];
+	struct net_device *netdev = pport->netdev;
+
+	if (link)
+		netif_carrier_on(netdev);
+	else
+		netif_carrier_off(netdev);
+}
+
+void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
+			    u32 enable)
+{
+	u32 intr;
+	struct netxen_niu_phy_interrupt *int_src;
+	struct netxen_port *port;
+
+	/*  This should clear the interrupt source */
+	netxen_nic_phy_read(adapter, portno,
+			    NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, &intr);
+	if (intr == 0) {
+		DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
+		return;
+	}
+	int_src = (struct netxen_niu_phy_interrupt *)&intr;
+	netxen_nic_disable_phy_interrupts(adapter, portno);
+
+	port = adapter->port[portno];
+
+	if (int_src->jabber)
+		DPRINTK(INFO, "NetXen: %s Jabber interrupt \n",
+			port->netdev->name);
+
+	if (int_src->polarity_changed)
+		DPRINTK(INFO, "NetXen: %s POLARITY CHANGED int \n",
+			port->netdev->name);
+
+	if (int_src->energy_detect)
+		DPRINTK(INFO, "NetXen: %s ENERGY DETECT INT \n",
+			port->netdev->name);
+
+	if (int_src->downshift)
+		DPRINTK(INFO, "NetXen: %s DOWNSHIFT INT \n",
+			port->netdev->name);
+	/* write it down later.. */
+	if ((int_src->speed_changed) || (int_src->link_status_changed)) {
+		struct netxen_niu_phy_status status;
+
+		DPRINTK(INFO, "NetXen: %s SPEED CHANGED OR"
+			" LINK STATUS CHANGED \n", port->netdev->name);
+
+		if (netxen_nic_phy_read(adapter, portno,
+					NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+					(netxen_crbword_t *) & status) == 0) {
+			if (int_src->link_status_changed) {
+				if (status.link) {
+					netxen_niu_gbe_init_port(adapter,
+								 portno);
+					printk("%s: %s Link UP\n",
+					       netxen_nic_driver_name,
+					       port->netdev->name);
+
+				} else {
+					printk("%s: %s Link DOWN\n",
+					       netxen_nic_driver_name,
+					       port->netdev->name);
+				}
+				netxen_indicate_link_status(adapter, portno,
+							    status.link);
+			}
+		}
+	}
+	netxen_nic_enable_phy_interrupts(adapter, portno);
+}
+
+void netxen_nic_isr_other(struct netxen_adapter *adapter)
+{
+	u32 enable, portno;
+	u32 i2qhi;
+
+	/*
+	 * bit 3 is for i2qInt, if high its enabled
+	 * check for phy interrupts
+	 * read vector and check for bit 45 for phy
+	 * clear int by writing the same value into ISR_INT_VECTOR REG
+	 */
+
+	DPRINTK(INFO, "I2Q is the source of INT \n");
+
+	/* verify the offset */
+	read_lock(&adapter->adapter_lock);
+	i2qhi = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI));
+	read_unlock(&adapter->adapter_lock);
+
+	DPRINTK(INFO, "isr NETXEN_I2Q_CLR_PCI_HI = 0x%x \n", i2qhi);
+
+	if (i2qhi & 0x4000) {
+		for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) {
+			DPRINTK(INFO, "External PHY interrupt ON PORT %d\n",
+				portno);
+
+			enable = 1;
+			netxen_handle_port_int(adapter, portno, enable);
+		}
+
+		/* Clear the interrupt on I2Q */
+		read_lock(&adapter->adapter_lock);
+		writel((u32) i2qhi,
+		       NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI));
+		read_unlock(&adapter->adapter_lock);
+
+	}
+}
+
+void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+	u32 val, val1;
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		val = readl(NETXEN_CRB_NORMALIZE(adapter, ISR_INT_VECTOR));
+		if (val & 0x4) {
+			adapter->stats.otherints++;
+			netxen_nic_isr_other(adapter);
+		}
+		break;
+
+	case NETXEN_NIC_XGBE:
+		{
+			struct net_device *netdev = adapter->port[0]->netdev;
+
+			/* WINDOW = 1 */
+			read_lock(&adapter->adapter_lock);
+			val1 =
+			    readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+			read_unlock(&adapter->adapter_lock);
+
+			if (adapter->ahw.xg_linkup == 1 && val1 != XG_LINK_UP) {
+				printk(KERN_INFO "%s: %s NIC Link is down\n",
+				       netxen_nic_driver_name, netdev->name);
+				adapter->ahw.xg_linkup = 0;
+				/* read twice to clear sticky bits */
+				/* WINDOW = 0 */
+				netxen_nic_read_w0(adapter,
+						   NETXEN_NIU_XG_STATUS, &val1);
+				netxen_nic_read_w0(adapter,
+						   NETXEN_NIU_XG_STATUS, &val1);
+
+				if ((val1 & 0xffb) != 0xffb) {
+					printk(KERN_INFO
+					       "%s ISR: Sync/Align BAD: 0x%08x\n",
+					       netxen_nic_driver_name, val1);
+				}
+
+			} else if (adapter->ahw.xg_linkup == 0
+				   && val1 == XG_LINK_UP) {
+				printk(KERN_INFO "%s: %s NIC Link is up\n",
+				       netxen_nic_driver_name, netdev->name);
+				adapter->ahw.xg_linkup = 1;
+			}
+
+		}
+		break;
+
+	default:
+		printk(KERN_ERR "%s ISR: Unknown board type\n",
+		       netxen_nic_driver_name);
+	}
+}


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 8/9] NetXen: Driver main file.
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
                   ` (6 preceding siblings ...)
  2006-07-05 13:42 ` [PATCH 2.6.17 7/9] NetXen: ioctl interface and intr routines Linsys Contractor Amit S. Kale
@ 2006-07-05 13:44 ` Linsys Contractor Amit S. Kale
  2006-07-05 13:47 ` [PATCH 2.6.17 9/9] NetXen: niu handling and CRB reg definitions Linsys Contractor Amit S. Kale
  8 siblings, 0 replies; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:44 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_main.c linux-2.6.17/drivers/net/netxen/netxen_nic_main.c
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_main.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_main.c	2006-07-05 01:18:40.368906241 -0700
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ *  Main source file for NetXen NIC Driver on Linux
+ *
+ */
+
+#include "netxen_nic.h"
+
+#define DEFINE_GLOBAL_RECV_CRB
+#include "netxen_nic_phan_reg.h"
+#include "netxen_nic_ioctl.h"
+
+MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
+
+char netxen_nic_driver_name[] = "netxen";
+char netxen_nic_driver_string[] = "NetXen Network Driver version "
+    NETXEN_NIC_LINUX_VERSIONID
+    "-" NETXEN_NIC_BUILD_NO " generated " NETXEN_NIC_TIMESTAMP;
+
+#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_ADAPTER_UP_MAGIC 777
+
+static int netxen_nic_probe_err = 0;
+
+/* Local functions to NetXen NIC driver */
+static int __devinit netxen_nic_probe(struct pci_dev *pdev,
+				      const struct pci_device_id *ent);
+static void __devexit netxen_nic_remove(struct pci_dev *pdev);
+static int netxen_nic_open(struct net_device *netdev);
+static int netxen_nic_close(struct net_device *netdev);
+static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
+static void netxen_tx_timeout(struct net_device *netdev);
+static void netxen_tx_timeout_task(struct net_device *netdev);
+static void netxen_watchdog(unsigned long);
+static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
+static int netxen_nic_ioctl(struct net_device *netdev,
+			    struct ifreq *ifr, int cmd);
+static int netxen_nic_poll(struct net_device *dev, int *budget);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void netxen_nic_poll_controller(struct net_device *netdev);
+#endif
+static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs);
+
+/*  PCI Device ID Table  */
+static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
+	NETXEN_PCI_ID(PCI_DEVICE_ID_NX_QG),
+	NETXEN_PCI_ID(PCI_DEVICE_ID_NX_XG),
+	NETXEN_PCI_ID(PCI_DEVICE_ID_NX_CX4),
+	NETXEN_PCI_ID(PCI_DEVICE_ID_NX_IMEZ),
+	NETXEN_PCI_ID(PCI_DEVICE_ID_NX_HMEZ),
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
+
+struct netxen_adapter *adapterlist[MAX_NUM_CARDS];
+
+/*
+ * netxen_nic_probe()
+ *
+ * Linux system will invoke this after identifying the vendor ID and device Id
+ * in the pci_tbl where this module will search for NetXen vendor and device ID for
+ * quad port adapter.
+ *
+ * Even though there are 4 seperate devices (functions) on the quad port NIC, but
+ * the probe will be invoked for the first device (function) only. This will
+ * initialize the adapter, and setup the global parameters along with the port's
+ * specific structure.
+ */
+static int __devinit
+netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct net_device *netdev = NULL;
+	struct netxen_adapter *adapter = NULL;
+	struct netxen_port *port = NULL;
+	u8 *mem_ptr = NULL;
+	u8 *db_ptr = NULL;
+	unsigned long mem_base, mem_len, db_base, db_len;
+	int pci_using_dac, i, err;
+	int boardno = 0;
+	int ring;
+	struct netxen_recv_context *recv_ctx = NULL;
+	struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+	struct netxen_cmd_buffer *cmd_buf_arr[MAX_RING_CTX] = { NULL };
+	struct netxen_ring_context *ctx;
+	static int netxen_cards_found = 0;
+	u64 mac_addr[FLASH_NUM_PORTS + 1];
+	int valid_mac;
+
+	if ((err = pci_enable_device(pdev))) {
+		netxen_nic_probe_err = err;
+		return err;
+	}
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		err = -ENODEV;
+		goto err_out_disable_pdev;
+	}
+
+	if ((err = pci_request_regions(pdev, netxen_nic_driver_name)))
+		goto err_out_disable_pdev;
+
+	pci_set_master(pdev);
+	if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) &&
+	    (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0))
+		pci_using_dac = 1;
+	else {
+		if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
+		    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
+			goto err_out_free_res;
+
+		pci_using_dac = 0;
+	}
+
+	/* remap phys address */
+	mem_base = pci_resource_start(pdev, 0);	/* 0 is for BAR 0 */
+	mem_len = pci_resource_len(pdev, 0);
+
+	/* 128 Meg of memory */
+	mem_ptr = ioremap(mem_base, NETXEN_PCI_MAPSIZE_BYTES);
+	if (mem_ptr == 0UL) {
+		printk(KERN_ERR "%s: Cannot ioremap adapter memory aborting."
+		       ":%p\n", netxen_nic_driver_name, mem_ptr);
+		err = -EIO;
+		goto err_out_free_res;
+	}
+	db_base = pci_resource_start(pdev, 4);	/* doorbell is on bar 4 */
+	db_len = pci_resource_len(pdev, 4);
+
+	if (db_len == 0) {
+		printk(KERN_ERR "%s: doorbell is disabled\n",
+		       netxen_nic_driver_name);
+		err = -EIO;
+		goto err_out_free_res;
+	}
+
+	DPRINTK(1, INFO, "doorbell ioremap from %lx a size of %lx\n", db_base,
+		db_len);
+
+	db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
+	if (db_ptr == 0UL) {
+		printk(KERN_ERR "%s: Failed to allocate doorbell map.",
+		       netxen_nic_driver_name);
+		err = -EIO;
+		goto err_out_free_res;
+	}
+	DPRINTK(1, INFO, "doorbell ioremaped at %p\n", db_ptr);
+
+/*
+ *      Allocate a adapter structure which will manage all the initialization
+ *      as well as the common resources for all ports...
+ *      all the ports will have pointer to this adapter as well as Adapter
+ *      will have pointers of all the ports structures.
+ */
+
+	/* One adapter structure for all 4 ports....   */
+	adapter = kzalloc(sizeof(struct netxen_adapter), GFP_KERNEL);
+	if (adapter == NULL) {
+		printk(KERN_ERR "%s: Could not allocate adapter memory:%d\n",
+		       netxen_nic_driver_name,
+		       (int)sizeof(struct netxen_adapter));
+		err = -ENOMEM;
+		goto err_out_iounmap;
+	}
+
+	netxen_check_options(adapter);
+	for (i = 0; i < MAX_RING_CTX; i++) {
+		cmd_buf_arr[i] =
+		    (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE(i));
+		if (cmd_buf_arr[i] == NULL) {
+			printk(KERN_ERR "%s: Failed to allocate memory for the"
+			       "device block.Check system memory resource "
+			       "usage.\n", netxen_nic_driver_name);
+			err = -ENOMEM;
+			goto err_out_free_adapter;
+		}
+		memset(cmd_buf_arr[i], 0, TX_RINGSIZE(i));
+	}
+
+	for (i = 0; i < MAX_RING_CTX; ++i) {
+		ctx = &adapter->ring_ctx[i];
+		recv_ctx = &ctx->recv_ctx;
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			rcv_desc = &recv_ctx->rcv_desc[ring];
+			switch (RCV_DESC_TYPE(ring)) {
+			case RCV_DESC_NORMAL:
+				rcv_desc->max_rx_desc_count =
+				    ctx->max_rx_desc_count;
+				rcv_desc->flags = RCV_DESC_NORMAL;
+				rcv_desc->dma_size = RX_DMA_MAP_LEN;
+				rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH;
+				break;
+
+			case RCV_DESC_JUMBO:
+				rcv_desc->max_rx_desc_count =
+				    ctx->max_jumbo_rx_desc_count;
+				rcv_desc->flags = RCV_DESC_JUMBO;
+				rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN;
+				rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
+				break;
+
+			default:
+				printk("%s: netxen_nic_probe: bad receive "
+				       "descriptor type %d\n",
+				       netxen_nic_driver_name,
+				       RCV_DESC_TYPE(ring));
+				break;
+			}
+			rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
+			    pci_alloc_consistent(pdev,
+						 RCV_BUFFSIZE,
+						 &rcv_desc->rx_buf_phys);
+
+			if (rcv_desc->rx_buf_arr == NULL) {
+				err = -ENOMEM;
+				goto err_out_free_rx_buffer;
+			}
+			memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE);
+		}
+
+	}
+
+	for (i = 0; i < MAX_RING_CTX; ++i) {
+		ctx = &adapter->ring_ctx[i];
+		ctx->cmd_buf_arr = cmd_buf_arr[i];
+	}
+	adapter->ahw.pci_base = (unsigned long)mem_ptr;
+	adapter->ahw.pci_len = mem_len;
+	adapter->ahw.crb_base = adapter->ahw.pci_base + NETXEN_PCI_CRBSPACE;
+	adapter->ahw.db_base = (unsigned long)db_ptr;
+	adapter->ahw.db_len = db_len;
+	rwlock_init(&adapter->adapter_lock);
+	spin_lock_init(&adapter->tx_lock);
+	spin_lock_init(&adapter->lock);
+	initialize_adapter_sw(adapter);	/* initialize the buffers in adapter */
+	/*
+	 * Set the CRB window to invalid. If any register in window 0 is
+	 * accessed it should set the window to 0 and then reset it to 1.
+	 */
+	adapter->curr_window = 255;
+	/*
+	 *  Adapter in our case is quad port so initialize it beofore
+	 *  initializing the ports
+	 */
+	initialize_adapter_hw(adapter);	/* initialize the adapter */
+	adapter->port = kcalloc(adapter->ahw.max_ports,
+				sizeof(struct netxen_adapter), GFP_KERNEL);
+	if (adapter->port == NULL) {
+		err = -ENOMEM;
+		goto err_out_free_rx_buffer;
+	}
+	init_timer(&adapter->watchdog_timer);
+	adapter->ahw.xg_linkup = 0;
+	adapter->watchdog_timer.function = &netxen_watchdog;
+	adapter->watchdog_timer.data = (unsigned long)adapter;
+	INIT_WORK(&adapter->watchdog_task,
+		  (void (*)(void *))netxen_watchdog_task, adapter);
+	adapter->ahw.vendor_id = pdev->vendor;
+	adapter->ahw.device_id = pdev->device;
+	adapter->ahw.pdev = pdev;
+	for (i = 0; i < MAX_RING_CTX; i++) {
+		adapter->ring_ctx[i].proc_cmd_buf_counter = 0;
+	}
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id);
+	pci_read_config_word(pdev, PCI_COMMAND, &adapter->ahw.pci_cmd_word);
+
+	if (pci_enable_msi(pdev)) {
+		adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
+		printk(KERN_WARNING "%s: unable to allocate MSI interrupt"
+		       " error\n", netxen_nic_driver_name);
+	} else
+		adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+
+	if (is_flash_supported(adapter) == 0 &&
+	    get_flash_mac_addr(adapter, mac_addr) == 0)
+		valid_mac = 1;
+	else
+		valid_mac = 0;
+
+	/* initialize the all the ports */
+
+	for (i = 0; i < adapter->ahw.max_ports; i++) {
+		netdev = alloc_etherdev(sizeof(struct netxen_port));
+		if (netdev) {
+			printk(KERN_ERR "%s: could not allocate netdev for port"
+			       " %d\n", netxen_nic_driver_name, i + 1);
+			goto err_out_free_dev;
+		}
+
+		SET_MODULE_OWNER(netdev);
+
+		port = netdev_priv(netdev);
+		port->netdev = netdev;
+		port->pdev = pdev;
+		port->adapter = adapter;
+		port->portnum = i;	/* Gigabit port number starting from 0-3 */
+		port->flags &= ~NETXEN_NETDEV_STATUS;
+
+		netdev->open = netxen_nic_open;
+		netdev->stop = netxen_nic_close;
+		netdev->hard_start_xmit = netxen_nic_xmit_frame;
+		netdev->get_stats = netxen_nic_get_stats;
+		netdev->set_multicast_list = netxen_nic_set_multi;
+		netdev->set_mac_address = netxen_nic_set_mac;
+		netdev->change_mtu = netxen_nic_change_mtu;
+		netdev->do_ioctl = netxen_nic_ioctl;
+		netdev->tx_timeout = netxen_tx_timeout;
+
+		SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
+
+		netdev->irq = pdev->irq;
+		netdev->poll = netxen_nic_poll;
+		netdev->weight = NETXEN_NETDEV_WEIGHT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+		netdev->poll_controller = netxen_nic_poll_controller;
+#endif
+		/* ScatterGather support */
+		netdev->features = NETIF_F_SG;
+		netdev->features |= NETIF_F_IP_CSUM;
+		netdev->features |= NETIF_F_TSO;
+
+		if (pci_using_dac)
+			netdev->features |= NETIF_F_HIGHDMA;
+
+		boardno = netxen_nic_get_board_num(adapter);
+		if (valid_mac) {
+			unsigned char *p = (unsigned char *)&mac_addr[i];
+			netdev->dev_addr[0] = *(p + 5);
+			netdev->dev_addr[1] = *(p + 4);
+			netdev->dev_addr[2] = *(p + 3);
+			netdev->dev_addr[3] = *(p + 2);
+			netdev->dev_addr[4] = *(p + 1);
+			netdev->dev_addr[5] = *(p + 0);
+
+			memcpy(netdev->perm_addr, netdev->dev_addr,
+				netdev->addr_len); 
+			if (!is_valid_ether_addr(netdev->perm_addr)) {
+				printk(KERN_ERR "%s: Bad MAC address "
+					"%02x:%02x:%02x:%02x:%02x:%02x.\n",
+				       netxen_nic_driver_name,
+				       netdev->dev_addr[0],
+				       netdev->dev_addr[1],
+				       netdev->dev_addr[2],
+				       netdev->dev_addr[3],
+				       netdev->dev_addr[4],
+				       netdev->dev_addr[5]);
+			} else {
+				netxen_nic_macaddr_set(port, netdev->dev_addr);
+			}
+		}
+		INIT_WORK(adapter->tx_timeout_task + i,
+			  (void (*)(void *))netxen_tx_timeout_task, netdev);
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+
+		if ((err = register_netdev(netdev))) {
+			printk(KERN_ERR "%s: register_netdev failed port #%d"
+			       " aborting\n", netxen_nic_driver_name, i + 1);
+			break;
+		}
+		adapter->active_ports = 0;
+		adapter->port_count++;	/* number of ports allocated */
+		adapter->port[i] = port;
+		pci_set_drvdata(pdev, port);
+	}
+
+	/*
+	 * check how many ports were configured. If due to some errors,
+	 * the port count == NULL, then free up the adapter structure,
+	 * do iounmap() else add the adapter to the global adapter list
+	 */
+
+	if (!adapter->port_count) {
+		/* unable to configure any port */
+		err = -EIO;
+		goto err_out_free_dev;
+	}
+
+	phantom_init(adapter);
+	/*
+	 * delay a while to ensure that the Pegs are up & running.
+	 * Otherwise, we might see some flaky behaviour.
+	 */
+	mdelay(1000);
+
+	switch (adapter->ahw.board_type) {
+	case NETXEN_BRDTYPE_P2_SB35_4G:
+		printk("%s: QUAD GbE board initialized\n",
+		       netxen_nic_driver_name);
+		break;
+
+	case NETXEN_BRDTYPE_P2_SB31_10G:
+	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+		printk("%s: XGbE board initialized\n", netxen_nic_driver_name);
+		break;
+	}
+
+	adapter->driver_mismatch = 0;
+
+	adapterlist[netxen_cards_found++] = adapter;
+	adapter->number = netxen_cards_found;
+	netxen_nic_probe_err = 0;
+	return 0;
+
+      err_out_free_dev:
+	for (port = pci_get_drvdata(pdev); port != NULL;) {
+		unregister_netdev(port->netdev);
+		free_netdev(port->netdev);
+		if (port->portnum <= 0)
+			break;
+		port = adapter->port[port->portnum - 1];
+	}
+	pci_set_drvdata(pdev, NULL);
+
+      err_out_free_rx_buffer:
+	for (i = 0; i < MAX_RING_CTX; ++i) {
+		ctx = &adapter->ring_ctx[i];
+		recv_ctx = &ctx->recv_ctx;
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			rcv_desc = &recv_ctx->rcv_desc[ring];
+			if (rcv_desc->rx_buf_arr != NULL) {
+				pci_free_consistent(pdev, RCV_BUFFSIZE,
+						    rcv_desc->rx_buf_arr,
+						    rcv_desc->rx_buf_phys);
+				rcv_desc->rx_buf_arr = NULL;
+			}
+		}
+	}
+
+	vfree(cmd_buf_arr);
+
+	kfree(adapter->port);
+
+      err_out_free_adapter:
+	for (i = 0; i < MAX_RING_CTX; i++) {
+		if (cmd_buf_arr[i] != NULL)
+			vfree(cmd_buf_arr[i]);
+	}
+
+	kfree(adapter);
+
+      err_out_iounmap:
+	iounmap((u8 *) mem_ptr);
+      err_out_free_res:
+	pci_release_regions(pdev);
+      err_out_disable_pdev:
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	netxen_nic_probe_err = err;
+	return err;
+}
+
+static void __devexit netxen_nic_remove(struct pci_dev *pdev)
+{
+	struct netxen_adapter *adapter;
+	struct netxen_port *port;
+	struct netxen_rx_buffer *buffer;
+	struct netxen_recv_context *recv_ctx;
+	struct netxen_rcv_desc_ctx *rcv_desc;
+	struct netxen_ring_context *ctx;
+	int i;
+	int ctxid, ring;
+
+	port = pci_get_drvdata(pdev);
+	if (port == NULL || port->netdev == NULL)
+		return;
+	adapter = ((struct netxen_port *)(netdev_priv(port->netdev)))->adapter;
+	if (adapter == NULL)
+		return;
+
+	netxen_nic_stop_all_ports(adapter);
+	/* leave the hw in the same state as reboot */
+	pinit_from_rom(adapter, 0);
+	udelay(500);
+	load_firmware(adapter);
+
+	if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		read_lock(&adapter->adapter_lock);
+		netxen_nic_disable_int(adapter);
+		read_unlock(&adapter->adapter_lock);
+	}
+	udelay(500);		/* Delay for a while to drain the DMA engines */
+
+	port = pci_get_drvdata(pdev);
+	if (adapter->irq)
+		free_irq(adapter->irq, adapter);
+	if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
+		pci_disable_msi(pdev);
+	while (port != NULL) {
+		unregister_netdev(port->netdev);
+		free_netdev(port->netdev);
+		if (port->portnum <= 0)
+			break;
+		port = adapter->port[port->portnum - 1];
+	}
+	pci_set_drvdata(pdev, NULL);
+
+	netxen_free_hw_resources(adapter);
+
+	iounmap((u8 *) adapter->ahw.pci_base);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+
+	for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+		ctx = &adapter->ring_ctx[ctxid];
+		recv_ctx = &ctx->recv_ctx;
+		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+			rcv_desc = &recv_ctx->rcv_desc[ring];
+			for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) {
+				buffer = &(rcv_desc->rx_buf_arr[i]);
+				if (buffer->state == NETXEN_BUFFER_FREE)
+					continue;
+				pci_unmap_single(pdev, buffer->dma,
+						 rcv_desc->dma_size,
+						 PCI_DMA_FROMDEVICE);
+				if (buffer->skb != NULL)
+					dev_kfree_skb_any(buffer->skb);
+			}
+			pci_free_consistent(pdev, RCV_BUFFSIZE,
+					    rcv_desc->rx_buf_arr,
+					    rcv_desc->rx_buf_phys);
+		}
+		vfree(ctx->cmd_buf_arr);
+	}
+
+	kfree(adapter->port);
+	kfree(adapter);
+}
+
+/*
+ * Called when a network interface is made active
+ * @returns 0 on success, negative value on failure
+ */
+static int netxen_nic_open(struct net_device *netdev)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+	struct netxen_adapter *adapter = port->adapter;
+	int err = 0;
+	int ctxid, ring;
+	static int opencount = 0;
+
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
+	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
+		err = init_firmware(adapter);
+		if (err != 0) {
+			printk(KERN_ERR "Failed to init firmware\n");
+			module_put(THIS_MODULE);
+			return -EIO;
+		}
+		netxen_nic_flash_print(adapter);
+
+		printk("NetXen adapter %d\n", opencount);
+		adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
+		/* setup all the resources for the Phantom... */
+		/* this include the descriptors for rcv, tx, and status */
+		netxen_nic_clear_stats(adapter);
+		err = netxen_nic_hw_resources(adapter);
+		if (err) {
+			printk(KERN_ERR "Error in setting hw resources:%d\n",
+			       err);
+			module_put(THIS_MODULE);
+			return err;
+		}
+		if (netxen_nic_init_port(port) != 0) {
+			printk(KERN_ERR "%s: Failed to initialize port %d\n",
+			       netxen_nic_driver_name, port->portnum);
+			module_put(THIS_MODULE);
+			netxen_free_hw_resources(adapter);
+			return -EIO;
+		}
+		netxen_nic_init_niu(adapter);
+		for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+			for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+				netxen_post_rx_buffers(adapter, ctxid, ring);
+			}
+		}
+
+		err = request_irq(netdev->irq, &netxen_intr,
+				  SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
+				  adapter);
+		if (err) {
+			printk(KERN_ERR "request_irq failed with: %d\n", err);
+			netxen_free_hw_resources(adapter);
+			module_put(THIS_MODULE);
+			return err;
+		}
+		adapter->irq = netdev->irq;
+		mod_timer(&adapter->watchdog_timer, jiffies);
+	}
+	++opencount;
+	adapter->active_ports++;
+	if (adapter->active_ports == 1) {
+		read_lock(&adapter->adapter_lock);
+		netxen_nic_enable_int(adapter);
+		read_unlock(&adapter->adapter_lock);
+	}
+
+	spin_lock_init(&port->stats_lock);
+
+	/* Done here again so that even if phantom sw overwrote it,
+	   we set it */
+	netxen_nic_macaddr_set(port, netdev->dev_addr);
+	netxen_nic_set_link_parameters(port);
+
+	netxen_nic_set_multi(netdev);
+	if (!adapter->driver_mismatch)
+		netif_start_queue(netdev);
+
+	return 0;
+}
+
+/**
+ * netxen_nic_close - Disables a network interface entry point
+ **/
+static int netxen_nic_close(struct net_device *netdev)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	netxen_nic_down(port);
+
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+	unsigned int nr_frags = 0;
+	struct netxen_adapter *adapter = port->adapter;
+	struct pci_dev *pdev;
+	unsigned int first_seg_len = skb->len - skb->data_len;
+	struct netxen_skb_frag *buffrag;
+	unsigned int i;
+	int ctxid = 0;
+	u32 producer = 0;
+	u32 saved_producer = 0;
+	struct cmd_desc_type0_t *hwdesc;
+	int k;
+	struct netxen_cmd_buffer *pbuf = NULL;
+	unsigned int tries = 0;
+	static int dropped_packet = 0;
+	struct netxen_skb_frag *frag;
+	int frag_count;
+	u32 local_producer = 0;
+	u32 max_tx_desc_count = 0;
+	u32 last_cmd_consumer = 0;
+	struct netxen_ring_context *ctx = &adapter->ring_ctx[0];
+	struct netxen_hardware_ring_context *hw_ring_ctx = &(ctx->hw_ring_ctx);
+	int no_of_desc;
+
+	port->stats.xmitcalled++;
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	frag_count = 1 + nr_frags;
+
+	if (unlikely(skb->len <= 0)) {
+		dev_kfree_skb_any(skb);
+		port->stats.badskblen++;
+		return 0;
+	}
+
+	if (frag_count > MAX_BUFFERS_PER_CMD) {
+		printk
+		    ("%s: %s netxen_nic_xmit_frame: frag_count (%d) too large, "
+		     "can handle only %d frags\n", netxen_nic_driver_name,
+		     netdev->name, frag_count, MAX_BUFFERS_PER_CMD);
+		goto drop_packet;
+	}
+
+	/*
+	 * Everything is set up. Now, we just need to transmit it out.
+	 * Note that we have to copy the contents of buffer over to
+	 * right place. Later on, this can be optimized out by de-coupling the
+	 * producer index from the buffer index.
+	 */
+      retry_getting_window:
+	spin_lock_bh(&adapter->tx_lock);
+	if (adapter->total_threads == MAX_XMIT_PRODUCERS) {
+		spin_unlock_bh(&adapter->tx_lock);
+		/*
+		 * Yield CPU
+		 */
+		if (!in_atomic())
+			schedule();
+		else {
+			for (i = 0; i < 20; i++)
+				cpu_relax();	/*This a nop instr on i386 */
+		}
+		goto retry_getting_window;
+	}
+	local_producer = ctx->cmd_producer;
+	/* There 4 fragments per descriptor */
+	no_of_desc = (frag_count + 3) >> 2;
+	if (skb_shinfo(skb)->tso_size > 0) {
+		no_of_desc++;
+		if (((skb->nh.iph)->ihl * sizeof(u32)) +
+		    ((skb->h.th)->doff * sizeof(u32)) +
+		    sizeof(struct ethhdr) >
+		    (sizeof(struct cmd_desc_type0_t) - NET_IP_ALIGN)) {
+			no_of_desc++;
+		}
+	}
+	k = ctx->cmd_producer;
+	max_tx_desc_count = ctx->max_tx_desc_count;
+	last_cmd_consumer = ctx->last_cmd_consumer;
+	if ((k + no_of_desc) >=
+	    ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
+	     last_cmd_consumer)) {
+		spin_unlock_bh(&adapter->tx_lock);
+		if (tries == 0) {
+			local_bh_disable();
+			for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+				netxen_process_cmd_ring((unsigned long)adapter,
+							ctxid);
+			}
+			local_bh_enable();
+			++tries;
+			goto retry_getting_window;
+		} else {
+			port->stats.nocmddescriptor++;
+			DPRINTK(ERR, "No command descriptors available,"
+				" producer = %d, consumer = %d count=%llu,"
+				" dropping packet\n", producer,
+				ctx->last_cmd_consumer,
+				port->stats.nocmddescriptor);
+			goto requeue_packet;
+		}
+	}
+	k = get_index_range(k, max_tx_desc_count, no_of_desc);
+	ctx->cmd_producer = k;
+	adapter->total_threads++;
+	adapter->num_threads++;
+
+	spin_unlock_bh(&adapter->tx_lock);
+	/* Copy the descriptors into the hardware    */
+	producer = local_producer;
+	saved_producer = producer;
+	hwdesc = &ctx->hw_ring_ctx.cmd_desc_head[producer];
+	memset(hwdesc, 0, sizeof(struct cmd_desc_type0_t));
+	/* Take skb->data itself */
+	pbuf = &ctx->cmd_buf_arr[producer];
+	if (skb_shinfo(skb)->tso_size > 0) {
+		pbuf->mss = skb_shinfo(skb)->tso_size;
+		hwdesc->mss = skb_shinfo(skb)->tso_size;
+	} else {
+		pbuf->mss = 0;
+		hwdesc->mss = 0;
+	}
+	pbuf->no_of_descriptors = no_of_desc;
+	pbuf->total_length = skb->len;
+	pbuf->skb = skb;
+	pbuf->cmd = TX_ETHER_PKT;
+	pbuf->frag_count = frag_count;
+	pbuf->port = port->portnum;
+	buffrag = &pbuf->frag_array[0];
+	buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len,
+				      PCI_DMA_TODEVICE);
+	buffrag->length = first_seg_len;
+	hwdesc->total_length = skb->len;
+	hwdesc->num_of_buffers = frag_count;
+	hwdesc->opcode = TX_ETHER_PKT;
+
+	hwdesc->port = port->portnum;
+	hwdesc->buffer1_length = first_seg_len;
+	hwdesc->addr_buffer1 = buffrag->dma;
+
+	for (i = 1, k = 1; i < frag_count; i++, k++) {
+		struct skb_frag_struct *frag;
+		int len, temp_len;
+		unsigned long offset;
+		dma_addr_t temp_dma;
+
+		/* move to next desc. if there is a need */
+		if ((i & 0x3) == 0) {
+			k = 0;
+			producer = get_next_index(producer,
+						  ctx->max_tx_desc_count);
+			hwdesc = &ctx->hw_ring_ctx.cmd_desc_head[producer];
+			memset(hwdesc, 0, sizeof(struct cmd_desc_type0_t));
+		}
+		frag = &skb_shinfo(skb)->frags[i - 1];
+		len = frag->size;
+		offset = frag->page_offset;
+
+		temp_len = len;
+		temp_dma = pci_map_page(port->pdev, frag->page, offset,
+					len, PCI_DMA_TODEVICE);
+
+		buffrag++;
+		buffrag->dma = temp_dma;
+		buffrag->length = temp_len;
+
+		DPRINTK(INFO, "for loop. i=%d k=%d\n", i, k);
+		switch (k) {
+		case 0:
+			hwdesc->buffer1_length = temp_len;
+			hwdesc->addr_buffer1 = temp_dma;
+			break;
+		case 1:
+			hwdesc->buffer2_length = temp_len;
+			hwdesc->addr_buffer2 = temp_dma;
+			break;
+		case 2:
+			hwdesc->buffer3_length = temp_len;
+			hwdesc->addr_buffer3 = temp_dma;
+			break;
+		case 3:
+			hwdesc->buffer4_length = temp_len;
+			hwdesc->addr_buffer4 = temp_dma;
+			break;
+		}
+		frag++;
+	}
+	producer = get_next_index(producer, ctx->max_tx_desc_count);
+
+	/* might change opcode to TX_TCP_LSO */
+	netxen_tso_check(adapter, &hw_ring_ctx->cmd_desc_head[saved_producer],
+			 skb);
+
+	/* For LSO, we need to copy the MAC/IP/TCP headers into
+	 * the descriptor ring
+	 */
+	if (hw_ring_ctx->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) {
+		int hdr_len, first_hdr_len, more_hdr;
+		hdr_len =
+		    hw_ring_ctx->cmd_desc_head[saved_producer].total_hdr_length;
+		if (hdr_len > (sizeof(struct cmd_desc_type0_t) - NET_IP_ALIGN)) {
+			first_hdr_len =
+			    sizeof(struct cmd_desc_type0_t) - NET_IP_ALIGN;
+			more_hdr = 1;
+		} else {
+			first_hdr_len = hdr_len;
+			more_hdr = 0;
+		}
+		/* copy the MAC/IP/TCP headers to the cmd descriptor list */
+		hwdesc = &hw_ring_ctx->cmd_desc_head[producer];
+
+		/* copy the first 64 bytes */
+		memcpy(((void *)hwdesc) + NET_IP_ALIGN,
+		       (void *)(skb->data), first_hdr_len);
+		producer = get_next_index(producer, max_tx_desc_count);
+
+		if (more_hdr) {
+			hwdesc = &hw_ring_ctx->cmd_desc_head[producer];
+			/* copy the next 64 bytes - should be enough except
+			 * for pathological case
+			 */
+			memcpy((void *)hwdesc, (void *)(skb->data) +
+			       first_hdr_len, hdr_len - first_hdr_len);
+			producer = get_next_index(producer, max_tx_desc_count);
+		}
+	}
+	spin_lock_bh(&adapter->tx_lock);
+	port->stats.txbytes +=
+	    hw_ring_ctx->cmd_desc_head[saved_producer].total_length;
+	/* Code to update the adapter considering how many producer threads
+	   are currently working */
+	if ((--adapter->num_threads) == 0) {
+		/* This is the last thread */
+		u32 crb_producer = ctx->cmd_producer;
+		struct ctx_msg msg = { 0 };
+		hw_ring_ctx->cmd_producer = ctx->cmd_producer;
+		msg.PegId = NETXEN_XMIT_PEG_DB_ID;
+		msg.Count = crb_producer;
+		msg.CtxId = 0;
+		msg.Opcode = NETXEN_CMD_PRODUCER;
+		read_lock(&adapter->adapter_lock);
+		writel(*(u32 *) & msg,
+		       DB_NORMALIZE(adapter, NETXEN_CMD_PRODUCER_OFFSET(0)));
+		read_unlock(&adapter->adapter_lock);
+
+		adapter->total_threads = 0;
+	} else {
+		u32 crb_producer = 0;
+		struct ctx_msg msg = { 0 };
+		read_lock(&adapter->adapter_lock);
+		*(u32 *) & msg =
+		    readl(DB_NORMALIZE(adapter, NETXEN_CMD_PRODUCER_OFFSET(0)));
+		read_unlock(&adapter->adapter_lock);
+		crb_producer = msg.Count;
+
+		if (crb_producer == local_producer) {
+			crb_producer = get_index_range(crb_producer,
+						       max_tx_desc_count,
+						       no_of_desc);
+			msg.PegId = NETXEN_XMIT_PEG_DB_ID;
+			msg.Count = crb_producer;
+			msg.CtxId = 0;
+			msg.Opcode = NETXEN_CMD_PRODUCER;
+			read_lock(&adapter->adapter_lock);
+			writel(*(u32 *) & msg,
+			       DB_NORMALIZE(adapter,
+					    NETXEN_CMD_PRODUCER_OFFSET(0)));
+			read_unlock(&adapter->adapter_lock);
+
+			hw_ring_ctx->cmd_producer = crb_producer;
+		}
+	}
+
+	port->stats.xmitfinished++;
+	spin_unlock_bh(&adapter->tx_lock);
+
+	netdev->trans_start = jiffies;
+
+	DPRINTK(INFO, "wrote CMD producer %x to phantom\n", producer);
+
+	DPRINTK(INFO, "Done. Send\n");
+	goto netxen_nic_xmit_success;
+
+      requeue_packet:
+	spin_lock_bh(&adapter->tx_lock);
+	netif_stop_queue(netdev);
+	port->flags |= NETXEN_NETDEV_STATUS;
+	spin_unlock_bh(&adapter->tx_lock);
+	return NETDEV_TX_BUSY;
+
+      drop_packet:
+	pbuf = &ctx->cmd_buf_arr[producer];
+	frag = &pbuf->frag_array[0];
+	pdev = port->pdev;
+	pci_unmap_single(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE);
+	for (i = 1; i < frag_count; i++) {
+		frag++;		/* Get the next frag */
+		pci_unmap_page(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE);
+	}
+
+	port->stats.txdropped++;
+	dev_kfree_skb_any(pbuf->skb);
+	pbuf->skb = NULL;
+	if ((++dropped_packet & 0xff) == 0xff)
+		printk("%s: %s droppped packets = %d\n", netxen_nic_driver_name,
+		       netdev->name, dropped_packet);
+
+      netxen_nic_xmit_success:
+	return NETDEV_TX_OK;
+}
+
+static void netxen_watchdog(unsigned long v)
+{
+	struct netxen_adapter *adapter = (struct netxen_adapter *)v;
+	schedule_work(&adapter->watchdog_task);
+}
+
+static void netxen_tx_timeout(struct net_device *netdev)
+{
+	struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+	struct netxen_adapter *adapter = port->adapter;
+
+	schedule_work(adapter->tx_timeout_task + port->portnum);
+}
+
+static void netxen_tx_timeout_task(struct net_device *netdev)
+{
+	struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+	unsigned long flags;
+
+	printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
+	       netxen_nic_driver_name, netdev->name);
+
+	spin_lock_irqsave(&port->adapter->lock, flags);
+	netxen_nic_close(netdev);
+	netxen_nic_open(netdev);
+	spin_unlock_irqrestore(&port->adapter->lock, flags);
+	netdev->trans_start = jiffies;
+	netif_wake_queue(netdev);
+}
+
+static int
+netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+	u32 ret = 0;
+
+	DPRINTK(INFO, "Entered handle ISR\n");
+
+	adapter->stats.ints++;
+
+	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		int count = 0;
+		u32 mask;
+		read_lock(&adapter->adapter_lock);
+		netxen_nic_disable_int(adapter);
+		/* Window = 0 or 1 */
+		do {
+			writel(0xffffffff, (void *)
+			       (adapter->ahw.pci_base + ISR_INT_TARGET_STATUS));
+			mask = readl((void *)
+				     (adapter->ahw.pci_base + ISR_INT_VECTOR));
+		} while (((mask & 0x80) != 0) && (++count < 32));
+		if ((mask & 0x80) != 0)
+			printk("Could not disable interrupt completely\n");
+
+		read_unlock(&adapter->adapter_lock);
+	}
+	adapter->stats.hostints++;
+
+	if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
+		if (netif_rx_schedule_prep(netdev)) {
+			/*
+			 * Interrupts are already disabled.
+			 */
+			__netif_rx_schedule(netdev);
+		} else {
+			static unsigned int intcount = 0;
+			if ((++intcount & 0xfff) == 0xfff)
+				printk(KERN_ERR
+				       "%s: %s interrupt %d while in poll\n",
+				       netxen_nic_driver_name, netdev->name,
+				       intcount);
+		}
+		ret = 1;
+	}
+
+	if (ret == 0) {
+		read_lock(&adapter->adapter_lock);
+		netxen_nic_enable_int(adapter);
+		read_unlock(&adapter->adapter_lock);
+	}
+
+	return ret;
+}
+
+/**
+ * netxen_intr - Interrupt Handler
+ * @irq: interrupt number
+ * data points to adapter stucture (which may be handling more than 1 port
+ **/
+irqreturn_t netxen_intr(int irq, void *data, struct pt_regs * regs)
+{
+	struct netxen_adapter *adapter;
+	struct netxen_port *port;
+	struct net_device *netdev;
+
+	if (unlikely(!irq)) {
+		return IRQ_NONE;	/* Not our interrupt */
+	}
+
+	adapter = (struct netxen_adapter *)data;
+	port = adapter->port[0];
+	netdev = port->netdev;
+
+	/* process our status queue (for all 4 ports) */
+	netxen_handle_int(adapter, netdev);
+
+	return IRQ_HANDLED;
+}
+
+static int netxen_nic_poll(struct net_device *netdev, int *budget)
+{
+	struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+	struct netxen_adapter *adapter = port->adapter;
+	int work_to_do = min(*budget, netdev->quota);
+	int done = 1;
+	int ctxid;
+	int this_work_done;
+
+	DPRINTK(INFO, "polling for %d descriptors\n", *budget);
+	port->stats.polled++;
+
+	adapter->work_done = 0;
+	for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+		/*
+		 * Fairness issue. This will give undue weight to the
+		 * receive context 0.
+		 */
+
+		/*
+		 * To avoid starvation, we give each of our receivers,
+		 * a fraction of the quota. Sometimes, it might happen that we
+		 * have enough quota to process every packet, but since all the
+		 * packets are on one context, it gets only half of the quota,
+		 * and ends up not processing it.
+		 */
+		this_work_done = netxen_process_rcv_ring(adapter, ctxid,
+							 work_to_do /
+							 MAX_RING_CTX);
+		adapter->work_done += this_work_done;
+	}
+
+	netdev->quota -= adapter->work_done;
+	*budget -= adapter->work_done;
+
+	if (adapter->work_done >= work_to_do
+	    && netxen_nic_rx_has_work(adapter) != 0)
+		done = 0;
+
+	for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
+		netxen_process_cmd_ring((unsigned long)adapter, ctxid);
+	}
+
+	DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
+		adapter->work_done, work_to_do);
+	if (done) {
+		netif_rx_complete(netdev);
+		read_lock(&adapter->adapter_lock);
+		netxen_nic_enable_int(adapter);
+		read_unlock(&adapter->adapter_lock);
+	}
+
+	return (done ? 0 : 1);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void netxen_nic_poll_controller(struct net_device *netdev)
+{
+	struct netxen_port *port = netdev_priv(netdev);
+	struct netxen_adapter *adapter = port->adapter;
+	disable_irq(netdev->irq);
+	netxen_intr(netdev->irq, adapter, NULL);
+	enable_irq(netdev->irq);
+}
+#endif
+
+/*
+ * netxen_nic_ioctl ()    We provide the tcl/phanmon support through these
+ * ioctls.
+ */
+static int
+netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	int err = 0;
+	struct netxen_port *port = netdev_priv(netdev);
+	struct netxen_adapter *adapter = port->adapter;
+
+	DPRINTK(INFO, "doing ioctl for %s\n", netdev->name);
+	switch (cmd) {
+	case NETXEN_NIC_CMD:
+		err = netxen_nic_do_ioctl(adapter, (void *)ifr->ifr_data, port);
+		break;
+
+	case NETXEN_NIC_NAME:
+		DPRINTK(INFO, "ioctl cmd for NetXen\n");
+		if (ifr->ifr_data) {
+			put_user(port->portnum, (u16 *) ifr->ifr_data);
+		}
+		break;
+
+	default:
+		DPRINTK(INFO, "ioctl cmd %x not supported\n", cmd);
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
+static struct pci_driver netxen_driver = {
+	.name = netxen_nic_driver_name,
+	.id_table = netxen_pci_tbl,
+	.probe = netxen_nic_probe,
+	.remove = __devexit_p(netxen_nic_remove),
+	.suspend = netxen_nic_suspend,
+	.resume = netxen_nic_resume
+};
+
+/* Driver Registration on NetXen card    */
+
+static int __init netxen_init_module(void)
+{
+	printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+
+	netxen_check_cmdline_params();
+	pci_module_init(&netxen_driver);
+
+	return netxen_nic_probe_err;
+}
+
+module_init(netxen_init_module);
+
+static void __exit netxen_exit_module(void)
+{
+	int i;
+	struct netxen_adapter *adapter;
+
+	for (i = 0; i < MAX_NUM_CARDS; i++) {
+		adapter = adapterlist[i];
+		if (adapter == NULL)
+			continue;
+		if (adapter->port != NULL && adapter->port[0]->netdev != NULL) {
+			read_lock(&adapter->adapter_lock);
+			netxen_nic_disable_int(adapter);
+			read_unlock(&adapter->adapter_lock);
+			pinit_from_rom(adapter, 0);
+		}
+	}
+
+	/*
+	 * Wait for some time to allow the dma to drain, if any.
+	 */
+	mdelay(5);
+	pci_unregister_driver(&netxen_driver);
+}
+
+module_exit(netxen_exit_module);


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2.6.17 9/9] NetXen: niu handling and CRB reg definitions
  2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
                   ` (7 preceding siblings ...)
  2006-07-05 13:44 ` [PATCH 2.6.17 8/9] NetXen: Driver main file Linsys Contractor Amit S. Kale
@ 2006-07-05 13:47 ` Linsys Contractor Amit S. Kale
  8 siblings, 0 replies; 17+ messages in thread
From: Linsys Contractor Amit S. Kale @ 2006-07-05 13:47 UTC (permalink / raw)
  To: netdev; +Cc: jeff, sanjeev, unmproj

diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_niu.c linux-2.6.17/drivers/net/netxen/netxen_nic_niu.c
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_niu.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_niu.c	2006-07-05 01:18:40.369906036 -0700
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ *
+ * Provides access to the Network Interface Unit h/w block.
+ *
+ */
+
+#include "netxen_nic.h"
+#include <linux/delay.h>
+
+/** 
+ * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ *       Individual phys are addressed as follows:
+ * @param phy  [15:8]  phy id
+ * @param reg  [7:0]   register number
+ *
+ * @returns  0 on success
+ *          -1 on error
+ *
+ **/
+long netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
+			     long reg, netxen_crbword_t * readval)
+{
+	long timeout = 0;
+	long result = 0;
+	long restore = 0;
+	struct netxen_niu_gb_mii_mgmt_address address;
+	struct netxen_niu_gb_mii_mgmt_command command;
+	struct netxen_niu_gb_mii_mgmt_indicators status;
+	struct netxen_niu_gb_mii_mgmt_config mii_cfg;
+	struct netxen_niu_gb_mac_config_0_t mac_cfg0;
+
+	/* MII mgmt all goes through port 0 MAC interface, so it cannot be in reset */
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+				  &mac_cfg0, 4))
+		return -EIO;
+	if (mac_cfg0.soft_reset) {
+		struct netxen_niu_gb_mac_config_0_t temp;
+		*(netxen_crbword_t *) & temp = 0;
+		temp.tx_reset_pb = 1;
+		temp.rx_reset_pb = 1;
+		temp.tx_reset_mac = 1;
+		temp.rx_reset_mac = 1;
+		if (netxen_nic_hw_write_wx(adapter,
+					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
+					   &temp, 4))
+			return -EIO;
+		restore = 1;
+	}
+
+	/* reset MII management interface */
+	*(netxen_crbword_t *) & mii_cfg = 0;
+	mii_cfg.clockselect = 7;
+	mii_cfg.reset = 1;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
+				   &mii_cfg, 4))
+		return -EIO;
+	mii_cfg.reset = 0;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
+				   &mii_cfg, 4))
+		return -EIO;
+
+	*(netxen_crbword_t *) & address = 0;
+	address.reg_addr = reg;
+	address.phy_addr = phy;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+				   &address, 4))
+		return -EIO;
+	*(netxen_crbword_t *) & command = 0;	/* turn off any prior activity */
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+				   &command, 4))
+		return -EIO;
+	/* send read command */
+	command.read_cycle = 1;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+				   &command, 4))
+		return -EIO;
+
+	*(netxen_crbword_t *) & status = 0;
+	do {
+		if (netxen_nic_hw_read_wx(adapter,
+					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
+					  &status, 4))
+			return -EIO;
+		timeout++;
+	} while ((status.busy || status.notvalid)
+		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
+
+	if (timeout < NETXEN_NIU_PHY_WAITMAX) {
+		if (netxen_nic_hw_read_wx(adapter,
+					  NETXEN_NIU_GB_MII_MGMT_STATUS(0),
+					  readval, 4))
+			return -EIO;
+		result = 0;
+	} else
+		result = -1;
+
+	if (restore)
+		if (netxen_nic_hw_write_wx(adapter,
+					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
+					   &mac_cfg0, 4))
+			return -EIO;
+
+	return result;
+}
+
+/** 
+ * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ *       Individual phys are addressed as follows:
+ * @param phy      [15:8]  phy id
+ * @param reg      [7:0]   register number
+ *
+ * @returns  0 on success
+ *          -1 on error
+ *
+ **/
+long netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
+			      long phy, long reg, netxen_crbword_t val)
+{
+	long timeout = 0;
+	long result = 0;
+	long restore = 0;
+	struct netxen_niu_gb_mii_mgmt_address address;
+	struct netxen_niu_gb_mii_mgmt_command command;
+	struct netxen_niu_gb_mii_mgmt_indicators status;
+	struct netxen_niu_gb_mac_config_0_t mac_cfg0;
+
+	/* MII mgmt all goes through port 0 MAC interface, so it cannot be in reset */
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+				  &mac_cfg0, 4))
+		return -EIO;
+	if (mac_cfg0.soft_reset) {
+		struct netxen_niu_gb_mac_config_0_t temp;
+		*(netxen_crbword_t *) & temp = 0;
+		temp.tx_reset_pb = 1;
+		temp.rx_reset_pb = 1;
+		temp.tx_reset_mac = 1;
+		temp.rx_reset_mac = 1;
+		if (netxen_nic_hw_write_wx(adapter,
+					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
+					   &temp, 4))
+			return -EIO;
+		restore = 1;
+	}
+
+	*(netxen_crbword_t *) & command = 0;	/* turn off any prior activity */
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+				   &command, 4))
+		return -EIO;
+
+	*(netxen_crbword_t *) & address = 0;
+	address.reg_addr = reg;
+	address.phy_addr = phy;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+				   &address, 4))
+		return -EIO;
+
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+				   &val, 4))
+		return -EIO;
+
+	*(netxen_crbword_t *) & status = 0;
+	do {
+		if (netxen_nic_hw_read_wx(adapter,
+					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
+					  &status, 4))
+			return -EIO;
+		timeout++;
+	} while ((status.busy) && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
+
+	if (timeout < NETXEN_NIU_PHY_WAITMAX)
+		result = 0;
+	else
+		result = -EIO;
+
+	/* restore the state of port 0 MAC in case we tampered with it */
+	if (restore)
+		if (netxen_nic_hw_write_wx(adapter,
+					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
+					   &mac_cfg0, 4))
+			return -EIO;
+
+	return result;
+}
+
+long netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
+					  long port)
+{
+	long result = 0;
+	struct netxen_niu_phy_interrupt enable;
+	*(netxen_crbword_t *) & enable = 0;
+	enable.link_status_changed = 1;
+	enable.autoneg_completed = 1;
+	enable.speed_changed = 1;
+
+	if (0 !=
+	    netxen_niu_gbe_phy_write(adapter, port,
+				     NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,
+				     *(netxen_crbword_t *) & enable))
+		result = -EIO;
+
+	return result;
+}
+
+long netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter,
+					   long port)
+{
+	long result = 0;
+	if (0 !=
+	    netxen_niu_gbe_phy_write(adapter, port,
+				     NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0))
+		result = -EIO;
+
+	return result;
+}
+
+long netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter,
+					 long port)
+{
+	long result = 0;
+	if (0 !=
+	    netxen_niu_gbe_phy_write(adapter, port,
+				     NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+				     -EIO))
+		result = -EIO;
+
+	return result;
+}
+
+/** 
+ * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
+ *
+ **/
+void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
+				 long port, long enable)
+{
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				    0x80000000);
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				    0x0000f0025);
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
+				    0xf1ff);
+	netxen_crb_writelit_adapter(adapter,
+				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
+	netxen_crb_writelit_adapter(adapter,
+				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
+	netxen_crb_writelit_adapter(adapter,
+				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+	netxen_crb_writelit_adapter(adapter,
+				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+	if (enable) {
+		/* 
+		 * Do NOT enable flow control until a suitable solution for 
+		 *  shutting down pause frames is found. 
+		 */
+		netxen_crb_writelit_adapter(adapter,
+					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
+					    0x5);
+	}
+
+	if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
+		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+	if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+}
+
+/** 
+ * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC
+ **/
+void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
+				  long port, long enable)
+{
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				    0x80000000);
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				    0x0000f0025);
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
+				    0xf2ff);
+	netxen_crb_writelit_adapter(adapter,
+				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
+	netxen_crb_writelit_adapter(adapter,
+				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
+	netxen_crb_writelit_adapter(adapter,
+				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+	netxen_crb_writelit_adapter(adapter,
+				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+	if (enable) {
+		/* 
+		 * Do NOT enable flow control until a suitable solution for 
+		 *  shutting down pause frames is found. 
+		 */
+		netxen_crb_writelit_adapter(adapter,
+					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
+					    0x5);
+	}
+
+	if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
+		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+	if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+}
+
+long netxen_niu_gbe_init_port(struct netxen_adapter *adapter, long port)
+{
+	long result = 0;
+	struct netxen_niu_phy_status status;
+
+	if (0 ==
+	    netxen_niu_gbe_phy_read(adapter, port,
+				    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+				    (netxen_crbword_t *) & status)) {
+		if (status.link) {
+			if (status.speed == 2) {
+				netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
+			} else if ((status.speed == 1) || (status.speed == 0)) {
+				netxen_niu_gbe_set_mii_mode(adapter, port, 1);
+			} else {
+				result = -1;
+			}
+
+		} else {
+			/* We don't have link. Cable  must be unconnected. */
+			/* Enable phy interrupts so we take action when plugged in */
+			netxen_crb_writelit_adapter(adapter,
+						    NETXEN_NIU_GB_MAC_CONFIG_0
+						    (port), 0x80000000);
+			netxen_crb_writelit_adapter(adapter,
+						    NETXEN_NIU_GB_MAC_CONFIG_0
+						    (port), 0x0000f0025);
+			if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+				printk(KERN_ERR PFX
+				       "ERROR clearing PHY interrupts\n");
+			if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
+				printk(KERN_ERR PFX
+				       "ERROR enabling PHY interrupts\n");
+			if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
+				printk(KERN_ERR PFX
+				       "ERROR clearing PHY interrupts\n");
+			result = -1;
+		}
+	} else {
+		result = -EIO;
+	}
+	return result;
+}
+
+/** 
+ * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts
+ * @param enable 0 means don't enable the port
+ *               1 means enable (or re-enable) the port
+ **/
+long netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
+					 long port, long enable)
+{
+	long result = 0;
+	struct netxen_niu_phy_interrupt int_src;
+
+	printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
+	       " (device enable = %d)\n", (int)port, (int)enable);
+
+	/* The read of the PHY INT status will clear the pending interrupt status */
+	if (netxen_niu_gbe_phy_read(adapter, port,
+				    NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+				    (netxen_crbword_t *) & int_src) != 0)
+		result = -EINVAL;
+	else {
+		printk(KERN_INFO PFX "PHY Interrupt source = 0x%x \n",
+		       *(u32 *) & int_src);
+		if (int_src.jabber)
+			printk(KERN_INFO PFX "jabber Interrupt ");
+		if (int_src.polarity_changed)
+			printk(KERN_INFO PFX "polarity changed ");
+		if (int_src.energy_detect)
+			printk(KERN_INFO PFX "energy detect \n");
+		if (int_src.downshift)
+			printk(KERN_INFO PFX "downshift \n");
+		if (int_src.mdi_xover_changed)
+			printk(KERN_INFO PFX "mdi_xover_changed ");
+		if (int_src.fifo_over_underflow)
+			printk(KERN_INFO PFX "fifo_over_underflow ");
+		if (int_src.false_carrier)
+			printk(KERN_INFO PFX "false_carrier ");
+		if (int_src.symbol_error)
+			printk(KERN_INFO PFX "symbol_error ");
+		if (int_src.autoneg_completed)
+			printk(KERN_INFO PFX "autoneg_completed ");
+		if (int_src.page_received)
+			printk(KERN_INFO PFX "page_received ");
+		if (int_src.duplex_changed)
+			printk(KERN_INFO PFX "duplex_changed ");
+		if (int_src.autoneg_error)
+			printk(KERN_INFO PFX "autoneg_error ");
+		if ((int_src.speed_changed) || (int_src.link_status_changed)) {
+			struct netxen_niu_phy_status status;
+
+			printk(KERN_INFO PFX
+			       "speed_changed or link status changed");
+			if (netxen_niu_gbe_phy_read
+			    (adapter, port,
+			     NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+			     (netxen_crbword_t *) & status) == 0) {
+				if (status.speed == 2) {
+					printk
+					    (KERN_INFO PFX "Link speed changed"
+					     " to 1000 Mbps\n");
+					netxen_niu_gbe_set_gmii_mode(adapter,
+								     port,
+								     enable);
+				} else if (status.speed == 1) {
+					printk
+					    (KERN_INFO PFX "Link speed changed"
+					     " to 100 Mbps\n");
+					netxen_niu_gbe_set_mii_mode(adapter,
+								    port,
+								    enable);
+				} else if (status.speed == 0) {
+					printk
+					    (KERN_INFO PFX "Link speed changed"
+					     " to 10 Mbps\n");
+					netxen_niu_gbe_set_mii_mode(adapter,
+								    port,
+								    enable);
+				} else {
+					printk(KERN_ERR PFX "ERROR reading"
+					       "PHY status. Illegal speed.\n");
+					result = -1;
+				}
+			} else {
+				printk(KERN_ERR PFX
+				       "ERROR reading PHY status.\n");
+				result = -1;
+			}
+
+		}
+		printk(KERN_INFO "\n");
+	}
+	return result;
+}
+
+/**
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ **/
+int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
+			   int phy, netxen_ethernet_macaddr_t * addr)
+{
+	u64 result = 0;
+	struct netxen_niu_gb_station_address_high stationhigh;
+	struct netxen_niu_gb_station_address_low stationlow;
+
+	if (addr == NULL)
+		return -EINVAL;
+	if ((phy < 0) || (phy > 3))
+		return -EINVAL;
+
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+				  &stationhigh, 4))
+		return -EIO;
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+				  &stationlow, 4))
+		return -EIO;
+
+	result = (u64) stationlow.address;
+	result |= (u64) stationhigh.address << 16;
+	memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+
+	return 0;
+}
+
+/**
+ * Set the station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ **/
+int netxen_niu_macaddr_set(struct netxen_adapter *adapter, int phy,
+			   netxen_ethernet_macaddr_t addr)
+{
+	netxen_crbword_t temp = 0;
+
+	if ((phy < 0) || (phy > 3))
+		return -EINVAL;
+
+	memcpy(&temp, addr, 2);
+	temp <<= 16;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+				   &temp, 4))
+		return -EIO;
+
+	temp = 0;
+
+	memcpy(&temp, ((u8 *) addr) + 2, sizeof(netxen_crbword_t));
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+				   &temp, 4))
+		return -2;
+
+	return 0;
+}
+
+/* Enable a GbE interface */
+long netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
+				long port, netxen_niu_gbe_ifmode_t mode)
+{
+	struct netxen_niu_gb_mac_config_0_t mac_cfg0;
+	struct netxen_niu_gb_mac_config_1_t mac_cfg1;
+	struct netxen_niu_gb_mii_mgmt_config mii_cfg;
+
+	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+		return -EINVAL;
+
+	*(netxen_crbword_t *) & mac_cfg0 = 0;
+	mac_cfg0.soft_reset = 1;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				   &mac_cfg0, 4))
+		return -EIO;
+	*(netxen_crbword_t *) & mac_cfg0 = 0;
+	mac_cfg0.tx_enable = 1;
+	mac_cfg0.rx_enable = 1;
+	mac_cfg0.rx_flowctl = 0;
+	mac_cfg0.tx_reset_pb = 1;
+	mac_cfg0.rx_reset_pb = 1;
+	mac_cfg0.tx_reset_mac = 1;
+	mac_cfg0.rx_reset_mac = 1;
+
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				   &mac_cfg0, 4))
+		return -EIO;
+	*(netxen_crbword_t *) & mac_cfg1 = 0;
+	mac_cfg1.preamblelen = 0xf;
+	mac_cfg1.duplex = 1;
+	mac_cfg1.crc_enable = 1;
+	mac_cfg1.padshort = 1;
+	mac_cfg1.checklength = 1;
+	mac_cfg1.hugeframes = 1;
+
+	if (mode == NETXEN_NIU_10_100_MB) {
+		mac_cfg1.intfmode = 1;
+		if (netxen_nic_hw_write_wx(adapter,
+					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
+					   &mac_cfg1, 4))
+			return -EIO;
+
+		/* set mii mode */
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
+					    (port << 3), 0);
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
+					    (port << 3), 1);
+
+	} else if (mode == NETXEN_NIU_1000_MB) {
+		mac_cfg1.intfmode = 2;
+		if (netxen_nic_hw_write_wx(adapter,
+					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
+					   &mac_cfg1, 4))
+			return -EIO;
+		/* set gmii mode */
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
+					    (port << 3), 0);
+		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
+					    (port << 3), 1);
+	}
+	*(netxen_crbword_t *) & mii_cfg = 0;
+	mii_cfg.clockselect = 7;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
+				   &mii_cfg, 4))
+		return -EIO;
+
+	*(netxen_crbword_t *) & mac_cfg0 = 0;
+	mac_cfg0.tx_enable = 1;
+	mac_cfg0.rx_enable = 1;
+	mac_cfg0.tx_flowctl = 0;
+	mac_cfg0.rx_flowctl = 0;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				   &mac_cfg0, 4))
+		return -EIO;
+	return 0;
+}
+
+/* Disable a GbE interface */
+long netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, long port)
+{
+	struct netxen_niu_gb_mac_config_0_t mac_cfg0;
+
+	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+		return -EINVAL;
+
+	*(netxen_crbword_t *) & mac_cfg0 = 0;
+	mac_cfg0.soft_reset = 1;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+				   &mac_cfg0, 4))
+		return -EIO;
+	return 0;
+}
+
+/* Disable an XG interface */
+long netxen_niu_disable_xg_port(struct netxen_adapter *adapter, long port)
+{
+	struct netxen_niu_xg_mac_config_0_t mac_cfg;
+
+	if (port != 0)
+		return -EINVAL;
+
+	*(netxen_crbword_t *) & mac_cfg = 0;
+	mac_cfg.soft_reset = 1;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_CONFIG_0,
+				   &mac_cfg, 4))
+		return -EIO;
+	return 0;
+}
+
+/* Set promiscuous mode for a GbE interface */
+long netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, long port,
+				     netxen_niu_prom_mode_t mode)
+{
+	struct netxen_niu_gb_drop_crc reg;
+	long data;
+
+	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+		return -EINVAL;
+
+	if (mode == NETXEN_NIU_PROMISCOUS_MODE)
+		data = 0;
+	else
+		data = 1;
+
+	/* save previous contents */
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+				  &reg, 4))
+		return -EIO;
+	switch (port) {
+	case 0:
+		reg.drop_gb0 = data;
+		break;
+	case 1:
+		reg.drop_gb0 = data;
+		break;
+	case 2:
+		reg.drop_gb0 = data;
+		break;
+	case 3:
+		reg.drop_gb0 = data;
+		break;
+	default:
+		return -EIO;
+	}
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+				   &reg, 4))
+		return -EIO;
+	return 0;
+}
+
+/**
+ * Set the MAC address for an XG port
+ * Note that the passed-in value must already be in network byte order.
+ **/
+int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, int phy,
+			      netxen_ethernet_macaddr_t addr)
+{
+	netxen_crbword_t temp = 0;
+
+	if ((phy < 0) || (phy > 3))
+		return -EINVAL;
+
+	memcpy(&temp, addr, 2);
+	temp <<= 16;
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+				   &temp, 4))
+		return -EIO;
+
+	temp = 0;
+
+	memcpy(&temp, ((u8 *) addr) + 2, sizeof(netxen_crbword_t));
+	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+				   &temp, 4))
+		return -EIO;
+
+	return 0;
+}
+
+/**
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ **/
+int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
+			      netxen_ethernet_macaddr_t * addr)
+{
+	netxen_crbword_t stationhigh;
+	netxen_crbword_t stationlow;
+	u64 result;
+
+	if (addr == NULL)
+		return -EINVAL;
+	if (phy != 0)
+		return -EINVAL;
+
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+				  &stationhigh, 4))
+		return -EIO;
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+				  &stationlow, 4))
+		return -EIO;
+
+	result = ((u64) stationlow) >> 16;
+	result |= (u64) stationhigh << 16;
+	memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+
+	return 0;
+}
+
+long netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
+					long port, netxen_niu_prom_mode_t mode)
+{
+	long reg;
+
+	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+		return -EINVAL;
+
+	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_CONFIG_1, &reg, 4))
+		return -EIO;
+	if (mode == NETXEN_NIU_PROMISCOUS_MODE)
+		reg = (reg | 0x2000UL);
+	else
+		reg = (reg & ~0x2000UL);
+
+	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_XGE_CONFIG_1, reg);
+
+	return 0;
+}
diff -Naru linux-2.6.17.orig/drivers/net/netxen/netxen_nic_phan_reg.h linux-2.6.17/drivers/net/netxen/netxen_nic_phan_reg.h
--- linux-2.6.17.orig/drivers/net/netxen/netxen_nic_phan_reg.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.17/drivers/net/netxen/netxen_nic_phan_reg.h	2006-07-05 01:18:40.361907675 -0700
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ * 
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ */
+
+#ifndef __NIC_PHAN_REG_H_
+#define __NIC_PHAN_REG_H_
+
+/** 
+ * CRB Registers or queue message done only at initialization time....
+ **/
+
+/**
+ * The following 2 are the base adresses for the CRB registers and their
+ * offsets will be added to get addresses for the index addresses.......
+ **/
+#define NIC_CRB_BASE_PORT1	NETXEN_CAM_RAM(0x200)
+#define NIC_CRB_BASE_PORT2	NETXEN_CAM_RAM(0x250)
+
+#define NETXEN_NIC_REG(X)	(NIC_CRB_BASE_PORT1+(X))
+
+/**
+ * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address
+ * which can be read by the Phantom host to get producer/consumer indexes from
+ * Phantom/Casper. If it is not HOST_SHARED_MEMORY, then the following
+ * registers will be used for the addresses of the ring's shared memory
+ * on the Phantom.
+ **/
+
+#define CRB_PHAN_CNTRL_LO_OFFSET	NETXEN_NIC_REG(0x00)
+#define CRB_PHAN_CNTRL_HI_OFFSET	NETXEN_NIC_REG(0x04)
+
+/* point to the indexes */
+#define CRB_CMD_PRODUCER_OFFSET		NETXEN_NIC_REG(0x08)
+#define CRB_CMD_CONSUMER_OFFSET		NETXEN_NIC_REG(0x0c)
+
+/* address of command descriptors in the host memory */
+#define CRB_HOST_CMD_ADDR_HI		NETXEN_NIC_REG(0x30)
+#define CRB_HOST_CMD_ADDR_LO		NETXEN_NIC_REG(0x34)
+
+/* The following 4 CRB registers are for doing performance coal */
+#define CRB_CMD_INTR_LOOP		NETXEN_NIC_REG(0x38)
+#define CRB_CMD_DMA_LOOP		NETXEN_NIC_REG(0x3c)
+#define CRB_RCV_INTR_LOOP		NETXEN_NIC_REG(0x40)
+#define CRB_RCV_DMA_LOOP		NETXEN_NIC_REG(0x44)
+
+/* Needed by the host to find out the state of Phantom's initialization */
+#define CRB_ENABLE_TX_INTR		NETXEN_NIC_REG(0x4c)
+#define CRB_CMDPEG_STATE		NETXEN_NIC_REG(0x50)
+#define CRB_CMDPEG_CMDRING		NETXEN_NIC_REG(0x54)
+
+/* Interrupt coalescing parameters */
+#define CRB_GLOBAL_INT_COAL		NETXEN_NIC_REG(0x80)
+#define CRB_INT_COAL_MODE		NETXEN_NIC_REG(0x84)
+#define CRB_MAX_RCV_BUFS		NETXEN_NIC_REG(0x88)
+#define CRB_TX_INT_THRESHOLD		NETXEN_NIC_REG(0x8c)
+#define CRB_RX_PKT_TIMER		NETXEN_NIC_REG(0x90)
+#define CRB_TX_PKT_TIMER		NETXEN_NIC_REG(0x94)
+#define CRB_RX_PKT_CNT			NETXEN_NIC_REG(0x98)
+#define CRB_RX_TMR_CNT			NETXEN_NIC_REG(0x9c)
+
+/* Register for communicating XG link status */
+#define CRB_XG_STATE			NETXEN_NIC_REG(0xa0)
+
+/* Debug registers for controlling NIC pkt gen agent */
+#define CRB_AGENT_GO			NETXEN_NIC_REG(0xb0)
+#define CRB_AGENT_TX_SIZE		NETXEN_NIC_REG(0xb4)
+#define CRB_AGENT_TX_TYPE		NETXEN_NIC_REG(0xb8)
+#define CRB_AGENT_TX_ADDR		NETXEN_NIC_REG(0xbc)
+#define CRB_AGENT_TX_MSS		NETXEN_NIC_REG(0xc0)
+
+/* Debug registers for observing NIC performance */
+#define CRB_TX_STATE			NETXEN_NIC_REG(0xd0)
+#define CRB_TX_COUNT			NETXEN_NIC_REG(0xd4)
+#define CRB_RX_STATE			NETXEN_NIC_REG(0xd8)
+#define CRB_CMD_RING_SIZE		NETXEN_NIC_REG(0xe0)
+#define CRB_CTX_ADDR_REG		NETXEN_NIC_REG(0xd0)
+#define CRB_CTX_SIGNATURE_REG		NETXEN_NIC_REG(0xd4)
+
+#define NETXEN_CMD_PRODUCER_DB_PAGE(ctx)           ((ctx) * 4)
+#define NETXEN_RCV_STATUS_CONSUMER_DB_PAGE(ctx)    (1 + ((ctx) * 4))
+#define NETXEN_RCV_PRODUCER_DB_PAGE(ctx,ring)      (2 + (ring) + ((ctx) * 4))
+
+/* CRB registers per Rcv Descriptor ring */
+struct netxen_rcv_desc_crb {
+	u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
+	u32 crb_rcv_consumer_offset;
+	u32 crb_globalrcv_ring;
+	u32 crb_rcv_ring_size;
+};
+
+/*
+ * CRB registers used by the receive peg logic. One instance of these
+ * needs to be instantiated per instance of the receive peg.
+ */
+
+struct netxen_recv_crb {
+	struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS];
+	u32 crb_rcvstatus_ring;
+	u32 crb_rcv_status_producer;
+	u32 crb_rcv_status_consumer;
+	u32 crb_rcvpeg_state;
+	u32 crb_status_ring_size;
+};
+
+#if defined(DEFINE_GLOBAL_RECV_CRB)
+struct netxen_recv_crb recv_crb_registers[] = {
+	/*
+	 * Instance 0.
+	 */
+	{
+	 /* rcv_desc_crb: */
+	 {
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x18),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x1c),
+	   /* crb_gloablrcv_ring: */
+	   NETXEN_NIC_REG(0x20),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xe4),
+	   },
+	  /* Jumbo frames */
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x100),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x104),
+	   /* crb_gloablrcv_ring: */
+	   NETXEN_NIC_REG(0x108),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xe8),
+	   }
+	  },
+	 /* crb_rcvstatus_ring: */
+	 NETXEN_NIC_REG(0x24),
+	 /* crb_rcv_status_producer: */
+	 NETXEN_NIC_REG(0x28),
+	 /* crb_rcv_status_consumer: */
+	 NETXEN_NIC_REG(0x2c),
+	 /* crb_rcvpeg_state: */
+	 NETXEN_NIC_REG(0x48),
+	 /* crb_status_ring_size: */
+	 NETXEN_NIC_REG(0xec),
+	 },
+	/*
+	 * Instance 1,
+	 */
+	{
+	 /* rcv_desc_crb: */
+	 {
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x80),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x84),
+	   /* crb_globalrcv_ring: */
+	   NETXEN_NIC_REG(0x88),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xf0),
+	   },
+	  /* Jumbo frames */
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x10C),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x110),
+	   /* crb_globalrcv_ring: */
+	   NETXEN_NIC_REG(0x114),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xf4),
+	   }
+	  },
+	 /* crb_rcvstatus_ring: */
+	 NETXEN_NIC_REG(0x8c),
+	 /* crb_rcv_status_producer: */
+	 NETXEN_NIC_REG(0x90),
+	 /* crb_rcv_status_consumer: */
+	 NETXEN_NIC_REG(0x94),
+	 /* crb_rcvpeg_state: */
+	 NETXEN_NIC_REG(0x98),
+	 /* crb_status_ring_size: */
+	 NETXEN_NIC_REG(0xf8),
+	 },
+	/*
+	 * Instance 2.
+	 */
+	{
+	 /* rcv_desc_crb: */
+	 {
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x18),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x1c),
+	   /* crb_globalrcv_ring: */
+	   NETXEN_NIC_REG(0x20),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xe4),
+	   },
+	  /* Jumbo frames */
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x100),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x104),
+	   /* crb_globalrcv_ring: */
+	   NETXEN_NIC_REG(0x108),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xe8),
+	   }
+	  },
+	 /* crb_rcvstatus_ring: */
+	 NETXEN_NIC_REG(0x24),
+	 /*  crb_rcv_status_producer: */
+	 NETXEN_NIC_REG(0x28),
+	 /*  crb_rcv_status_consumer: */
+	 NETXEN_NIC_REG(0x2c),
+	 /*  crb_rcvpeg_state: */
+	 NETXEN_NIC_REG(0x48),
+	 /* crb_status_ring_size: */
+	 NETXEN_NIC_REG(0xec),
+	 },
+	/*
+	 * Instance 3,
+	 */
+	{
+	 /* rcv_desc_crb: */
+	 {
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x80),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x84),
+	   /* crb_globalrcv_ring: */
+	   NETXEN_NIC_REG(0x88),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xf0),
+	   },
+	  /* Jumbo frames */
+	  {
+	   /* crb_rcv_producer_offset: */
+	   NETXEN_NIC_REG(0x10C),
+	   /* crb_rcv_consumer_offset: */
+	   NETXEN_NIC_REG(0x110),
+	   /* crb_globalrcv_ring: */
+	   NETXEN_NIC_REG(0x114),
+	   /* crb_rcv_ring_size: */
+	   NETXEN_NIC_REG(0xf4),
+	   }
+	  },
+	 /* crb_rcvstatus_ring: */
+	 NETXEN_NIC_REG(0x8c),
+	 /* crb_rcv_status_producer: */
+	 NETXEN_NIC_REG(0x90),
+	 /*  crb_rcv_status_consumer: */
+	 NETXEN_NIC_REG(0x94),
+	 /* crb_rcvpeg_state */
+	 NETXEN_NIC_REG(0x98),
+	 /* crb_status_ring_size: */
+	 NETXEN_NIC_REG(0xf8),
+	 },
+};
+#else
+extern struct netxen_recv_crb recv_crb_registers[];
+#endif				/* DEFINE_GLOBAL_RECEIVE_CRB */
+
+#endif				/* __NIC_PHAN_REG_H_ */

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface
  2006-07-05 13:20 ` [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface Linsys Contractor Amit S. Kale
@ 2006-07-05 15:34   ` Jeff Garzik
  2006-07-06 13:50     ` Pradeep Dalvi
  0 siblings, 1 reply; 17+ messages in thread
From: Jeff Garzik @ 2006-07-05 15:34 UTC (permalink / raw)
  To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj

Linsys Contractor Amit S. Kale wrote:
> +static int
> +netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
> +{
> +    struct netxen_port *port = netdev_priv(dev);
> +    struct netxen_adapter *adapter = port->adapter;
> +    struct netxen_niu_phy_status status;
> +
> +    /* read which mode */
> +    if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
> +        /* autonegotiation */
> +        if (netxen_nic_phy_write(port->adapter, port->portnum,
> +                     NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
> +                     (netxen_crbword_t) ecmd->autoneg) != 0)
> +            return -EIO;
> +        else
> +            port->link_autoneg = ecmd->autoneg;
> +
> +        if (netxen_nic_phy_read(port->adapter, port->portnum,
> +                    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> +                    (netxen_crbword_t *) & status) != 0)
> +            return -EIO;
> +
> +        /* speed */
> +        switch (ecmd->speed) {
> +        case SPEED_10:
> +            status.speed = 0;
> +            break;
> +        case SPEED_100:
> +            status.speed = 1;
> +            break;
> +        case SPEED_1000:
> +            status.speed = 2;
> +            break;
> +        }
> +        /* set duplex mode */
> +        if (ecmd->duplex == DUPLEX_HALF)
> +            status.duplex = 0;
> +        if (ecmd->duplex == DUPLEX_FULL)
> +            status.duplex = 1;
> +
> +        if (netxen_nic_phy_write(port->adapter, port->portnum,
> +                     NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> +                     *((int *)&status)) != 0)
> +            return -EIO;
> +        else {
> +            port->link_speed = ecmd->speed;
> +            port->link_duplex = ecmd->duplex;
> +        }
> +    }
> +    if (netif_running(dev)) {
> +        dev->stop(dev);
> +        dev->open(dev);
> +    }
> +    return 0;
> +}
> +

> +/* Restart Link Process */
> +static int netxen_nic_nway_reset(struct net_device *dev)
> +{
> +    if (netif_running(dev)) {
> +        dev->stop(dev);    /* verify */
> +        dev->open(dev);
> +    }
> +    return 0;
> +}

Direct calls to dev->stop() and dev->open() are likely buggy, because 
the locking/context differs between the above quoted calls and the calls 
from inside the net stack.


> +struct ethtool_ops netxen_nic_ethtool_ops = {
> +    .get_settings = netxen_nic_get_settings,
> +    .set_settings = netxen_nic_set_settings,
> +    .get_drvinfo = netxen_nic_get_drvinfo,
> +    .get_regs_len = netxen_nic_get_regs_len,
> +    .get_regs = netxen_nic_get_regs,
> +    .get_wol = netxen_nic_get_wol,
> +    .nway_reset = netxen_nic_nway_reset,
> +    .get_link = netxen_nic_get_link,
> +    .get_eeprom_len = netxen_nic_get_eeprom_len,
> +    .get_eeprom = netxen_nic_get_eeprom,
> +    .get_ringparam = netxen_nic_get_ringparam,
> +    .get_pauseparam = netxen_nic_get_pauseparam,
> +    .set_pauseparam = netxen_nic_set_pauseparam,
> +    .get_tx_csum = ethtool_op_get_tx_csum,
> +    .set_tx_csum = ethtool_op_set_tx_csum,
> +    .get_sg = ethtool_op_get_sg,
> +    .set_sg = ethtool_op_set_sg,
> +#ifdef NETIF_F_TSO
> +    .get_tso = ethtool_op_get_tso,
> +    .set_tso = ethtool_op_set_tso,
> +#endif

kill this #ifdef

	Jeff



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 2/9] NetXen: Main header file.
  2006-07-05 13:29 ` [PATCH 2.6.17 2/9] NetXen: Main header file Linsys Contractor Amit S. Kale
@ 2006-07-05 15:46   ` Jeff Garzik
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2006-07-05 15:46 UTC (permalink / raw)
  To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj, Andrew Morton

Linsys Contractor Amit S. Kale wrote:
> +#define NETXEN_NIC_FW_VERSIONID "2.1.39"

This duplicates the driver version, rather than being used for its 
intended purpose, firmware version.

If firmware (or if no firmware on card, silicon) version is not 
available, just use the string "n/a"


> +#define NETXEN_NIC_TIMESTAMP "Mon May  1 01:34:07 PDT 2006"

why is this needed?



> +#define NETXEN_CRB_NORMALIZE(adapter, reg) \
> +    (void *)(ptrdiff_t)(adapter->ahw.pci_base+ (reg)    \
> +    - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST)
> +
> +#define DB_NORMALIZE(adapter, off) \
> +    (void *)(ptrdiff_t)(adapter->ahw.db_base + (off))

Highly likely that this needs __iomem marking, and potentially 
additional attention.



> +#define get_next_index(index, length)    \
> +    ((((index) + 1) == length) ? \
> +        0 : \
> +        (index) +1)
> +
> +#define get_index_range(index,length,count)    \
> +    ((((index) + (count)) >= length) ?    \
> +        (((index) + (count))-(length)) :    \
> +        ((index) + (count)))

Seems like you could eliminate the branches with power-of-2 + masks.


> + * Following data structures describe the descriptors that will be used.
> + * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it 
> only when
> + * we are doing LSO (above the 1500 size packet) only.
> + **/
> +
> +/**
> + * The size of reference handle been changed to 16 bits to pass the MSS 
> fields
> + * for the LSO packet
> + **/
> +
> +#define FLAGS_CHECKSUM_ENABLED    0x01
> +#define FLAGS_LSO_ENABLED    0x02
> +#define FLAGS_IPSEC_SA_ADD    0x04
> +#define FLAGS_IPSEC_SA_DELETE    0x08
> +#define FLAGS_VLAN_TAGGED    0x10
> +
> +struct cmd_desc_type0_t {
> +    u64 netxen_next;    /* for fragments handled by Phantom */
> +    union {
> +        struct {
> +            u32 addr_low_part2;
> +            u32 addr_high_part2;
> +        };
> +        u64 addr_buffer2;
> +    };
> +
> +    u64 total_length:24,    /* Total size of the packet */
> +     tcp_hdr_offset:8,    /* For LSO only */
> +     ip_hdr_offset:8,    /* For LSO only */
> +     num_of_buffers:8,    /* total number of segments */
> +     flags:8,        /* as defined above */
> +     opcode:8;
> +
> +    u64 reference_handle:16,    /* changed to u16 to add mss */
> +     mss:16,        /* passed by NDIS_PACKET for LSO */
> +     port:4,
> +     ctx_id:4,
> +     total_hdr_length:8,    /* LSO only : MAC+IP+TCP Hdr size */
> +     conn_id:16;        /* IPSec offoad only */
> +
> +    union {
> +        struct {
> +            u32 addr_low_part3;
> +            u32 addr_high_part3;
> +        };
> +        u64 addr_buffer3;
> +    };
> +
> +    union {
> +        struct {
> +            u32 addr_low_part1;
> +            u32 addr_high_part1;
> +        };
> +        u64 addr_buffer1;
> +    };
> +
> +    u64 buffer1_length:16,
> +        buffer2_length:16, buffer3_length:16, buffer4_length:16;
> +
> +    union {
> +        struct {
> +            u32 addr_low_part4;
> +            u32 addr_high_part4;
> +        };
> +        u64 addr_buffer4;
> +    };
> +
> +} __attribute__ ((aligned(64)));
> +
> +/* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
> +struct rcv_desc_t {
> +    u64 reference_handle:16,
> +     reserved:16,
> +     buffer_length:32;    /* allocated buffer length (usually 2K) */
> +    u64 addr_buffer;
> +};

Problems:

1) bitfields are not endian-clean

2) it's silly to use bitfields of sizes 8, 16, and 32.  This generates 
grossly sub-optimal code compared to use of u8, u16, u32 C types.

3) Most likely you should be using __le32, etc.



> +/* opcode field in status_desc_t */
> +#define RCV_NIC_PKT    (0xA)
> +#define STATUS_NIC_PKT    ((RCV_NIC_PKT) << 12)
> +
> +/* for status field in status_desc_t */
> +#define STATUS_NEED_CKSUM    (1)
> +#define STATUS_CKSUM_OK        (2)
> +
> +/* owner bits of status_desc_t */
> +#define STATUS_OWNER_HOST    (1ULL)
> +#define STATUS_OWNER_PHANTOM    (2ULL)
> +#define HOST_STATUS_DESC    ((STATUS_OWNER_HOST) << 48)
> +#define PHANTOM_STATUS_DESC    ((STATUS_OWNER_PHANTOM) << 48)
> +
> +#define NETXEN_PROT_IP        (1)
> +#define NETXEN_PROT_UNKNOWN    (0)
> +
> +/* Note: sizeof(status_desc) should always be a mutliple of 2 */
> +struct status_desc_t {
> +    u64 port:4,        /* initially to be used but noe now */
> +     status:4,        /* completion status may not have use */
> +     type:4,        /* type/index of descriptor ring */
> +     opcode:4,        /* Completion of receive or transmit */
> +     total_length:16,    /* NIC mode */
> +     reference_handle:16,    /* handle for the associated packet */
> +     owner:2,        /* Owner of the descriptor */
> +     prot:4;        /* protocol type for skb (Linux) */
> +} __attribute__ ((aligned(8)));

ditto above comments




> +struct netxen_board_info {
> +    u32 header_version;
> +
> +    u32 board_mfg;
> +    u32 board_type;
> +    u32 board_num;
> +    u32 chip_id;
> +    u32 chip_minor;
> +    u32 chip_major;
> +    u32 chip_pkg;
> +    u32 chip_lot;
> +
> +    u32 port_mask;        /* available niu ports */
> +    u32 peg_mask;        /* available pegs */
> +    u32 icache_ok;        /* can we run with icache? */
> +    u32 dcache_ok;        /* can we run with dcache? */
> +    u32 casper_ok;
> +
> +    u32 mac_addr_lo_0;
> +    u32 mac_addr_lo_1;
> +    u32 mac_addr_lo_2;
> +    u32 mac_addr_lo_3;
> +
> +    /* MN-related config */
> +    u32 mn_sync_mode;    /* enable/ sync shift cclk/ sync shift mclk */
> +    u32 mn_sync_shift_cclk;
> +    u32 mn_sync_shift_mclk;
> +    u32 mn_wb_en;
> +    u32 mn_crystal_freq;    /* in MHz */
> +    u32 mn_speed;        /* in MHz */
> +    u32 mn_org;
> +    u32 mn_depth;
> +    u32 mn_ranks_0;        /* ranks per slot */
> +    u32 mn_ranks_1;        /* ranks per slot */
> +    u32 mn_rd_latency_0;
> +    u32 mn_rd_latency_1;
> +    u32 mn_rd_latency_2;
> +    u32 mn_rd_latency_3;
> +    u32 mn_rd_latency_4;
> +    u32 mn_rd_latency_5;
> +    u32 mn_rd_latency_6;
> +    u32 mn_rd_latency_7;
> +    u32 mn_rd_latency_8;
> +    u32 mn_dll_val[18];
> +    u32 mn_mode_reg;    /* MIU DDR Mode Register */
> +    u32 mn_ext_mode_reg;    /* MIU DDR Extended Mode Register */
> +    u32 mn_timing_0;    /* MIU Memory Control Timing Rgister */
> +    u32 mn_timing_1;    /* MIU Extended Memory Ctrl Timing Register */
> +    u32 mn_timing_2;    /* MIU Extended Memory Ctrl Timing2 Register */
> +
> +    /* SN-related config */
> +    u32 sn_sync_mode;    /* enable/ sync shift cclk / sync shift mclk */
> +    u32 sn_pt_mode;        /* pass through mode */
> +    u32 sn_ecc_en;
> +    u32 sn_wb_en;
> +    u32 sn_crystal_freq;
> +    u32 sn_speed;
> +    u32 sn_org;
> +    u32 sn_depth;
> +    u32 sn_dll_tap;
> +    u32 sn_rd_latency;
> +
> +    u32 mac_addr_hi_0;
> +    u32 mac_addr_hi_1;
> +    u32 mac_addr_hi_2;
> +    u32 mac_addr_hi_3;
> +
> +    u32 magic;        /* indicates flash has been initialized */
> +
> +    u32 mn_rdimm;
> +    u32 mn_dll_override;
> +
> +};
> +
> +#define FLASH_NUM_PORTS        (4)
> +
> +struct netxen_flash_mac_addr {
> +    u32 flash_addr[32];
> +};
> +
> +#define FLASH_NUM_MAC_PER_PORT    32
> +struct netxen_user_info {
> +    u8 flash_md5[16 * 64];
> +    /* bootloader */
> +    u32 bootld_version;
> +    u32 bootld_size;
> +    /* image */
> +    u32 image_version;
> +    u32 image_size;
> +    /* primary image status */
> +    u32 primary_status;
> +    u32 secondary_present;
> +
> +    /* MAC address , 4 ports, 32 address per port */
> +    u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
> +    u32 sub_sys_id;
> +    u8 serial_num[32];
> +
> +    /* Any user defined data */
> +};
> +
> +/*
> + * Flash Layout - new format.
> + */
> +#define FLASH_NUM_MAC_PER_PORT    32
> +struct netxen_new_user_info {
> +    u8 flash_md5[16 * 64];
> +    /* bootloader */
> +    u32 bootld_version;
> +    u32 bootld_size;
> +    /* image */
> +    u32 image_version;
> +    u32 image_size;
> +    /* primary image status */
> +    u32 primary_status;
> +    u32 secondary_present;
> +
> +    /* MAC address , 4 ports, 32 address per port */
> +    u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
> +    u32 sub_sys_id;
> +    u8 serial_num[32];
> +
> +    /* Any user defined data */
> +};
> +
> +#define SECONDARY_IMAGE_PRESENT 0xb3b4b5b6
> +#define SECONDARY_IMAGE_ABSENT    0xffffffff
> +#define PRIMARY_IMAGE_GOOD    0x5a5a5a5a
> +#define PRIMARY_IMAGE_BAD    0xffffffff
> +
> +/* Flash memory map */
> +typedef enum {
> +    CRBINIT_START = 0,    /* Crbinit section */
> +    BRDCFG_START = 0x4000,    /* board config */
> +    INITCODE_START = 0x6000,    /* pegtune code */
> +    BOOTLD_START = 0x10000,    /* bootld */
> +    IMAGE_START = 0x43000,    /* compressed image */
> +    SECONDARY_START = 0x200000,    /* backup images */
> +    PXE_START = 0x3E0000,    /* user defined region */
> +    USER_START = 0x3E8000,    /* User defined region for new boards */
> +    FIXED_START = 0x3F0000    /* backup of crbinit */
> +} netxen_flash_map_t;
> +
> +#define USER_START_OLD PXE_START    /* for backward compatibility */
> +
> +#define FLASH_START        (CRBINIT_START)
> +#define INIT_SECTOR        (0)
> +#define PRIMARY_START         (BOOTLD_START)
> +#define FLASH_CRBINIT_SIZE     (0x4000)
> +#define FLASH_BRDCFG_SIZE     (sizeof(struct netxen_board_info))
> +#define FLASH_USER_SIZE        (sizeof(netxen_user_info)/sizeof(u32))
> +#define FLASH_SECONDARY_SIZE     (USER_START-SECONDARY_START)
> +#define NUM_PRIMARY_SECTORS    (0x20)
> +#define NUM_CONFIG_SECTORS     (1)
> +int is_flash_supported(struct netxen_adapter *adapter);
> +int get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
> +extern char netxen_nic_driver_string[];
> +extern void netxen_change_ringparam(struct netxen_adapter *adapter);
> +extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
> +                int *valp);
> +
> +extern struct ethtool_ops netxen_nic_ethtool_ops;
> +
> +/*
> + * The PCI VendorID and DeviceID for our board.
> + */
> +#define PCI_VENDOR_ID_NX       0x4040
> +#define PCI_DEVICE_ID_NX_XG    0x0001
> +#define PCI_DEVICE_ID_NX_CX4   0x0002
> +#define PCI_DEVICE_ID_NX_QG    0x0003
> +#define PCI_DEVICE_ID_NX_IMEZ  0x0004
> +#define PCI_DEVICE_ID_NX_HMEZ  0x0005
> +
> +#define NETXEN_PCI_ID(X) { PCI_DEVICE(PCI_VENDOR_ID_NX, (X)) }

why do you need these defines at all?  Device IDs used on only one place 
can normally just be directly coded as a numeric hexidecimal constant.


> +#define PFX "netxen: "
> +
> +/* Note: Make sure to not call this before adapter->port is valid */
> +#if !defined(NETXEN_DEBUG)
> +#define DPRINTK(klevel, fmt, args...)    do { \
> +    } while (0)
> +#else
> +#define DPRINTK(klevel, fmt, args...)    do { \
> +    printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
> +        (adapter != NULL && adapter->port != NULL && \
> +        adapter->port[0] != NULL && \
> +        adapter->port[0]->netdev != NULL) ? \
> +        adapter->port[0]->netdev->name : NULL, \
> +        ## args); } while(0)
> +#endif
> +
> +/* Number of status descriptors to handle per interrupt */
> +#define MAX_STATUS_HANDLE    (128)
> +
> +/*
> + * netxen_skb_frag{} is to contain mapping info for each SG list. This
> + * has to be freed when DMA is complete. This is part of 
> netxen_tx_buffer{}.
> + */
> +struct netxen_skb_frag {
> +    u64 dma;
> +    u32 length;
> +};

This generated padding -- is that ok?



> +/*    Following defines are for the state of the buffers    */
> +#define    NETXEN_BUFFER_FREE    0
> +#define    NETXEN_BUFFER_BUSY    1
> +
> +/*
> + * There will be one netxen_buffer per skb packet.    These will be
> + * used to save the dma info for pci_unmap_page()
> + */
> +struct netxen_cmd_buffer {
> +    struct sk_buff *skb;
> +    struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
> +    u32 total_length;
> +    u32 mss;
> +    u32 port:16, cmd:8, frag_count:8;
> +    unsigned long time_stamp;
> +    u32 state;
> +    u32 no_of_descriptors;
> +};

ditto bitfield comments.

In general bitfields are to be avoided for many reasons.


> +/* In rx_buffer, we do not need multiple fragments as is a single 
> buffer */
> +struct netxen_rx_buffer {
> +    struct sk_buff *skb;
> +    u64 dma;
> +    u32 ref_handle:16, state:16;
> +};

ditto


> +/* Board types */
> +#define    NETXEN_NIC_GBE    0x01
> +#define    NETXEN_NIC_XGBE    0x02
> +
> +/*
> + * One hardware_context{} per adapter
> + * contains interrupt info as well shared hardware info.
> + */
> +struct netxen_hardware_context {
> +    struct pci_dev *pdev;
> +    unsigned long pci_base;    /* base of mapped phantom memory */
> +    unsigned long pci_len;    /* length of mapped phantom memory */

kill pci_base, pci_len


> +    u16 vendor_id;
> +    u16 device_id;
> +    u8 revision_id;

kill all three of these


> +    u16 pci_cmd_word;

kill


> +    u16 board_type;
> +    u16 max_ports;
> +    struct netxen_board_info boardcfg;
> +    u32 xg_linkup;
> +    struct netxen_adapter *adapter;
> +    u32 crb_base;
> +    unsigned long db_base;    /* base of mapped db memory */
> +    unsigned long db_len;    /* length of mapped db memory */

kill db_base, db_len


> +#define MINIMUM_ETHERNET_FRAME_SIZE    64    /* With FCS */
> +#define ETHERNET_FCS_SIZE        4
> +
> +struct netxen_adapter_stats {
> +    u64 ints;
> +    u64 hostints;
> +    u64 otherints;
> +    u64 process_rcv;
> +    u64 process_xmit;
> +    u64 noxmitdone;
> +    u64 xmitcsummed;
> +    u64 post_called;
> +    u64 posted;
> +    u64 lastposted;
> +    u64 goodskbposts;
> +};
> +
> +/*
> + * Ring which will hold the skbs which can be fed to receive ring
> + */
> +#define NETXEN_SKB_ARRAY_SIZE    1024
> +
> +struct netxen_recv_skb_ring {
> +    struct sk_buff **skb_array;
> +    u32 interrupt_index;
> +    u32 tasklet_index;
> +    u32 data_size;
> +};
> +
> +/*
> + * Rcv Descriptor Context. One such per Rcv Descriptor. There may
> + * be one Rcv Descriptor for normal packets, one for jumbo and may be 
> others.
> + */
> +struct netxen_rcv_desc_ctx {
> +    u32 flags;
> +    u32 producer;
> +    u32 rcv_pending;    /* Num of bufs posted in phantom */
> +    u32 rcv_free;        /* Num of bufs in free list */
> +    u32 phys_addr;
> +    struct rcv_desc_t *desc_head;    /* address of rx ring in Phantom */
> +    u32 max_rx_desc_count;
> +    u32 dma_size;
> +    u32 skb_size;
> +    struct netxen_rx_buffer *rx_buf_arr;    /* rx buffers for receive   */
> +    dma_addr_t rx_buf_phys;    /* physical address of above */
> +    int begin_alloc;
> +};
> +
> +/*
> + * Receive context. There is one such structure per instance of the
> + * receive processing. Any state information that is relevant to
> + * the receive, and is must be in this structure. The global data may be
> + * present elsewhere.
> + */
> +struct netxen_recv_context {
> +    struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
> +    u32 status_rx_producer;
> +    u32 status_rx_consumer;
> +    u32 rcv_status_desc_phys_addr;
> +    struct status_desc_t *rcv_status_desc_head;
> +};
> +
> +#define NETXEN_NIC_MSI_ENABLED 0x02
> +
> +struct netxen_hardware_ring_context {
> +    /* Address of cmd ring in Phantom */
> +    struct cmd_desc_type0_t *cmd_desc_head;
> +    u32 cmd_producer;
> +    u32 cmd_consumer;
> +    u32 status_rx_producer;
> +    u32 status_rx_consumer;
> +    u32 cmd_desc_phys_addr;
> +};
> +
> +struct netxen_ring_context {
> +    struct netxen_hardware_ring_context hw_ring_ctx;
> +    u32 cmd_producer;
> +    u32 *cmd_consumer;
> +
> +    u32 last_cmd_consumer;
> +    /* Num of bufs posted in phantom */
> +    u32 pending_cmd_count;
> +    u32 free_cmd_count;    /* Num of bufs in free list */
> +    u32 max_tx_desc_count;
> +    u32 max_rx_desc_count;
> +    u32 max_jumbo_rx_desc_count;
> +    /* Num of instances active on cmd buffer ring */
> +    u32 proc_cmd_buf_counter;
> +    volatile u32 cmd_peg_consumer;
> +
> +    struct netxen_cmd_buffer *cmd_buf_arr;    /* Command buffers for 
> xmit */
> +    struct netxen_rx_buffer *rx_buf_arr;    /* rx buffers for receive   */
> +
> +    /*
> +     * Receive instance.
> +     */
> +    struct netxen_recv_context recv_ctx;
> +
> +    /* context interface shared between card and host */
> +    struct ring_context *ctx_desc;
> +    u32 ctx_desc_phys_addr;
> +
> +};
> +
> +/* this structure by all ports on the adapter */
> +struct netxen_adapter {
> +    struct netxen_hardware_context ahw;
> +    int port_count;        /* Number of configured ports  */
> +    int active_ports;    /* Number of open ports */
> +    struct netxen_port **port;    /* ptr to each port  */
> +    spinlock_t tx_lock;
> +    rwlock_t adapter_lock;
> +    spinlock_t lock;

Most likely need to eliminate some locks here.


> +    struct work_struct watchdog_task;
> +    struct work_struct tx_timeout_task[4];

Why do you have 4 tx_timeout_tasks ?


> +    struct timer_list watchdog_timer;
> +
> +    u32 curr_window;
> +
> +    u32 num_threads, total_threads;    /*Use to keep track of xmit 
> threads */
> +
> +    u32 flags;
> +    u32 irq;
> +    int driver_mismatch;
> +
> +    struct netxen_adapter_stats stats;
> +
> +    struct netxen_ring_context ring_ctx[MAX_RING_CTX];
> +    int number;
> +    int is_up;
> +    int work_done;
> +};                /* netxen_adapter structure */
> +
> +/* Max number of xmit producer threads that can run simultaneously */
> +#define    MAX_XMIT_PRODUCERS        16
> +
> +struct netxen_port_stats {
> +    u64 rcvdbadskb;
> +    u64 xmitcalled;
> +    u64 xmitedframes;
> +    u64 xmitfinished;
> +    u64 badskblen;
> +    u64 nocmddescriptor;
> +    u64 polled;
> +    u64 uphappy;
> +    u64 updropped;
> +    u64 uplcong;
> +    u64 uphcong;
> +    u64 upmcong;
> +    u64 updunno;
> +    u64 skbfreed;
> +    u64 txdropped;
> +    u64 txnullskb;
> +    u64 csummed;
> +    u64 no_rcv;
> +    u64 rxbytes;
> +    u64 txbytes;
> +};
> +
> +struct netxen_port {
> +    struct netxen_adapter *adapter;
> +
> +    u16 portnum;        /* GBE port number */
> +    u16 link_speed;
> +    u16 link_duplex;
> +    u16 link_autoneg;
> +
> +    int flags;
> +    spinlock_t stats_lock;
> +
> +    struct net_device *netdev;
> +    struct pci_dev *pdev;
> +    struct net_device_stats net_stats;
> +    struct netxen_port_stats stats;
> +};
> +
> +extern char netxen_nic_driver_name[];
> +
> +#define NETXEN_CTX_SIGNATURE    0xdee0
> +#define MAX_PEG_RING_CTX    4
> +
> +#define RX_PRODUCER 0
> +#define RX_PRODUCER_JUMBO 1
> +#define TX_PRODUCER 2
> +#define STS_PRODUCER 3
> +
> +#define NUM_DB_CODE 16
> +
> +#define NETXEN_RCV_PRODUCER(ringid)    (ringid)
> +
> +#define NETXEN_CMD_PRODUCER 2
> +#define NETXEN_RCV_STATUS_CONSUMER 3
> +
> +struct ctx_msg {
> +    u32 PegId:2, Count:16, CtxId:10, Opcode:4;
> +};

bitfields


> +struct rcv_context {
> +    u64 RcvRingAddrLo:32, RcvRingAddrHi:32;
> +    u32 RcvRingSize;
> +    u32 Rsrv;
> +};
> +
> +struct ring_context {
> +
> +    u64 CMD_CONSUMER_OFFSET;
> +    u64 CmdRingAddrLo:32, CmdRingAddrHi:32;
> +    u32 CmdRingSize;
> +    u32 Rsrv;
> +    struct rcv_context RcvContext[2];
> +    u64 StsRingAddrLo:32, StsRingAddrHi:32;
> +    u32 StsRingSize;
> +    u32 CtxId;
> +} __attribute__ ((aligned(64)));

ditto, ditto



> +static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
> +{
> +    u32 mask;
> +
> +    mask = 0x7ff;
> +
> +    /*
> +     * ISR_INT_MASK: Can be read from window 0 or 1.
> +     */
> +    writel(mask, (void *)(adapter->ahw.pci_base + ISR_INT_MASK));
> +}

kill 'mask' variable


> +static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
> +{
> +    u32 mask;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        mask = 0x77b;
> +        break;
> +    case NETXEN_NIC_XGBE:
> +        mask = 0x77f;
> +        break;
> +    default:
> +        mask = 0x7ff;
> +        break;
> +    }
> +
> +    writel(mask, (void *)(adapter->ahw.pci_base + ISR_INT_MASK));
> +
> +    if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
> +        mask = 0xbff;
> +        writel(mask,
> +               (void *)(adapter->ahw.pci_base + ISR_INT_TARGET_MASK));
> +    }
> +}
> +
> +#endif                /* __NETXEN_NIC_H_ */
> 
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 3/9] NetXen: Registers info header file.
  2006-07-05 13:31 ` [PATCH 2.6.17 3/9] NetXen: Registers info " Linsys Contractor Amit S. Kale
@ 2006-07-05 15:51   ` Jeff Garzik
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2006-07-05 15:51 UTC (permalink / raw)
  To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj, Andrew Morton

Linsys Contractor Amit S. Kale wrote:
=> +extern struct netxen_adapter *g_adapter;
> +
> +/*
> + * The basic unit of access when reading/writing control registers.
> + */
> +
> +typedef u32 netxen_crbword_t;    /* single word in CRB space */
> +
> +#define NETXEN_HW_H0_CH_HUB_ADR    0x05
> +#define NETXEN_HW_H1_CH_HUB_ADR    0x0E
> +#define NETXEN_HW_H2_CH_HUB_ADR    0x03
> +#define NETXEN_HW_H3_CH_HUB_ADR    0x01
> +#define NETXEN_HW_H4_CH_HUB_ADR    0x06
> +#define NETXEN_HW_H5_CH_HUB_ADR    0x07
> +#define NETXEN_HW_H6_CH_HUB_ADR    0x08
> +
> +/*  Hub 0 */
> +#define NETXEN_HW_MN_CRB_AGT_ADR    0x15
> +#define NETXEN_HW_MS_CRB_AGT_ADR    0x25
> +
> +/*  Hub 1 */
> +#define NETXEN_HW_PS_CRB_AGT_ADR    0x73
> +#define NETXEN_HW_SS_CRB_AGT_ADR    0x20
> +#define NETXEN_HW_RPMX3_CRB_AGT_ADR    0x0b
> +#define NETXEN_HW_QMS_CRB_AGT_ADR    0x00
> +#define NETXEN_HW_SQGS0_CRB_AGT_ADR    0x01
> +#define NETXEN_HW_SQGS1_CRB_AGT_ADR    0x02
> +#define NETXEN_HW_SQGS2_CRB_AGT_ADR    0x03
> +#define NETXEN_HW_SQGS3_CRB_AGT_ADR    0x04
> +#define NETXEN_HW_C2C0_CRB_AGT_ADR    0x58
> +#define NETXEN_HW_C2C1_CRB_AGT_ADR    0x59
> +#define NETXEN_HW_C2C2_CRB_AGT_ADR    0x5a
> +#define NETXEN_HW_RPMX2_CRB_AGT_ADR    0x0a
> +#define NETXEN_HW_RPMX4_CRB_AGT_ADR    0x0c
> +#define NETXEN_HW_RPMX7_CRB_AGT_ADR    0x0f
> +#define NETXEN_HW_RPMX9_CRB_AGT_ADR    0x12
> +#define NETXEN_HW_SMB_CRB_AGT_ADR    0x18


overall, enums are preferred over #define.  It provides type info to the 
compiler, provides symbol info to debuggers and similar tools, and other 
benefits.

e.g.

enum {
	NETXEN_HW_RPMX9_CRB_AGT_ADR	= 0x12,
	NETXEN_HW_SMB_CRB_AGT_ADR	= 0x18,
};



> +#define NETXEN_PCI_MAPSIZE    128
> +#define NETXEN_PCI_DDR_NET    (unsigned long)0x00000000
> +#define NETXEN_PCI_QDR_NET    (unsigned long)0x04000000
> +#define NETXEN_PCI_DIRECT_CRB    (unsigned long)0x04400000
> +#define NETXEN_PCI_CAMQM_MAX    (unsigned long)0x04ffffff
> +#define NETXEN_PCI_OCM0        (unsigned long)0x05000000
> +#define NETXEN_PCI_OCM0_MAX    (unsigned long)0x050fffff
> +#define NETXEN_PCI_OCM1        (unsigned long)0x05100000
> +#define NETXEN_PCI_OCM1_MAX    (unsigned long)0x051fffff
> +#define NETXEN_PCI_CRBSPACE    (unsigned long)0x06000000

Use the 'UL' suffix, not a cast



> +struct netxen_pcix_crb_window {
> +    netxen_crbword_t rsvd1:25, addrbit:1,    /* bit 25 of CRB address */
> +     rsvd2:6;
> +};

see bitfields objections in another email


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 4/9] NetXen: hardware access routines.
  2006-07-05 13:34 ` [PATCH 2.6.17 4/9] NetXen: hardware access routines Linsys Contractor Amit S. Kale
@ 2006-07-05 16:00   ` Jeff Garzik
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2006-07-05 16:00 UTC (permalink / raw)
  To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj, Andrew Morton

Linsys Contractor Amit S. Kale wrote:
> +/**
> + * netxen_nic_set_multi - Multicast
> + **/
> +void netxen_nic_set_multi(struct net_device *netdev)
> +{
> +    struct netxen_port *port = netdev_priv(netdev);
> +    struct dev_mc_list *mc_ptr;
> +
> +    mc_ptr = netdev->mc_list;
> +    if (netdev->flags & IFF_PROMISC)
> +        netxen_nic_set_promisc_mode(port);
> +    else
> +        netxen_nic_unset_promisc_mode(port);
> +}

This appears unfinished, it does not handle multicast at all.



> +int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu)
> +{
> +    struct netxen_port *port = netdev_priv(netdev);
> +
> +    if (new_mtu & 0xffff0000)
> +        return -EINVAL;
> +
> +    if (new_mtu > 8000) {

please use named constants here, rather than magic numbers


> +        printk(KERN_ERR "%s: %s MTU > 8000 is not supported\n",
> +               netxen_nic_driver_name, netdev->name);
> +        return -EINVAL;
> +    }
> +
> +    netxen_nic_set_mtu(port, new_mtu);
> +    netdev->mtu = new_mtu;
> +
> +    return 0;
> +}
> +
> +/*
> + * check if the firmware has been downloaded and ready to run  and
> + * setup the address for the descriptors in the adapter
> + */

ah hah!  so you do have a firmware!  Well, export that version via 
ethtool...



> +/*
> + * Changes the CRB window to the specified window.
> + */
> +void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, 
> u32 wndw)
> +{
> +    struct netxen_pcix_crb_window window;
> +    unsigned long offset;
> +    u32 tmp;
> +
> +    if (adapter->curr_window == wndw)
> +        return;
> +
> +    /*
> +     * Move the CRB window.
> +     * We need to write to the "direct access" region of PCI
> +     * to avoid a race condition where the window register has
> +     * not been successfully written across CRB before the target
> +     * register address is received by PCI. The direct region bypasses
> +     * the CRB bus.
> +     */
> +    offset = adapter->ahw.pci_base + NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW);
> +
> +    *(netxen_crbword_t *) & window = 0;

WTF is this code doing?  It looks quite wrong...


> +    window.addrbit = wndw;
> +    writel(*(unsigned int *)&window, (void *)(offset));

bug:  code is backwards.  was this code ever tested?


> +    /* MUST make sure window is set before we forge on... */
> +    while ((tmp = readl((void *)offset)) != *(u32 *) & window)
> +        printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
> +               "registered properly: 0x%08x.\n",
> +               netxen_nic_driver_name, __FUNCTION__, tmp);

infinite printk loop.


> +    adapter->curr_window = wndw;
> +}
> +
> +/*
> + * Set the CRB window based on the offset.
> + */
> +static inline unsigned long
> +netxen_nic_pci_set_crbwindow(struct netxen_adapter *adapter, u64 off)
> +{
> +    /*
> +     * See if we are currently pointing to the region we want to use next.
> +     */
> +
> +    if ((off >= NETXEN_CRB_PCIX_HOST) && (off < NETXEN_CRB_DDR_NET)) {
> +        /*
> +         * No need to change window. PCIX and PCIE regs are in both
> +         * windows.
> +         */
> +        return off;
> +    }
> +
> +    if ((off >= NETXEN_CRB_PCIX_HOST) && (off < NETXEN_CRB_PCIX_HOST2)) {
> +        /* We are in first CRB window */
> +        if (adapter->curr_window != 0)
> +            netxen_nic_pci_change_crbwindow(adapter, 0);
> +
> +        return off;
> +    }
> +
> +    if ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) {
> +        /* We are in second CRB window */
> +        off = off - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST;
> +
> +        if (adapter->curr_window != 1)
> +            netxen_nic_pci_change_crbwindow(adapter, 1);
> +
> +        return off;
> +    }
> +
> +    if ((off >= NETXEN_PCI_DIRECT_CRB) && (off < NETXEN_PCI_CAMQM_MAX)) {
> +        /*
> +         * We are in the QM or direct access register region - do
> +         * nothing
> +         */
> +        return off;
> +    }
> +
> +    /* strange address given */
> +    dump_stack();
> +    printk(KERN_WARNING
> +           "%s: Warning: netxen_nic_pci_set_crbwindow called with"
> +           " an unknown address(%llx)\n", netxen_nic_driver_name, off);
> +
> +    return off;
> +}
> +
> +int
> +netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void 
> *data,
> +               int len)
> +{
> +    void *addr;
> +    unsigned long flags = 0;
> +
> +    if (ADDR_IN_WINDOW1(off)) {
> +        addr = NETXEN_CRB_NORMALIZE(adapter, off);
> +        read_lock(&adapter->adapter_lock);
> +    } else {        /* Window 0 */
> +        addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
> +        write_lock_irqsave(&adapter->adapter_lock, flags);
> +        netxen_nic_pci_change_crbwindow(adapter, 0);
> +    }
> +
> +    DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
> +        " data %llx len %d\n",
> +        adapter->ahw.pci_base, off, addr,
> +        *(unsigned long long *)data, len);
> +    switch (len) {
> +    case 1:
> +        writeb(*(u8 *) data, addr);
> +        break;
> +    case 2:
> +        writew(*(u16 *) data, addr);
> +        break;
> +    case 4:
> +        writel(*(u32 *) data, addr);
> +        break;
> +    case 8:
> +        writeq(*(u64 *) data, addr);
> +        break;
> +    default:
> +        DPRINTK(INFO,
> +            "writing data %lx to offset %llx, num words=%d\n",
> +            *(unsigned long *)data, off, (len >> 3));
> +
> +        NETXEN_NIC_HW_BLOCK_WRITE_64(data, addr, (len >> 3));
> +        break;
> +    }
> +    if (ADDR_IN_WINDOW1(off))
> +        read_unlock(&adapter->adapter_lock);
> +    else {            /* Window 0 */
> +        netxen_nic_pci_change_crbwindow(adapter, 1);
> +        write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +    }

buggy locking?  you read-lock when writing to registers.


> +int
> +netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
> +              int len)
> +{
> +    void *addr;
> +    unsigned long flags = 0;
> +
> +    if (ADDR_IN_WINDOW1(off)) {    /* Window 1 */
> +        addr = NETXEN_CRB_NORMALIZE(adapter, off);
> +        read_lock(&adapter->adapter_lock);
> +    } else {        /* Window 0 */
> +        addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
> +        write_lock_irqsave(&adapter->adapter_lock, flags);
> +        netxen_nic_pci_change_crbwindow(adapter, 0);
> +    }
> +
> +    DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
> +        adapter->ahw.pci_base, off, addr);
> +    switch (len) {
> +    case 1:
> +        *(u8 *) data = readb(addr);
> +        break;
> +    case 2:
> +        *(u16 *) data = readw(addr);
> +        break;
> +    case 4:
> +        *(u32 *) data = readl(addr);
> +        break;
> +    case 8:
> +        *(u64 *) data = readq(addr);
> +        break;
> +    default:
> +        NETXEN_NIC_HW_BLOCK_READ_64(data, addr, (len >> 3));
> +        break;
> +    }
> +    DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
> +
> +    if (ADDR_IN_WINDOW1(off))
> +        read_unlock(&adapter->adapter_lock);
> +    else {            /* Window 0 */
> +        netxen_nic_pci_change_crbwindow(adapter, 1);
> +        write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +    }
> +
> +    return 0;
> +}
> +
> +void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 
> val)
> +{                /* Only for window 1 */
> +    void *addr;
> +
> +    read_lock(&adapter->adapter_lock);
> +
> +    if (adapter->curr_window != 1)
> +        netxen_nic_pci_change_crbwindow(adapter, 1);
> +    addr = NETXEN_CRB_NORMALIZE(adapter, off);
> +    DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
> +        adapter->ahw.pci_base, off, addr, val);
> +    writel(val, addr);
> +
> +    read_unlock(&adapter->adapter_lock);
> +}
> +
> +int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
> +{                /* Only for window 1 */
> +    void *addr;
> +    int val;
> +
> +    read_lock(&adapter->adapter_lock);
> +    addr = NETXEN_CRB_NORMALIZE(adapter, off);
> +    DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
> +        adapter->ahw.pci_base, off, addr);
> +    val = readl(addr);
> +    writel(val, addr);
> +    read_unlock(&adapter->adapter_lock);
> +
> +    return val;
> +}
> +
> +/* Change the window to 0, write and change back to window 1. */
> +void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 
> value)
> +{
> +    unsigned long flags;
> +    void *addr;
> +
> +    write_lock_irqsave(&adapter->adapter_lock, flags);
> +    netxen_nic_pci_change_crbwindow(adapter, 0);
> +    addr = (void *)(adapter->ahw.pci_base + index);
> +    writel(value, addr);
> +    netxen_nic_pci_change_crbwindow(adapter, 1);
> +    write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +}
> +
> +/* Change the window to 0, read and change back to window 1. */
> +void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 
> * value)
> +{
> +    unsigned long flags;
> +    void *addr;
> +
> +    addr = (void *)(adapter->ahw.pci_base + index);
> +
> +    write_lock_irqsave(&adapter->adapter_lock, flags);
> +    netxen_nic_pci_change_crbwindow(adapter, 0);
> +    *value = readl(addr);
> +    netxen_nic_pci_change_crbwindow(adapter, 1);
> +    write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +}

highly sub-optimal, deadlock-prone locking.

every register read/write should not acquire a lock.


> +static unsigned long
> +netxen_nic_pci_set_window(unsigned long long pci_base, unsigned long 
> long addr)
> +{
> +    static int ddr_mn_window = -1;
> +    static int qdr_sn_window = -1;
> +    int window;
> +
> +    if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, 
> NETXEN_ADDR_DDR_NET_MAX)) {
> +        /* DDR network side */
> +        addr -= NETXEN_ADDR_DDR_NET;
> +        window = (addr >> 25) & 0x3ff;
> +        if (ddr_mn_window != window) {
> +            ddr_mn_window = window;
> +            writel(window, (void *)(ptrdiff_t) (pci_base +
> +                                NETXEN_PCIX_PH_REG
> +                                (PCIX_MN_WINDOW)));
> +            /* MUST make sure window is set before we forge on... */
> +            readl((void *)(ptrdiff_t) (pci_base +
> +                           NETXEN_PCIX_PH_REG
> +                           (PCIX_MN_WINDOW)));
> +        }
> +        addr -= (window * 0x2000000);
> +        addr += NETXEN_PCI_DDR_NET;
> +    } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, 
> NETXEN_ADDR_OCM0_MAX)) {
> +        addr -= NETXEN_ADDR_OCM0;
> +        addr += NETXEN_PCI_OCM0;
> +    } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, 
> NETXEN_ADDR_OCM1_MAX)) {
> +        addr -= NETXEN_ADDR_OCM1;
> +        addr += NETXEN_PCI_OCM1;
> +    } else
> +        if (ADDR_IN_RANGE
> +        (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
> +        /* QDR network side */
> +        addr -= NETXEN_ADDR_QDR_NET;
> +        window = (addr >> 22) & 0x3f;
> +        if (qdr_sn_window != window) {
> +            qdr_sn_window = window;
> +            writel((window << 22),
> +                   (void *)(ptrdiff_t) (pci_base +
> +                            NETXEN_PCIX_PH_REG
> +                            (PCIX_SN_WINDOW)));
> +            /* MUST make sure window is set before we forge on... */
> +            readl((void *)(ptrdiff_t) (pci_base +
> +                           NETXEN_PCIX_PH_REG
> +                           (PCIX_SN_WINDOW)));
> +        }
> +        addr -= (window * 0x400000);
> +        addr += NETXEN_PCI_QDR_NET;
> +    } else {
> +        /*
> +         * peg gdb frequently accesses memory that doesn't exist,
> +         * this limits the chit chat so debugging isn't slowed down.
> +         */
> +        if ((netxen_pci_set_window_warning_count++ < 8)
> +            || (netxen_pci_set_window_warning_count % 64 == 0))
> +            printk("%s: Warning:netxen_nic_pci_set_window()"
> +                   " Unknown address range!\n",
> +                   netxen_nic_driver_name);
> +
> +    }
> +    return addr;
> +}
> +
> +/* read num_words from hardware (num_words in 64 bits    */
> +void
> +netxen_nic_mem_block_read(struct netxen_adapter *adapter, u64 off,
> +              void *data, int num_words)
> +{
> +    void *addr;
> +    unsigned long flags;
> +
> +    write_lock_irqsave(&adapter->adapter_lock, flags);
> +    off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off);
> +    addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
> +    DPRINTK(INFO, "reading from base %lx offset %lx addr %p\n",
> +        adapter->ahw.pci_base, (unsigned long)off, addr);
> +    NETXEN_NIC_HW_BLOCK_READ_64(data, addr, num_words);
> +    write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +}
> +
> +int
> +netxen_nic_pci_mem_write(struct netxen_adapter *adapter, u64 off,
> +             void *data, int size)
> +{
> +    unsigned long flags;
> +    void *addr;
> +    int ret = 0;
> +
> +    write_lock_irqsave(&adapter->adapter_lock, flags);
> +    off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off);
> +    addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
> +    DPRINTK(INFO, "writing data %llx to offset %llx\n",
> +        *(unsigned long long *)data, off);
> +    switch (size) {
> +    case 1:
> +        writeb(*(u8 *) data, addr);
> +        break;
> +    case 2:
> +        writew(*(u16 *) data, addr);
> +        break;
> +    case 4:
> +        writel(*(u32 *) data, addr);
> +        break;
> +    case 8:
> +        writeq(*(u64 *) data, addr);
> +        break;
> +    default:
> +        ret = 1;
> +        break;
> +    }
> +    write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +    DPRINTK(INFO, "wrote %llx\n", *(unsigned long long *)data);
> +
> +    return ret;
> +}
> +
> +int
> +netxen_nic_pci_mem_read(struct netxen_adapter *adapter,
> +            u64 off, void *data, int size)
> +{
> +    unsigned long flags;
> +    void *addr;
> +    int ret = 0;
> +
> +    if (data == NULL || off > NETXEN_MEMADDR_MAX) {
> +        printk(KERN_ERR "data: %p off:%llx\n", data, off);
> +        return 1;
> +    }
> +    write_lock_irqsave(&adapter->adapter_lock, flags);
> +    off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off);
> +    addr = (void *)(ptrdiff_t) (adapter->ahw.pci_base + off);
> +    switch (size) {
> +    case 1:
> +        *(u8 *) data = readb(addr);
> +        break;
> +    case 2:
> +        *(u16 *) data = readw(addr);
> +        break;
> +    case 4:
> +        *(u32 *) data = readl(addr);
> +        break;
> +    case 8:
> +        *(u64 *) data = readq(addr);
> +        break;
> +    default:
> +        ret = 1;
> +        break;
> +    }
> +    write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +    DPRINTK(INFO, "read %llx\n", *(unsigned long long *)data);
> +
> +    return ret;
> +}

Delete the above routines and just open-code the register accesses.


> +int netxen_nic_get_board_info(struct netxen_adapter *adapter)
> +{
> +    int rv = 0;
> +    int addr = BRDCFG_START;
> +    struct netxen_board_info *boardinfo;
> +    int index;
> +    u32 *ptr32;
> +
> +    boardinfo = &adapter->ahw.boardcfg;
> +    ptr32 = (u32 *) boardinfo;
> +
> +    for (index = 0; index < sizeof(struct netxen_board_info) / 
> sizeof(u32);
> +         index++) {
> +        if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
> +            rv = -1;
> +            return rv;
> +        }
> +        ptr32++;
> +        addr += sizeof(u32);
> +    }
> +    if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
> +        printk("%s: ERROR reading %s board config."
> +               " Read %x, expected %x\n", netxen_nic_driver_name,
> +               netxen_nic_driver_name,
> +               boardinfo->magic, NETXEN_BDINFO_MAGIC);
> +        rv = -1;
> +    }
> +    if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
> +        printk("%s: Unknown board config version."
> +               " Read %x, expected %x\n", netxen_nic_driver_name,
> +               boardinfo->header_version, NETXEN_BDINFO_VERSION);
> +        rv = -1;
> +    }
> +
> +    DPRINTK(INFO, "Discovered board type:0x%x  ", boardinfo->board_type);
> +    switch ((netxen_brdtype_t) boardinfo->board_type) {
> +    case NETXEN_BRDTYPE_P2_SB35_4G:
> +        adapter->ahw.board_type = NETXEN_NIC_GBE;
> +        break;
> +    case NETXEN_BRDTYPE_P2_SB31_10G:
> +    case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
> +    case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
> +    case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
> +        adapter->ahw.board_type = NETXEN_NIC_XGBE;
> +        break;
> +    case NETXEN_BRDTYPE_P1_BD:
> +    case NETXEN_BRDTYPE_P1_SB:
> +    case NETXEN_BRDTYPE_P1_SMAX:
> +    case NETXEN_BRDTYPE_P1_SOCK:
> +        adapter->ahw.board_type = NETXEN_NIC_GBE;
> +        break;
> +    default:
> +        printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
> +               boardinfo->board_type);
> +        break;
> +    }
> +
> +    return rv;
> +}
> +
> +inline int netxen_nic_get_board_num(struct netxen_adapter *adapter)
> +{
> +    return adapter->ahw.boardcfg.board_num;
> +}
> +
> +/* NIU access sections */
> +
> +/* Set the MAC address for a port */
> +int netxen_nic_macaddr_set(struct netxen_port *port, u8 * addr)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    int phy = port->portnum, ret = 0;
> +
> +    if ((phy < 0) || (phy > 3))
> +        return -1;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        ret = netxen_niu_macaddr_set(adapter, phy, addr);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        ret = netxen_niu_xg_macaddr_set(adapter, phy, addr);
> +        break;
> +
> +    default:
> +        dump_stack();
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +/* Return the current MAC address of the given port. */
> +int netxen_nic_macaddr_get(struct netxen_port *port, u8 ** addr)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    int phy = port->portnum;
> +    int ret = 0;
> +
> +    if (addr == NULL)
> +        return -1;
> +    if ((phy < 0) || (phy > 3))
> +        return -1;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        ret = netxen_niu_macaddr_get(adapter, phy,
> +                         (netxen_ethernet_macaddr_t *) *
> +                         addr);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
> +               netxen_nic_driver_name, __FUNCTION__);
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +int netxen_nic_set_mtu(struct netxen_port *port, int new_mtu)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    int ret = 0;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        netxen_nic_write_w0(adapter,
> +                    NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum),
> +                    new_mtu);
> +
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        new_mtu += 100;    /* so that MAC accepts frames > MTU */
> +        netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE,
> +                    new_mtu);
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +int netxen_nic_set_promisc_mode(struct netxen_port *port)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    int phy = port->portnum;
> +    int ret = 0;
> +
> +    if ((phy < 0) || (phy > 3))
> +        return -1;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        ret = netxen_niu_set_promiscuous_mode(adapter, phy,
> +                              NETXEN_NIU_PROMISCOUS_MODE);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        ret = netxen_niu_xg_set_promiscuous_mode(adapter, phy,
> +                             NETXEN_NIU_PROMISCOUS_MODE);
> +
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +int netxen_nic_unset_promisc_mode(struct netxen_port *port)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    int phy = port->portnum;
> +    int ret = 0;
> +
> +    if ((phy < 0) || (phy > 3))
> +        return -1;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        ret = netxen_niu_set_promiscuous_mode(adapter, phy,
> +                              NETXEN_NIU_NON_PROMISCOUS_MODE);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        ret = netxen_niu_xg_set_promiscuous_mode(adapter, phy,
> +                             NETXEN_NIU_NON_PROMISCOUS_MODE);
> +
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }

1) two functions for such a simple task is overkill

2) just create separate hooks for GBE and XGBE, and eliminate these 
wrapper functions that do nothing but "switch (adapter->ahw.board_type)" 
before calling board-specific functions.


> +long
> +netxen_nic_phy_read(struct netxen_adapter *adapter, long phy, long reg,
> +            u32 * readval)
> +{
> +    long ret = 0;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        ret = netxen_niu_gbe_phy_read(adapter, phy, reg, readval);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
> +               netxen_nic_driver_name, __FUNCTION__);
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +long netxen_nic_phy_write(struct netxen_adapter *adapter, long phy, 
> long reg,
> +              u32 val)
> +{
> +    long ret = 0;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        ret = netxen_niu_gbe_phy_write(adapter, phy, reg, val);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        printk(KERN_ERR "%s: Function %s is not implemented for XG\n",
> +               netxen_nic_driver_name, __FUNCTION__);
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +long netxen_nic_init_port(struct netxen_port *port)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    long portnum = port->portnum;
> +    long ret = 0;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        netxen_nic_disable_phy_interrupts(adapter, portnum);
> +        udelay(20000);

NAK!!  It is unacceptable to spin the CPU for so long.


> +        netxen_niu_gbe_init_port(adapter, portnum);
> +
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        /* Nothing to be done for XG */
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +        ret = -1;
> +    }
> +
> +    return ret;
> +}
> +
> +void netxen_nic_init_niu(struct netxen_adapter *adapter)
> +{
> +    int portno;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++)
> +            netxen_niu_gbe_init_port(adapter, portno);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        /* Do nothing */
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +    }
> +}
> +
> +void netxen_nic_stop_port(struct netxen_port *port)
> +{
> +    long portnum = port->portnum;
> +    struct netxen_adapter *adapter = port->adapter;
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        netxen_niu_disable_gbe_port(adapter, portnum);
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        netxen_niu_disable_xg_port(adapter, portnum);
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +               netxen_nic_driver_name);
> +    }
> +}
> +
> +void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
> +{
> +    int port_nr;
> +    struct netxen_port *port;
> +
> +    for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
> +        port = adapter->port[port_nr];
> +        netxen_nic_stop_port(port);
> +    }
> +}
> +
> +void
> +netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned 
> long off,
> +                int data)
> +{
> +    unsigned long flags;
> +    void *addr;
> +
> +    if (ADDR_IN_WINDOW1(off)) {
> +        read_lock(&adapter->adapter_lock);
> +        writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
> +        read_unlock(&adapter->adapter_lock);
> +    } else {
> +        write_lock_irqsave(&adapter->adapter_lock, flags);
> +        netxen_nic_pci_change_crbwindow(adapter, 0);
> +        addr = (void *)(adapter->ahw.pci_base + off);
> +        writel(data, addr);
> +        netxen_nic_pci_change_crbwindow(adapter, 1);
> +        write_unlock_irqrestore(&adapter->adapter_lock, flags);
> +    }
> +}
> +
> +void netxen_nic_set_link_parameters(struct netxen_port *port)
> +{
> +    struct netxen_adapter *adapter = port->adapter;
> +    struct netxen_niu_phy_status status;
> +    u16 autoneg;
> +    struct netxen_niu_control mode;
> +
> +    netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, (u32 *) & mode);
> +    if (mode.enable_ge) {    /* Gb 10/100/1000 Mbps mode */
> +        if (netxen_nic_phy_read(port->adapter, port->portnum,
> +                    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> +                    (netxen_crbword_t *) & status) == 0) {
> +            if (status.link) {
> +                switch (status.speed) {
> +                case 0:
> +                    port->link_speed = SPEED_10;
> +                    break;
> +                case 1:
> +                    port->link_speed = SPEED_100;
> +                    break;
> +                case 2:
> +                    port->link_speed = SPEED_1000;
> +                    break;
> +                default:
> +                    port->link_speed = -1;    /* unknown speed */
> +                    break;
> +                }
> +                switch (status.duplex) {
> +                case 0:
> +                    port->link_duplex = DUPLEX_HALF;
> +                    break;
> +                case 1:
> +                    port->link_duplex = DUPLEX_FULL;
> +                    break;
> +                default:
> +                    port->link_duplex = -1;    /* unknown mode */
> +                    break;
> +                }
> +                if (netxen_nic_phy_read(port->adapter,
> +                            port->portnum,
> +                            NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
> +                            (netxen_crbword_t *) &
> +                            autoneg) != 0)
> +                    port->link_autoneg = autoneg;
> +            } else
> +                goto link_down;
> +        } else {
> +              link_down:
> +            port->link_speed = -1;
> +            port->link_duplex = -1;
> +        }
> +    }
> +}
> +
> +void netxen_nic_flash_print(struct netxen_adapter *adapter)
> +{
> +    int valid = 1;
> +    u32 fw_major = 0;
> +    u32 fw_minor = 0;
> +    u32 fw_build = 0;
> +
> +    struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
> +    if (board_info->magic != NETXEN_BDINFO_MAGIC) {
> +        printk
> +            ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n",
> +             board_info->magic, NETXEN_BDINFO_MAGIC);
> +        valid = 0;
> +    }
> +    if (board_info->header_version != NETXEN_BDINFO_VERSION) {
> +        printk("NetXen Unknown board config version."
> +               " Read %x, expected %x\n",
> +               board_info->header_version, NETXEN_BDINFO_VERSION);
> +        valid = 0;
> +    }
> +    if (valid) {
> +        printk("NetXen %s Board #%d, Chip id 0x%x\n",
> +               board_info->board_type == 0x0b ? "XGB" : "GBE",
> +               board_info->board_num, board_info->chip_id);
> +        read_lock(&adapter->adapter_lock);
> +        fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
> +                              NETXEN_FW_VERSION_MAJOR));
> +        fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
> +                              NETXEN_FW_VERSION_MINOR));
> +        fw_build =
> +            readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
> +        read_unlock(&adapter->adapter_lock);
> +
> +        printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor,
> +               fw_build);
> +    }
> +    if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
> +        printk(KERN_ERR "The mismatch in driver version and firmware "
> +               "version major number\n"
> +               "Driver version major number = %d \t"
> +               "Firmware version major number = %d \n",
> +               _NETXEN_NIC_LINUX_MAJOR, fw_major);
> +        adapter->driver_mismatch = 1;
> +    }
> +    if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
> +        printk(KERN_ERR "The mismatch in driver version and firmware "
> +               "version minor number\n"
> +               "Driver version minor number = %d \t"
> +               "Firmware version minor number = %d \n",
> +               _NETXEN_NIC_LINUX_MINOR, fw_minor);
> +        adapter->driver_mismatch = 1;
> +    }
> +    if (adapter->driver_mismatch)
> +        printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n",
> +               fw_major, fw_minor);
> +}
> 
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 5/9] NetXen: hardware access header file
  2006-07-05 13:38 ` [PATCH 2.6.17 5/9] NetXen: hardware access header file Linsys Contractor Amit S. Kale
@ 2006-07-05 16:04   ` Jeff Garzik
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2006-07-05 16:04 UTC (permalink / raw)
  To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj

Linsys Contractor Amit S. Kale wrote:
> +#ifndef readq

this test fails where readq is not a macro


> +static inline u64 readq(void __iomem * addr)
> +{
> +    return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
> +}
> +#endif
> +
> +#ifndef writeq
> +static inline void writeq(u64 val, void __iomem * addr)
> +{
> +    writel(((u32) (val)), (addr));
> +    writel(((u32) (val >> 32)), (addr + 4));
> +}
> +#endif

overall, don't define these.

If you have a platform that doesn't support readq(), add it there...



> +/*
> + * NIU GB MAC Config Register 0 (applies to GB0, GB1, GB2, GB3)
> + */
> +struct netxen_niu_gb_mac_config_0_t {
> +    netxen_crbword_t tx_enable:1,    /* 1:enable frame xmit, 0:disable */
> +     tx_synched:1,        /* R/O: xmit enable synched to xmit stream */
> +     rx_enable:1,        /* 1:enable frame recv, 0:disable */
> +     rx_synched:1,        /* R/O: recv enable synched to recv stream */
> +     tx_flowctl:1,        /* 1:enable pause frame generation, 0:disable*/
> +     rx_flowctl:1,        /* 1:act on recv'd pause frames, 0:ignore */
> +     rsvd1:2,
> +     loopback:1,        /* 1:loop MAC xmits to MAC recvs, 0:normal */
> +     rsvd2:7,
> +     tx_reset_pb:1,        /* 1:reset frame xmit protocol blk, 0:no-op */
> +     rx_reset_pb:1,        /* 1:reset frame recv protocol blk, 0:no-op */
> +     tx_reset_mac:1,    /* 1:reset data/ctl multiplexer blk, 0:no-op */
> +     rx_reset_mac:1,    /* 1:reset ctl frames & timers blk, 0:no-op */
> +     rsvd3:11,
> +     soft_reset:1;    /* 1:reset the MAC and the SERDES, 0:no-op */
> +};

More bitfields to kill


> +/*
> + * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3)
> + */
> +struct netxen_niu_gb_mac_config_1_t {
> +    netxen_crbword_t duplex:1,    /* 1:full duplex mode, 0:half duplex */
> +     crc_enable:1,    /* 1:append CRC to xmit frames, 0:dont append */
> +     padshort:1,    /* 1:pad short frames and add CRC, 0:dont pad */
> +     rsvd1:1,
> +     checklength:1,    /* 1:check framelen with actual, 0:dont check */
> +     hugeframes:1,    /* 1:allow oversize xmit frames, 0:dont allow */
> +     rsvd2:2,
> +     intfmode:2,    /* 01:nibble (10/100), 10:byte (1000) */
> +     rsvd3:2,
> +     preamblelen:4,    /* preamble field length in bytes, default 7 */
> +     rsvd4:16;
> +};

ditto


> +/*
> + * NIU GB Station Address High Register
> + * NOTE: this value is in network byte order.
> + */
> +struct netxen_niu_gb_station_address_high {
> +    netxen_crbword_t address:32;    /* station address [47:16] */
> +};
> +
> +/*
> + * NIU GB Station Address Low Register
> + * NOTE: this value is in network byte order.
> + */
> +struct netxen_niu_gb_station_address_low {
> +    netxen_crbword_t rsvd:16, address:16;    /* station address [15:0] */
> +};

ditto


  +/*
> + * NIU GB MII Mgmt Config Register (applies to GB0, GB1, GB2, GB3)
> + */
> +struct netxen_niu_gb_mii_mgmt_config {
> +    netxen_crbword_t clockselect:3,
> +        /* 0:clk/4,  1:clk/4,  2:clk/6,  3:clk/8 */
> +        /* 4:clk/10, 5:clk/14, 6:clk/20, 7:clk/28 */
> +     rsvd1:1, nopreamble:1,    /* 1:suppress preamble generation, 
> 0:normal */
> +     scanauto:1, rsvd2:25, reset:1;    /* 1:reset MII mgmt, 0:no-op */
> +};
> +
> +/*
> + * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
> + */
> +struct netxen_niu_gb_mii_mgmt_command {
> +    /* 1:perform single read cycle, 0:no-op */
> +    netxen_crbword_t read_cycle:1,
> +     scan_cycle:1,        /* 1:perform continuous read cycles, 0:no-op */
> +     rsvd:30;
> +};
> +
> +/*
> + * NIU GB MII Mgmt Address Register (applies to GB0, GB1, GB2, GB3)
> + */
> +struct netxen_niu_gb_mii_mgmt_address {
> +    /* which mgmt register we want to talk to */
> +    netxen_crbword_t reg_addr:5,
> +     rsvd1:3, phy_addr:5,    /* which PHY to talk to (0 is reserved) */
> +     rsvd:19;
> +};
> +
> +/*
> + * NIU GB MII Mgmt Indicators Register (applies to GB0, GB1, GB2, GB3)
> + * Read-only register.
> + */
> +struct netxen_niu_gb_mii_mgmt_indicators {
> +    /* 1:performing an MII mgmt cycle, 0:idle */
> +    netxen_crbword_t busy:1,
> +     scanning:1,        /* 1:scan operation in progress, 0:idle */
> +     notvalid:1,        /* 1:mgmt result data not yet valid, 0:idle */
> +     rsvd:29;
> +};

ditto x 4


> +typedef enum {
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26,
> +    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27
> +} netxen_niu_phy_register_t;
> +
> +/*
> + * PHY-Specific Status Register (reg 17).
> + */
> +struct netxen_niu_phy_status {
> +    netxen_crbword_t jabber:1,    /* 1:jabber detected, 0:not */
> +     polarity:1,        /* 1:polarity reversed, 0:normal */
> +     recvpause:1,        /* 1:receive pause enabled, 0:disabled */
> +     xmitpause:1,        /* 1:transmit pause enabled, 0:disabled */
> +     energydetect:1,    /* 1:sleep, 0:active */
> +     downshift:1,        /* 1:downshift, 0:no downshift */
> +     crossover:1,        /* 1:MDIX (crossover), 0:MDI (no crossover) */
> +     cablelen:3,        /* not valid in 10Mb/s mode */
> +        /* 0:<50m, 1:50-80m, 2:80-110m, 3:110-140m, 4:>140m */
> +     link:1,        /* 1:link up, 0:link down */
> +     resolved:1,        /* 1:speed and duplex resolved, 0:not yet */
> +     pagercvd:1,        /* 1:page received, 0:page not received */
> +     duplex:1,        /* 1:full duplex, 0:half duplex */
> +     speed:2,        /* 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd */
> +     rsvd:16;
> +};
> +
> +/*
> + * Interrupt Register definition
> + * This definition applies to registers 18 and 19 (int enable and int 
> status).
> + */
> +struct netxen_niu_phy_interrupt {
> +    netxen_crbword_t
> +        jabber:1,
> +        polarity_changed:1,
> +        reserved:2,
> +        energy_detect:1,
> +        downshift:1,
> +        mdi_xover_changed:1,
> +        fifo_over_underflow:1,
> +        false_carrier:1,
> +        symbol_error:1,
> +        link_status_changed:1,
> +        autoneg_completed:1,
> +        page_received:1,
> +        duplex_changed:1, speed_changed:1, autoneg_error:1, rsvd:16;
> +};
> +
> +/*
> + * NIU Mode Register.
> + */
> +struct netxen_niu_control {
> +    netxen_crbword_t enable_fc:1,    /* enable FibreChannel */
> +     enable_ge:1,        /* enable 10/100/1000 Ethernet */
> +     enable_xgb:1,        /* enable 10Gb Ethernet */
> +     rsvd:29;
> +};
> +
> +/* Promiscous mode options (GbE mode only) */
> +typedef enum {
> +    NETXEN_NIU_PROMISCOUS_MODE = 0,
> +    NETXEN_NIU_NON_PROMISCOUS_MODE
> +} netxen_niu_prom_mode_t;
> +
> +/*
> + * NIU GB Drop CRC Register
> + */
> +struct netxen_niu_gb_drop_crc {
> +    /* 1:drop pkts with bad CRCs, 0:pass them on */
> +    netxen_crbword_t drop_gb0:1,
> +     drop_gb1:1,        /* 1:drop pkts with bad CRCs, 0:pass them on */
> +     drop_gb2:1,        /* 1:drop pkts with bad CRCs, 0:pass them on */
> +     drop_gb3:1,        /* 1:drop pkts with bad CRCs, 0:pass them on */
> +     rsvd:28;
> +};
> +
> +/*
> + * NIU XG MAC Config Register
> + */
> +struct netxen_niu_xg_mac_config_0_t {
> +    netxen_crbword_t tx_enable:1,    /* 1:enable frame xmit, 0:disable */
> +     rsvd1:1, rx_enable:1,    /* 1:enable frame recv, 0:disable */
> +     rsvd2:1, soft_reset:1,    /* 1:reset the MAC , 0:no-op */
> +     rsvd3:22,
> +        xaui_framer_reset:1,
> +        xaui_rx_reset:1,
> +        xaui_tx_reset:1, xg_ingress_afifo_reset:1, 
> xg_egress_afifo_reset:1;
> +};

many more structs with bitfields




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 6/9] NetXen: hw initialization routines
  2006-07-05 13:40 ` [PATCH 2.6.17 6/9] NetXen: hw initialization routines Linsys Contractor Amit S. Kale
@ 2006-07-05 16:12   ` Jeff Garzik
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2006-07-05 16:12 UTC (permalink / raw)
  To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj, Andrew Morton

Linsys Contractor Amit S. Kale wrote:

> +    while (state != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
> +        udelay(100);
> +        /* Window 1 call */
> +        read_lock(&adapter->adapter_lock);
> +        state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
> +        read_unlock(&adapter->adapter_lock);
> +
> +        loops++;
> +    }
> +    if (loops >= 200000) {
> +        printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
> +               state);
> +        err = -EIO;
> +        return err;
> +    }

worst case udelay() spins CPU for far too long, locking out other tasks

Good thing this driver isn't used in latency-senstitive applications, or 
medical equipment!


> +void initialize_adapter_sw(struct netxen_adapter *adapter)
> +{
> +    int ctxid, ring;
> +    u32 i;
> +    u32 num_rx_bufs = 0;
> +    struct netxen_rcv_desc_ctx *rcv_desc;
> +    struct netxen_ring_context *ctx;
> +
> +    DPRINTK(INFO, "initializing some queues: %p\n", adapter);
> +    for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
> +        ctx = &adapter->ring_ctx[ctxid];
> +        ctx->free_cmd_count = ctx->max_tx_desc_count;
> +        for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
> +            struct netxen_rx_buffer *rx_buf;
> +            rcv_desc = &ctx->recv_ctx.rcv_desc[ring];
> +            rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
> +            rcv_desc->begin_alloc = 0;
> +            rx_buf = rcv_desc->rx_buf_arr;
> +            num_rx_bufs = rcv_desc->max_rx_desc_count;
> +            /*
> +             * Now go through all of them, set reference handles
> +             * and put them in the queues.
> +             */
> +            for (i = 0; i < num_rx_bufs; i++) {
> +                rx_buf->ref_handle = i;
> +                rx_buf->state = NETXEN_BUFFER_FREE;
> +
> +                DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
> +                    "%p\n", ctxid, i, rx_buf);
> +                rx_buf++;
> +            }
> +        }
> +    }
> +    DPRINTK(INFO, "initialized buffers for %s and %s\n",
> +        "adapter->free_cmd_buf_list", "adapter->free_rxbuf");
> +}
> +
> +int initialize_adapter_hw(struct netxen_adapter *adapter)
> +{
> +    u32 value = 0;
> +
> +    if (netxen_nic_get_board_info(adapter) != 0)
> +        printk("%s: Error getting board config info.\n",
> +            netxen_nic_driver_name);
> +
> +    switch (adapter->ahw.board_type) {
> +    case NETXEN_NIC_GBE:
> +        adapter->ahw.max_ports = 4;
> +        break;
> +
> +    case NETXEN_NIC_XGBE:
> +        adapter->ahw.max_ports = 1;
> +        break;
> +
> +    default:
> +        printk(KERN_ERR "%s: Unknown board type\n",
> +            netxen_nic_driver_name);
> +    }
> +
> +    return value;
> +}
> +
> +/*
> + * netxen_decode_crb_addr(0 - utility to translate from internal 
> Phantom CRB
> + * address to external PCI CRB address.
> + */
> +unsigned long netxen_decode_crb_addr(unsigned long addr)
> +{
> +    int i;
> +    unsigned long base_addr, offset, pci_base;
> +
> +    crb_addr_transform_setup();
> +
> +    pci_base = NETXEN_ADDR_ERROR;
> +    base_addr = addr & 0xfff00000;
> +    offset = addr & 0x000fffff;
> +
> +    for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) {
> +        if (crb_addr_xform[i] == base_addr) {
> +            pci_base = i << 20;
> +            break;
> +        }
> +    }
> +    if (pci_base == NETXEN_ADDR_ERROR)
> +        return pci_base;
> +    else
> +        return (pci_base + offset);
> +}
> +
> +static long rom_max_timeout = 10000;
> +static long rom_lock_timeout = 100000000;
> +
> +int rom_lock(struct netxen_adapter *adapter)
> +{
> +    int iter;
> +    int done = 0, timeout = 0;
> +
> +    while (!done) {
> +        /* acquire semaphore2 from PCI HW block */
> +        netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
> +                   &done);
> +        if (done == 1)
> +            break;
> +        if (timeout >= rom_lock_timeout)
> +            return -1;
> +
> +        timeout++;
> +        /*
> +         * Yield CPU
> +         */
> +        if (!in_atomic())
> +            schedule();
> +        else {
> +            for (iter = 0; iter < 20; iter++)
> +                cpu_relax();    /*This a nop instr on i386 */

when is this function ever used in atomic context?

> +int netxen_wait_rom_done(struct netxen_adapter *adapter)
> +{
> +    long timeout = 0;
> +    long done = 0;
> +
> +    while (done == 0) {
> +        done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
> +        done &= 2;
> +        timeout++;
> +        if (timeout >= rom_max_timeout) {
> +            printk("Timeout reached  waiting for rom done");
> +            return -1;
> +        }
> +    }
> +    return 0;

how long does this spin the cpu?


> +int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
> +{
> +    netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
> +    netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
> +    udelay(100);        /* prevent bursting on CRB */

likely PCI posting bug


> +    netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
> +    netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
> +    if (netxen_wait_rom_done(adapter)) {
> +        printk("Error waiting for rom done\n");
> +        return -1;
> +    }
> +    /* reset abyte_cnt and dummy_byte_cnt */
> +    netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
> +    udelay(100);        /* prevent bursting on CRB */

ditto



> +    netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
> +
> +    *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
> +    return 0;
> +}
> +
> +int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int 
> *valp)
> +{
> +    int ret;
> +
> +    if (rom_lock(adapter) != 0)
> +        return -1;
> +
> +    ret = do_rom_fast_read(adapter, addr, valp);
> +    rom_unlock(adapter);
> +    return ret;
> +}
> +
> +int pinit_from_rom(struct netxen_adapter *adapter, int verbose)
> +{
> +    int addr, val, status;
> +    int n, i;
> +    int init_delay = 0;
> +    struct crb_addr_pair *buf;
> +    unsigned long off;
> +    unsigned long flags;
> +
> +    /* resetall */
> +    status = netxen_nic_get_board_info(adapter);
> +    if (status)
> +        printk("%s: pinit_from_rom: Error getting board info\n",
> +               netxen_nic_driver_name);
> +
> +    netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
> +                    0xffffffff);
> +
> +    if (verbose) {
> +        int val;
> +        if (netxen_rom_fast_read(adapter, 0x4008, &val) == 0)
> +            printk("P2 ROM board type: 0x%08x\n", val);
> +        else
> +            printk("Could not read board type\n");
> +        if (netxen_rom_fast_read(adapter, 0x400c, &val) == 0)
> +            printk("P2 ROM board  num: 0x%08x\n", val);
> +        else
> +            printk("Could not read board number\n");
> +        if (netxen_rom_fast_read(adapter, 0x4010, &val) == 0)
> +            printk("P2 ROM chip   num: 0x%08x\n", val);
> +        else
> +            printk("Could not read chip number\n");
> +    }
> +
> +    if (netxen_rom_fast_read(adapter, 0, &n) == 0 && (n & 
> 0x800000000ULL)) {
> +        n &= ~0x80000000ULL;

kill magic numbers, use named constants


> +        if (n < 1024) {
> +            if (verbose)
> +                printk("%s: %d CRB init values found"
> +                       " in ROM.\n", netxen_nic_driver_name, n);
> +        } else {
> +            printk("%s:n=0x%x Error! NetXen card flash not"
> +                   " initialized.\n", __FUNCTION__, n);
> +            return -1;
> +        }
> +        buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
> +        if (buf == NULL) {
> +            printk("%s: pinit_from_rom: Unable to calloc memory.\n",
> +                   netxen_nic_driver_name);
> +            return -1;
> +        }
> +        for (i = 0; i < n; i++) {
> +            if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
> +                || netxen_rom_fast_read(adapter, 8 * i + 8,
> +                            &addr) != 0)
> +                goto error_ret;
> +
> +            buf[i].addr = addr;
> +            buf[i].data = val;
> +
> +            if (verbose)
> +                printk("%s: PCI:     0x%08x == 0x%08x\n",
> +                       netxen_nic_driver_name, (unsigned int)
> +                       netxen_decode_crb_addr((unsigned long)
> +                                  addr), val);
> +        }
> +        for (i = 0; i < n; i++) {
> +
> +            off =
> +                netxen_decode_crb_addr((unsigned long)buf[i].addr) +
> +                NETXEN_PCI_CRBSPACE;
> +            /* skipping cold reboot MAGIC */
> +            if (off == NETXEN_CAM_RAM(0x1fc))
> +                continue;
> +
> +            /* After writing this register, HW needs time for CRB */
> +            /* to quiet down (else crb_window returns 0xffffffff) */
> +            if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
> +                init_delay = 1;
> +                /* hold xdma in reset also */
> +                buf[i].data = 0x8000ff;
> +            }
> +
> +            if (ADDR_IN_WINDOW1(off)) {
> +                read_lock(&adapter->adapter_lock);
> +                writel(buf[i].data,
> +                       NETXEN_CRB_NORMALIZE(adapter, off));
> +                read_unlock(&adapter->adapter_lock);
> +            } else {
> +                write_lock_irqsave(&adapter->adapter_lock,
> +                           flags);
> +                netxen_nic_pci_change_crbwindow(adapter, 0);
> +                off = adapter->ahw.pci_base + off;
> +                writel(buf[i].data, (void *)off);
> +                netxen_nic_pci_change_crbwindow(adapter, 1);
> +                write_unlock_irqrestore(&adapter->adapter_lock,
> +                            flags);
> +            }
> +            if (init_delay == 1) {
> +                msleep(1000);

ssleep()

> +                init_delay = 0;
> +            }
> +            msleep(1);
> +        }
> +        kfree(buf);
> +
> +        /* disable_peg_cache_all */
> +
> +        /* unreset_net_cache */
> +        netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
> +                      4);
> +        netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
> +                        (val & 0xffffff0f));
> +        /* p2dn replyCount */
> +        netxen_crb_writelit_adapter(adapter,
> +                        NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
> +        /* disable_peg_cache 0 */
> +        netxen_crb_writelit_adapter(adapter,
> +                        NETXEN_CRB_PEG_NET_D + 0x4c, 8);
> +        /* disable_peg_cache 1 */
> +        netxen_crb_writelit_adapter(adapter,
> +                        NETXEN_CRB_PEG_NET_I + 0x4c, 8);
> +
> +        /* peg_clr_all */
> +
> +        /* peg_clr 0 */
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
> +                        0);
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
> +                        0);
> +        /* peg_clr 1 */
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
> +                        0);
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
> +                        0);
> +        /* peg_clr 2 */
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
> +                        0);
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
> +                        0);
> +        /* peg_clr 3 */
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
> +                        0);
> +        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
> +                        0);
> +    }
> +    return 0;
> +      error_ret:
> +    return -1;
> +}
> +
> +void phantom_init(struct netxen_adapter *adapter)
> +{
> +    u32 val = 0;
> +    int loops = 0;
> +
> +    read_lock(&adapter->adapter_lock);
> +    netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 
> &val, 4);
> +    writel(1,
> +           NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
> +
> +    if (0 == val) {
> +        while (val != PHAN_INITIALIZE_COMPLETE && loops < 2000000) {
> +            udelay(100);

locks up CPU for too long



> +            val =
> +                readl(NETXEN_CRB_NORMALIZE
> +                  (adapter, CRB_CMDPEG_STATE));
> +            loops++;
> +        }
> +        if (val != PHAN_INITIALIZE_COMPLETE)
> +            printk("WARNING: Initial boot wait loop failed...\n");
> +    }
> +    read_unlock(&adapter->adapter_lock);
> +}
> +
> +void load_firmware(struct netxen_adapter *adapter)
> +{
> +    int i;
> +    long data, size = 0;
> +    long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
> +
> +    size = (16 * 1024) / 4;
> +    read_lock(&adapter->adapter_lock);
> +    writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
> +    read_unlock(&adapter->adapter_lock);
> +
> +    for (i = 0; i < size; i++) {
> +        if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
> +            DPRINTK(ERR,
> +                "Error in netxen_rom_fast_read(). Will skip"
> +                "loading flash image\n");
> +            return;
> +        }
> +        netxen_nic_pci_mem_write(adapter, memaddr, &data, 4);
> +        flashaddr += 4;
> +        memaddr += 4;
> +    }
> +    udelay(100);

PCI posting


> +    read_lock(&adapter->adapter_lock);
> +    /* make sure Casper is powered on */
> +    writel(0x3fff,
> +           NETXEN_CRB_NORMALIZE(adapter, 
> NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
> +    writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
> +    read_unlock(&adapter->adapter_lock);
> +
> +    udelay(10000);

delay far too long


> +int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
> +{
> +    int ctxid;
> +
> +    for (ctxid = 0; ctxid < MAX_RING_CTX; ++ctxid) {
> +        struct netxen_ring_context *ctx = &adapter->ring_ctx[ctxid];
> +        struct netxen_recv_context *recv_ctx = &(ctx->recv_ctx);
> +        u32 consumer;
> +        struct status_desc_t *desc_head;
> +        struct status_desc_t *desc;    /* used to read status desc here */
> +
> +        consumer = recv_ctx->status_rx_consumer;
> +        desc_head = recv_ctx->rcv_status_desc_head;
> +        desc = &desc_head[consumer];
> +
> +        if ((desc->owner & STATUS_OWNER_HOST))
> +            return 1;
> +    }
> +
> +    return 0;
> +}

put function near user, and mark 'static', to enable possibility of inlining



> +void netxen_watchdog_task(unsigned long v)
> +{
> +    int port_num;
> +    struct netxen_port *port;
> +    struct net_device *netdev;
> +    struct netxen_adapter *adapter = (struct netxen_adapter *)v;
> +    unsigned long flags;
> +
> +    if (adapter->driver_mismatch) {
> +        /* We return without turning on the netdev queue as there
> +         * was a mismatch in driver and firmware version
> +         */
> +        return;

huh?  when will this ever happen?


> +    for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
> +        port = adapter->port[port_num];
> +        netdev = port->netdev;
> +
> +        if ((netdev->flags & IFF_UP) && !netif_carrier_ok(netdev)) {

don't test IFF_UP, you likely want netif_running(), etc.


> +            printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
> +                   netxen_nic_driver_name, port_num, netdev->name);
> +            netif_carrier_on(netdev);
> +        }
> +
> +        if (netif_queue_stopped(netdev))


Calling netif_wake_queue() without doing something useful with TX queue 
is bogus



> +inline void
> +netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
> +           struct status_desc_t *desc)

inline without static is likely wrong


> +{
> +    struct netxen_port *port = adapter->port[desc->port];
> +    struct pci_dev *pdev = port->pdev;
> +    struct net_device *netdev = port->netdev;
> +    int index = desc->reference_handle;
> +    struct netxen_recv_context *recv_ctx =
> +        &(adapter->ring_ctx[ctxid].recv_ctx);
> +    struct netxen_rx_buffer *buffer;
> +    struct sk_buff *skb;
> +    u32 length = desc->total_length;
> +    u32 desc_ctx;
> +    struct netxen_rcv_desc_ctx *rcv_desc;
> +    int ret;
> +
> +    desc_ctx = desc->type;
> +    if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
> +        printk("%s: %s Bad Rcv descriptor ring\n",
> +               netxen_nic_driver_name, netdev->name);
> +        return;
> +    }
> +
> +    rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
> +    buffer = &rcv_desc->rx_buf_arr[index];
> +
> +    pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
> +             PCI_DMA_FROMDEVICE);
> +
> +    skb = (struct sk_buff *)buffer->skb;
> +
> +    if (unlikely(skb == NULL)) {
> +        /*
> +         * This should not happen and if it does, it is serious,
> +         * catch it
> +         */

When will this EVER happen?

Kill all this code...


Got tired of reviewing at this point.

Please fix the mentioned issues and repost --as one big patch-- (i.e. 
requires a URL).

	Jeff



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface
  2006-07-05 15:34   ` Jeff Garzik
@ 2006-07-06 13:50     ` Pradeep Dalvi
  0 siblings, 0 replies; 17+ messages in thread
From: Pradeep Dalvi @ 2006-07-06 13:50 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Linsys Contractor Amit S. Kale, netdev, sanjeev, unmproj

Jeff,

Thanks a lot for feedback.

We are working on incorporating the feedback. And we will upload the entire 
single patch soon.

Thanks,
pradeep

On Wednesday 05 July 2006 21:04, Jeff Garzik wrote:
> Linsys Contractor Amit S. Kale wrote:
> > +static int
> > +netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd
> > *ecmd) +{
> > +    struct netxen_port *port = netdev_priv(dev);
> > +    struct netxen_adapter *adapter = port->adapter;
> > +    struct netxen_niu_phy_status status;
> > +
> > +    /* read which mode */
> > +    if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
> > +        /* autonegotiation */
> > +        if (netxen_nic_phy_write(port->adapter, port->portnum,
> > +                     NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
> > +                     (netxen_crbword_t) ecmd->autoneg) != 0)
> > +            return -EIO;
> > +        else
> > +            port->link_autoneg = ecmd->autoneg;
> > +
> > +        if (netxen_nic_phy_read(port->adapter, port->portnum,
> > +                    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> > +                    (netxen_crbword_t *) & status) != 0)
> > +            return -EIO;
> > +
> > +        /* speed */
> > +        switch (ecmd->speed) {
> > +        case SPEED_10:
> > +            status.speed = 0;
> > +            break;
> > +        case SPEED_100:
> > +            status.speed = 1;
> > +            break;
> > +        case SPEED_1000:
> > +            status.speed = 2;
> > +            break;
> > +        }
> > +        /* set duplex mode */
> > +        if (ecmd->duplex == DUPLEX_HALF)
> > +            status.duplex = 0;
> > +        if (ecmd->duplex == DUPLEX_FULL)
> > +            status.duplex = 1;
> > +
> > +        if (netxen_nic_phy_write(port->adapter, port->portnum,
> > +                     NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> > +                     *((int *)&status)) != 0)
> > +            return -EIO;
> > +        else {
> > +            port->link_speed = ecmd->speed;
> > +            port->link_duplex = ecmd->duplex;
> > +        }
> > +    }
> > +    if (netif_running(dev)) {
> > +        dev->stop(dev);
> > +        dev->open(dev);
> > +    }
> > +    return 0;
> > +}
> > +
> >
> > +/* Restart Link Process */
> > +static int netxen_nic_nway_reset(struct net_device *dev)
> > +{
> > +    if (netif_running(dev)) {
> > +        dev->stop(dev);    /* verify */
> > +        dev->open(dev);
> > +    }
> > +    return 0;
> > +}
>
> Direct calls to dev->stop() and dev->open() are likely buggy, because
> the locking/context differs between the above quoted calls and the calls
> from inside the net stack.
>
> > +struct ethtool_ops netxen_nic_ethtool_ops = {
> > +    .get_settings = netxen_nic_get_settings,
> > +    .set_settings = netxen_nic_set_settings,
> > +    .get_drvinfo = netxen_nic_get_drvinfo,
> > +    .get_regs_len = netxen_nic_get_regs_len,
> > +    .get_regs = netxen_nic_get_regs,
> > +    .get_wol = netxen_nic_get_wol,
> > +    .nway_reset = netxen_nic_nway_reset,
> > +    .get_link = netxen_nic_get_link,
> > +    .get_eeprom_len = netxen_nic_get_eeprom_len,
> > +    .get_eeprom = netxen_nic_get_eeprom,
> > +    .get_ringparam = netxen_nic_get_ringparam,
> > +    .get_pauseparam = netxen_nic_get_pauseparam,
> > +    .set_pauseparam = netxen_nic_set_pauseparam,
> > +    .get_tx_csum = ethtool_op_get_tx_csum,
> > +    .set_tx_csum = ethtool_op_set_tx_csum,
> > +    .get_sg = ethtool_op_get_sg,
> > +    .set_sg = ethtool_op_set_sg,
> > +#ifdef NETIF_F_TSO
> > +    .get_tso = ethtool_op_get_tso,
> > +    .set_tso = ethtool_op_set_tso,
> > +#endif
>
> kill this #ifdef
>
> 	Jeff

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2006-07-06 13:50 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-05 13:15 [PATCH 2.6.17 0/9] NetXen: ethernet nic driver Linsys Contractor Amit S. Kale
2006-07-05 13:20 ` [PATCH 2.6.17 1/9] NetXen: Makefile and ethtool interface Linsys Contractor Amit S. Kale
2006-07-05 15:34   ` Jeff Garzik
2006-07-06 13:50     ` Pradeep Dalvi
2006-07-05 13:29 ` [PATCH 2.6.17 2/9] NetXen: Main header file Linsys Contractor Amit S. Kale
2006-07-05 15:46   ` Jeff Garzik
2006-07-05 13:31 ` [PATCH 2.6.17 3/9] NetXen: Registers info " Linsys Contractor Amit S. Kale
2006-07-05 15:51   ` Jeff Garzik
2006-07-05 13:34 ` [PATCH 2.6.17 4/9] NetXen: hardware access routines Linsys Contractor Amit S. Kale
2006-07-05 16:00   ` Jeff Garzik
2006-07-05 13:38 ` [PATCH 2.6.17 5/9] NetXen: hardware access header file Linsys Contractor Amit S. Kale
2006-07-05 16:04   ` Jeff Garzik
2006-07-05 13:40 ` [PATCH 2.6.17 6/9] NetXen: hw initialization routines Linsys Contractor Amit S. Kale
2006-07-05 16:12   ` Jeff Garzik
2006-07-05 13:42 ` [PATCH 2.6.17 7/9] NetXen: ioctl interface and intr routines Linsys Contractor Amit S. Kale
2006-07-05 13:44 ` [PATCH 2.6.17 8/9] NetXen: Driver main file Linsys Contractor Amit S. Kale
2006-07-05 13:47 ` [PATCH 2.6.17 9/9] NetXen: niu handling and CRB reg definitions Linsys Contractor Amit S. Kale

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).