]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/s2io.c
Merge branch 'master'
[linux-2.6-omap-h63xx.git] / drivers / net / s2io.c
index 28d6d3746c8073de9387754eb437929082cd1437..d303d162974f9caedf905bd603c583a8b6c538b9 100644 (file)
@@ -1,5 +1,5 @@
 /************************************************************************
- * s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
  * Copyright(c) 2002-2005 Neterion Inc.
 
  * This software may be used and distributed according to the terms of
@@ -28,7 +28,7 @@
  * explaination of all the variables.
  * rx_ring_num : This can be used to program the number of receive rings used
  * in the driver.
- * rx_ring_len: This defines the number of descriptors each ring can have. This
+ * rx_ring_sz: This defines the number of descriptors each ring can have. This
  * is also an array of size 8.
  * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
  * tx_fifo_len: This too is an array of 8. Each element defines the number of
@@ -55,6 +55,7 @@
 #include <linux/ethtool.h>
 #include <linux/version.h>
 #include <linux/workqueue.h>
+#include <linux/if_vlan.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include "s2io.h"
 #include "s2io-regs.h"
 
+#define DRV_VERSION "Version 2.0.9.1"
+
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = "Version 1.7.7";
+static char s2io_driver_version[] = DRV_VERSION;
 
 static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 {
@@ -83,9 +86,10 @@ static inline int RXD_IS_UP2DT(RxD_t *rxdp)
  * problem, 600B, 600C, 600D, 640B, 640C and 640D.
  * macro below identifies these cards given the subsystem_id.
  */
-#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \
-               (((subid >= 0x600B) && (subid <= 0x600D)) || \
-                ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0
+#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \
+       (dev_type == XFRAME_I_DEVICE) ?                 \
+               ((((subid >= 0x600B) && (subid <= 0x600D)) || \
+                ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0
 
 #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
                                      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
@@ -168,6 +172,36 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
 #define S2IO_TEST_LEN  sizeof(s2io_gstrings) / ETH_GSTRING_LEN
 #define S2IO_STRINGS_LEN       S2IO_TEST_LEN * ETH_GSTRING_LEN
 
+#define S2IO_TIMER_CONF(timer, handle, arg, exp)               \
+                       init_timer(&timer);                     \
+                       timer.function = handle;                \
+                       timer.data = (unsigned long) arg;       \
+                       mod_timer(&timer, (jiffies + exp))      \
+
+/* Add the vlan */
+static void s2io_vlan_rx_register(struct net_device *dev,
+                                       struct vlan_group *grp)
+{
+       nic_t *nic = dev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&nic->tx_lock, flags);
+       nic->vlgrp = grp;
+       spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
+
+/* Unregister the vlan */
+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
+{
+       nic_t *nic = dev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&nic->tx_lock, flags);
+       if (nic->vlgrp)
+               nic->vlgrp->vlan_devices[vid] = NULL;
+       spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
+
 /*
  * Constants to be programmed into the Xena's registers, to configure
  * the XAUI.
@@ -176,7 +210,28 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
 #define SWITCH_SIGN    0xA5A5A5A5A5A5A5A5ULL
 #define        END_SIGN        0x0
 
-static u64 default_mdio_cfg[] = {
+static u64 herc_act_dtx_cfg[] = {
+       /* Set address */
+       0x8000051536750000ULL, 0x80000515367500E0ULL,
+       /* Write data */
+       0x8000051536750004ULL, 0x80000515367500E4ULL,
+       /* Set address */
+       0x80010515003F0000ULL, 0x80010515003F00E0ULL,
+       /* Write data */
+       0x80010515003F0004ULL, 0x80010515003F00E4ULL,
+       /* Set address */
+       0x801205150D440000ULL, 0x801205150D4400E0ULL,
+       /* Write data */
+       0x801205150D440004ULL, 0x801205150D4400E4ULL,
+       /* Set address */
+       0x80020515F2100000ULL, 0x80020515F21000E0ULL,
+       /* Write data */
+       0x80020515F2100004ULL, 0x80020515F21000E4ULL,
+       /* Done */
+       END_SIGN
+};
+
+static u64 xena_mdio_cfg[] = {
        /* Reset PMA PLL */
        0xC001010000000000ULL, 0xC0010100000000E0ULL,
        0xC0010100008000E4ULL,
@@ -186,7 +241,7 @@ static u64 default_mdio_cfg[] = {
        END_SIGN
 };
 
-static u64 default_dtx_cfg[] = {
+static u64 xena_dtx_cfg[] = {
        0x8000051500000000ULL, 0x80000515000000E0ULL,
        0x80000515D93500E4ULL, 0x8001051500000000ULL,
        0x80010515000000E0ULL, 0x80010515001E00E4ULL,
@@ -248,9 +303,14 @@ static unsigned int mc_pause_threshold_q4q7 = 187;
 static unsigned int shared_splits;
 static unsigned int tmac_util_period = 5;
 static unsigned int rmac_util_period = 5;
+static unsigned int bimodal = 0;
 #ifndef CONFIG_S2IO_NAPI
 static unsigned int indicate_max_pkts;
 #endif
+/* Frequency of Rx desc syncs expressed as power of 2 */
+static unsigned int rxsync_frequency = 3;
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+static unsigned int intr_type = 0;
 
 /*
  * S2IO device table.
@@ -298,7 +358,7 @@ static int init_shared_mem(struct s2io_nic *nic)
        int lst_size, lst_per_page;
        struct net_device *dev = nic->dev;
 #ifdef CONFIG_2BUFF_MODE
-       u64 tmp;
+       unsigned long tmp;
        buffAdd_t *ba;
 #endif
 
@@ -315,10 +375,9 @@ static int init_shared_mem(struct s2io_nic *nic)
                size += config->tx_cfg[i].fifo_len;
        }
        if (size > MAX_AVAILABLE_TXDS) {
-               DBG_PRINT(ERR_DBG, "%s: Total number of Tx FIFOs ",
-                         dev->name);
-               DBG_PRINT(ERR_DBG, "exceeds the maximum value ");
-               DBG_PRINT(ERR_DBG, "that can be used\n");
+               DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ",
+                         __FUNCTION__);
+               DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
                return FAILURE;
        }
 
@@ -349,7 +408,7 @@ static int init_shared_mem(struct s2io_nic *nic)
                    config->tx_cfg[i].fifo_len - 1;
                mac_control->fifos[i].fifo_no = i;
                mac_control->fifos[i].nic = nic;
-               mac_control->fifos[i].max_txds = MAX_SKB_FRAGS;
+               mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
 
                for (j = 0; j < page_num; j++) {
                        int k = 0;
@@ -363,6 +422,26 @@ static int init_shared_mem(struct s2io_nic *nic)
                                DBG_PRINT(ERR_DBG, "failed for TxDL\n");
                                return -ENOMEM;
                        }
+                       /* If we got a zero DMA address(can happen on
+                        * certain platforms like PPC), reallocate.
+                        * Store virtual address of page we don't want,
+                        * to be freed later.
+                        */
+                       if (!tmp_p) {
+                               mac_control->zerodma_virt_addr = tmp_v;
+                               DBG_PRINT(INIT_DBG, 
+                               "%s: Zero DMA address for TxDL. ", dev->name);
+                               DBG_PRINT(INIT_DBG, 
+                               "Virtual address %p\n", tmp_v);
+                               tmp_v = pci_alloc_consistent(nic->pdev,
+                                                    PAGE_SIZE, &tmp_p);
+                               if (!tmp_v) {
+                                       DBG_PRINT(ERR_DBG,
+                                         "pci_alloc_consistent ");
+                                       DBG_PRINT(ERR_DBG, "failed for TxDL\n");
+                                       return -ENOMEM;
+                               }
+                       }
                        while (k < lst_per_page) {
                                int l = (j * lst_per_page) + k;
                                if (l == config->tx_cfg[i].fifo_len)
@@ -487,18 +566,18 @@ static int init_shared_mem(struct s2io_nic *nic)
                                    (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
                                if (!ba->ba_0_org)
                                        return -ENOMEM;
-                               tmp = (u64) ba->ba_0_org;
+                               tmp = (unsigned long) ba->ba_0_org;
                                tmp += ALIGN_SIZE;
-                               tmp &= ~((u64) ALIGN_SIZE);
+                               tmp &= ~((unsigned long) ALIGN_SIZE);
                                ba->ba_0 = (void *) tmp;
 
                                ba->ba_1_org = (void *) kmalloc
                                    (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
                                if (!ba->ba_1_org)
                                        return -ENOMEM;
-                               tmp = (u64) ba->ba_1_org;
+                               tmp = (unsigned long) ba->ba_1_org;
                                tmp += ALIGN_SIZE;
-                               tmp &= ~((u64) ALIGN_SIZE);
+                               tmp &= ~((unsigned long) ALIGN_SIZE);
                                ba->ba_1 = (void *) tmp;
                                k++;
                        }
@@ -545,7 +624,7 @@ static void free_shared_mem(struct s2io_nic *nic)
        mac_info_t *mac_control;
        struct config_param *config;
        int lst_size, lst_per_page;
-
+       struct net_device *dev = nic->dev;
 
        if (!nic)
                return;
@@ -561,8 +640,10 @@ static void free_shared_mem(struct s2io_nic *nic)
                                                lst_per_page);
                for (j = 0; j < page_num; j++) {
                        int mem_blks = (j * lst_per_page);
+                       if (!mac_control->fifos[i].list_info)
+                               return; 
                        if (!mac_control->fifos[i].list_info[mem_blks].
-                           list_virt_addr)
+                                list_virt_addr)
                                break;
                        pci_free_consistent(nic->pdev, PAGE_SIZE,
                                            mac_control->fifos[i].
@@ -572,6 +653,19 @@ static void free_shared_mem(struct s2io_nic *nic)
                                            list_info[mem_blks].
                                            list_phy_addr);
                }
+               /* If we got a zero DMA address during allocation,
+                * free the page now
+                */
+               if (mac_control->zerodma_virt_addr) {
+                       pci_free_consistent(nic->pdev, PAGE_SIZE,
+                                           mac_control->zerodma_virt_addr,
+                                           (dma_addr_t)0);
+                       DBG_PRINT(INIT_DBG, 
+                               "%s: Freeing TxDL with zero DMA addr. ",
+                               dev->name);
+                       DBG_PRINT(INIT_DBG, "Virtual address %p\n",
+                               mac_control->zerodma_virt_addr);
+               }
                kfree(mac_control->fifos[i].list_info);
        }
 
@@ -624,6 +718,87 @@ static void free_shared_mem(struct s2io_nic *nic)
        }
 }
 
+/**
+ * s2io_verify_pci_mode -
+ */
+
+static int s2io_verify_pci_mode(nic_t *nic)
+{
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
+       register u64 val64 = 0;
+       int     mode;
+
+       val64 = readq(&bar0->pci_mode);
+       mode = (u8)GET_PCI_MODE(val64);
+
+       if ( val64 & PCI_MODE_UNKNOWN_MODE)
+               return -1;      /* Unknown PCI mode */
+       return mode;
+}
+
+
+/**
+ * s2io_print_pci_mode -
+ */
+static int s2io_print_pci_mode(nic_t *nic)
+{
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
+       register u64 val64 = 0;
+       int     mode;
+       struct config_param *config = &nic->config;
+
+       val64 = readq(&bar0->pci_mode);
+       mode = (u8)GET_PCI_MODE(val64);
+
+       if ( val64 & PCI_MODE_UNKNOWN_MODE)
+               return -1;      /* Unknown PCI mode */
+
+       if (val64 & PCI_MODE_32_BITS) {
+               DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
+       } else {
+               DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name);
+       }
+
+       switch(mode) {
+               case PCI_MODE_PCI_33:
+                       DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
+                       config->bus_speed = 33;
+                       break;
+               case PCI_MODE_PCI_66:
+                       DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
+                       config->bus_speed = 133;
+                       break;
+               case PCI_MODE_PCIX_M1_66:
+                       DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
+                       config->bus_speed = 133; /* Herc doubles the clock rate */
+                       break;
+               case PCI_MODE_PCIX_M1_100:
+                       DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
+                       config->bus_speed = 200;
+                       break;
+               case PCI_MODE_PCIX_M1_133:
+                       DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
+                       config->bus_speed = 266;
+                       break;
+               case PCI_MODE_PCIX_M2_66:
+                       DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
+                       config->bus_speed = 133;
+                       break;
+               case PCI_MODE_PCIX_M2_100:
+                       DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
+                       config->bus_speed = 200;
+                       break;
+               case PCI_MODE_PCIX_M2_133:
+                       DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
+                       config->bus_speed = 266;
+                       break;
+               default:
+                       return -1;      /* Unsupported bus speed */
+       }
+
+       return mode;
+}
+
 /**
  *  init_nic - Initialization of hardware
  *  @nic: device peivate variable
@@ -656,6 +831,16 @@ static int init_nic(struct s2io_nic *nic)
                return -1;
        }
 
+       /*
+        * Herc requires EOI to be removed from reset before XGXS, so..
+        */
+       if (nic->device_type & XFRAME_II_DEVICE) {
+               val64 = 0xA500000000ULL;
+               writeq(val64, &bar0->sw_reset);
+               msleep(500);
+               val64 = readq(&bar0->sw_reset);
+       }
+
        /* Remove XGXS from reset state */
        val64 = 0;
        writeq(val64, &bar0->sw_reset);
@@ -687,41 +872,51 @@ static int init_nic(struct s2io_nic *nic)
         * of 64 bit values into two registers in a particular
         * sequence. Hence a macro 'SWITCH_SIGN' has been defined
         * which will be defined in the array of configuration values
-        * (default_dtx_cfg & default_mdio_cfg) at appropriate places
+        * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
         * to switch writing from one regsiter to another. We continue
         * writing these values until we encounter the 'END_SIGN' macro.
         * For example, After making a series of 21 writes into
         * dtx_control register the 'SWITCH_SIGN' appears and hence we
         * start writing into mdio_control until we encounter END_SIGN.
         */
-       while (1) {
-             dtx_cfg:
-               while (default_dtx_cfg[dtx_cnt] != END_SIGN) {
-                       if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
-                               dtx_cnt++;
-                               goto mdio_cfg;
-                       }
-                       SPECIAL_REG_WRITE(default_dtx_cfg[dtx_cnt],
+       if (nic->device_type & XFRAME_II_DEVICE) {
+               while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
+                       SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
                                          &bar0->dtx_control, UF);
-                       val64 = readq(&bar0->dtx_control);
+                       if (dtx_cnt & 0x1)
+                               msleep(1); /* Necessary!! */
                        dtx_cnt++;
                }
-             mdio_cfg:
-               while (default_mdio_cfg[mdio_cnt] != END_SIGN) {
-                       if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+       } else {
+               while (1) {
+                     dtx_cfg:
+                       while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+                               if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
+                                       dtx_cnt++;
+                                       goto mdio_cfg;
+                               }
+                               SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+                                                 &bar0->dtx_control, UF);
+                               val64 = readq(&bar0->dtx_control);
+                               dtx_cnt++;
+                       }
+                     mdio_cfg:
+                       while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
+                               if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+                                       mdio_cnt++;
+                                       goto dtx_cfg;
+                               }
+                               SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
+                                                 &bar0->mdio_control, UF);
+                               val64 = readq(&bar0->mdio_control);
                                mdio_cnt++;
+                       }
+                       if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
+                           (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
+                               break;
+                       } else {
                                goto dtx_cfg;
                        }
-                       SPECIAL_REG_WRITE(default_mdio_cfg[mdio_cnt],
-                                         &bar0->mdio_control, UF);
-                       val64 = readq(&bar0->mdio_control);
-                       mdio_cnt++;
-               }
-               if ((default_dtx_cfg[dtx_cnt] == END_SIGN) &&
-                   (default_mdio_cfg[mdio_cnt] == END_SIGN)) {
-                       break;
-               } else {
-                       goto dtx_cfg;
                }
        }
 
@@ -772,7 +967,8 @@ static int init_nic(struct s2io_nic *nic)
         * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
         * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
         */
-       if (get_xena_rev_id(nic->pdev) < 4)
+       if ((nic->device_type == XFRAME_I_DEVICE) &&
+               (get_xena_rev_id(nic->pdev) < 4))
                writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
 
        val64 = readq(&bar0->tx_fifo_partition_0);
@@ -802,7 +998,11 @@ static int init_nic(struct s2io_nic *nic)
         * configured Rings.
         */
        val64 = 0;
-       mem_size = 64;
+       if (nic->device_type & XFRAME_II_DEVICE)
+               mem_size = 32;
+       else
+               mem_size = 64;
+
        for (i = 0; i < config->rx_ring_num; i++) {
                switch (i) {
                case 0:
@@ -1085,6 +1285,11 @@ static int init_nic(struct s2io_nic *nic)
        /* Program statistics memory */
        writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
 
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = STAT_BC(0x320);
+               writeq(val64, &bar0->stat_byte_cnt);
+       }
+
        /*
         * Initializing the sampling rate for the device to calculate the
         * bandwidth utilization.
@@ -1103,12 +1308,18 @@ static int init_nic(struct s2io_nic *nic)
         * 250 interrupts per sec. Continuous interrupts are enabled
         * by default.
         */
-       val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
-           TTI_DATA1_MEM_TX_URNG_A(0xA) |
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               int count = (nic->config.bus_speed * 125)/2;
+               val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
+       } else {
+
+               val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
+       }
+       val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
            TTI_DATA1_MEM_TX_URNG_B(0x10) |
            TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
-       if (use_continuous_tx_intrs)
-               val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
+               if (use_continuous_tx_intrs)
+                       val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
        writeq(val64, &bar0->tti_data1_mem);
 
        val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
@@ -1140,42 +1351,91 @@ static int init_nic(struct s2io_nic *nic)
                time++;
        }
 
-       /* RTI Initialization */
-       val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) |
-           RTI_DATA1_MEM_RX_URNG_A(0xA) |
-           RTI_DATA1_MEM_RX_URNG_B(0x10) |
-           RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
+       if (nic->config.bimodal) {
+               int k = 0;
+               for (k = 0; k < config->rx_ring_num; k++) {
+                       val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
+                       val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
+                       writeq(val64, &bar0->tti_command_mem);
 
-       writeq(val64, &bar0->rti_data1_mem);
+               /*
+                * Once the operation completes, the Strobe bit of the command
+                * register will be reset. We poll for this particular condition
+                * We wait for a maximum of 500ms for the operation to complete,
+                * if it's not complete by then we return error.
+               */
+                       time = 0;
+                       while (TRUE) {
+                               val64 = readq(&bar0->tti_command_mem);
+                               if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
+                                       break;
+                               }
+                               if (time > 10) {
+                                       DBG_PRINT(ERR_DBG,
+                                               "%s: TTI init Failed\n",
+                                       dev->name);
+                                       return -1;
+                               }
+                               time++;
+                               msleep(50);
+                       }
+               }
+       } else {
 
-       val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
-           RTI_DATA2_MEM_RX_UFC_B(0x2) |
-           RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
-       writeq(val64, &bar0->rti_data2_mem);
+               /* RTI Initialization */
+               if (nic->device_type == XFRAME_II_DEVICE) {
+                       /*
+                        * Programmed to generate Apprx 500 Intrs per
+                        * second
+                        */
+                       int count = (nic->config.bus_speed * 125)/4;
+                       val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
+               } else {
+                       val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
+               }
+               val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
+                   RTI_DATA1_MEM_RX_URNG_B(0x10) |
+                   RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
+
+               writeq(val64, &bar0->rti_data1_mem);
+
+               val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
+                   RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+               if (nic->intr_type == MSI_X)
+                   val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
+                               RTI_DATA2_MEM_RX_UFC_D(0x40));
+               else
+                   val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
+                               RTI_DATA2_MEM_RX_UFC_D(0x80));
+               writeq(val64, &bar0->rti_data2_mem);
 
-       val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD;
-       writeq(val64, &bar0->rti_command_mem);
+               for (i = 0; i < config->rx_ring_num; i++) {
+                       val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
+                                       | RTI_CMD_MEM_OFFSET(i);
+                       writeq(val64, &bar0->rti_command_mem);
 
-       /*
-        * Once the operation completes, the Strobe bit of the
-        * command register will be reset. We poll for this
-        * particular condition. We wait for a maximum of 500ms
-        * for the operation to complete, if it's not complete
-        * by then we return error.
-        */
-       time = 0;
-       while (TRUE) {
-               val64 = readq(&bar0->rti_command_mem);
-               if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
-                       break;
-               }
-               if (time > 10) {
-                       DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
-                                 dev->name);
-                       return -1;
+                       /*
+                        * Once the operation completes, the Strobe bit of the
+                        * command register will be reset. We poll for this
+                        * particular condition. We wait for a maximum of 500ms
+                        * for the operation to complete, if it's not complete
+                        * by then we return error.
+                        */
+                       time = 0;
+                       while (TRUE) {
+                               val64 = readq(&bar0->rti_command_mem);
+                               if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
+                                       break;
+                               }
+                               if (time > 10) {
+                                       DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
+                                                 dev->name);
+                                       return -1;
+                               }
+                               time++;
+                               msleep(50);
+                       }
                }
-               time++;
-               msleep(50);
        }
 
        /*
@@ -1186,7 +1446,7 @@ static int init_nic(struct s2io_nic *nic)
        writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);
 
        /* Disable RMAC PAD STRIPPING */
-       add = (void *) &bar0->mac_cfg;
+       add = &bar0->mac_cfg;
        val64 = readq(&bar0->mac_cfg);
        val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);
        writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
@@ -1236,8 +1496,35 @@ static int init_nic(struct s2io_nic *nic)
        val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
        writeq(val64, &bar0->pic_control);
 
+       /*
+        * Programming the Herc to split every write transaction
+        * that does not start on an ADB to reduce disconnects.
+        */
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = WREQ_SPLIT_MASK_SET_MASK(255);
+               writeq(val64, &bar0->wreq_split_mask);
+       }
+
+       /* Setting Link stability period to 64 ms */ 
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = MISC_LINK_STABILITY_PRD(3);
+               writeq(val64, &bar0->misc_control);
+       }
+
        return SUCCESS;
 }
+#define LINK_UP_DOWN_INTERRUPT         1
+#define MAC_RMAC_ERR_TIMER             2
+
+int s2io_link_fault_indication(nic_t *nic)
+{
+       if (nic->intr_type != INTA)
+               return MAC_RMAC_ERR_TIMER;
+       if (nic->device_type == XFRAME_II_DEVICE)
+               return LINK_UP_DOWN_INTERRUPT;
+       else
+               return MAC_RMAC_ERR_TIMER;
+}
 
 /**
  *  en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1265,11 +1552,22 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
                        /*
-                        * Disabled all PCIX, Flash, MDIO, IIC and GPIO
+                        * If Hercules adapter enable GPIO otherwise
+                        * disabled all PCIX, Flash, MDIO, IIC and GPIO
                         * interrupts for now.
                         * TODO
                         */
-                       writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
+                       if (s2io_link_fault_indication(nic) ==
+                                       LINK_UP_DOWN_INTERRUPT ) {
+                               temp64 = readq(&bar0->pic_int_mask);
+                               temp64 &= ~((u64) PIC_INT_GPIO);
+                               writeq(temp64, &bar0->pic_int_mask);
+                               temp64 = readq(&bar0->gpio_int_mask);
+                               temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
+                               writeq(temp64, &bar0->gpio_int_mask);
+                       } else {
+                               writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
+                       }
                        /*
                         * No MSI Support is available presently, so TTI and
                         * RTI interrupts are also disabled.
@@ -1360,17 +1658,8 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        writeq(temp64, &bar0->general_int_mask);
                        /*
                         * All MAC block error interrupts are disabled for now
-                        * except the link status change interrupt.
                         * TODO
                         */
-                       val64 = MAC_INT_STATUS_RMAC_INT;
-                       temp64 = readq(&bar0->mac_int_mask);
-                       temp64 &= ~((u64) val64);
-                       writeq(temp64, &bar0->mac_int_mask);
-
-                       val64 = readq(&bar0->mac_rmac_err_mask);
-                       val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT);
-                       writeq(val64, &bar0->mac_rmac_err_mask);
                } else if (flag == DISABLE_INTRS) {
                        /*
                         * Disable MAC Intrs in the general intr mask register
@@ -1478,18 +1767,18 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
        }
 }
 
-static int check_prc_pcc_state(u64 val64, int flag, int rev_id)
+static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc)
 {
        int ret = 0;
 
        if (flag == FALSE) {
-               if (rev_id >= 4) {
+               if ((!herc && (rev_id >= 4)) || herc) {
                        if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
                            ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
                             ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
                                ret = 1;
                        }
-               } else {
+               }else {
                        if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
                            ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
                             ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
@@ -1497,7 +1786,7 @@ static int check_prc_pcc_state(u64 val64, int flag, int rev_id)
                        }
                }
        } else {
-               if (rev_id >= 4) {
+               if ((!herc && (rev_id >= 4)) || herc) {
                        if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
                             ADAPTER_STATUS_RMAC_PCC_IDLE) &&
                            (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
@@ -1533,10 +1822,11 @@ static int check_prc_pcc_state(u64 val64, int flag, int rev_id)
 
 static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
 {
-       int ret = 0;
+       int ret = 0, herc;
        u64 tmp64 = ~((u64) val64);
        int rev_id = get_xena_rev_id(sp->pdev);
 
+       herc = (sp->device_type == XFRAME_II_DEVICE);
        if (!
            (tmp64 &
             (ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY |
@@ -1544,7 +1834,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
              ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY |
              ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK |
              ADAPTER_STATUS_P_PLL_LOCK))) {
-               ret = check_prc_pcc_state(val64, flag, rev_id);
+               ret = check_prc_pcc_state(val64, flag, rev_id, herc);
        }
 
        return ret;
@@ -1603,6 +1893,8 @@ static int start_nic(struct s2io_nic *nic)
                       &bar0->prc_rxd0_n[i]);
 
                val64 = readq(&bar0->prc_ctrl_n[i]);
+               if (nic->config.bimodal)
+                       val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
 #ifndef CONFIG_2BUFF_MODE
                val64 |= PRC_CTRL_RC_ENABLED;
 #else
@@ -1656,9 +1948,14 @@ static int start_nic(struct s2io_nic *nic)
        }
 
        /*  Enable select interrupts */
-       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
-           RX_MAC_INTR | MC_INTR;
-       en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+       if (nic->intr_type != INTA)
+               en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
+       else {
+               interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+               interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+               interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+               en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+       }
 
        /*
         * With some switches, link might be already up at this point.
@@ -1675,12 +1972,13 @@ static int start_nic(struct s2io_nic *nic)
 
        /* SXE-002: Initialize link and activity LED */
        subid = nic->pdev->subsystem_device;
-       if ((subid & 0xFF) >= 0x07) {
+       if (((subid & 0xFF) >= 0x07) &&
+           (nic->device_type == XFRAME_I_DEVICE)) {
                val64 = readq(&bar0->gpio_control);
                val64 |= 0x0000800000000000ULL;
                writeq(val64, &bar0->gpio_control);
                val64 = 0x0411040400000000ULL;
-               writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+               writeq(val64, (void __iomem *)bar0 + 0x2700);
        }
 
        /*
@@ -1780,8 +2078,9 @@ static void stop_nic(struct s2io_nic *nic)
        config = &nic->config;
 
        /*  Disable all interrupts */
-       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
-           RX_MAC_INTR | MC_INTR;
+       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+       interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+       interruptible |= TX_MAC_INTR | RX_MAC_INTR;
        en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
        /*  Disable PRCs */
@@ -1834,6 +2133,7 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 #ifndef CONFIG_S2IO_NAPI
        unsigned long flags;
 #endif
+       RxD_t *first_rxdp = NULL;
 
        mac_control = &nic->mac_control;
        config = &nic->config;
@@ -1953,6 +2253,10 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                if (!skb) {
                        DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
                        DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
+                       if (first_rxdp) {
+                               wmb();
+                               first_rxdp->Control_1 |= RXD_OWN_XENA;
+                       }
                        return -ENOMEM;
                }
 #ifndef        CONFIG_2BUFF_MODE
@@ -1963,7 +2267,8 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                rxdp->Control_2 &= (~MASK_BUFFER0_SIZE);
                rxdp->Control_2 |= SET_BUFFER0_SIZE(size);
                rxdp->Host_Control = (unsigned long) (skb);
-               rxdp->Control_1 |= RXD_OWN_XENA;
+               if (alloc_tab & ((1 << rxsync_frequency) - 1))
+                       rxdp->Control_1 |= RXD_OWN_XENA;
                off++;
                off %= (MAX_RXDS_PER_BLOCK + 1);
                mac_control->rings[ring_no].rx_curr_put_info.offset = off;
@@ -1990,17 +2295,34 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */
                rxdp->Control_2 |= BIT(0);      /* Set Buffer_Empty bit. */
                rxdp->Host_Control = (u64) ((unsigned long) (skb));
-               rxdp->Control_1 |= RXD_OWN_XENA;
+               if (alloc_tab & ((1 << rxsync_frequency) - 1))
+                       rxdp->Control_1 |= RXD_OWN_XENA;
                off++;
                mac_control->rings[ring_no].rx_curr_put_info.offset = off;
 #endif
                rxdp->Control_2 |= SET_RXD_MARKER;
 
+               if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
+                       if (first_rxdp) {
+                               wmb();
+                               first_rxdp->Control_1 |= RXD_OWN_XENA;
+                       }
+                       first_rxdp = rxdp;
+               }
                atomic_inc(&nic->rx_bufs_left[ring_no]);
                alloc_tab++;
        }
 
       end:
+       /* Transfer ownership of first descriptor to adapter just before
+        * exiting. Before that, use memory barrier so that ownership
+        * and other fields are seen by adapter correctly.
+        */
+       if (first_rxdp) {
+               wmb();
+               first_rxdp->Control_1 |= RXD_OWN_XENA;
+       }
+
        return SUCCESS;
 }
 
@@ -2117,7 +2439,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
        int pkt_cnt = 0, org_pkts_to_process;
        mac_info_t *mac_control;
        struct config_param *config;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 val64;
        int i;
 
@@ -2201,9 +2523,10 @@ static void rx_intr_handler(ring_info_t *ring_data)
 #endif
        spin_lock(&nic->rx_lock);
        if (atomic_read(&nic->card_state) == CARD_DOWN) {
-               DBG_PRINT(ERR_DBG, "%s: %s going down for reset\n",
+               DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
                          __FUNCTION__, dev->name);
                spin_unlock(&nic->rx_lock);
+               return;
        }
 
        get_info = ring_data->rx_curr_get_info;
@@ -2318,8 +2641,14 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
                if (txdlp->Control_1 & TXD_T_CODE) {
                        unsigned long long err;
                        err = txdlp->Control_1 & TXD_T_CODE;
-                       DBG_PRINT(ERR_DBG, "***TxD error %llx\n",
-                                 err);
+                       if ((err >> 48) == 0xA) {
+                               DBG_PRINT(TX_DBG, "TxD returned due \
+to loss of link\n");
+                       }
+                       else {
+                               DBG_PRINT(ERR_DBG, "***TxD error \
+%llx\n", err);
+                       }
                }
 
                skb = (struct sk_buff *) ((unsigned long)
@@ -2345,6 +2674,8 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
                        for (j = 0; j < frg_cnt; j++, txdlp++) {
                                skb_frag_t *frag =
                                    &skb_shinfo(skb)->frags[j];
+                               if (!txdlp->Buffer_Pointer)
+                                       break;
                                pci_unmap_page(nic->pdev,
                                               (dma_addr_t)
                                               txdlp->
@@ -2394,10 +2725,12 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        register u64 val64 = 0, err_reg = 0;
 
        /* Handling link status change error Intr */
-       err_reg = readq(&bar0->mac_rmac_err_reg);
-       writeq(err_reg, &bar0->mac_rmac_err_reg);
-       if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
-               schedule_work(&nic->set_link_task);
+       if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+               err_reg = readq(&bar0->mac_rmac_err_reg);
+               writeq(err_reg, &bar0->mac_rmac_err_reg);
+               if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
+                       schedule_work(&nic->set_link_task);
+               }
        }
 
        /* Handling Ecc errors */
@@ -2407,11 +2740,17 @@ static void alarm_intr_handler(struct s2io_nic *nic)
                if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
                        nic->mac_control.stats_info->sw_stat.
                                double_ecc_errs++;
-                       DBG_PRINT(ERR_DBG, "%s: Device indicates ",
+                       DBG_PRINT(INIT_DBG, "%s: Device indicates ",
                                  dev->name);
-                       DBG_PRINT(ERR_DBG, "double ECC error!!\n");
-                       netif_stop_queue(dev);
-                       schedule_work(&nic->rst_timer_task);
+                       DBG_PRINT(INIT_DBG, "double ECC error!!\n");
+                       if (nic->device_type != XFRAME_II_DEVICE) {
+                               /* Reset XframeI only if critical error */
+                               if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
+                                            MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
+                                       netif_stop_queue(dev);
+                                       schedule_work(&nic->rst_timer_task);
+                               }
+                       }
                } else {
                        nic->mac_control.stats_info->sw_stat.
                                single_ecc_errs++;
@@ -2422,7 +2761,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        val64 = readq(&bar0->serr_source);
        if (val64 & SERR_SOURCE_ANY) {
                DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
-               DBG_PRINT(ERR_DBG, "serious error!!\n");
+               DBG_PRINT(ERR_DBG, "serious error %llx!!\n", 
+                         (unsigned long long)val64);
                netif_stop_queue(dev);
                schedule_work(&nic->rst_timer_task);
        }
@@ -2493,6 +2833,9 @@ void s2io_reset(nic_t * sp)
        u64 val64;
        u16 subid, pci_cmd;
 
+       /* Back up  the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
+       pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));
+
        val64 = SW_RESET_ALL;
        writeq(val64, &bar0->sw_reset);
 
@@ -2510,9 +2853,10 @@ void s2io_reset(nic_t * sp)
         */
        msleep(250);
 
-       /* Restore the PCI state saved during initializarion. */
+       /* Restore the PCI state saved during initialization. */
        pci_restore_state(sp->pdev);
-
+       pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
+                                    pci_cmd);
        s2io_init_pci(sp);
 
        msleep(250);
@@ -2520,29 +2864,42 @@ void s2io_reset(nic_t * sp)
        /* Set swapper to enable I/O register access */
        s2io_set_swapper(sp);
 
+       /* Restore the MSIX table entries from local variables */
+       restore_xmsi_data(sp);
+
        /* Clear certain PCI/PCI-X fields after reset */
-       pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
-       pci_cmd &= 0x7FFF; /* Clear parity err detect bit */
-       pci_write_config_word(sp->pdev, PCI_COMMAND, pci_cmd);
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               /* Clear parity err detect bit */
+               pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
 
-       val64 = readq(&bar0->txpic_int_reg);
-       val64 &= ~BIT(62); /* Clearing PCI_STATUS error reflected here */
-       writeq(val64, &bar0->txpic_int_reg);
+               /* Clearing PCIX Ecc status register */
+               pci_write_config_dword(sp->pdev, 0x68, 0x7C);
 
-       /* Clearing PCIX Ecc status register */
-       pci_write_config_dword(sp->pdev, 0x68, 0);
+               /* Clearing PCI_STATUS error reflected here */
+               writeq(BIT(62), &bar0->txpic_int_reg);
+       }
 
        /* Reset device statistics maintained by OS */
        memset(&sp->stats, 0, sizeof (struct net_device_stats));
 
        /* SXE-002: Configure link and activity LED to turn it off */
        subid = sp->pdev->subsystem_device;
-       if ((subid & 0xFF) >= 0x07) {
+       if (((subid & 0xFF) >= 0x07) &&
+           (sp->device_type == XFRAME_I_DEVICE)) {
                val64 = readq(&bar0->gpio_control);
                val64 |= 0x0000800000000000ULL;
                writeq(val64, &bar0->gpio_control);
                val64 = 0x0411040400000000ULL;
-               writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+               writeq(val64, (void __iomem *)bar0 + 0x2700);
+       }
+
+       /*
+        * Clear spurious ECC interrupts that would have occured on
+        * XFRAME II cards after reset.
+        */
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               val64 = readq(&bar0->pcc_err_reg);
+               writeq(val64, &bar0->pcc_err_reg);
        }
 
        sp->device_enabled_once = FALSE;
@@ -2639,8 +2996,9 @@ int s2io_set_swapper(nic_t * sp)
                 SWAPPER_CTRL_RXD_W_FE |
                 SWAPPER_CTRL_RXF_W_FE |
                 SWAPPER_CTRL_XMSI_FE |
-                SWAPPER_CTRL_XMSI_SE |
                 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+       if (sp->intr_type == INTA)
+               val64 |= SWAPPER_CTRL_XMSI_SE;
        writeq(val64, &bar0->swapper_ctrl);
 #else
        /*
@@ -2661,8 +3019,9 @@ int s2io_set_swapper(nic_t * sp)
                 SWAPPER_CTRL_RXD_W_SE |
                 SWAPPER_CTRL_RXF_W_FE |
                 SWAPPER_CTRL_XMSI_FE |
-                SWAPPER_CTRL_XMSI_SE |
                 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+       if (sp->intr_type == INTA)
+               val64 |= SWAPPER_CTRL_XMSI_SE;
        writeq(val64, &bar0->swapper_ctrl);
 #endif
        val64 = readq(&bar0->swapper_ctrl);
@@ -2684,6 +3043,201 @@ int s2io_set_swapper(nic_t * sp)
        return SUCCESS;
 }
 
+int wait_for_msix_trans(nic_t *nic, int i)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64;
+       int ret = 0, cnt = 0;
+
+       do {
+               val64 = readq(&bar0->xmsi_access);
+               if (!(val64 & BIT(15)))
+                       break;
+               mdelay(1);
+               cnt++;
+       } while(cnt < 5);
+       if (cnt == 5) {
+               DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+void restore_xmsi_data(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64;
+       int i;
+
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+               writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
+               writeq(nic->msix_info[i].data, &bar0->xmsi_data);
+               val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
+               writeq(val64, &bar0->xmsi_access);
+               if (wait_for_msix_trans(nic, i)) {
+                       DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+                       continue;
+               }
+       }
+}
+
+void store_xmsi_data(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64, addr, data;
+       int i;
+
+       /* Store and display */
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+               val64 = (BIT(15) | vBIT(i, 26, 6));
+               writeq(val64, &bar0->xmsi_access);
+               if (wait_for_msix_trans(nic, i)) {
+                       DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+                       continue;
+               }
+               addr = readq(&bar0->xmsi_address);
+               data = readq(&bar0->xmsi_data);
+               if (addr && data) {
+                       nic->msix_info[i].addr = addr;
+                       nic->msix_info[i].data = data;
+               }
+       }
+}
+
+int s2io_enable_msi(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u16 msi_ctrl, msg_val;
+       struct config_param *config = &nic->config;
+       struct net_device *dev = nic->dev;
+       u64 val64, tx_mat, rx_mat;
+       int i, err;
+
+       val64 = readq(&bar0->pic_control);
+       val64 &= ~BIT(1);
+       writeq(val64, &bar0->pic_control);
+
+       err = pci_enable_msi(nic->pdev);
+       if (err) {
+               DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
+                         nic->dev->name);
+               return err;
+       }
+
+       /*
+        * Enable MSI and use MSI-1 in stead of the standard MSI-0
+        * for interrupt handling.
+        */
+       pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+       msg_val ^= 0x1;
+       pci_write_config_word(nic->pdev, 0x4c, msg_val);
+       pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+
+       pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
+       msi_ctrl |= 0x10;
+       pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
+
+       /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
+       tx_mat = readq(&bar0->tx_mat0_n[0]);
+       for (i=0; i<config->tx_fifo_num; i++) {
+               tx_mat |= TX_MAT_SET(i, 1);
+       }
+       writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+       rx_mat = readq(&bar0->rx_mat);
+       for (i=0; i<config->rx_ring_num; i++) {
+               rx_mat |= RX_MAT_SET(i, 1);
+       }
+       writeq(rx_mat, &bar0->rx_mat);
+
+       dev->irq = nic->pdev->irq;
+       return 0;
+}
+
+int s2io_enable_msi_x(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 tx_mat, rx_mat;
+       u16 msi_control; /* Temp variable */
+       int ret, i, j, msix_indx = 1;
+
+       nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
+                              GFP_KERNEL);
+       if (nic->entries == NULL) {
+               DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+       memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+
+       nic->s2io_entries =
+               kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
+                                  GFP_KERNEL);
+       if (nic->s2io_entries == NULL) {
+               DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+               kfree(nic->entries);
+               return -ENOMEM;
+       }
+       memset(nic->s2io_entries, 0,
+              MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+               nic->entries[i].entry = i;
+               nic->s2io_entries[i].entry = i;
+               nic->s2io_entries[i].arg = NULL;
+               nic->s2io_entries[i].in_use = 0;
+       }
+
+       tx_mat = readq(&bar0->tx_mat0_n[0]);
+       for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
+               tx_mat |= TX_MAT_SET(i, msix_indx);
+               nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
+               nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
+               nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+       }
+       writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+       if (!nic->config.bimodal) {
+               rx_mat = readq(&bar0->rx_mat);
+               for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+                       rx_mat |= RX_MAT_SET(j, msix_indx);
+                       nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+                       nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+                       nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+               }
+               writeq(rx_mat, &bar0->rx_mat);
+       } else {
+               tx_mat = readq(&bar0->tx_mat0_n[7]);
+               for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+                       tx_mat |= TX_MAT_SET(i, msix_indx);
+                       nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+                       nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+                       nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+               }
+               writeq(tx_mat, &bar0->tx_mat0_n[7]);
+       }
+
+       ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+       if (ret) {
+               DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+               kfree(nic->entries);
+               kfree(nic->s2io_entries);
+               nic->entries = NULL;
+               nic->s2io_entries = NULL;
+               return -ENOMEM;
+       }
+
+       /*
+        * To enable MSI-X, MSI also needs to be enabled, due to a bug
+        * in the herc NIC. (Temp change, needs to be removed later)
+        */
+       pci_read_config_word(nic->pdev, 0x42, &msi_control);
+       msi_control |= 0x1; /* Enable MSI */
+       pci_write_config_word(nic->pdev, 0x42, msi_control);
+
+       return 0;
+}
+
 /* ********************************************************* *
  * Functions defined below concern the OS part of the driver *
  * ********************************************************* */
@@ -2704,13 +3258,15 @@ int s2io_open(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int err = 0;
+       int i;
+       u16 msi_control; /* Temp variable */
 
        /*
         * Make sure you have link off by default every time
         * Nic is initialized
         */
        netif_carrier_off(dev);
-       sp->last_link_state = 0; /* Unkown link state */
+       sp->last_link_state = 0;
 
        /* Initialize H/W and enable interrupts */
        if (s2io_card_up(sp)) {
@@ -2720,13 +3276,55 @@ int s2io_open(struct net_device *dev)
                goto hw_init_failed;
        }
 
+       /* Store the values of the MSIX table in the nic_t structure */
+       store_xmsi_data(sp);
+
        /* After proper initialization of H/W, register ISR */
-       err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
-                         sp->name, dev);
-       if (err) {
-               DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
-                         dev->name);
-               goto isr_registration_failed;
+       if (sp->intr_type == MSI) {
+               err = request_irq((int) sp->pdev->irq, s2io_msi_handle, 
+                       SA_SHIRQ, sp->name, dev);
+               if (err) {
+                       DBG_PRINT(ERR_DBG, "%s: MSI registration \
+failed\n", dev->name);
+                       goto isr_registration_failed;
+               }
+       }
+       if (sp->intr_type == MSI_X) {
+               for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+                       if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+                               sprintf(sp->desc1, "%s:MSI-X-%d-TX",
+                                       dev->name, i);
+                               err = request_irq(sp->entries[i].vector,
+                                         s2io_msix_fifo_handle, 0, sp->desc1,
+                                         sp->s2io_entries[i].arg);
+                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, 
+                                                       sp->msix_info[i].addr);
+                       } else {
+                               sprintf(sp->desc2, "%s:MSI-X-%d-RX",
+                                       dev->name, i);
+                               err = request_irq(sp->entries[i].vector,
+                                         s2io_msix_ring_handle, 0, sp->desc2,
+                                         sp->s2io_entries[i].arg);
+                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, 
+                                                       sp->msix_info[i].addr);
+                       }
+                       if (err) {
+                               DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
+failed\n", dev->name, i);
+                               DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+                               goto isr_registration_failed;
+                       }
+                       sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+               }
+       }
+       if (sp->intr_type == INTA) {
+               err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+                               sp->name, dev);
+               if (err) {
+                       DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+                                 dev->name);
+                       goto isr_registration_failed;
+               }
        }
 
        if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
@@ -2739,10 +3337,37 @@ int s2io_open(struct net_device *dev)
        return 0;
 
 setting_mac_address_failed:
-       free_irq(sp->pdev->irq, dev);
+       if (sp->intr_type != MSI_X)
+               free_irq(sp->pdev->irq, dev);
 isr_registration_failed:
+       del_timer_sync(&sp->alarm_timer);
+       if (sp->intr_type == MSI_X) {
+               if (sp->device_type == XFRAME_II_DEVICE) {
+                       for (i=1; (sp->s2io_entries[i].in_use == 
+                               MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_disable_msix(sp->pdev);
+
+                       /* Temp */
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+               }
+       }
+       else if (sp->intr_type == MSI)
+               pci_disable_msi(sp->pdev);
        s2io_reset(sp);
 hw_init_failed:
+       if (sp->intr_type == MSI_X) {
+               if (sp->entries)
+                       kfree(sp->entries);
+               if (sp->s2io_entries)
+                       kfree(sp->s2io_entries);
+       }
        return err;
 }
 
@@ -2762,12 +3387,35 @@ hw_init_failed:
 int s2io_close(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
+       int i;
+       u16 msi_control;
+
        flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
-       free_irq(sp->pdev->irq, dev);
+       if (sp->intr_type == MSI_X) {
+               if (sp->device_type == XFRAME_II_DEVICE) {
+                       for (i=1; (sp->s2io_entries[i].in_use == 
+                                       MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+                       pci_disable_msix(sp->pdev);
+               }
+       }
+       else {
+               free_irq(sp->pdev->irq, dev);
+               if (sp->intr_type == MSI)
+                       pci_disable_msi(sp->pdev);
+       }       
        sp->device_close_flag = TRUE;   /* Device is shut down. */
        return 0;
 }
@@ -2796,6 +3444,8 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 #ifdef NETIF_F_TSO
        int mss;
 #endif
+       u16 vlan_tag = 0;
+       int vlan_priority = 0;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -2814,6 +3464,13 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 
        queue = 0;
 
+       /* Get Fifo number to Transmit based on vlan priority */
+       if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+               vlan_tag = vlan_tx_tag_get(skb);
+               vlan_priority = vlan_tag >> 13;
+               queue = config->fifo_mapping[vlan_priority];
+       }
+
        put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset;
        get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset;
        txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off].
@@ -2822,12 +3479,21 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
        /* Avoid "put" pointer going beyond "get" pointer */
        if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
-               DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n");
+               DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
                netif_stop_queue(dev);
                dev_kfree_skb(skb);
                spin_unlock_irqrestore(&sp->tx_lock, flags);
                return 0;
        }
+
+       /* A buffer with no data will be dropped */
+       if (!skb->len) {
+               DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name);
+               dev_kfree_skb(skb);
+               spin_unlock_irqrestore(&sp->tx_lock, flags);
+               return 0;
+       }
+
 #ifdef NETIF_F_TSO
        mss = skb_shinfo(skb)->tso_size;
        if (mss) {
@@ -2849,6 +3515,12 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        txdp->Control_2 |= config->tx_intr_type;
+
+       if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+               txdp->Control_2 |= TXD_VLAN_ENABLE;
+               txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
+       }
+
        txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |
                            TXD_GATHER_CODE_FIRST);
        txdp->Control_1 |= TXD_LIST_OWN_XENA;
@@ -2856,6 +3528,9 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        /* For fragmented SKB. */
        for (i = 0; i < frg_cnt; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+               /* A '0' length fragment will be ignored */
+               if (!frag->size)
+                       continue;
                txdp++;
                txdp->Buffer_Pointer = (u64) pci_map_page
                    (sp->pdev, frag->page, frag->page_offset,
@@ -2868,8 +3543,6 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
        writeq(val64, &tx_fifo->TxDL_Pointer);
 
-       wmb();
-
        val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
                 TX_FIFO_LAST_LIST);
 
@@ -2879,6 +3552,8 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
        writeq(val64, &tx_fifo->List_Control);
 
+       mmiowb();
+
        put_off++;
        put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
        mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
@@ -2897,6 +3572,160 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static void
+s2io_alarm_handle(unsigned long data)
+{
+       nic_t *sp = (nic_t *)data;
+
+       alarm_intr_handler(sp);
+       mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
+}
+
+static irqreturn_t
+s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       nic_t *sp = dev->priv;
+       int i;
+       int ret;
+       mac_info_t *mac_control;
+       struct config_param *config;
+
+       atomic_inc(&sp->isr_cnt);
+       mac_control = &sp->mac_control;
+       config = &sp->config;
+       DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
+
+       /* If Intr is because of Rx Traffic */
+       for (i = 0; i < config->rx_ring_num; i++)
+               rx_intr_handler(&mac_control->rings[i]);
+
+       /* If Intr is because of Tx Traffic */
+       for (i = 0; i < config->tx_fifo_num; i++)
+               tx_intr_handler(&mac_control->fifos[i]);
+
+       /*
+        * If the Rx buffer count is below the panic threshold then
+        * reallocate the buffers from the interrupt handler itself,
+        * else schedule a tasklet to reallocate the buffers.
+        */
+       for (i = 0; i < config->rx_ring_num; i++) {
+               int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+               int level = rx_buffer_level(sp, rxb_size, i);
+
+               if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                       if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                         dev->name);
+                               DBG_PRINT(ERR_DBG, " in ISR!!\n");
+                               clear_bit(0, (&sp->tasklet_status));
+                               atomic_dec(&sp->isr_cnt);
+                               return IRQ_HANDLED;
+                       }
+                       clear_bit(0, (&sp->tasklet_status));
+               } else if (level == LOW) {
+                       tasklet_schedule(&sp->task);
+               }
+       }
+
+       atomic_dec(&sp->isr_cnt);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+       ring_info_t *ring = (ring_info_t *)dev_id;
+       nic_t *sp = ring->nic;
+       int rxb_size, level, rng_n;
+
+       atomic_inc(&sp->isr_cnt);
+       rx_intr_handler(ring);
+
+       rng_n = ring->ring_no;
+       rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+       level = rx_buffer_level(sp, rxb_size, rng_n);
+
+       if ((level == PANIC) && (!TASKLET_IN_USE)) {
+               int ret;
+               DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+               DBG_PRINT(INTR_DBG, "PANIC levels\n");
+               if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+                       DBG_PRINT(ERR_DBG, "Out of memory in %s",
+                                 __FUNCTION__);
+                       clear_bit(0, (&sp->tasklet_status));
+                       return IRQ_HANDLED;
+               }
+               clear_bit(0, (&sp->tasklet_status));
+       } else if (level == LOW) {
+               tasklet_schedule(&sp->task);
+       }
+       atomic_dec(&sp->isr_cnt);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+       fifo_info_t *fifo = (fifo_info_t *)dev_id;
+       nic_t *sp = fifo->nic;
+
+       atomic_inc(&sp->isr_cnt);
+       tx_intr_handler(fifo);
+       atomic_dec(&sp->isr_cnt);
+       return IRQ_HANDLED;
+}
+
+static void s2io_txpic_intr_handle(nic_t *sp)
+{
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
+       u64 val64;
+
+       val64 = readq(&bar0->pic_int_status);
+       if (val64 & PIC_INT_GPIO) {
+               val64 = readq(&bar0->gpio_int_reg);
+               if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
+                   (val64 & GPIO_INT_REG_LINK_UP)) {
+                       val64 |=  GPIO_INT_REG_LINK_DOWN;
+                       val64 |= GPIO_INT_REG_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_reg);
+                       goto masking;
+               }
+
+               if (((sp->last_link_state == LINK_UP) &&
+                       (val64 & GPIO_INT_REG_LINK_DOWN)) ||
+               ((sp->last_link_state == LINK_DOWN) &&
+               (val64 & GPIO_INT_REG_LINK_UP))) {
+                       val64 = readq(&bar0->gpio_int_mask);
+                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
+                       val64 |= GPIO_INT_MASK_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_mask);
+                       s2io_set_link((unsigned long)sp);
+               }
+masking:
+               if (sp->last_link_state == LINK_UP) {
+                       /*enable down interrupt */
+                       val64 = readq(&bar0->gpio_int_mask);
+                       /* unmasks link down intr */
+                       val64 &=  ~GPIO_INT_MASK_LINK_DOWN;
+                       /* masks link up intr */
+                       val64 |= GPIO_INT_MASK_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_mask);
+               } else {
+                       /*enable UP Interrupt */
+                       val64 = readq(&bar0->gpio_int_mask);
+                       /* unmasks link up interrupt */
+                       val64 &= ~GPIO_INT_MASK_LINK_UP;
+                       /* masks link down interrupt */
+                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
+                       writeq(val64, &bar0->gpio_int_mask);
+               }
+       }
+}
+
 /**
  *  s2io_isr - ISR handler of the device .
  *  @irq: the irq of the device.
@@ -2941,9 +3770,6 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
-       if (reason & (GEN_ERROR_INTR))
-               alarm_intr_handler(sp);
-
 #ifdef CONFIG_S2IO_NAPI
        if (reason & GEN_INTR_RXTRAFFIC) {
                if (netif_rx_schedule_prep(dev)) {
@@ -2982,6 +3808,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                        tx_intr_handler(&mac_control->fifos[i]);
        }
 
+       if (reason & GEN_INTR_TXPIC)
+               s2io_txpic_intr_handle(sp);
        /*
         * If the Rx buffer count is below the panic threshold then
         * reallocate the buffers from the interrupt handler itself,
@@ -3147,7 +3975,7 @@ static void s2io_set_multicast(struct net_device *dev)
 
                val64 = readq(&bar0->mac_cfg);
                sp->promisc_flg = 1;
-               DBG_PRINT(ERR_DBG, "%s: entered promiscuous mode\n",
+               DBG_PRINT(INFO_DBG, "%s: entered promiscuous mode\n",
                          dev->name);
        } else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) {
                /*  Remove the NIC from promiscuous mode */
@@ -3162,7 +3990,7 @@ static void s2io_set_multicast(struct net_device *dev)
 
                val64 = readq(&bar0->mac_cfg);
                sp->promisc_flg = 0;
-               DBG_PRINT(ERR_DBG, "%s: left promiscuous mode\n",
+               DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
                          dev->name);
        }
 
@@ -3351,11 +4179,10 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
 {
        nic_t *sp = dev->priv;
 
-       strncpy(info->driver, s2io_driver_name, sizeof(s2io_driver_name));
-       strncpy(info->version, s2io_driver_version,
-               sizeof(s2io_driver_version));
-       strncpy(info->fw_version, "", 32);
-       strncpy(info->bus_info, pci_name(sp->pdev), 32);
+       strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
+       strncpy(info->version, s2io_driver_version, sizeof(info->version));
+       strncpy(info->fw_version, "", sizeof(info->fw_version));
+       strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
        info->regdump_len = XENA_REG_SPACE;
        info->eedump_len = XENA_EEPROM_SPACE;
        info->testinfo_len = S2IO_TEST_LEN;
@@ -3410,7 +4237,8 @@ static void s2io_phy_id(unsigned long data)
        u16 subid;
 
        subid = sp->pdev->subsystem_device;
-       if ((subid & 0xFF) >= 0x07) {
+       if ((sp->device_type == XFRAME_II_DEVICE) ||
+                  ((subid & 0xFF) >= 0x07)) {
                val64 = readq(&bar0->gpio_control);
                val64 ^= GPIO_CTRL_GPIO_0;
                writeq(val64, &bar0->gpio_control);
@@ -3447,7 +4275,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
 
        subid = sp->pdev->subsystem_device;
        last_gpio_ctrl_val = readq(&bar0->gpio_control);
-       if ((subid & 0xFF) < 0x07) {
+       if ((sp->device_type == XFRAME_I_DEVICE) &&
+               ((subid & 0xFF) < 0x07)) {
                val64 = readq(&bar0->adapter_control);
                if (!(val64 & ADAPTER_CNTL_EN)) {
                        printk(KERN_ERR
@@ -3467,7 +4296,7 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
                msleep_interruptible(MAX_FLICKER_TIME);
        del_timer_sync(&sp->id_timer);
 
-       if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+       if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) {
                writeq(last_gpio_ctrl_val, &bar0->gpio_control);
                last_gpio_ctrl_val = readq(&bar0->gpio_control);
        }
@@ -3549,29 +4378,53 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
  */
 
 #define S2IO_DEV_ID            5
-static int read_eeprom(nic_t * sp, int off, u32 * data)
+static int read_eeprom(nic_t * sp, int off, u64 * data)
 {
        int ret = -1;
        u32 exit_cnt = 0;
        u64 val64;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
-       val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-           I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
-           I2C_CONTROL_CNTL_START;
-       SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+                   I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
+                   I2C_CONTROL_CNTL_START;
+               SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
 
-       while (exit_cnt < 5) {
-               val64 = readq(&bar0->i2c_control);
-               if (I2C_CONTROL_CNTL_END(val64)) {
-                       *data = I2C_CONTROL_GET_DATA(val64);
-                       ret = 0;
-                       break;
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->i2c_control);
+                       if (I2C_CONTROL_CNTL_END(val64)) {
+                               *data = I2C_CONTROL_GET_DATA(val64);
+                               ret = 0;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
                }
-               msleep(50);
-               exit_cnt++;
        }
 
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+                       SPI_CONTROL_BYTECNT(0x3) | 
+                       SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               val64 |= SPI_CONTROL_REQ;
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->spi_control);
+                       if (val64 & SPI_CONTROL_NACK) {
+                               ret = 1;
+                               break;
+                       } else if (val64 & SPI_CONTROL_DONE) {
+                               *data = readq(&bar0->spi_data);
+                               *data &= 0xffffff;
+                               ret = 0;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
+               }
+       }
        return ret;
 }
 
@@ -3590,28 +4443,53 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
  *  0 on success, -1 on failure.
  */
 
-static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
+static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
 {
        int exit_cnt = 0, ret = -1;
        u64 val64;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
-       val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-           I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) |
-           I2C_CONTROL_CNTL_START;
-       SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+                   I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
+                   I2C_CONTROL_CNTL_START;
+               SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->i2c_control);
+                       if (I2C_CONTROL_CNTL_END(val64)) {
+                               if (!(val64 & I2C_CONTROL_NACK))
+                                       ret = 0;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
+               }
+       }
 
-       while (exit_cnt < 5) {
-               val64 = readq(&bar0->i2c_control);
-               if (I2C_CONTROL_CNTL_END(val64)) {
-                       if (!(val64 & I2C_CONTROL_NACK))
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               int write_cnt = (cnt == 8) ? 0 : cnt;
+               writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
+
+               val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+                       SPI_CONTROL_BYTECNT(write_cnt) | 
+                       SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               val64 |= SPI_CONTROL_REQ;
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->spi_control);
+                       if (val64 & SPI_CONTROL_NACK) {
+                               ret = 1;
+                               break;
+                       } else if (val64 & SPI_CONTROL_DONE) {
                                ret = 0;
-                       break;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
                }
-               msleep(50);
-               exit_cnt++;
        }
-
        return ret;
 }
 
@@ -3631,7 +4509,8 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
 static int s2io_ethtool_geeprom(struct net_device *dev,
                         struct ethtool_eeprom *eeprom, u8 * data_buf)
 {
-       u32 data, i, valid;
+       u32 i, valid;
+       u64 data;
        nic_t *sp = dev->priv;
 
        eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -3669,7 +4548,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
                                u8 * data_buf)
 {
        int len = eeprom->len, cnt = 0;
-       u32 valid = 0, data;
+       u64 valid = 0, data;
        nic_t *sp = dev->priv;
 
        if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
@@ -3717,7 +4596,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
 static int s2io_register_test(nic_t * sp, uint64_t * data)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
-       u64 val64 = 0;
+       u64 val64 = 0, exp_val;
        int fail = 0;
 
        val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -3733,7 +4612,11 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
        }
 
        val64 = readq(&bar0->rx_queue_cfg);
-       if (val64 != 0x0808080808080808ULL) {
+       if (sp->device_type == XFRAME_II_DEVICE)
+               exp_val = 0x0404040404040404ULL;
+       else
+               exp_val = 0x0808080808080808ULL;
+       if (val64 != exp_val) {
                fail = 1;
                DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
        }
@@ -3761,7 +4644,7 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
        }
 
        *data = fail;
-       return 0;
+       return fail;
 }
 
 /**
@@ -3780,58 +4663,83 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
 static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
 {
        int fail = 0;
-       u32 ret_data;
+       u64 ret_data, org_4F0, org_7F0;
+       u8 saved_4F0 = 0, saved_7F0 = 0;
+       struct net_device *dev = sp->dev;
 
        /* Test Write Error at offset 0 */
-       if (!write_eeprom(sp, 0, 0, 3))
-               fail = 1;
+       /* Note that SPI interface allows write access to all areas
+        * of EEPROM. Hence doing all negative testing only for Xframe I.
+        */
+       if (sp->device_type == XFRAME_I_DEVICE)
+               if (!write_eeprom(sp, 0, 0, 3))
+                       fail = 1;
+
+       /* Save current values at offsets 0x4F0 and 0x7F0 */
+       if (!read_eeprom(sp, 0x4F0, &org_4F0))
+               saved_4F0 = 1;
+       if (!read_eeprom(sp, 0x7F0, &org_7F0))
+               saved_7F0 = 1;
 
        /* Test Write at offset 4f0 */
-       if (write_eeprom(sp, 0x4F0, 0x01234567, 3))
+       if (write_eeprom(sp, 0x4F0, 0x012345, 3))
                fail = 1;
        if (read_eeprom(sp, 0x4F0, &ret_data))
                fail = 1;
 
-       if (ret_data != 0x01234567)
+       if (ret_data != 0x012345) {
+               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
                fail = 1;
+       }
 
        /* Reset the EEPROM data go FFFF */
-       write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3);
+       write_eeprom(sp, 0x4F0, 0xFFFFFF, 3);
 
        /* Test Write Request Error at offset 0x7c */
-       if (!write_eeprom(sp, 0x07C, 0, 3))
-               fail = 1;
+       if (sp->device_type == XFRAME_I_DEVICE)
+               if (!write_eeprom(sp, 0x07C, 0, 3))
+                       fail = 1;
 
-       /* Test Write Request at offset 0x7fc */
-       if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
+       /* Test Write Request at offset 0x7f0 */
+       if (write_eeprom(sp, 0x7F0, 0x012345, 3))
                fail = 1;
-       if (read_eeprom(sp, 0x7FC, &ret_data))
+       if (read_eeprom(sp, 0x7F0, &ret_data))
                fail = 1;
 
-       if (ret_data != 0x01234567)
+       if (ret_data != 0x012345) {
+               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
                fail = 1;
+       }
 
        /* Reset the EEPROM data go FFFF */
-       write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
+       write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
 
-       /* Test Write Error at offset 0x80 */
-       if (!write_eeprom(sp, 0x080, 0, 3))
-               fail = 1;
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               /* Test Write Error at offset 0x80 */
+               if (!write_eeprom(sp, 0x080, 0, 3))
+                       fail = 1;
 
-       /* Test Write Error at offset 0xfc */
-       if (!write_eeprom(sp, 0x0FC, 0, 3))
-               fail = 1;
+               /* Test Write Error at offset 0xfc */
+               if (!write_eeprom(sp, 0x0FC, 0, 3))
+                       fail = 1;
 
-       /* Test Write Error at offset 0x100 */
-       if (!write_eeprom(sp, 0x100, 0, 3))
-               fail = 1;
+               /* Test Write Error at offset 0x100 */
+               if (!write_eeprom(sp, 0x100, 0, 3))
+                       fail = 1;
 
-       /* Test Write Error at offset 4ec */
-       if (!write_eeprom(sp, 0x4EC, 0, 3))
-               fail = 1;
+               /* Test Write Error at offset 4ec */
+               if (!write_eeprom(sp, 0x4EC, 0, 3))
+                       fail = 1;
+       }
+
+       /* Restore values at offsets 0x4F0 and 0x7F0 */
+       if (saved_4F0)
+               write_eeprom(sp, 0x4F0, org_4F0, 3);
+       if (saved_7F0)
+               write_eeprom(sp, 0x7F0, org_7F0, 3);
 
        *data = fail;
-       return 0;
+       return fail;
 }
 
 /**
@@ -3913,7 +4821,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
-       int cnt, iteration = 0, test_pass = 0;
+       int cnt, iteration = 0, test_fail = 0;
 
        val64 = readq(&bar0->adapter_control);
        val64 &= ~ADAPTER_ECC_EN;
@@ -3921,7 +4829,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
 
        val64 = readq(&bar0->mc_rldram_test_ctrl);
        val64 |= MC_RLDRAM_TEST_MODE;
-       writeq(val64, &bar0->mc_rldram_test_ctrl);
+       SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
        val64 = readq(&bar0->mc_rldram_mrs);
        val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE;
@@ -3949,17 +4857,12 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
                }
                writeq(val64, &bar0->mc_rldram_test_d2);
 
-               val64 = (u64) (0x0000003fffff0000ULL);
+               val64 = (u64) (0x0000003ffffe0100ULL);
                writeq(val64, &bar0->mc_rldram_test_add);
 
-
-               val64 = MC_RLDRAM_TEST_MODE;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
-
-               val64 |=
-                   MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
-                   MC_RLDRAM_TEST_GO;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
+               val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
+                       MC_RLDRAM_TEST_GO;
+               SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
                for (cnt = 0; cnt < 5; cnt++) {
                        val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -3971,11 +4874,8 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
                if (cnt == 5)
                        break;
 
-               val64 = MC_RLDRAM_TEST_MODE;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
-
-               val64 |= MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
+               val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
+               SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
                for (cnt = 0; cnt < 5; cnt++) {
                        val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -3988,18 +4888,18 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
                        break;
 
                val64 = readq(&bar0->mc_rldram_test_ctrl);
-               if (val64 & MC_RLDRAM_TEST_PASS)
-                       test_pass = 1;
+               if (!(val64 & MC_RLDRAM_TEST_PASS))
+                       test_fail = 1;
 
                iteration++;
        }
 
-       if (!test_pass)
-               *data = 1;
-       else
-               *data = 0;
+       *data = test_fail;
 
-       return 0;
+       /* Bring the adapter out of test mode */
+       SPECIAL_REG_WRITE(0, &bar0->mc_rldram_test_ctrl, LF);
+
+       return test_fail;
 }
 
 /**
@@ -4081,44 +4981,91 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        StatInfo_t *stat_info = sp->mac_control.stats_info;
 
        s2io_updt_stats(sp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_frms_oflow) << 32  |
+               le32_to_cpu(stat_info->tmac_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_data_octets_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_data_octets);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_mcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_mcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_bcst_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_any_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_vld_ip);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_drop_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_drop_ip);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_icmp_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_icmp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_rst_tcp_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_rst_tcp);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_udp_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_udp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_vld_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_vld_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_data_octets_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_data_octets);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_vld_mcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_vld_bcst_frms);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_discarded_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_usized_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_osized_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_osized_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_frag_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_frag_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_jabber_frms);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_ip);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_drop_ip);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_icmp);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_udp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_err_drp_udp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_pause_cnt);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_accepted_ip);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
        tmp_stats[i++] = 0;
        tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
@@ -4246,14 +5193,6 @@ int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 int s2io_change_mtu(struct net_device *dev, int new_mtu)
 {
        nic_t *sp = dev->priv;
-       XENA_dev_config_t __iomem *bar0 = sp->bar0;
-       register u64 val64;
-
-       if (netif_running(dev)) {
-               DBG_PRINT(ERR_DBG, "%s: Must be stopped to ", dev->name);
-               DBG_PRINT(ERR_DBG, "change its MTU\n");
-               return -EBUSY;
-       }
 
        if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
                DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
@@ -4261,11 +5200,22 @@ int s2io_change_mtu(struct net_device *dev, int new_mtu)
                return -EPERM;
        }
 
-       /* Set the new MTU into the PYLD register of the NIC */
-       val64 = new_mtu;
-       writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
-
        dev->mtu = new_mtu;
+       if (netif_running(dev)) {
+               s2io_card_down(sp);
+               netif_stop_queue(dev);
+               if (s2io_card_up(sp)) {
+                       DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+                                 __FUNCTION__);
+               }
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
+       } else { /* Device is down */
+               XENA_dev_config_t __iomem *bar0 = sp->bar0;
+               u64 val64 = new_mtu;
+
+               writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
+       }
 
        return 0;
 }
@@ -4333,11 +5283,13 @@ static void s2io_set_link(unsigned long data)
        }
 
        subid = nic->pdev->subsystem_device;
-       /*
-        * Allow a small delay for the NICs self initiated
-        * cleanup to complete.
-        */
-       msleep(100);
+       if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+               /*
+                * Allow a small delay for the NICs self initiated
+                * cleanup to complete.
+                */
+               msleep(100);
+       }
 
        val64 = readq(&bar0->adapter_status);
        if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
@@ -4345,7 +5297,8 @@ static void s2io_set_link(unsigned long data)
                        val64 = readq(&bar0->adapter_control);
                        val64 |= ADAPTER_CNTL_EN;
                        writeq(val64, &bar0->adapter_control);
-                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+                                                            subid)) {
                                val64 = readq(&bar0->gpio_control);
                                val64 |= GPIO_CTRL_GPIO_0;
                                writeq(val64, &bar0->gpio_control);
@@ -4354,20 +5307,24 @@ static void s2io_set_link(unsigned long data)
                                val64 |= ADAPTER_LED_ON;
                                writeq(val64, &bar0->adapter_control);
                        }
-                       val64 = readq(&bar0->adapter_status);
-                       if (!LINK_IS_UP(val64)) {
-                               DBG_PRINT(ERR_DBG, "%s:", dev->name);
-                               DBG_PRINT(ERR_DBG, " Link down");
-                               DBG_PRINT(ERR_DBG, "after ");
-                               DBG_PRINT(ERR_DBG, "enabling ");
-                               DBG_PRINT(ERR_DBG, "device \n");
+                       if (s2io_link_fault_indication(nic) ==
+                                               MAC_RMAC_ERR_TIMER) {
+                               val64 = readq(&bar0->adapter_status);
+                               if (!LINK_IS_UP(val64)) {
+                                       DBG_PRINT(ERR_DBG, "%s:", dev->name);
+                                       DBG_PRINT(ERR_DBG, " Link down");
+                                       DBG_PRINT(ERR_DBG, "after ");
+                                       DBG_PRINT(ERR_DBG, "enabling ");
+                                       DBG_PRINT(ERR_DBG, "device \n");
+                               }
                        }
                        if (nic->device_enabled_once == FALSE) {
                                nic->device_enabled_once = TRUE;
                        }
                        s2io_link(nic, LINK_UP);
                } else {
-                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+                                                             subid)) {
                                val64 = readq(&bar0->gpio_control);
                                val64 &= ~GPIO_CTRL_GPIO_0;
                                writeq(val64, &bar0->gpio_control);
@@ -4390,6 +5347,7 @@ static void s2io_card_down(nic_t * sp)
        unsigned long flags;
        register u64 val64 = 0;
 
+       del_timer_sync(&sp->alarm_timer);
        /* If s2io_set_link task is executing, wait till it completes. */
        while (test_and_set_bit(0, &(sp->link_state))) {
                msleep(50);
@@ -4445,7 +5403,7 @@ static void s2io_card_down(nic_t * sp)
 
 static int s2io_card_up(nic_t * sp)
 {
-       int i, ret;
+       int i, ret = 0;
        mac_info_t *mac_control;
        struct config_param *config;
        struct net_device *dev = (struct net_device *) sp->dev;
@@ -4457,6 +5415,15 @@ static int s2io_card_up(nic_t * sp)
                return -ENODEV;
        }
 
+       if (sp->intr_type == MSI)
+               ret = s2io_enable_msi(sp);
+       else if (sp->intr_type == MSI_X)
+               ret = s2io_enable_msi_x(sp);
+       if (ret) {
+               DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+               sp->intr_type = INTA;
+       }
+
        /*
         * Initializing the Rx buffers. For now we are considering only 1
         * Rx ring and initializing buffers into 30 Rx blocks
@@ -4492,6 +5459,8 @@ static int s2io_card_up(nic_t * sp)
                return -ENODEV;
        }
 
+       S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+
        atomic_set(&sp->card_state, CARD_UP);
        return 0;
 }
@@ -4633,9 +5602,21 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
 
        skb->protocol = eth_type_trans(skb, dev);
 #ifdef CONFIG_S2IO_NAPI
-       netif_receive_skb(skb);
+       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               /* Queueing the vlan frame to the upper layer */
+               vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+                       RXD_GET_VLAN_TAG(rxdp->Control_2));
+       } else {
+               netif_receive_skb(skb);
+       }
 #else
-       netif_rx(skb);
+       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               /* Queueing the vlan frame to the upper layer */
+               vlan_hwaccel_rx(skb, sp->vlgrp,
+                       RXD_GET_VLAN_TAG(rxdp->Control_2));
+       } else {
+               netif_rx(skb);
+       }
 #endif
        dev->last_rx = jiffies;
        atomic_dec(&sp->rx_bufs_left[ring_no]);
@@ -4727,6 +5708,8 @@ static void s2io_init_pci(nic_t * sp)
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
 module_param(tx_fifo_num, int, 0);
 module_param(rx_ring_num, int, 0);
 module_param_array(tx_fifo_len, uint, NULL, 0);
@@ -4739,9 +5722,12 @@ module_param(mc_pause_threshold_q4q7, int, 0);
 module_param(shared_splits, int, 0);
 module_param(tmac_util_period, int, 0);
 module_param(rmac_util_period, int, 0);
+module_param(bimodal, bool, 0);
 #ifndef CONFIG_S2IO_NAPI
 module_param(indicate_max_pkts, int, 0);
 #endif
+module_param(rxsync_frequency, int, 0);
+module_param(intr_type, int, 0);
 
 /**
  *  s2io_init_nic - Initialization of the adapter .
@@ -4770,9 +5756,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        u16 subid;
        mac_info_t *mac_control;
        struct config_param *config;
+       int mode;
+       u8 dev_intr_type = intr_type;
 
 #ifdef CONFIG_S2IO_NAPI
-       DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+       if (dev_intr_type != INTA) {
+               DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
+is enabled. Defaulting to INTA\n");
+               dev_intr_type = INTA;
+       }
+       else
+               DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
 #endif
 
        if ((ret = pci_enable_device(pdev))) {
@@ -4799,10 +5793,35 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                return -ENOMEM;
        }
 
-       if (pci_request_regions(pdev, s2io_driver_name)) {
-               DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
-                   pci_disable_device(pdev);
-               return -ENODEV;
+       if ((dev_intr_type == MSI_X) && 
+                       ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+                       (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+               DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
+Defaulting to INTA\n");
+               dev_intr_type = INTA;
+       }
+       if (dev_intr_type != MSI_X) {
+               if (pci_request_regions(pdev, s2io_driver_name)) {
+                       DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+                           pci_disable_device(pdev);
+                       return -ENODEV;
+               }
+       }
+       else {
+               if (!(request_mem_region(pci_resource_start(pdev, 0),
+                                pci_resource_len(pdev, 0), s2io_driver_name))) {
+                       DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
+                       pci_disable_device(pdev);
+                       return -ENODEV;
+               }
+               if (!(request_mem_region(pci_resource_start(pdev, 2),
+                                pci_resource_len(pdev, 2), s2io_driver_name))) {
+                       DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
+                       release_mem_region(pci_resource_start(pdev, 0),
+                                   pci_resource_len(pdev, 0));
+                       pci_disable_device(pdev);
+                       return -ENODEV;
+               }
        }
 
        dev = alloc_etherdev(sizeof(nic_t));
@@ -4825,7 +5844,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        sp->pdev = pdev;
        sp->high_dma_flag = dma_flag;
        sp->device_enabled_once = FALSE;
+       sp->intr_type = dev_intr_type;
+
+       if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
+               (pdev->device == PCI_DEVICE_ID_HERC_UNI))
+               sp->device_type = XFRAME_II_DEVICE;
+       else
+               sp->device_type = XFRAME_I_DEVICE;
 
+               
        /* Initialize some PCI/PCI-X fields of the NIC. */
        s2io_init_pci(sp);
 
@@ -4840,7 +5867,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        config = &sp->config;
 
        /* Tx side parameters. */
-       tx_fifo_len[0] = DEFAULT_FIFO_LEN;      /* Default value. */
+       if (tx_fifo_len[0] == 0)
+               tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
        config->tx_fifo_num = tx_fifo_num;
        for (i = 0; i < MAX_TX_FIFOS; i++) {
                config->tx_cfg[i].fifo_len = tx_fifo_len[i];
@@ -4860,10 +5888,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                        break;
                }
        }
-       config->max_txds = MAX_SKB_FRAGS;
+       config->max_txds = MAX_SKB_FRAGS + 1;
 
        /* Rx side parameters. */
-       rx_ring_sz[0] = SMALL_BLK_CNT;  /* Default value. */
+       if (rx_ring_sz[0] == 0)
+               rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
        config->rx_ring_num = rx_ring_num;
        for (i = 0; i < MAX_RX_RINGS; i++) {
                config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -4893,7 +5922,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        /*  initialize the shared memory used by the NIC and the host */
        if (init_shared_mem(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
-                         dev->name);
+                         __FUNCTION__);
                ret = -ENOMEM;
                goto mem_alloc_failed;
        }
@@ -4934,6 +5963,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        dev->do_ioctl = &s2io_ioctl;
        dev->change_mtu = &s2io_change_mtu;
        SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+       dev->vlan_rx_register = s2io_vlan_rx_register;
+       dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
 
        /*
         * will use eth_mac_addr() for  dev->set_mac_address
@@ -4968,12 +6000,26 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto set_swap_failed;
        }
 
-       /*
-        * Fix for all "FFs" MAC address problems observed on
-        * Alpha platforms
-        */
-       fix_mac_address(sp);
-       s2io_reset(sp);
+       /* Verify if the Herc works on the slot its placed into */
+       if (sp->device_type & XFRAME_II_DEVICE) {
+               mode = s2io_verify_pci_mode(sp);
+               if (mode < 0) {
+                       DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__);
+                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
+                       ret = -EBADSLT;
+                       goto set_swap_failed;
+               }
+       }
+
+       /* Not needed for Herc */
+       if (sp->device_type & XFRAME_I_DEVICE) {
+               /*
+                * Fix for all "FFs" MAC address problems observed on
+                * Alpha platforms
+                */
+               fix_mac_address(sp);
+               s2io_reset(sp);
+       }
 
        /*
         * MAC address initialization.
@@ -4998,22 +6044,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16);
        sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24);
 
-       DBG_PRINT(INIT_DBG,
-                 "DEFAULT MAC ADDR:0x%02x-%02x-%02x-%02x-%02x-%02x\n",
-                 sp->def_mac_addr[0].mac_addr[0],
-                 sp->def_mac_addr[0].mac_addr[1],
-                 sp->def_mac_addr[0].mac_addr[2],
-                 sp->def_mac_addr[0].mac_addr[3],
-                 sp->def_mac_addr[0].mac_addr[4],
-                 sp->def_mac_addr[0].mac_addr[5]);
-
        /*  Set the factory defined MAC address initially   */
        dev->addr_len = ETH_ALEN;
        memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
 
        /*
         * Initialize the tasklet status and link state flags
-        * and the card statte parameter
+        * and the card state parameter
         */
        atomic_set(&(sp->card_state), 0);
        sp->tasklet_status = 0;
@@ -5048,9 +6085,85 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto register_failed;
        }
 
+       if (sp->device_type & XFRAME_II_DEVICE) {
+               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
+                         dev->name);
+               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+                               get_xena_rev_id(sp->pdev),
+                               s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+               DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+               switch(sp->intr_type) {
+                       case INTA:
+                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
+                               break;
+                       case MSI:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
+                               break;
+                       case MSI_X:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+                               break;
+               }
+
+               DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
+               DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                         sp->def_mac_addr[0].mac_addr[0],
+                         sp->def_mac_addr[0].mac_addr[1],
+                         sp->def_mac_addr[0].mac_addr[2],
+                         sp->def_mac_addr[0].mac_addr[3],
+                         sp->def_mac_addr[0].mac_addr[4],
+                         sp->def_mac_addr[0].mac_addr[5]);
+               mode = s2io_print_pci_mode(sp);
+               if (mode < 0) {
+                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
+                       ret = -EBADSLT;
+                       goto set_swap_failed;
+               }
+       } else {
+               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
+                         dev->name);
+               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+                                       get_xena_rev_id(sp->pdev),
+                                       s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+               DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+               switch(sp->intr_type) {
+                       case INTA:
+                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
+                               break;
+                       case MSI:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
+                               break;
+                       case MSI_X:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+                               break;
+               }
+               DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
+               DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                         sp->def_mac_addr[0].mac_addr[0],
+                         sp->def_mac_addr[0].mac_addr[1],
+                         sp->def_mac_addr[0].mac_addr[2],
+                         sp->def_mac_addr[0].mac_addr[3],
+                         sp->def_mac_addr[0].mac_addr[4],
+                         sp->def_mac_addr[0].mac_addr[5]);
+       }
+
        /* Initialize device name */
        strcpy(sp->name, dev->name);
-       strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+       if (sp->device_type & XFRAME_II_DEVICE)
+               strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
+       else
+               strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+
+       /* Initialize bimodal Interrupts */
+       sp->config.bimodal = bimodal;
+       if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) {
+               sp->config.bimodal = 0;
+               DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n",
+                       dev->name);
+       }
 
        /*
         * Make Link state as off at this point, when the Link change
@@ -5070,7 +6183,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
       mem_alloc_failed:
        free_shared_mem(sp);
        pci_disable_device(pdev);
-       pci_release_regions(pdev);
+       if (dev_intr_type != MSI_X)
+               pci_release_regions(pdev);
+       else {
+               release_mem_region(pci_resource_start(pdev, 0),
+                       pci_resource_len(pdev, 0));
+               release_mem_region(pci_resource_start(pdev, 2),
+                       pci_resource_len(pdev, 2));
+       }
        pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
 
@@ -5104,7 +6224,14 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
        iounmap(sp->bar0);
        iounmap(sp->bar1);
        pci_disable_device(pdev);
-       pci_release_regions(pdev);
+       if (sp->intr_type != MSI_X)
+               pci_release_regions(pdev);
+       else {
+               release_mem_region(pci_resource_start(pdev, 0),
+                       pci_resource_len(pdev, 0));
+               release_mem_region(pci_resource_start(pdev, 2),
+                       pci_resource_len(pdev, 2));
+       }
        pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
 }