--- /dev/null
- /* enable GPHY LinkChange Interrrupt */
+ /*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * Contact Information:
+ * Xiong Huang <xiong.huang@atheros.com>
+ * Jie Yang <jie.yang@atheros.com>
+ * Chris Snook <csnook@redhat.com>
+ * Jay Cliburn <jcliburn@gmail.com>
+ *
+ * This version is adapted from the Attansic reference driver.
+ *
+ * TODO:
+ * Add more ethtool functions.
+ * Fix abstruse irq enable/disable condition described here:
+ * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
+ *
+ * NEEDS TESTING:
+ * VLAN
+ * multicast
+ * promiscuous mode
+ * interrupt coalescing
+ * SMP torture testing
+ */
+
+ #include <linux/atomic.h>
+ #include <asm/byteorder.h>
+
+ #include <linux/compiler.h>
+ #include <linux/crc32.h>
+ #include <linux/delay.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/etherdevice.h>
+ #include <linux/hardirq.h>
+ #include <linux/if_ether.h>
+ #include <linux/if_vlan.h>
+ #include <linux/in.h>
+ #include <linux/interrupt.h>
+ #include <linux/ip.h>
+ #include <linux/irqflags.h>
+ #include <linux/irqreturn.h>
+ #include <linux/jiffies.h>
+ #include <linux/mii.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/net.h>
+ #include <linux/netdevice.h>
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/pm.h>
+ #include <linux/skbuff.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/string.h>
+ #include <linux/tcp.h>
+ #include <linux/timer.h>
+ #include <linux/types.h>
+ #include <linux/workqueue.h>
+
+ #include <net/checksum.h>
+
+ #include "atl1.h"
+
+ #define ATLX_DRIVER_VERSION "2.1.3"
+ MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, "
+ "Chris Snook <csnook@redhat.com>, "
+ "Jay Cliburn <jcliburn@gmail.com>");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(ATLX_DRIVER_VERSION);
+
+ /* Temporary hack for merging atl1 and atl2 */
+ #include "atlx.c"
+
+ static const struct ethtool_ops atl1_ethtool_ops;
+
+ /*
+ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+ #define ATL1_MAX_NIC 4
+
+ #define OPTION_UNSET -1
+ #define OPTION_DISABLED 0
+ #define OPTION_ENABLED 1
+
+ #define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+
+ /*
+ * Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 100 (200us)
+ */
+ static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+ static unsigned int num_int_mod_timer;
+ module_param_array_named(int_mod_timer, int_mod_timer, int,
+ &num_int_mod_timer, 0);
+ MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+
+ #define DEFAULT_INT_MOD_CNT 100 /* 200us */
+ #define MAX_INT_MOD_CNT 65000
+ #define MIN_INT_MOD_CNT 50
+
+ struct atl1_option {
+ enum { enable_option, range_option, list_option } type;
+ char *name;
+ char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ struct atl1_opt_list {
+ int i;
+ char *str;
+ } *p;
+ } l;
+ } arg;
+ };
+
+ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
+ struct pci_dev *pdev)
+ {
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ dev_info(&pdev->dev, "%s enabled\n", opt->name);
+ return 0;
+ case OPTION_DISABLED:
+ dev_info(&pdev->dev, "%s disabled\n", opt->name);
+ return 0;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+ *value);
+ return 0;
+ }
+ break;
+ case list_option:{
+ int i;
+ struct atl1_opt_list *ent;
+
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ dev_info(&pdev->dev, "%s\n",
+ ent->str);
+ return 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+ opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+ }
+
+ /*
+ * atl1_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input. If an invalid value is given, or if no user specified
+ * value exists, a default value is used. The final value is stored
+ * in a variable in the adapter structure.
+ */
+ static void __devinit atl1_check_options(struct atl1_adapter *adapter)
+ {
+ struct pci_dev *pdev = adapter->pdev;
+ int bd = adapter->bd_number;
+ if (bd >= ATL1_MAX_NIC) {
+ dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+ dev_notice(&pdev->dev, "using defaults for all values\n");
+ }
+ { /* Interrupt Moderate Timer */
+ struct atl1_option opt = {
+ .type = range_option,
+ .name = "Interrupt Moderator Timer",
+ .err = "using default of "
+ __MODULE_STRING(DEFAULT_INT_MOD_CNT),
+ .def = DEFAULT_INT_MOD_CNT,
+ .arg = {.r = {.min = MIN_INT_MOD_CNT,
+ .max = MAX_INT_MOD_CNT} }
+ };
+ int val;
+ if (num_int_mod_timer > bd) {
+ val = int_mod_timer[bd];
+ atl1_validate_option(&val, &opt, pdev);
+ adapter->imt = (u16) val;
+ } else
+ adapter->imt = (u16) (opt.def);
+ }
+ }
+
+ /*
+ * atl1_pci_tbl - PCI Device ID Table
+ */
+ static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = {
+ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
+ /* required last entry */
+ {0,}
+ };
+ MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
+
+ static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+ NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
+
+ static int debug = -1;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
+
+ /*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0 or idle status (if error)
+ */
+ static s32 atl1_reset_hw(struct atl1_hw *hw)
+ {
+ struct pci_dev *pdev = hw->back->pdev;
+ struct atl1_adapter *adapter = hw->back;
+ u32 icr;
+ int i;
+
+ /*
+ * Clear Interrupt mask to stop board from generating
+ * interrupts & Clear any pending interrupt events
+ */
+ /*
+ * iowrite32(0, hw->hw_addr + REG_IMR);
+ * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
+ */
+
+ /*
+ * Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
+ ioread32(hw->hw_addr + REG_MASTER_CTRL);
+
+ iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
+ ioread16(hw->hw_addr + REG_PHY_ENABLE);
+
+ /* delay about 1ms */
+ msleep(1);
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (i = 0; i < 10; i++) {
+ icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
+ if (!icr)
+ break;
+ /* delay 1 ms */
+ msleep(1);
+ /* FIXME: still the right way to do this? */
+ cpu_relax();
+ }
+
+ if (icr) {
+ if (netif_msg_hw(adapter))
+ dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
+ return icr;
+ }
+
+ return 0;
+ }
+
+ /* function about EEPROM
+ *
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+ static int atl1_check_eeprom_exist(struct atl1_hw *hw)
+ {
+ u32 value;
+ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+ }
+
+ value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+ }
+
+ static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
+ {
+ int i;
+ u32 control;
+
+ if (offset & 3)
+ /* address do not align */
+ return false;
+
+ iowrite32(0, hw->hw_addr + REG_VPD_DATA);
+ control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+ iowrite32(control, hw->hw_addr + REG_VPD_CAP);
+ ioread32(hw->hw_addr + REG_VPD_CAP);
+
+ for (i = 0; i < 10; i++) {
+ msleep(2);
+ control = ioread32(hw->hw_addr + REG_VPD_CAP);
+ if (control & VPD_CAP_VPD_FLAG)
+ break;
+ }
+ if (control & VPD_CAP_VPD_FLAG) {
+ *p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
+ return true;
+ }
+ /* timeout */
+ return false;
+ }
+
+ /*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+ static s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
+ {
+ u32 val;
+ int i;
+
+ val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
+ MDIO_CLK_SEL_SHIFT;
+ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+ ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16) val;
+ return 0;
+ }
+ return ATLX_ERR_PHY;
+ }
+
+ #define CUSTOM_SPI_CS_SETUP 2
+ #define CUSTOM_SPI_CLK_HI 2
+ #define CUSTOM_SPI_CLK_LO 2
+ #define CUSTOM_SPI_CS_HOLD 2
+ #define CUSTOM_SPI_CS_HI 3
+
+ static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
+ {
+ int i;
+ u32 value;
+
+ iowrite32(0, hw->hw_addr + REG_SPI_DATA);
+ iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
+
+ value = SPI_FLASH_CTRL_WAIT_READY |
+ (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+ SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
+ SPI_FLASH_CTRL_CLK_HI_MASK) <<
+ SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
+ SPI_FLASH_CTRL_CLK_LO_MASK) <<
+ SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
+ SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+ SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
+ SPI_FLASH_CTRL_CS_HI_MASK) <<
+ SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
+ SPI_FLASH_CTRL_INS_SHIFT;
+
+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+ value |= SPI_FLASH_CTRL_START;
+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+ ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+ for (i = 0; i < 10; i++) {
+ msleep(1);
+ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+ if (!(value & SPI_FLASH_CTRL_START))
+ break;
+ }
+
+ if (value & SPI_FLASH_CTRL_START)
+ return false;
+
+ *buf = ioread32(hw->hw_addr + REG_SPI_DATA);
+
+ return true;
+ }
+
+ /*
+ * get_permanent_address
+ * return 0 if get valid mac address,
+ */
+ static int atl1_get_permanent_address(struct atl1_hw *hw)
+ {
+ u32 addr[2];
+ u32 i, control;
+ u16 reg;
+ u8 eth_addr[ETH_ALEN];
+ bool key_valid;
+
+ if (is_valid_ether_addr(hw->perm_mac_addr))
+ return 0;
+
+ /* init */
+ addr[0] = addr[1] = 0;
+
+ if (!atl1_check_eeprom_exist(hw)) {
+ reg = 0;
+ key_valid = false;
+ /* Read out all EEPROM content */
+ i = 0;
+ while (1) {
+ if (atl1_read_eeprom(hw, i + 0x100, &control)) {
+ if (key_valid) {
+ if (reg == REG_MAC_STA_ADDR)
+ addr[0] = control;
+ else if (reg == (REG_MAC_STA_ADDR + 4))
+ addr[1] = control;
+ key_valid = false;
+ } else if ((control & 0xff) == 0x5A) {
+ key_valid = true;
+ reg = (u16) (control >> 16);
+ } else
+ break;
+ } else
+ /* read error */
+ break;
+ i += 4;
+ }
+
+ *(u32 *) ð_addr[2] = swab32(addr[0]);
+ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+ }
+
+ /* see if SPI FLAGS exist ? */
+ addr[0] = addr[1] = 0;
+ reg = 0;
+ key_valid = false;
+ i = 0;
+ while (1) {
+ if (atl1_spi_read(hw, i + 0x1f000, &control)) {
+ if (key_valid) {
+ if (reg == REG_MAC_STA_ADDR)
+ addr[0] = control;
+ else if (reg == (REG_MAC_STA_ADDR + 4))
+ addr[1] = control;
+ key_valid = false;
+ } else if ((control & 0xff) == 0x5A) {
+ key_valid = true;
+ reg = (u16) (control >> 16);
+ } else
+ /* data end */
+ break;
+ } else
+ /* read error */
+ break;
+ i += 4;
+ }
+
+ *(u32 *) ð_addr[2] = swab32(addr[0]);
+ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+
+ /*
+ * On some motherboards, the MAC address is written by the
+ * BIOS directly to the MAC register during POST, and is
+ * not stored in eeprom. If all else thus far has failed
+ * to fetch the permanent MAC address, try reading it directly.
+ */
+ addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+ addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+ *(u32 *) ð_addr[2] = swab32(addr[0]);
+ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /*
+ * Reads the adapter's MAC address from the EEPROM
+ * hw - Struct containing variables accessed by shared code
+ */
+ static s32 atl1_read_mac_addr(struct atl1_hw *hw)
+ {
+ u16 i;
+
+ if (atl1_get_permanent_address(hw))
+ random_ether_addr(hw->perm_mac_addr);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ hw->mac_addr[i] = hw->perm_mac_addr[i];
+ return 0;
+ }
+
+ /*
+ * Hashes an address to determine its location in the multicast table
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *
+ * atl1_hash_mc_addr
+ * purpose
+ * set hash value for a multicast address
+ * hash calcu processing :
+ * 1. calcu 32bit CRC for multicast address
+ * 2. reverse crc with MSB to LSB
+ */
+ static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
+ {
+ u32 crc32, value = 0;
+ int i;
+
+ crc32 = ether_crc_le(6, mc_addr);
+ for (i = 0; i < 32; i++)
+ value |= (((crc32 >> i) & 1) << (31 - i));
+
+ return value;
+ }
+
+ /*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+ static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
+ {
+ u32 hash_bit, hash_reg;
+ u32 mta;
+
+ /*
+ * The HASH Table is a register array of 2 32-bit registers.
+ * It is treated like an array of 64 bits. We want to set
+ * bit BitArray[hash_value]. So we figure out what register
+ * the bit is in, read it, OR in the new bit, then write
+ * back the new value. The register is determined by the
+ * upper 7 bits of the hash value and the bit within that
+ * register are determined by the lower 5 bits of the value.
+ */
+ hash_reg = (hash_value >> 31) & 0x1;
+ hash_bit = (hash_value >> 26) & 0x1F;
+ mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+ mta |= (1 << hash_bit);
+ iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+ }
+
+ /*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+ static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
+ {
+ int i;
+ u32 val;
+
+ val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+ ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return 0;
+
+ return ATLX_ERR_PHY;
+ }
+
+ /*
+ * Make L001's PHY out of Power Saving State (bug)
+ * hw - Struct containing variables accessed by shared code
+ * when power on, L001's PHY always on Power saving State
+ * (Gigabit Link forbidden)
+ */
+ static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
+ {
+ s32 ret;
+ ret = atl1_write_phy_reg(hw, 29, 0x0029);
+ if (ret)
+ return ret;
+ return atl1_write_phy_reg(hw, 30, 0);
+ }
+
+ /*
+ * Resets the PHY and make all config validate
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+ */
+ static s32 atl1_phy_reset(struct atl1_hw *hw)
+ {
+ struct pci_dev *pdev = hw->back->pdev;
+ struct atl1_adapter *adapter = hw->back;
+ s32 ret_val;
+ u16 phy_data;
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL)
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+ else {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+ MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default:
+ /* MEDIA_TYPE_10M_HALF: */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ }
+ }
+
+ ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /* pcie serdes link may be down! */
+ if (netif_msg_hw(adapter))
+ dev_dbg(&pdev->dev, "pcie phy link down\n");
+
+ for (i = 0; i < 25; i++) {
+ msleep(1);
+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
+ if (netif_msg_hw(adapter))
+ dev_warn(&pdev->dev,
+ "pcie link down at least 25ms\n");
+ return ret_val;
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * Configures PHY autoneg and flow control advertisement settings
+ * hw - Struct containing variables accessed by shared code
+ */
+ static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
+ {
+ s32 ret_val;
+ s16 mii_autoneg_adv_reg;
+ s16 mii_1000t_ctrl_reg;
+
+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
+
+ /*
+ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T Control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
+
+ /*
+ * Need to parse media_type and set up
+ * the appropriate PHY registers.
+ */
+ switch (hw->media_type) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS |
+ MII_AR_100TX_FD_CAPS);
+ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
+ break;
+
+ case MEDIA_TYPE_1000M_FULL:
+ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
+ break;
+
+ case MEDIA_TYPE_100M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+ break;
+
+ case MEDIA_TYPE_100M_HALF:
+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+ break;
+
+ case MEDIA_TYPE_10M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+ break;
+
+ default:
+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+ break;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+ ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+
+ return 0;
+ }
+
+ /*
+ * Configures link settings.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ */
+ static s32 atl1_setup_link(struct atl1_hw *hw)
+ {
+ struct pci_dev *pdev = hw->back->pdev;
+ struct atl1_adapter *adapter = hw->back;
+ s32 ret_val;
+
+ /*
+ * Options:
+ * PHY will advertise value(s) parsed from
+ * autoneg_advertised and fc
+ * no matter what autoneg is , We will not wait link result.
+ */
+ ret_val = atl1_phy_setup_autoneg_adv(hw);
+ if (ret_val) {
+ if (netif_msg_link(adapter))
+ dev_dbg(&pdev->dev,
+ "error setting up autonegotiation\n");
+ return ret_val;
+ }
+ /* SW.Reset , En-Auto-Neg if needed */
+ ret_val = atl1_phy_reset(hw);
+ if (ret_val) {
+ if (netif_msg_link(adapter))
+ dev_dbg(&pdev->dev, "error resetting phy\n");
+ return ret_val;
+ }
+ hw->phy_configured = true;
+ return ret_val;
+ }
+
+ static void atl1_init_flash_opcode(struct atl1_hw *hw)
+ {
+ if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
+ /* Atmel */
+ hw->flash_vendor = 0;
+
+ /* Init OP table */
+ iowrite8(flash_table[hw->flash_vendor].cmd_program,
+ hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
+ iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
+ hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
+ iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
+ hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
+ iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
+ hw->hw_addr + REG_SPI_FLASH_OP_RDID);
+ iowrite8(flash_table[hw->flash_vendor].cmd_wren,
+ hw->hw_addr + REG_SPI_FLASH_OP_WREN);
+ iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
+ hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
+ iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
+ hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
+ iowrite8(flash_table[hw->flash_vendor].cmd_read,
+ hw->hw_addr + REG_SPI_FLASH_OP_READ);
+ }
+
+ /*
+ * Performs basic configuration of the adapter.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+ static s32 atl1_init_hw(struct atl1_hw *hw)
+ {
+ u32 ret_val = 0;
+
+ /* Zero out the Multicast HASH table */
+ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+ /* clear the old settings from the multicast hash table */
+ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+ atl1_init_flash_opcode(hw);
+
+ if (!hw->phy_configured) {
++ /* enable GPHY LinkChange Interrupt */
+ ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
+ if (ret_val)
+ return ret_val;
+ /* make PHY out of power-saving state */
+ ret_val = atl1_phy_leave_power_saving(hw);
+ if (ret_val)
+ return ret_val;
+ /* Call a subroutine to configure the link */
+ ret_val = atl1_setup_link(hw);
+ }
+ return ret_val;
+ }
+
+ /*
+ * Detects the current speed and duplex settings of the hardware.
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+ static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
+ {
+ struct pci_dev *pdev = hw->back->pdev;
+ struct atl1_adapter *adapter = hw->back;
+ s32 ret_val;
+ u16 phy_data;
+
+ /* ; --- Read PHY Specific Status Register (17) */
+ ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
+ return ATLX_ERR_PHY_RES;
+
+ switch (phy_data & MII_ATLX_PSSR_SPEED) {
+ case MII_ATLX_PSSR_1000MBS:
+ *speed = SPEED_1000;
+ break;
+ case MII_ATLX_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_ATLX_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ if (netif_msg_hw(adapter))
+ dev_dbg(&pdev->dev, "error getting speed\n");
+ return ATLX_ERR_PHY_SPEED;
+ break;
+ }
+ if (phy_data & MII_ATLX_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return 0;
+ }
+
+ static void atl1_set_mac_addr(struct atl1_hw *hw)
+ {
+ u32 value;
+ /*
+ * 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword
+ */
+ value = (((u32) hw->mac_addr[2]) << 24) |
+ (((u32) hw->mac_addr[3]) << 16) |
+ (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
+ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+ /* high dword */
+ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+ iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
+ }
+
+ /*
+ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+ static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+ {
+ struct atl1_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+
+ hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+ hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+
+ adapter->wol = 0;
+ device_set_wakeup_enable(&adapter->pdev->dev, false);
+ adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
+ adapter->ict = 50000; /* 100ms */
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+
+ hw->phy_configured = false;
+ hw->preamble_len = 7;
+ hw->ipgt = 0x60;
+ hw->min_ifg = 0x50;
+ hw->ipgr1 = 0x40;
+ hw->ipgr2 = 0x60;
+ hw->max_retry = 0xf;
+ hw->lcol = 0x37;
+ hw->jam_ipg = 7;
+ hw->rfd_burst = 8;
+ hw->rrd_burst = 8;
+ hw->rfd_fetch_gap = 1;
+ hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
+ hw->rx_jumbo_lkah = 1;
+ hw->rrd_ret_timer = 16;
+ hw->tpd_burst = 4;
+ hw->tpd_fetch_th = 16;
+ hw->txf_burst = 0x100;
+ hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
+ hw->tpd_fetch_gap = 1;
+ hw->rcb_value = atl1_rcb_64;
+ hw->dma_ord = atl1_dma_ord_enh;
+ hw->dmar_block = atl1_dma_req_256;
+ hw->dmaw_block = atl1_dma_req_256;
+ hw->cmb_rrd = 4;
+ hw->cmb_tpd = 4;
+ hw->cmb_rx_timer = 1; /* about 2us */
+ hw->cmb_tx_timer = 1; /* about 2us */
+ hw->smb_timer = 100000; /* about 200ms */
+
+ spin_lock_init(&adapter->lock);
+ spin_lock_init(&adapter->mb_lock);
+
+ return 0;
+ }
+
+ static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+ return result;
+ }
+
+ static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+ int val)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ atl1_write_phy_reg(&adapter->hw, reg_num, val);
+ }
+
+ /*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+ static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ int retval;
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+
+ return retval;
+ }
+
+ /*
+ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+ static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
+ {
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_ring_header *ring_header = &adapter->ring_header;
+ struct pci_dev *pdev = adapter->pdev;
+ int size;
+ u8 offset = 0;
+
+ size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
+ tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+ if (unlikely(!tpd_ring->buffer_info)) {
+ if (netif_msg_drv(adapter))
+ dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
+ size);
+ goto err_nomem;
+ }
+ rfd_ring->buffer_info =
+ (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+
+ /*
+ * real ring DMA buffer
+ * each ring/block may need up to 8 bytes for alignment, hence the
+ * additional 40 bytes tacked onto the end.
+ */
+ ring_header->size = size =
+ sizeof(struct tx_packet_desc) * tpd_ring->count
+ + sizeof(struct rx_free_desc) * rfd_ring->count
+ + sizeof(struct rx_return_desc) * rrd_ring->count
+ + sizeof(struct coals_msg_block)
+ + sizeof(struct stats_msg_block)
+ + 40;
+
+ ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+ &ring_header->dma);
+ if (unlikely(!ring_header->desc)) {
+ if (netif_msg_drv(adapter))
+ dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
+ goto err_nomem;
+ }
+
+ memset(ring_header->desc, 0, ring_header->size);
+
+ /* init TPD ring */
+ tpd_ring->dma = ring_header->dma;
+ offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
+ tpd_ring->dma += offset;
+ tpd_ring->desc = (u8 *) ring_header->desc + offset;
+ tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
+
+ /* init RFD ring */
+ rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
+ offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
+ rfd_ring->dma += offset;
+ rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
+ rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
+
+
+ /* init RRD ring */
+ rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
+ offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
+ rrd_ring->dma += offset;
+ rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
+ rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
+
+
+ /* init CMB */
+ adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
+ offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
+ adapter->cmb.dma += offset;
+ adapter->cmb.cmb = (struct coals_msg_block *)
+ ((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
+
+ /* init SMB */
+ adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
+ offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
+ adapter->smb.dma += offset;
+ adapter->smb.smb = (struct stats_msg_block *)
+ ((u8 *) adapter->cmb.cmb +
+ (sizeof(struct coals_msg_block) + offset));
+
+ return 0;
+
+ err_nomem:
+ kfree(tpd_ring->buffer_info);
+ return -ENOMEM;
+ }
+
+ static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
+ {
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+
+ atomic_set(&tpd_ring->next_to_use, 0);
+ atomic_set(&tpd_ring->next_to_clean, 0);
+
+ rfd_ring->next_to_clean = 0;
+ atomic_set(&rfd_ring->next_to_use, 0);
+
+ rrd_ring->next_to_use = 0;
+ atomic_set(&rrd_ring->next_to_clean, 0);
+ }
+
+ /*
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
+ */
+ static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+ {
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_buffer *buffer_info;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Rx ring sk_buffs */
+ for (i = 0; i < rfd_ring->count; i++) {
+ buffer_info = &rfd_ring->buffer_info[i];
+ if (buffer_info->dma) {
+ pci_unmap_page(pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+ }
+ if (buffer_info->skb) {
+ dev_kfree_skb(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ }
+
+ size = sizeof(struct atl1_buffer) * rfd_ring->count;
+ memset(rfd_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+ memset(rfd_ring->desc, 0, rfd_ring->size);
+
+ rfd_ring->next_to_clean = 0;
+ atomic_set(&rfd_ring->next_to_use, 0);
+
+ rrd_ring->next_to_use = 0;
+ atomic_set(&rrd_ring->next_to_clean, 0);
+ }
+
+ /*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+ static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+ {
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Tx ring sk_buffs */
+ for (i = 0; i < tpd_ring->count; i++) {
+ buffer_info = &tpd_ring->buffer_info[i];
+ if (buffer_info->dma) {
+ pci_unmap_page(pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+ }
+
+ for (i = 0; i < tpd_ring->count; i++) {
+ buffer_info = &tpd_ring->buffer_info[i];
+ if (buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ }
+
+ size = sizeof(struct atl1_buffer) * tpd_ring->count;
+ memset(tpd_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+ memset(tpd_ring->desc, 0, tpd_ring->size);
+
+ atomic_set(&tpd_ring->next_to_use, 0);
+ atomic_set(&tpd_ring->next_to_clean, 0);
+ }
+
+ /*
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+ static void atl1_free_ring_resources(struct atl1_adapter *adapter)
+ {
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_ring_header *ring_header = &adapter->ring_header;
+
+ atl1_clean_tx_ring(adapter);
+ atl1_clean_rx_ring(adapter);
+
+ kfree(tpd_ring->buffer_info);
+ pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+ ring_header->dma);
+
+ tpd_ring->buffer_info = NULL;
+ tpd_ring->desc = NULL;
+ tpd_ring->dma = 0;
+
+ rfd_ring->buffer_info = NULL;
+ rfd_ring->desc = NULL;
+ rfd_ring->dma = 0;
+
+ rrd_ring->desc = NULL;
+ rrd_ring->dma = 0;
+
+ adapter->cmb.dma = 0;
+ adapter->cmb.cmb = NULL;
+
+ adapter->smb.dma = 0;
+ adapter->smb.smb = NULL;
+ }
+
+ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+ {
+ u32 value;
+ struct atl1_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+ /* duplex */
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+ /* speed */
+ value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+ MAC_CTRL_SPEED_SHIFT);
+ /* flow control */
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+ /* PAD & CRC */
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ /* preamble length */
+ value |= (((u32) adapter->hw.preamble_len
+ & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+ /* vlan */
+ __atlx_vlan_mode(netdev->features, &value);
+ /* rx checksum
+ if (adapter->rx_csum)
+ value |= MAC_CTRL_RX_CHKSUM_EN;
+ */
+ /* filter mode */
+ value |= MAC_CTRL_BC_EN;
+ if (netdev->flags & IFF_PROMISC)
+ value |= MAC_CTRL_PROMIS_EN;
+ else if (netdev->flags & IFF_ALLMULTI)
+ value |= MAC_CTRL_MC_ALL_EN;
+ /* value |= MAC_CTRL_LOOPBACK; */
+ iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+ }
+
+ static u32 atl1_check_link(struct atl1_adapter *adapter)
+ {
+ struct atl1_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ u32 ret_val;
+ u16 speed, duplex, phy_data;
+ int reconfig = 0;
+
+ /* MII_BMSR must read twice */
+ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+ if (!(phy_data & BMSR_LSTATUS)) {
+ /* link down */
+ if (netif_carrier_ok(netdev)) {
+ /* old link state: Up */
+ if (netif_msg_link(adapter))
+ dev_info(&adapter->pdev->dev, "link is down\n");
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ }
+ return 0;
+ }
+
+ /* Link Up */
+ ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val)
+ return ret_val;
+
+ switch (hw->media_type) {
+ case MEDIA_TYPE_1000M_FULL:
+ if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_100M_FULL:
+ if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_10M_HALF:
+ if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+ reconfig = 1;
+ break;
+ }
+
+ /* link result is our setting */
+ if (!reconfig) {
+ if (adapter->link_speed != speed ||
+ adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl1_setup_mac_ctrl(adapter);
+ if (netif_msg_link(adapter))
+ dev_info(&adapter->pdev->dev,
+ "%s link is up %d Mbps %s\n",
+ netdev->name, adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
+ "full duplex" : "half duplex");
+ }
+ if (!netif_carrier_ok(netdev)) {
+ /* Link down -> Up */
+ netif_carrier_on(netdev);
+ }
+ return 0;
+ }
+
+ /* change original link status */
+ if (netif_carrier_ok(netdev)) {
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+
+ if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+ hw->media_type != MEDIA_TYPE_1000M_FULL) {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+ MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default:
+ /* MEDIA_TYPE_10M_HALF: */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ }
+ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ return 0;
+ }
+
+ /* auto-neg, insert timer to re-config phy */
+ if (!adapter->phy_timer_pending) {
+ adapter->phy_timer_pending = true;
+ mod_timer(&adapter->phy_config_timer,
+ round_jiffies(jiffies + 3 * HZ));
+ }
+
+ return 0;
+ }
+
+ static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+ {
+ u32 hi, lo, value;
+
+ /* RFD Flow Control */
+ value = adapter->rfd_ring.count;
+ hi = value / 16;
+ if (hi < 2)
+ hi = 2;
+ lo = value * 7 / 8;
+
+ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+ /* RRD Flow Control */
+ value = adapter->rrd_ring.count;
+ lo = value / 16;
+ hi = value * 7 / 8;
+ if (lo < 2)
+ lo = 2;
+ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+ }
+
+ static void set_flow_ctrl_new(struct atl1_hw *hw)
+ {
+ u32 hi, lo, value;
+
+ /* RXF Flow Control */
+ value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+ lo = value / 16;
+ if (lo < 192)
+ lo = 192;
+ hi = value * 7 / 8;
+ if (hi < lo)
+ hi = lo + 16;
+ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+ /* RRD Flow Control */
+ value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+ lo = value / 8;
+ hi = value * 7 / 8;
+ if (lo < 2)
+ lo = 2;
+ if (hi < lo)
+ hi = lo + 3;
+ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+ }
+
+ /*
+ * atl1_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+ static u32 atl1_configure(struct atl1_adapter *adapter)
+ {
+ struct atl1_hw *hw = &adapter->hw;
+ u32 value;
+
+ /* clear interrupt status */
+ iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
+ /* set MAC Address */
+ value = (((u32) hw->mac_addr[2]) << 24) |
+ (((u32) hw->mac_addr[3]) << 16) |
+ (((u32) hw->mac_addr[4]) << 8) |
+ (((u32) hw->mac_addr[5]));
+ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+ iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+
+ /* tx / rx ring */
+
+ /* HI base address */
+ iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+ hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+ /* LO base address */
+ iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+ iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+ iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+ iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+ iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+
+ /* element count */
+ value = adapter->rrd_ring.count;
+ value <<= 16;
+ value += adapter->rfd_ring.count;
+ iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+ iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+ REG_DESC_TPD_RING_SIZE);
+
+ /* Load Ptr */
+ iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
+ /* config Mailbox */
+ value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+ & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+ ((atomic_read(&adapter->rrd_ring.next_to_clean)
+ & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+ ((atomic_read(&adapter->rfd_ring.next_to_use)
+ & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_MAILBOX);
+
+ /* config IPG/IFG */
+ value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+ << MAC_IPG_IFG_IPGT_SHIFT) |
+ (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+ << MAC_IPG_IFG_MIFG_SHIFT) |
+ (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+ << MAC_IPG_IFG_IPGR1_SHIFT) |
+ (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+ << MAC_IPG_IFG_IPGR2_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+
+ /* config Half-Duplex Control */
+ value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+ (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+ << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+ MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+ (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+ (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+ << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+
+ /* set Interrupt Moderator Timer */
+ iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+ iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+
+ /* set Interrupt Clear Timer */
+ iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
+ /* set max frame size hw will accept */
+ iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
+
+ /* jumbo size & rrd retirement timer */
+ value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+ << RXQ_JMBOSZ_TH_SHIFT) |
+ (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+ << RXQ_JMBO_LKAH_SHIFT) |
+ (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+ << RXQ_RRD_TIMER_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+
+ /* Flow Control */
+ switch (hw->dev_rev) {
+ case 0x8001:
+ case 0x9001:
+ case 0x9002:
+ case 0x9003:
+ set_flow_ctrl_old(adapter);
+ break;
+ default:
+ set_flow_ctrl_new(hw);
+ break;
+ }
+
+ /* config TXQ */
+ value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+ << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+ (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+ << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+ (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+ << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+ TXQ_CTRL_EN;
+ iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+
+ /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+ value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+ << TX_JUMBO_TASK_TH_SHIFT) |
+ (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+ << TX_TPD_MIN_IPG_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+
+ /* config RXQ */
+ value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+ << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+ (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+ << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+ (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+ << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+ RXQ_CTRL_EN;
+ iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+
+ /* config DMA Engine */
+ value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+ ((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+ << DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+ DMA_CTRL_DMAW_EN;
+ value |= (u32) hw->dma_ord;
+ if (atl1_rcb_128 == hw->rcb_value)
+ value |= DMA_CTRL_RCB_VALUE;
+ iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+
+ /* config CMB / SMB */
+ value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
+ hw->cmb_tpd : adapter->tpd_ring.count;
+ value <<= 16;
+ value |= hw->cmb_rrd;
+ iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+ value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+ iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+ iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+
+ /* --- enable CMB / SMB */
+ value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+ iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+
+ value = ioread32(adapter->hw.hw_addr + REG_ISR);
+ if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+ value = 1; /* config failed */
+ else
+ value = 0;
+
+ /* clear all interrupt status */
+ iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+ iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+ return value;
+ }
+
+ /*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+ static void atl1_pcie_patch(struct atl1_adapter *adapter)
+ {
+ u32 value;
+
+ /* much vendor magic here */
+ value = 0x6500;
+ iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+ /* pcie flow control mode change */
+ value = ioread32(adapter->hw.hw_addr + 0x1008);
+ value |= 0x8000;
+ iowrite32(value, adapter->hw.hw_addr + 0x1008);
+ }
+
+ /*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+ static void atl1_via_workaround(struct atl1_adapter *adapter)
+ {
+ unsigned long value;
+
+ value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+ if (value & PCI_COMMAND_INTX_DISABLE)
+ value &= ~PCI_COMMAND_INTX_DISABLE;
+ iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+ }
+
+ static void atl1_inc_smb(struct atl1_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+ struct stats_msg_block *smb = adapter->smb.smb;
+
+ /* Fill out the OS statistics structure */
+ adapter->soft_stats.rx_packets += smb->rx_ok;
+ adapter->soft_stats.tx_packets += smb->tx_ok;
+ adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+ adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+ adapter->soft_stats.multicast += smb->rx_mcast;
+ adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+ smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
+
+ /* Rx Errors */
+ adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+ smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+ smb->rx_rrd_ov + smb->rx_align_err);
+ adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+ adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+ adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+ adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+ adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+ smb->rx_rxf_ov);
+
+ adapter->soft_stats.rx_pause += smb->rx_pause;
+ adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+ adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+
+ /* Tx Errors */
+ adapter->soft_stats.tx_errors += (smb->tx_late_col +
+ smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
+ adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+ adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+ adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+
+ adapter->soft_stats.excecol += smb->tx_abort_col;
+ adapter->soft_stats.deffer += smb->tx_defer;
+ adapter->soft_stats.scc += smb->tx_1_col;
+ adapter->soft_stats.mcc += smb->tx_2_col;
+ adapter->soft_stats.latecol += smb->tx_late_col;
+ adapter->soft_stats.tx_underun += smb->tx_underrun;
+ adapter->soft_stats.tx_trunc += smb->tx_trunc;
+ adapter->soft_stats.tx_pause += smb->tx_pause;
+
+ netdev->stats.rx_packets = adapter->soft_stats.rx_packets;
+ netdev->stats.tx_packets = adapter->soft_stats.tx_packets;
+ netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes;
+ netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes;
+ netdev->stats.multicast = adapter->soft_stats.multicast;
+ netdev->stats.collisions = adapter->soft_stats.collisions;
+ netdev->stats.rx_errors = adapter->soft_stats.rx_errors;
+ netdev->stats.rx_over_errors =
+ adapter->soft_stats.rx_missed_errors;
+ netdev->stats.rx_length_errors =
+ adapter->soft_stats.rx_length_errors;
+ netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+ netdev->stats.rx_frame_errors =
+ adapter->soft_stats.rx_frame_errors;
+ netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+ netdev->stats.rx_missed_errors =
+ adapter->soft_stats.rx_missed_errors;
+ netdev->stats.tx_errors = adapter->soft_stats.tx_errors;
+ netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+ netdev->stats.tx_aborted_errors =
+ adapter->soft_stats.tx_aborted_errors;
+ netdev->stats.tx_window_errors =
+ adapter->soft_stats.tx_window_errors;
+ netdev->stats.tx_carrier_errors =
+ adapter->soft_stats.tx_carrier_errors;
+ }
+
+ static void atl1_update_mailbox(struct atl1_adapter *adapter)
+ {
+ unsigned long flags;
+ u32 tpd_next_to_use;
+ u32 rfd_next_to_use;
+ u32 rrd_next_to_clean;
+ u32 value;
+
+ spin_lock_irqsave(&adapter->mb_lock, flags);
+
+ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+ rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+ rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+ MB_RFD_PROD_INDX_SHIFT) |
+ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+ MB_RRD_CONS_INDX_SHIFT) |
+ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+ MB_TPD_PROD_INDX_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+ spin_unlock_irqrestore(&adapter->mb_lock, flags);
+ }
+
+ static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd, u16 offset)
+ {
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+
+ while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+ rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+ if (++rfd_ring->next_to_clean == rfd_ring->count) {
+ rfd_ring->next_to_clean = 0;
+ }
+ }
+ }
+
+ static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd)
+ {
+ u16 num_buf;
+
+ num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+ adapter->rx_buffer_len;
+ if (rrd->num_buf == num_buf)
+ /* clean alloc flag for bad rrd */
+ atl1_clean_alloc_flag(adapter, rrd, num_buf);
+ }
+
+ static void atl1_rx_checksum(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd, struct sk_buff *skb)
+ {
+ struct pci_dev *pdev = adapter->pdev;
+
+ /*
+ * The L1 hardware contains a bug that erroneously sets the
+ * PACKET_FLAG_ERR and ERR_FLAG_L4_CHKSUM bits whenever a
+ * fragmented IP packet is received, even though the packet
+ * is perfectly valid and its checksum is correct. There's
+ * no way to distinguish between one of these good packets
+ * and a packet that actually contains a TCP/UDP checksum
+ * error, so all we can do is allow it to be handed up to
+ * the higher layers and let it be sorted out there.
+ */
+
+ skb_checksum_none_assert(skb);
+
+ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+ if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+ ERR_FLAG_CODE | ERR_FLAG_OV)) {
+ adapter->hw_csum_err++;
+ if (netif_msg_rx_err(adapter))
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "rx checksum error\n");
+ return;
+ }
+ }
+
+ /* not IPv4 */
+ if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+ /* checksum is invalid, but it's not an IPv4 pkt, so ok */
+ return;
+
+ /* IPv4 packet */
+ if (likely(!(rrd->err_flg &
+ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ adapter->hw_csum_good++;
+ return;
+ }
+ }
+
+ /*
+ * atl1_alloc_rx_buffers - Replace used receive buffers
+ * @adapter: address of board private structure
+ */
+ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+ {
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct pci_dev *pdev = adapter->pdev;
+ struct page *page;
+ unsigned long offset;
+ struct atl1_buffer *buffer_info, *next_info;
+ struct sk_buff *skb;
+ u16 num_alloc = 0;
+ u16 rfd_next_to_use, next_next;
+ struct rx_free_desc *rfd_desc;
+
+ next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
+ if (++next_next == rfd_ring->count)
+ next_next = 0;
+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+ next_info = &rfd_ring->buffer_info[next_next];
+
+ while (!buffer_info->alloced && !next_info->alloced) {
+ if (buffer_info->skb) {
+ buffer_info->alloced = 1;
+ goto next;
+ }
+
+ rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+ skb = netdev_alloc_skb_ip_align(adapter->netdev,
+ adapter->rx_buffer_len);
+ if (unlikely(!skb)) {
+ /* Better luck next round */
+ adapter->netdev->stats.rx_dropped++;
+ break;
+ }
+
+ buffer_info->alloced = 1;
+ buffer_info->skb = skb;
+ buffer_info->length = (u16) adapter->rx_buffer_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(pdev, page, offset,
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
+ rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+ rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+ rfd_desc->coalese = 0;
+
+ next:
+ rfd_next_to_use = next_next;
+ if (unlikely(++next_next == rfd_ring->count))
+ next_next = 0;
+
+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+ next_info = &rfd_ring->buffer_info[next_next];
+ num_alloc++;
+ }
+
+ if (num_alloc) {
+ /*
+ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+ atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+ }
+ return num_alloc;
+ }
+
+ static void atl1_intr_rx(struct atl1_adapter *adapter)
+ {
+ int i, count;
+ u16 length;
+ u16 rrd_next_to_clean;
+ u32 value;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_buffer *buffer_info;
+ struct rx_return_desc *rrd;
+ struct sk_buff *skb;
+
+ count = 0;
+
+ rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+
+ while (1) {
+ rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+ i = 1;
+ if (likely(rrd->xsz.valid)) { /* packet valid */
+ chk_rrd:
+ /* check rrd status */
+ if (likely(rrd->num_buf == 1))
+ goto rrd_ok;
+ else if (netif_msg_rx_err(adapter)) {
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "unexpected RRD buffer count\n");
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "rx_buf_len = %d\n",
+ adapter->rx_buffer_len);
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "RRD num_buf = %d\n",
+ rrd->num_buf);
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "RRD pkt_len = %d\n",
+ rrd->xsz.xsum_sz.pkt_size);
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "RRD pkt_flg = 0x%08X\n",
+ rrd->pkt_flg);
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "RRD err_flg = 0x%08X\n",
+ rrd->err_flg);
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "RRD vlan_tag = 0x%08X\n",
+ rrd->vlan_tag);
+ }
+
+ /* rrd seems to be bad */
+ if (unlikely(i-- > 0)) {
+ /* rrd may not be DMAed completely */
+ udelay(1);
+ goto chk_rrd;
+ }
+ /* bad rrd */
+ if (netif_msg_rx_err(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "bad RRD\n");
+ /* see if update RFD index */
+ if (rrd->num_buf > 1)
+ atl1_update_rfd_index(adapter, rrd);
+
+ /* update rrd */
+ rrd->xsz.valid = 0;
+ if (++rrd_next_to_clean == rrd_ring->count)
+ rrd_next_to_clean = 0;
+ count++;
+ continue;
+ } else { /* current rrd still not be updated */
+
+ break;
+ }
+ rrd_ok:
+ /* clean alloc flag for bad rrd */
+ atl1_clean_alloc_flag(adapter, rrd, 0);
+
+ buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+ if (++rfd_ring->next_to_clean == rfd_ring->count)
+ rfd_ring->next_to_clean = 0;
+
+ /* update rrd next to clean */
+ if (++rrd_next_to_clean == rrd_ring->count)
+ rrd_next_to_clean = 0;
+ count++;
+
+ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+ if (!(rrd->err_flg &
+ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+ | ERR_FLAG_LEN))) {
+ /* packet error, don't need upstream */
+ buffer_info->alloced = 0;
+ rrd->xsz.valid = 0;
+ continue;
+ }
+ }
+
+ /* Good Receive */
+ pci_unmap_page(adapter->pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+ skb = buffer_info->skb;
+ length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+
+ skb_put(skb, length - ETH_FCS_LEN);
+
+ /* Receive Checksum Offload */
+ atl1_rx_checksum(adapter, rrd, skb);
+ skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+ if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) {
+ u16 vlan_tag = (rrd->vlan_tag >> 4) |
+ ((rrd->vlan_tag & 7) << 13) |
+ ((rrd->vlan_tag & 8) << 9);
+
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
+ }
+ netif_rx(skb);
+
+ /* let protocol layer free skb */
+ buffer_info->skb = NULL;
+ buffer_info->alloced = 0;
+ rrd->xsz.valid = 0;
+ }
+
+ atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+
+ atl1_alloc_rx_buffers(adapter);
+
+ /* update mailbox ? */
+ if (count) {
+ u32 tpd_next_to_use;
+ u32 rfd_next_to_use;
+
+ spin_lock(&adapter->mb_lock);
+
+ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+ rfd_next_to_use =
+ atomic_read(&adapter->rfd_ring.next_to_use);
+ rrd_next_to_clean =
+ atomic_read(&adapter->rrd_ring.next_to_clean);
+ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+ MB_RFD_PROD_INDX_SHIFT) |
+ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+ MB_RRD_CONS_INDX_SHIFT) |
+ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+ MB_TPD_PROD_INDX_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+ spin_unlock(&adapter->mb_lock);
+ }
+ }
+
+ static void atl1_intr_tx(struct atl1_adapter *adapter)
+ {
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ u16 sw_tpd_next_to_clean;
+ u16 cmb_tpd_next_to_clean;
+
+ sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+ cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+
+ while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+ buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+ if (buffer_info->dma) {
+ pci_unmap_page(adapter->pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+
+ if (buffer_info->skb) {
+ dev_kfree_skb_irq(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+
+ if (++sw_tpd_next_to_clean == tpd_ring->count)
+ sw_tpd_next_to_clean = 0;
+ }
+ atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+
+ if (netif_queue_stopped(adapter->netdev) &&
+ netif_carrier_ok(adapter->netdev))
+ netif_wake_queue(adapter->netdev);
+ }
+
+ static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
+ {
+ u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+ u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
+ return (next_to_clean > next_to_use) ?
+ next_to_clean - next_to_use - 1 :
+ tpd_ring->count + next_to_clean - next_to_use - 1;
+ }
+
+ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
+ struct tx_packet_desc *ptpd)
+ {
+ u8 hdr_len, ip_off;
+ u32 real_len;
+ int err;
+
+ if (skb_shinfo(skb)->gso_size) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (unlikely(err))
+ return -1;
+ }
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+
+ real_len = (((unsigned char *)iph - skb->data) +
+ ntohs(iph->tot_len));
+ if (real_len < skb->len)
+ pskb_trim(skb, real_len);
+ hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+ if (skb->len == hdr_len) {
+ iph->check = 0;
+ tcp_hdr(skb)->check =
+ ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, tcp_hdrlen(skb),
+ IPPROTO_TCP, 0);
+ ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
+ TPD_IPHL_SHIFT;
+ ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+ TPD_TCPHDRLEN_MASK) <<
+ TPD_TCPHDRLEN_SHIFT;
+ ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
+ ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
+ return 1;
+ }
+
+ iph->check = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0, IPPROTO_TCP, 0);
+ ip_off = (unsigned char *)iph -
+ (unsigned char *) skb_network_header(skb);
+ if (ip_off == 8) /* 802.3-SNAP frame */
+ ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
+ else if (ip_off != 0)
+ return -2;
+
+ ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
+ TPD_IPHL_SHIFT;
+ ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+ TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
+ ptpd->word3 |= (skb_shinfo(skb)->gso_size &
+ TPD_MSS_MASK) << TPD_MSS_SHIFT;
+ ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+ return 3;
+ }
+ }
+ return false;
+ }
+
+ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
+ struct tx_packet_desc *ptpd)
+ {
+ u8 css, cso;
+
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ css = skb_checksum_start_offset(skb);
+ cso = css + (u8) skb->csum_offset;
+ if (unlikely(css & 0x1)) {
+ /* L1 hardware requires an even number here */
+ if (netif_msg_tx_err(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "payload offset not an even number\n");
+ return -1;
+ }
+ ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) <<
+ TPD_PLOADOFFSET_SHIFT;
+ ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) <<
+ TPD_CCSUMOFFSET_SHIFT;
+ ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
+ return true;
+ }
+ return 0;
+ }
+
+ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+ struct tx_packet_desc *ptpd)
+ {
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ u16 buf_len = skb->len;
+ struct page *page;
+ unsigned long offset;
+ unsigned int nr_frags;
+ unsigned int f;
+ int retval;
+ u16 next_to_use;
+ u16 data_len;
+ u8 hdr_len;
+
+ buf_len -= skb->data_len;
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ next_to_use = atomic_read(&tpd_ring->next_to_use);
+ buffer_info = &tpd_ring->buffer_info[next_to_use];
+ BUG_ON(buffer_info->skb);
+ /* put skb in last TPD */
+ buffer_info->skb = NULL;
+
+ retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
+ if (retval) {
+ /* TSO */
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ buffer_info->length = hdr_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(adapter->pdev, page,
+ offset, hdr_len,
+ PCI_DMA_TODEVICE);
+
+ if (++next_to_use == tpd_ring->count)
+ next_to_use = 0;
+
+ if (buf_len > hdr_len) {
+ int i, nseg;
+
+ data_len = buf_len - hdr_len;
+ nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
+ for (i = 0; i < nseg; i++) {
+ buffer_info =
+ &tpd_ring->buffer_info[next_to_use];
+ buffer_info->skb = NULL;
+ buffer_info->length =
+ (ATL1_MAX_TX_BUF_LEN >=
+ data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
+ data_len -= buffer_info->length;
+ page = virt_to_page(skb->data +
+ (hdr_len + i * ATL1_MAX_TX_BUF_LEN));
+ offset = (unsigned long)(skb->data +
+ (hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
+ ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(adapter->pdev,
+ page, offset, buffer_info->length,
+ PCI_DMA_TODEVICE);
+ if (++next_to_use == tpd_ring->count)
+ next_to_use = 0;
+ }
+ }
+ } else {
+ /* not TSO */
+ buffer_info->length = buf_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(adapter->pdev, page,
+ offset, buf_len, PCI_DMA_TODEVICE);
+ if (++next_to_use == tpd_ring->count)
+ next_to_use = 0;
+ }
+
+ for (f = 0; f < nr_frags; f++) {
+ const struct skb_frag_struct *frag;
+ u16 i, nseg;
+
+ frag = &skb_shinfo(skb)->frags[f];
+ buf_len = skb_frag_size(frag);
+
+ nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
+ for (i = 0; i < nseg; i++) {
+ buffer_info = &tpd_ring->buffer_info[next_to_use];
+ BUG_ON(buffer_info->skb);
+
+ buffer_info->skb = NULL;
+ buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
+ ATL1_MAX_TX_BUF_LEN : buf_len;
+ buf_len -= buffer_info->length;
+ buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
+ frag, i * ATL1_MAX_TX_BUF_LEN,
+ buffer_info->length, DMA_TO_DEVICE);
+
+ if (++next_to_use == tpd_ring->count)
+ next_to_use = 0;
+ }
+ }
+
+ /* last tpd's buffer-info */
+ buffer_info->skb = skb;
+ }
+
+ static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
+ struct tx_packet_desc *ptpd)
+ {
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ struct tx_packet_desc *tpd;
+ u16 j;
+ u32 val;
+ u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
+
+ for (j = 0; j < count; j++) {
+ buffer_info = &tpd_ring->buffer_info[next_to_use];
+ tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
+ if (tpd != ptpd)
+ memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
+ tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+ tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT);
+ tpd->word2 |= (cpu_to_le16(buffer_info->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
+
+ /*
+ * if this is the first packet in a TSO chain, set
+ * TPD_HDRFLAG, otherwise, clear it.
+ */
+ val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
+ TPD_SEGMENT_EN_MASK;
+ if (val) {
+ if (!j)
+ tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
+ else
+ tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
+ }
+
+ if (j == (count - 1))
+ tpd->word3 |= 1 << TPD_EOP_SHIFT;
+
+ if (++next_to_use == tpd_ring->count)
+ next_to_use = 0;
+ }
+ /*
+ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+
+ atomic_set(&tpd_ring->next_to_use, next_to_use);
+ }
+
+ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
+ struct net_device *netdev)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ int len;
+ int tso;
+ int count = 1;
+ int ret_val;
+ struct tx_packet_desc *ptpd;
+ u16 vlan_tag;
+ unsigned int nr_frags = 0;
+ unsigned int mss = 0;
+ unsigned int f;
+ unsigned int proto_hdr_len;
+
+ len = skb_headlen(skb);
+
+ if (unlikely(skb->len <= 0)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ for (f = 0; f < nr_frags; f++) {
+ unsigned int f_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
+ count += (f_size + ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
+ }
+
+ mss = skb_shinfo(skb)->gso_size;
+ if (mss) {
+ if (skb->protocol == htons(ETH_P_IP)) {
+ proto_hdr_len = (skb_transport_offset(skb) +
+ tcp_hdrlen(skb));
+ if (unlikely(proto_hdr_len > len)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ /* need additional TPD ? */
+ if (proto_hdr_len != len)
+ count += (len - proto_hdr_len +
+ ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
+ }
+ }
+
+ if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
+ /* not enough descriptors */
+ netif_stop_queue(netdev);
+ if (netif_msg_tx_queued(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "tx busy\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ ptpd = ATL1_TPD_DESC(tpd_ring,
+ (u16) atomic_read(&tpd_ring->next_to_use));
+ memset(ptpd, 0, sizeof(struct tx_packet_desc));
+
+ if (vlan_tx_tag_present(skb)) {
+ vlan_tag = vlan_tx_tag_get(skb);
+ vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
+ ((vlan_tag >> 9) & 0x8);
+ ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
+ ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) <<
+ TPD_VLANTAG_SHIFT;
+ }
+
+ tso = atl1_tso(adapter, skb, ptpd);
+ if (tso < 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (!tso) {
+ ret_val = atl1_tx_csum(adapter, skb, ptpd);
+ if (ret_val < 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ }
+
+ atl1_tx_map(adapter, skb, ptpd);
+ atl1_tx_queue(adapter, count, ptpd);
+ atl1_update_mailbox(adapter);
+ mmiowb();
+ return NETDEV_TX_OK;
+ }
+
+ /*
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+ static irqreturn_t atl1_intr(int irq, void *data)
+ {
+ struct atl1_adapter *adapter = netdev_priv(data);
+ u32 status;
+ int max_ints = 10;
+
+ status = adapter->cmb.cmb->int_stats;
+ if (!status)
+ return IRQ_NONE;
+
+ do {
+ /* clear CMB interrupt status at once */
+ adapter->cmb.cmb->int_stats = 0;
+
+ if (status & ISR_GPHY) /* clear phy status */
+ atlx_clear_phy_int(adapter);
+
+ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+ iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+ /* check if SMB intr */
+ if (status & ISR_SMB)
+ atl1_inc_smb(adapter);
+
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ if (netif_msg_intr(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "pcie phy link down %x\n", status);
+ if (netif_running(adapter->netdev)) { /* reset MAC */
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ schedule_work(&adapter->pcie_dma_to_rst_task);
+ return IRQ_HANDLED;
+ }
+ }
+
+ /* check if DMA read/write error ? */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ if (netif_msg_intr(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "pcie DMA r/w error (status = 0x%x)\n",
+ status);
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ schedule_work(&adapter->pcie_dma_to_rst_task);
+ return IRQ_HANDLED;
+ }
+
+ /* link event */
+ if (status & ISR_GPHY) {
+ adapter->soft_stats.tx_carrier_errors++;
+ atl1_check_for_link(adapter);
+ }
+
+ /* transmit event */
+ if (status & ISR_CMB_TX)
+ atl1_intr_tx(adapter);
+
+ /* rx exception */
+ if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+ ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+ if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+ ISR_HOST_RRD_OV))
+ if (netif_msg_intr(adapter))
+ dev_printk(KERN_DEBUG,
+ &adapter->pdev->dev,
+ "rx exception, ISR = 0x%x\n",
+ status);
+ atl1_intr_rx(adapter);
+ }
+
+ if (--max_ints < 0)
+ break;
+
+ } while ((status = adapter->cmb.cmb->int_stats));
+
+ /* re-enable Interrupt */
+ iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+ return IRQ_HANDLED;
+ }
+
+
+ /*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+ static void atl1_phy_config(unsigned long data)
+ {
+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+ struct atl1_hw *hw = &adapter->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ adapter->phy_timer_pending = false;
+ atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
+ atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ }
+
+ /*
+ * Orphaned vendor comment left intact here:
+ * <vendor comment>
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ * </vendor comment>
+ */
+
+ static int atl1_reset(struct atl1_adapter *adapter)
+ {
+ int ret;
+ ret = atl1_reset_hw(&adapter->hw);
+ if (ret)
+ return ret;
+ return atl1_init_hw(&adapter->hw);
+ }
+
+ static s32 atl1_up(struct atl1_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+ int err;
+ int irq_flags = 0;
+
+ /* hardware has been reset, we need to reload some things */
+ atlx_set_multi(netdev);
+ atl1_init_ring_ptrs(adapter);
+ atlx_restore_vlan(adapter);
+ err = atl1_alloc_rx_buffers(adapter);
+ if (unlikely(!err))
+ /* no RX BUFFER allocated */
+ return -ENOMEM;
+
+ if (unlikely(atl1_configure(adapter))) {
+ err = -EIO;
+ goto err_up;
+ }
+
+ err = pci_enable_msi(adapter->pdev);
+ if (err) {
+ if (netif_msg_ifup(adapter))
+ dev_info(&adapter->pdev->dev,
+ "Unable to enable MSI: %d\n", err);
+ irq_flags |= IRQF_SHARED;
+ }
+
+ err = request_irq(adapter->pdev->irq, atl1_intr, irq_flags,
+ netdev->name, netdev);
+ if (unlikely(err))
+ goto err_up;
+
+ atlx_irq_enable(adapter);
+ atl1_check_link(adapter);
+ netif_start_queue(netdev);
+ return 0;
+
+ err_up:
+ pci_disable_msi(adapter->pdev);
+ /* free rx_buffers */
+ atl1_clean_rx_ring(adapter);
+ return err;
+ }
+
+ static void atl1_down(struct atl1_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+
+ netif_stop_queue(netdev);
+ del_timer_sync(&adapter->phy_config_timer);
+ adapter->phy_timer_pending = false;
+
+ atlx_irq_disable(adapter);
+ free_irq(adapter->pdev->irq, netdev);
+ pci_disable_msi(adapter->pdev);
+ atl1_reset_hw(&adapter->hw);
+ adapter->cmb.cmb->int_stats = 0;
+
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+ netif_carrier_off(netdev);
+
+ atl1_clean_tx_ring(adapter);
+ atl1_clean_rx_ring(adapter);
+ }
+
+ static void atl1_tx_timeout_task(struct work_struct *work)
+ {
+ struct atl1_adapter *adapter =
+ container_of(work, struct atl1_adapter, tx_timeout_task);
+ struct net_device *netdev = adapter->netdev;
+
+ netif_device_detach(netdev);
+ atl1_down(adapter);
+ atl1_up(adapter);
+ netif_device_attach(netdev);
+ }
+
+ /*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+ static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int old_mtu = netdev->mtu;
+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+ if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ if (netif_msg_link(adapter))
+ dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+ return -EINVAL;
+ }
+
+ adapter->hw.max_frame_size = max_frame;
+ adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+ adapter->rx_buffer_len = (max_frame + 7) & ~7;
+ adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+ netdev->mtu = new_mtu;
+ if ((old_mtu != new_mtu) && netif_running(netdev)) {
+ atl1_down(adapter);
+ atl1_up(adapter);
+ }
+
+ return 0;
+ }
+
+ /*
+ * atl1_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+ static int atl1_open(struct net_device *netdev)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ netif_carrier_off(netdev);
+
+ /* allocate transmit descriptors */
+ err = atl1_setup_ring_resources(adapter);
+ if (err)
+ return err;
+
+ err = atl1_up(adapter);
+ if (err)
+ goto err_up;
+
+ return 0;
+
+ err_up:
+ atl1_reset(adapter);
+ return err;
+ }
+
+ /*
+ * atl1_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+ static int atl1_close(struct net_device *netdev)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ atl1_down(adapter);
+ atl1_free_ring_resources(adapter);
+ return 0;
+ }
+
+ #ifdef CONFIG_PM
+ static int atl1_suspend(struct device *dev)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ u32 ctrl = 0;
+ u32 wufc = adapter->wol;
+ u32 val;
+ u16 speed;
+ u16 duplex;
+
+ netif_device_detach(netdev);
+ if (netif_running(netdev))
+ atl1_down(adapter);
+
+ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+ val = ctrl & BMSR_LSTATUS;
+ if (val)
+ wufc &= ~ATLX_WUFC_LNKC;
+ if (!wufc)
+ goto disable_wol;
+
+ if (val) {
+ val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+ if (val) {
+ if (netif_msg_ifdown(adapter))
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "error getting speed/duplex\n");
+ goto disable_wol;
+ }
+
+ ctrl = 0;
+
+ /* enable magic packet WOL */
+ if (wufc & ATLX_WUFC_MAG)
+ ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);
+ iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+ ioread32(hw->hw_addr + REG_WOL_CTRL);
+
+ /* configure the mac */
+ ctrl = MAC_CTRL_RX_EN;
+ ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 :
+ MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT);
+ if (duplex == FULL_DUPLEX)
+ ctrl |= MAC_CTRL_DUPLX;
+ ctrl |= (((u32)adapter->hw.preamble_len &
+ MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+ __atlx_vlan_mode(netdev->features, &ctrl);
+ if (wufc & ATLX_WUFC_MAG)
+ ctrl |= MAC_CTRL_BC_EN;
+ iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+ ioread32(hw->hw_addr + REG_MAC_CTRL);
+
+ /* poke the PHY */
+ ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
+ ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
+ } else {
+ ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+ iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+ ioread32(hw->hw_addr + REG_WOL_CTRL);
+ iowrite32(0, hw->hw_addr + REG_MAC_CTRL);
+ ioread32(hw->hw_addr + REG_MAC_CTRL);
+ hw->phy_configured = false;
+ }
+
+ return 0;
+
+ disable_wol:
+ iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+ ioread32(hw->hw_addr + REG_WOL_CTRL);
+ ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
+ ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
+ hw->phy_configured = false;
+
+ return 0;
+ }
+
+ static int atl1_resume(struct device *dev)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+
+ atl1_reset_hw(&adapter->hw);
+
+ if (netif_running(netdev)) {
+ adapter->cmb.cmb->int_stats = 0;
+ atl1_up(adapter);
+ }
+ netif_device_attach(netdev);
+
+ return 0;
+ }
+
+ static SIMPLE_DEV_PM_OPS(atl1_pm_ops, atl1_suspend, atl1_resume);
+ #define ATL1_PM_OPS (&atl1_pm_ops)
+
+ #else
+
+ static int atl1_suspend(struct device *dev) { return 0; }
+
+ #define ATL1_PM_OPS NULL
+ #endif
+
+ static void atl1_shutdown(struct pci_dev *pdev)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ atl1_suspend(&pdev->dev);
+ pci_wake_from_d3(pdev, adapter->wol);
+ pci_set_power_state(pdev, PCI_D3hot);
+ }
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void atl1_poll_controller(struct net_device *netdev)
+ {
+ disable_irq(netdev->irq);
+ atl1_intr(netdev->irq, netdev);
+ enable_irq(netdev->irq);
+ }
+ #endif
+
+ static const struct net_device_ops atl1_netdev_ops = {
+ .ndo_open = atl1_open,
+ .ndo_stop = atl1_close,
+ .ndo_start_xmit = atl1_xmit_frame,
+ .ndo_set_rx_mode = atlx_set_multi,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = atl1_set_mac,
+ .ndo_change_mtu = atl1_change_mtu,
+ .ndo_fix_features = atlx_fix_features,
+ .ndo_set_features = atlx_set_features,
+ .ndo_do_ioctl = atlx_ioctl,
+ .ndo_tx_timeout = atlx_tx_timeout,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = atl1_poll_controller,
+ #endif
+ };
+
+ /*
+ * atl1_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+ static int __devinit atl1_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+ struct net_device *netdev;
+ struct atl1_adapter *adapter;
+ static int cards_found = 0;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ /*
+ * The atl1 chip can DMA to 64-bit addresses, but it uses a single
+ * shared register for the high 32 bits, so only a single, aligned,
+ * 4 GB physical address range can be used at a time.
+ *
+ * Supporting 64-bit DMA on this hardware is more trouble than it's
+ * worth. It is far easier to limit to 32-bit DMA than update
+ * various kernel subsystems to support the mechanics required by a
+ * fixed-high-32-bit system.
+ */
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev, "no usable DMA configuration\n");
+ goto err_dma;
+ }
+ /*
+ * Mark all PCI regions associated with PCI device
+ * pdev as being reserved by owner atl1_driver_name
+ */
+ err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
+ if (err)
+ goto err_request_regions;
+
+ /*
+ * Enables bus-mastering on the device and calls
+ * pcibios_set_master to do the needed arch specific settings
+ */
+ pci_set_master(pdev);
+
+ netdev = alloc_etherdev(sizeof(struct atl1_adapter));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ pci_set_drvdata(pdev, netdev);
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.back = adapter;
+ adapter->msg_enable = netif_msg_init(debug, atl1_default_msg);
+
+ adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
+ if (!adapter->hw.hw_addr) {
+ err = -EIO;
+ goto err_pci_iomap;
+ }
+ /* get device revision number */
+ adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
+ (REG_MASTER_CTRL + 2));
+ if (netif_msg_probe(adapter))
+ dev_info(&pdev->dev, "version %s\n", ATLX_DRIVER_VERSION);
+
+ /* set default ring resource counts */
+ adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
+ adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
+
+ adapter->mii.dev = netdev;
+ adapter->mii.mdio_read = mdio_read;
+ adapter->mii.mdio_write = mdio_write;
+ adapter->mii.phy_id_mask = 0x1f;
+ adapter->mii.reg_num_mask = 0x1f;
+
+ netdev->netdev_ops = &atl1_netdev_ops;
+ netdev->watchdog_timeo = 5 * HZ;
+
+ netdev->ethtool_ops = &atl1_ethtool_ops;
+ adapter->bd_number = cards_found;
+
+ /* setup the private structure */
+ err = atl1_sw_init(adapter);
+ if (err)
+ goto err_common;
+
+ netdev->features = NETIF_F_HW_CSUM;
+ netdev->features |= NETIF_F_SG;
+ netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+
+ netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO |
+ NETIF_F_HW_VLAN_RX;
+
+ /* is this valid? see atl1_setup_mac_ctrl() */
+ netdev->features |= NETIF_F_RXCSUM;
+
+ /*
+ * patch for some L1 of old version,
+ * the final version of L1 may not need these
+ * patches
+ */
+ /* atl1_pcie_patch(adapter); */
+
+ /* really reset GPHY core */
+ iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
+
+ /*
+ * reset the controller to
+ * put the device in a known good starting state
+ */
+ if (atl1_reset_hw(&adapter->hw)) {
+ err = -EIO;
+ goto err_common;
+ }
+
+ /* copy the MAC address out of the EEPROM */
+ atl1_read_mac_addr(&adapter->hw);
+ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ err = -EIO;
+ goto err_common;
+ }
+
+ atl1_check_options(adapter);
+
+ /* pre-init the MAC, and setup link */
+ err = atl1_init_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_common;
+ }
+
+ atl1_pcie_patch(adapter);
+ /* assume we have no link for now */
+ netif_carrier_off(netdev);
+
+ setup_timer(&adapter->phy_config_timer, atl1_phy_config,
+ (unsigned long)adapter);
+ adapter->phy_timer_pending = false;
+
+ INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+
+ INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
+
+ INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
+
+ err = register_netdev(netdev);
+ if (err)
+ goto err_common;
+
+ cards_found++;
+ atl1_via_workaround(adapter);
+ return 0;
+
+ err_common:
+ pci_iounmap(pdev, adapter->hw.hw_addr);
+ err_pci_iomap:
+ free_netdev(netdev);
+ err_alloc_etherdev:
+ pci_release_regions(pdev);
+ err_dma:
+ err_request_regions:
+ pci_disable_device(pdev);
+ return err;
+ }
+
+ /*
+ * atl1_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+ static void __devexit atl1_remove(struct pci_dev *pdev)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter;
+ /* Device not available. Return. */
+ if (!netdev)
+ return;
+
+ adapter = netdev_priv(netdev);
+
+ /*
+ * Some atl1 boards lack persistent storage for their MAC, and get it
+ * from the BIOS during POST. If we've been messing with the MAC
+ * address, we need to save the permanent one.
+ */
+ if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
+ memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+ ETH_ALEN);
+ atl1_set_mac_addr(&adapter->hw);
+ }
+
+ iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
+ unregister_netdev(netdev);
+ pci_iounmap(pdev, adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+ free_netdev(netdev);
+ pci_disable_device(pdev);
+ }
+
+ static struct pci_driver atl1_driver = {
+ .name = ATLX_DRIVER_NAME,
+ .id_table = atl1_pci_tbl,
+ .probe = atl1_probe,
+ .remove = __devexit_p(atl1_remove),
+ .shutdown = atl1_shutdown,
+ .driver.pm = ATL1_PM_OPS,
+ };
+
+ /*
+ * atl1_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1_exit_module is called just before the driver is removed
+ * from memory.
+ */
+ static void __exit atl1_exit_module(void)
+ {
+ pci_unregister_driver(&atl1_driver);
+ }
+
+ /*
+ * atl1_init_module - Driver Registration Routine
+ *
+ * atl1_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+ static int __init atl1_init_module(void)
+ {
+ return pci_register_driver(&atl1_driver);
+ }
+
+ module_init(atl1_init_module);
+ module_exit(atl1_exit_module);
+
+ struct atl1_stats {
+ char stat_string[ETH_GSTRING_LEN];
+ int sizeof_stat;
+ int stat_offset;
+ };
+
+ #define ATL1_STAT(m) \
+ sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m)
+
+ static struct atl1_stats atl1_gstrings_stats[] = {
+ {"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
+ {"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
+ {"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
+ {"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
+ {"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
+ {"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
+ {"multicast", ATL1_STAT(soft_stats.multicast)},
+ {"collisions", ATL1_STAT(soft_stats.collisions)},
+ {"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
+ {"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+ {"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
+ {"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
+ {"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
+ {"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+ {"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
+ {"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
+ {"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
+ {"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
+ {"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
+ {"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
+ {"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
+ {"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
+ {"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
+ {"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
+ {"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
+ {"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
+ {"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
+ {"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
+ {"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
+ };
+
+ static void atl1_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int i;
+ char *p;
+
+ for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+ p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
+ data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+
+ }
+
+ static int atl1_get_sset_count(struct net_device *netdev, int sset)
+ {
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(atl1_gstrings_stats);
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ static int atl1_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_TP);
+ ecmd->advertising = ADVERTISED_TP;
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->advertising |=
+ (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Full);
+ } else
+ ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+ }
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = 0;
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ if (netif_carrier_ok(adapter->netdev)) {
+ u16 link_speed, link_duplex;
+ atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
+ ethtool_cmd_speed_set(ecmd, link_speed);
+ if (link_duplex == FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ } else {
+ ethtool_cmd_speed_set(ecmd, -1);
+ ecmd->duplex = -1;
+ }
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL)
+ ecmd->autoneg = AUTONEG_ENABLE;
+ else
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ return 0;
+ }
+
+ static int atl1_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ u16 phy_data;
+ int ret_val = 0;
+ u16 old_media_type = hw->media_type;
+
+ if (netif_running(adapter->netdev)) {
+ if (netif_msg_link(adapter))
+ dev_dbg(&adapter->pdev->dev,
+ "ethtool shutting down adapter\n");
+ atl1_down(adapter);
+ }
+
+ if (ecmd->autoneg == AUTONEG_ENABLE)
+ hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+ else {
+ u32 speed = ethtool_cmd_speed(ecmd);
+ if (speed == SPEED_1000) {
+ if (ecmd->duplex != DUPLEX_FULL) {
+ if (netif_msg_link(adapter))
+ dev_warn(&adapter->pdev->dev,
+ "1000M half is invalid\n");
+ ret_val = -EINVAL;
+ goto exit_sset;
+ }
+ hw->media_type = MEDIA_TYPE_1000M_FULL;
+ } else if (speed == SPEED_100) {
+ if (ecmd->duplex == DUPLEX_FULL)
+ hw->media_type = MEDIA_TYPE_100M_FULL;
+ else
+ hw->media_type = MEDIA_TYPE_100M_HALF;
+ } else {
+ if (ecmd->duplex == DUPLEX_FULL)
+ hw->media_type = MEDIA_TYPE_10M_FULL;
+ else
+ hw->media_type = MEDIA_TYPE_10M_HALF;
+ }
+ }
+ switch (hw->media_type) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ ecmd->advertising =
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_Autoneg | ADVERTISED_TP;
+ break;
+ case MEDIA_TYPE_1000M_FULL:
+ ecmd->advertising =
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_Autoneg | ADVERTISED_TP;
+ break;
+ default:
+ ecmd->advertising = 0;
+ break;
+ }
+ if (atl1_phy_setup_autoneg_adv(hw)) {
+ ret_val = -EINVAL;
+ if (netif_msg_link(adapter))
+ dev_warn(&adapter->pdev->dev,
+ "invalid ethtool speed/duplex setting\n");
+ goto exit_sset;
+ }
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL)
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+ else {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+ MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default:
+ /* MEDIA_TYPE_10M_HALF: */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ }
+ }
+ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ exit_sset:
+ if (ret_val)
+ hw->media_type = old_media_type;
+
+ if (netif_running(adapter->netdev)) {
+ if (netif_msg_link(adapter))
+ dev_dbg(&adapter->pdev->dev,
+ "ethtool starting adapter\n");
+ atl1_up(adapter);
+ } else if (!ret_val) {
+ if (netif_msg_link(adapter))
+ dev_dbg(&adapter->pdev->dev,
+ "ethtool resetting adapter\n");
+ atl1_reset(adapter);
+ }
+ return ret_val;
+ }
+
+ static void atl1_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, ATLX_DRIVER_VERSION,
+ sizeof(drvinfo->version));
+ strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+ sizeof(drvinfo->bus_info));
+ drvinfo->eedump_len = ATL1_EEDUMP_LEN;
+ }
+
+ static void atl1_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = 0;
+ if (adapter->wol & ATLX_WUFC_MAG)
+ wol->wolopts |= WAKE_MAGIC;
+ }
+
+ static int atl1_set_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
+ WAKE_ARP | WAKE_MAGICSECURE))
+ return -EOPNOTSUPP;
+ adapter->wol = 0;
+ if (wol->wolopts & WAKE_MAGIC)
+ adapter->wol |= ATLX_WUFC_MAG;
+
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+ return 0;
+ }
+
+ static u32 atl1_get_msglevel(struct net_device *netdev)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ return adapter->msg_enable;
+ }
+
+ static void atl1_set_msglevel(struct net_device *netdev, u32 value)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ adapter->msg_enable = value;
+ }
+
+ static int atl1_get_regs_len(struct net_device *netdev)
+ {
+ return ATL1_REG_COUNT * sizeof(u32);
+ }
+
+ static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
+ void *p)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ unsigned int i;
+ u32 *regbuf = p;
+
+ for (i = 0; i < ATL1_REG_COUNT; i++) {
+ /*
+ * This switch statement avoids reserved regions
+ * of register space.
+ */
+ switch (i) {
+ case 6 ... 9:
+ case 14:
+ case 29 ... 31:
+ case 34 ... 63:
+ case 75 ... 127:
+ case 136 ... 1023:
+ case 1027 ... 1087:
+ case 1091 ... 1151:
+ case 1194 ... 1195:
+ case 1200 ... 1201:
+ case 1206 ... 1213:
+ case 1216 ... 1279:
+ case 1290 ... 1311:
+ case 1323 ... 1343:
+ case 1358 ... 1359:
+ case 1368 ... 1375:
+ case 1378 ... 1383:
+ case 1388 ... 1391:
+ case 1393 ... 1395:
+ case 1402 ... 1403:
+ case 1410 ... 1471:
+ case 1522 ... 1535:
+ /* reserved region; don't read it */
+ regbuf[i] = 0;
+ break;
+ default:
+ /* unreserved region */
+ regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32)));
+ }
+ }
+ }
+
+ static void atl1_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
+
+ ring->rx_max_pending = ATL1_MAX_RFD;
+ ring->tx_max_pending = ATL1_MAX_TPD;
+ ring->rx_pending = rxdr->count;
+ ring->tx_pending = txdr->count;
+ }
+
+ static int atl1_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
+ struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
+ struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
+
+ struct atl1_tpd_ring tpd_old, tpd_new;
+ struct atl1_rfd_ring rfd_old, rfd_new;
+ struct atl1_rrd_ring rrd_old, rrd_new;
+ struct atl1_ring_header rhdr_old, rhdr_new;
+ struct atl1_smb smb;
+ struct atl1_cmb cmb;
+ int err;
+
+ tpd_old = adapter->tpd_ring;
+ rfd_old = adapter->rfd_ring;
+ rrd_old = adapter->rrd_ring;
+ rhdr_old = adapter->ring_header;
+
+ if (netif_running(adapter->netdev))
+ atl1_down(adapter);
+
+ rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
+ rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
+ rfdr->count;
+ rfdr->count = (rfdr->count + 3) & ~3;
+ rrdr->count = rfdr->count;
+
+ tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
+ tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
+ tpdr->count;
+ tpdr->count = (tpdr->count + 3) & ~3;
+
+ if (netif_running(adapter->netdev)) {
+ /* try to get new resources before deleting old */
+ err = atl1_setup_ring_resources(adapter);
+ if (err)
+ goto err_setup_ring;
+
+ /*
+ * save the new, restore the old in order to free it,
+ * then restore the new back again
+ */
+
+ rfd_new = adapter->rfd_ring;
+ rrd_new = adapter->rrd_ring;
+ tpd_new = adapter->tpd_ring;
+ rhdr_new = adapter->ring_header;
+ adapter->rfd_ring = rfd_old;
+ adapter->rrd_ring = rrd_old;
+ adapter->tpd_ring = tpd_old;
+ adapter->ring_header = rhdr_old;
+ /*
+ * Save SMB and CMB, since atl1_free_ring_resources
+ * will clear them.
+ */
+ smb = adapter->smb;
+ cmb = adapter->cmb;
+ atl1_free_ring_resources(adapter);
+ adapter->rfd_ring = rfd_new;
+ adapter->rrd_ring = rrd_new;
+ adapter->tpd_ring = tpd_new;
+ adapter->ring_header = rhdr_new;
+ adapter->smb = smb;
+ adapter->cmb = cmb;
+
+ err = atl1_up(adapter);
+ if (err)
+ return err;
+ }
+ return 0;
+
+ err_setup_ring:
+ adapter->rfd_ring = rfd_old;
+ adapter->rrd_ring = rrd_old;
+ adapter->tpd_ring = tpd_old;
+ adapter->ring_header = rhdr_old;
+ atl1_up(adapter);
+ return err;
+ }
+
+ static void atl1_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *epause)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ epause->autoneg = AUTONEG_ENABLE;
+ } else {
+ epause->autoneg = AUTONEG_DISABLE;
+ }
+ epause->rx_pause = 1;
+ epause->tx_pause = 1;
+ }
+
+ static int atl1_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *epause)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ epause->autoneg = AUTONEG_ENABLE;
+ } else {
+ epause->autoneg = AUTONEG_DISABLE;
+ }
+
+ epause->rx_pause = 1;
+ epause->tx_pause = 1;
+
+ return 0;
+ }
+
+ static void atl1_get_strings(struct net_device *netdev, u32 stringset,
+ u8 *data)
+ {
+ u8 *p = data;
+ int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+ memcpy(p, atl1_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
+ }
+ }
+
+ static int atl1_nway_reset(struct net_device *netdev)
+ {
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ if (netif_running(netdev)) {
+ u16 phy_data;
+ atl1_down(adapter);
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+ } else {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data = MII_CR_FULL_DUPLEX |
+ MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data = MII_CR_FULL_DUPLEX |
+ MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default:
+ /* MEDIA_TYPE_10M_HALF */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ }
+ }
+ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ atl1_up(adapter);
+ }
+ return 0;
+ }
+
+ static const struct ethtool_ops atl1_ethtool_ops = {
+ .get_settings = atl1_get_settings,
+ .set_settings = atl1_set_settings,
+ .get_drvinfo = atl1_get_drvinfo,
+ .get_wol = atl1_get_wol,
+ .set_wol = atl1_set_wol,
+ .get_msglevel = atl1_get_msglevel,
+ .set_msglevel = atl1_set_msglevel,
+ .get_regs_len = atl1_get_regs_len,
+ .get_regs = atl1_get_regs,
+ .get_ringparam = atl1_get_ringparam,
+ .set_ringparam = atl1_set_ringparam,
+ .get_pauseparam = atl1_get_pauseparam,
+ .set_pauseparam = atl1_set_pauseparam,
+ .get_link = ethtool_op_get_link,
+ .get_strings = atl1_get_strings,
+ .nway_reset = atl1_nway_reset,
+ .get_ethtool_stats = atl1_get_ethtool_stats,
+ .get_sset_count = atl1_get_sset_count,
+ };
--- /dev/null
-#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12)
+ /* bnx2.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004-2011 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ */
+
+
+ #ifndef BNX2_H
+ #define BNX2_H
+
+ /* Hardware data structures and register definitions automatically
+ * generated from RTL code. Do not modify.
+ */
+
+ /*
+ * tx_bd definition
+ */
+ struct tx_bd {
+ u32 tx_bd_haddr_hi;
+ u32 tx_bd_haddr_lo;
+ u32 tx_bd_mss_nbytes;
+ #define TX_BD_TCP6_OFF2_SHL (14)
+ u32 tx_bd_vlan_tag_flags;
+ #define TX_BD_FLAGS_CONN_FAULT (1<<0)
+ #define TX_BD_FLAGS_TCP6_OFF0_MSK (3<<1)
+ #define TX_BD_FLAGS_TCP6_OFF0_SHL (1)
+ #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
+ #define TX_BD_FLAGS_IP_CKSUM (1<<2)
+ #define TX_BD_FLAGS_VLAN_TAG (1<<3)
+ #define TX_BD_FLAGS_COAL_NOW (1<<4)
+ #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5)
+ #define TX_BD_FLAGS_END (1<<6)
+ #define TX_BD_FLAGS_START (1<<7)
+ #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
+ #define TX_BD_FLAGS_TCP6_OFF4_SHL (12)
+ #define TX_BD_FLAGS_SW_FLAGS (1<<13)
+ #define TX_BD_FLAGS_SW_SNAP (1<<14)
+ #define TX_BD_FLAGS_SW_LSO (1<<15)
+
+ };
+
+
+ /*
+ * rx_bd definition
+ */
+ struct rx_bd {
+ u32 rx_bd_haddr_hi;
+ u32 rx_bd_haddr_lo;
+ u32 rx_bd_len;
+ u32 rx_bd_flags;
+ #define RX_BD_FLAGS_NOPUSH (1<<0)
+ #define RX_BD_FLAGS_DUMMY (1<<1)
+ #define RX_BD_FLAGS_END (1<<2)
+ #define RX_BD_FLAGS_START (1<<3)
+
+ };
+
+ #define BNX2_RX_ALIGN 16
+
+ /*
+ * status_block definition
+ */
+ struct status_block {
+ u32 status_attn_bits;
+ #define STATUS_ATTN_BITS_LINK_STATE (1L<<0)
+ #define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT (1L<<1)
+ #define STATUS_ATTN_BITS_TX_BD_READ_ABORT (1L<<2)
+ #define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT (1L<<3)
+ #define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT (1L<<4)
+ #define STATUS_ATTN_BITS_TX_DMA_ABORT (1L<<5)
+ #define STATUS_ATTN_BITS_TX_PATCHUP_ABORT (1L<<6)
+ #define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT (1L<<7)
+ #define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT (1L<<8)
+ #define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT (1L<<9)
+ #define STATUS_ATTN_BITS_RX_MBUF_ABORT (1L<<10)
+ #define STATUS_ATTN_BITS_RX_LOOKUP_ABORT (1L<<11)
+ #define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT (1L<<12)
+ #define STATUS_ATTN_BITS_RX_V2P_ABORT (1L<<13)
+ #define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT (1L<<14)
+ #define STATUS_ATTN_BITS_RX_DMA_ABORT (1L<<15)
+ #define STATUS_ATTN_BITS_COMPLETION_ABORT (1L<<16)
+ #define STATUS_ATTN_BITS_HOST_COALESCE_ABORT (1L<<17)
+ #define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT (1L<<18)
+ #define STATUS_ATTN_BITS_CONTEXT_ABORT (1L<<19)
+ #define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT (1L<<20)
+ #define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT (1L<<21)
+ #define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT (1L<<22)
+ #define STATUS_ATTN_BITS_MAC_ABORT (1L<<23)
+ #define STATUS_ATTN_BITS_TIMER_ABORT (1L<<24)
+ #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25)
+ #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26)
+ #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27)
+ #define STATUS_ATTN_BITS_EPB_ERROR (1L<<30)
+ #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31)
+
+ u32 status_attn_bits_ack;
+ #if defined(__BIG_ENDIAN)
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_completion_producer_index;
+ u16 status_cmd_consumer_index;
+ u16 status_idx;
+ u8 status_unused;
+ u8 status_blk_num;
+ #elif defined(__LITTLE_ENDIAN)
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_cmd_consumer_index;
+ u16 status_completion_producer_index;
+ u8 status_blk_num;
+ u8 status_unused;
+ u16 status_idx;
+ #endif
+ };
+
+ /*
+ * status_block definition
+ */
+ struct status_block_msix {
+ #if defined(__BIG_ENDIAN)
+ u16 status_tx_quick_consumer_index;
+ u16 status_rx_quick_consumer_index;
+ u16 status_completion_producer_index;
+ u16 status_cmd_consumer_index;
+ u32 status_unused;
+ u16 status_idx;
+ u8 status_unused2;
+ u8 status_blk_num;
+ #elif defined(__LITTLE_ENDIAN)
+ u16 status_rx_quick_consumer_index;
+ u16 status_tx_quick_consumer_index;
+ u16 status_cmd_consumer_index;
+ u16 status_completion_producer_index;
+ u32 status_unused;
+ u8 status_blk_num;
+ u8 status_unused2;
+ u16 status_idx;
+ #endif
+ };
+
+ #define BNX2_SBLK_MSIX_ALIGN_SIZE 128
+
+
+ /*
+ * statistics_block definition
+ */
+ struct statistics_block {
+ u32 stat_IfHCInOctets_hi;
+ u32 stat_IfHCInOctets_lo;
+ u32 stat_IfHCInBadOctets_hi;
+ u32 stat_IfHCInBadOctets_lo;
+ u32 stat_IfHCOutOctets_hi;
+ u32 stat_IfHCOutOctets_lo;
+ u32 stat_IfHCOutBadOctets_hi;
+ u32 stat_IfHCOutBadOctets_lo;
+ u32 stat_IfHCInUcastPkts_hi;
+ u32 stat_IfHCInUcastPkts_lo;
+ u32 stat_IfHCInMulticastPkts_hi;
+ u32 stat_IfHCInMulticastPkts_lo;
+ u32 stat_IfHCInBroadcastPkts_hi;
+ u32 stat_IfHCInBroadcastPkts_lo;
+ u32 stat_IfHCOutUcastPkts_hi;
+ u32 stat_IfHCOutUcastPkts_lo;
+ u32 stat_IfHCOutMulticastPkts_hi;
+ u32 stat_IfHCOutMulticastPkts_lo;
+ u32 stat_IfHCOutBroadcastPkts_hi;
+ u32 stat_IfHCOutBroadcastPkts_lo;
+ u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
+ u32 stat_Dot3StatsCarrierSenseErrors;
+ u32 stat_Dot3StatsFCSErrors;
+ u32 stat_Dot3StatsAlignmentErrors;
+ u32 stat_Dot3StatsSingleCollisionFrames;
+ u32 stat_Dot3StatsMultipleCollisionFrames;
+ u32 stat_Dot3StatsDeferredTransmissions;
+ u32 stat_Dot3StatsExcessiveCollisions;
+ u32 stat_Dot3StatsLateCollisions;
+ u32 stat_EtherStatsCollisions;
+ u32 stat_EtherStatsFragments;
+ u32 stat_EtherStatsJabbers;
+ u32 stat_EtherStatsUndersizePkts;
+ u32 stat_EtherStatsOverrsizePkts;
+ u32 stat_EtherStatsPktsRx64Octets;
+ u32 stat_EtherStatsPktsRx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsRx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsRx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
+ u32 stat_EtherStatsPktsTx64Octets;
+ u32 stat_EtherStatsPktsTx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsTx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsTx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
+ u32 stat_XonPauseFramesReceived;
+ u32 stat_XoffPauseFramesReceived;
+ u32 stat_OutXonSent;
+ u32 stat_OutXoffSent;
+ u32 stat_FlowControlDone;
+ u32 stat_MacControlFramesReceived;
+ u32 stat_XoffStateEntered;
+ u32 stat_IfInFramesL2FilterDiscards;
+ u32 stat_IfInRuleCheckerDiscards;
+ u32 stat_IfInFTQDiscards;
+ u32 stat_IfInMBUFDiscards;
+ u32 stat_IfInRuleCheckerP4Hit;
+ u32 stat_CatchupInRuleCheckerDiscards;
+ u32 stat_CatchupInFTQDiscards;
+ u32 stat_CatchupInMBUFDiscards;
+ u32 stat_CatchupInRuleCheckerP4Hit;
+ u32 stat_GenStat00;
+ u32 stat_GenStat01;
+ u32 stat_GenStat02;
+ u32 stat_GenStat03;
+ u32 stat_GenStat04;
+ u32 stat_GenStat05;
+ u32 stat_GenStat06;
+ u32 stat_GenStat07;
+ u32 stat_GenStat08;
+ u32 stat_GenStat09;
+ u32 stat_GenStat10;
+ u32 stat_GenStat11;
+ u32 stat_GenStat12;
+ u32 stat_GenStat13;
+ u32 stat_GenStat14;
+ u32 stat_GenStat15;
+ u32 stat_FwRxDrop;
+ };
+
+
+ /*
+ * l2_fhdr definition
+ */
+ struct l2_fhdr {
+ u32 l2_fhdr_status;
+ #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0)
+ #define L2_FHDR_STATUS_RULE_P2 (1<<3)
+ #define L2_FHDR_STATUS_RULE_P3 (1<<4)
+ #define L2_FHDR_STATUS_RULE_P4 (1<<5)
+ #define L2_FHDR_STATUS_L2_VLAN_TAG (1<<6)
+ #define L2_FHDR_STATUS_L2_LLC_SNAP (1<<7)
+ #define L2_FHDR_STATUS_RSS_HASH (1<<8)
+ #define L2_FHDR_STATUS_IP_DATAGRAM (1<<13)
+ #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14)
+ #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
+
+ #define L2_FHDR_STATUS_SPLIT (1<<16)
+ #define L2_FHDR_ERRORS_BAD_CRC (1<<17)
+ #define L2_FHDR_ERRORS_PHY_DECODE (1<<18)
+ #define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
+ #define L2_FHDR_ERRORS_TOO_SHORT (1<<20)
+ #define L2_FHDR_ERRORS_GIANT_FRAME (1<<21)
+ #define L2_FHDR_ERRORS_TCP_XSUM (1<<28)
+ #define L2_FHDR_ERRORS_UDP_XSUM (1<<31)
+
+ #define L2_FHDR_STATUS_USE_RXHASH \
+ (L2_FHDR_STATUS_TCP_SEGMENT | L2_FHDR_STATUS_RSS_HASH)
+
+ u32 l2_fhdr_hash;
+ #if defined(__BIG_ENDIAN)
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_ip_xsum;
+ u16 l2_fhdr_tcp_udp_xsum;
+ #elif defined(__LITTLE_ENDIAN)
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_tcp_udp_xsum;
+ u16 l2_fhdr_ip_xsum;
+ #endif
+ };
+
+ #define BNX2_RX_OFFSET (sizeof(struct l2_fhdr) + 2)
+
+ /*
+ * l2_context definition
+ */
+ #define BNX2_L2CTX_TYPE 0x00000000
+ #define BNX2_L2CTX_TYPE_SIZE_L2 ((0xc0/0x20)<<16)
+ #define BNX2_L2CTX_TYPE_TYPE (0xf<<28)
+ #define BNX2_L2CTX_TYPE_TYPE_EMPTY (0<<28)
+ #define BNX2_L2CTX_TYPE_TYPE_L2 (1<<28)
+
+ #define BNX2_L2CTX_TX_HOST_BIDX 0x00000088
+ #define BNX2_L2CTX_EST_NBD 0x00000088
+ #define BNX2_L2CTX_CMD_TYPE 0x00000088
+ #define BNX2_L2CTX_CMD_TYPE_TYPE (0xf<<24)
+ #define BNX2_L2CTX_CMD_TYPE_TYPE_L2 (0<<24)
+ #define BNX2_L2CTX_CMD_TYPE_TYPE_TCP (1<<24)
+
+ #define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090
+ #define BNX2_L2CTX_TSCH_BSEQ 0x00000094
+ #define BNX2_L2CTX_TBDR_BSEQ 0x00000098
+ #define BNX2_L2CTX_TBDR_BOFF 0x0000009c
+ #define BNX2_L2CTX_TBDR_BIDX 0x0000009c
+ #define BNX2_L2CTX_TBDR_BHADDR_HI 0x000000a0
+ #define BNX2_L2CTX_TBDR_BHADDR_LO 0x000000a4
+ #define BNX2_L2CTX_TXP_BOFF 0x000000a8
+ #define BNX2_L2CTX_TXP_BIDX 0x000000a8
+ #define BNX2_L2CTX_TXP_BSEQ 0x000000ac
+
+ #define BNX2_L2CTX_TYPE_XI 0x00000080
+ #define BNX2_L2CTX_CMD_TYPE_XI 0x00000240
+ #define BNX2_L2CTX_TBDR_BHADDR_HI_XI 0x00000258
+ #define BNX2_L2CTX_TBDR_BHADDR_LO_XI 0x0000025c
+
+ /*
+ * l2_bd_chain_context definition
+ */
+ #define BNX2_L2CTX_BD_PRE_READ 0x00000000
+ #define BNX2_L2CTX_CTX_SIZE 0x00000000
+ #define BNX2_L2CTX_CTX_TYPE 0x00000000
+ #define BNX2_L2CTX_FLOW_CTRL_ENABLE 0x000000ff
+ #define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16)
+ #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28)
+ #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28)
+ #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28)
+
+ #define BNX2_L2CTX_HOST_BDIDX 0x00000004
+ #define BNX2_L2CTX_L5_STATUSB_NUM_SHIFT 16
+ #define BNX2_L2CTX_L2_STATUSB_NUM_SHIFT 24
+ #define BNX2_L2CTX_L5_STATUSB_NUM(sb_id) \
+ (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L5_STATUSB_NUM_SHIFT) : 0)
+ #define BNX2_L2CTX_L2_STATUSB_NUM(sb_id) \
+ (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT) : 0)
+ #define BNX2_L2CTX_HOST_BSEQ 0x00000008
+ #define BNX2_L2CTX_NX_BSEQ 0x0000000c
+ #define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010
+ #define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014
+ #define BNX2_L2CTX_NX_BDIDX 0x00000018
+
+ #define BNX2_L2CTX_HOST_PG_BDIDX 0x00000044
+ #define BNX2_L2CTX_PG_BUF_SIZE 0x00000048
+ #define BNX2_L2CTX_RBDC_KEY 0x0000004c
+ #define BNX2_L2CTX_RBDC_JUMBO_KEY 0x3ffe
+ #define BNX2_L2CTX_NX_PG_BDHADDR_HI 0x00000050
+ #define BNX2_L2CTX_NX_PG_BDHADDR_LO 0x00000054
+
+ /*
+ * pci_config_l definition
+ * offset: 0000
+ */
+ #define BNX2_PCICFG_MSI_CONTROL 0x00000058
+ #define BNX2_PCICFG_MSI_CONTROL_ENABLE (1L<<16)
+
+ #define BNX2_PCICFG_MISC_CONFIG 0x00000068
+ #define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2)
+ #define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3)
+ #define BNX2_PCICFG_MISC_CONFIG_RESERVED1 (1L<<4)
+ #define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5)
+ #define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6)
+ #define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7)
+ #define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8)
+ #define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9)
+ #define BNX2_PCICFG_MISC_CONFIG_GRC_WIN1_SWAP_EN (1L<<10)
+ #define BNX2_PCICFG_MISC_CONFIG_GRC_WIN2_SWAP_EN (1L<<11)
+ #define BNX2_PCICFG_MISC_CONFIG_GRC_WIN3_SWAP_EN (1L<<12)
+ #define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16)
+ #define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24)
+ #define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28)
+
+ #define BNX2_PCICFG_MISC_STATUS 0x0000006c
+ #define BNX2_PCICFG_MISC_STATUS_INTA_VALUE (1L<<0)
+ #define BNX2_PCICFG_MISC_STATUS_32BIT_DET (1L<<1)
+ #define BNX2_PCICFG_MISC_STATUS_M66EN (1L<<2)
+ #define BNX2_PCICFG_MISC_STATUS_PCIX_DET (1L<<3)
+ #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED (0x3L<<4)
+ #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66 (0L<<4)
+ #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4)
+ #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4)
+ #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4)
+ #define BNX2_PCICFG_MISC_STATUS_BAD_MEM_WRITE_BE (1L<<8)
+
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_17 (1L<<17)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_19 (1L<<19)
+ #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+ #define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078
+ #define BNX2_PCICFG_REG_WINDOW_ADDRESS_VAL (0xfffffL<<2)
+
+ #define BNX2_PCICFG_REG_WINDOW 0x00000080
+ #define BNX2_PCICFG_INT_ACK_CMD 0x00000084
+ #define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0)
+ #define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16)
+ #define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17)
+ #define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18)
+ #define BNX2_PCICFG_INT_ACK_CMD_INTERRUPT_NUM (0xfL<<24)
+ #define BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT 24
+
+ #define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
+ #define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c
+ #define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090
+ #define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094
+
+ #define BNX2_PCICFG_DEVICE_CONTROL 0x000000b4
+ #define BNX2_PCICFG_DEVICE_STATUS_NO_PEND ((1L<<5)<<16)
+
+ /*
+ * pci_reg definition
+ * offset: 0x400
+ */
+ #define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400
+ #define BNX2_PCI_GRC_WINDOW_ADDR_VALUE (0x1ffL<<13)
+ #define BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN (1L<<31)
+
+ #define BNX2_PCI_GRC_WINDOW2_BASE 0xc000
+ #define BNX2_PCI_GRC_WINDOW3_BASE 0xe000
+
+ #define BNX2_PCI_CONFIG_1 0x00000404
+ #define BNX2_PCI_CONFIG_1_RESERVED0 (0xffL<<0)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32 (2L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64 (3L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128 (4L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256 (5L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512 (6L<<8)
+ #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024 (7L<<8)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY (0x7L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF (0L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16 (1L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32 (2L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64 (3L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128 (4L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11)
+ #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11)
+ #define BNX2_PCI_CONFIG_1_RESERVED1 (0x3ffffL<<14)
+
+ #define BNX2_PCI_CONFIG_2 0x00000408
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0)
+ #define BNX2_PCI_CONFIG_2_BAR1_64ENA (1L<<4)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5)
+ #define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6)
+ #define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K (1L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K (2L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K (3L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K (4L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K (5L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K (6L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K (7L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K (8L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K (9L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K (10L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M (11L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M (12L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M (13L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M (14L<<8)
+ #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M (15L<<8)
+ #define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT (0x1fL<<16)
+ #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT (0x3L<<21)
+ #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512 (0L<<21)
+ #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K (1L<<21)
+ #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K (2L<<21)
+ #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K (3L<<21)
+ #define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23)
+ #define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24)
+ #define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25)
+ #define BNX2_PCI_CONFIG_2_RESERVED0 (0x3fL<<26)
+ #define BNX2_PCI_CONFIG_2_BAR_PREFETCH_XI (1L<<16)
+ #define BNX2_PCI_CONFIG_2_RESERVED0_XI (0x7fffL<<17)
+
+ #define BNX2_PCI_CONFIG_3 0x0000040c
+ #define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0)
+ #define BNX2_PCI_CONFIG_3_REG_STICKY_BYTE (0xffL<<8)
+ #define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24)
+ #define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25)
+ #define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26)
+ #define BNX2_PCI_CONFIG_3_PM_STATE (0x3L<<27)
+ #define BNX2_PCI_CONFIG_3_VAUX_PRESET (1L<<30)
+ #define BNX2_PCI_CONFIG_3_PCI_POWER (1L<<31)
+
+ #define BNX2_PCI_PM_DATA_A 0x00000410
+ #define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG (0xffL<<0)
+ #define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG (0xffL<<8)
+ #define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG (0xffL<<16)
+ #define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG (0xffL<<24)
+
+ #define BNX2_PCI_PM_DATA_B 0x00000414
+ #define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG (0xffL<<0)
+ #define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG (0xffL<<8)
+ #define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG (0xffL<<16)
+ #define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG (0xffL<<24)
+
+ #define BNX2_PCI_SWAP_DIAG0 0x00000418
+ #define BNX2_PCI_SWAP_DIAG1 0x0000041c
+ #define BNX2_PCI_EXP_ROM_ADDR 0x00000420
+ #define BNX2_PCI_EXP_ROM_ADDR_ADDRESS (0x3fffffL<<2)
+ #define BNX2_PCI_EXP_ROM_ADDR_REQ (1L<<31)
+
+ #define BNX2_PCI_EXP_ROM_DATA 0x00000424
+ #define BNX2_PCI_VPD_INTF 0x00000428
+ #define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0)
+
+ #define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c
+ #define BNX2_PCI_VPD_ADDR_FLAG_MSK 0x0000ffff
+ #define BNX2_PCI_VPD_ADDR_FLAG_SL 0L
+ #define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fffL<<2)
+ #define BNX2_PCI_VPD_ADDR_FLAG_WR (1L<<15)
+
+ #define BNX2_PCI_VPD_DATA 0x00000430
+ #define BNX2_PCI_ID_VAL1 0x00000434
+ #define BNX2_PCI_ID_VAL1_DEVICE_ID (0xffffL<<0)
+ #define BNX2_PCI_ID_VAL1_VENDOR_ID (0xffffL<<16)
+
+ #define BNX2_PCI_ID_VAL2 0x00000438
+ #define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID (0xffffL<<0)
+ #define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID (0xffffL<<16)
+
+ #define BNX2_PCI_ID_VAL3 0x0000043c
+ #define BNX2_PCI_ID_VAL3_CLASS_CODE (0xffffffL<<0)
+ #define BNX2_PCI_ID_VAL3_REVISION_ID (0xffL<<24)
+
+ #define BNX2_PCI_ID_VAL4 0x00000440
+ #define BNX2_PCI_ID_VAL4_CAP_ENA (0xfL<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_0 (0L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_1 (1L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_2 (2L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_3 (3L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_4 (4L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_5 (5L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_6 (6L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_7 (7L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_8 (8L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_9 (9L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_10 (10L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_11 (11L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_12 (12L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0)
+ #define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0)
+ #define BNX2_PCI_ID_VAL4_RESERVED0 (0x3L<<4)
+ #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6)
+ #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6)
+ #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6)
+ #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6)
+ #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6)
+ #define BNX2_PCI_ID_VAL4_MSI_PV_MASK_CAP (1L<<8)
+ #define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9)
+ #define BNX2_PCI_ID_VAL4_MULTI_MSG_CAP (0x7L<<12)
+ #define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15)
+ #define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16)
+ #define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17)
+ #define BNX2_PCI_ID_VAL4_RESERVED2 (0x7L<<18)
+ #define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B21 (0x3L<<21)
+ #define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B21 (0x3L<<23)
+ #define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B0 (1L<<25)
+ #define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE_B10 (0x3L<<26)
+ #define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B0 (1L<<28)
+ #define BNX2_PCI_ID_VAL4_RESERVED3 (0x7L<<29)
+ #define BNX2_PCI_ID_VAL4_RESERVED3_XI (0xffffL<<16)
+
+ #define BNX2_PCI_ID_VAL5 0x00000444
+ #define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0)
+ #define BNX2_PCI_ID_VAL5_D2_SUPPORT (1L<<1)
+ #define BNX2_PCI_ID_VAL5_PME_IN_D0 (1L<<2)
+ #define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3)
+ #define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4)
+ #define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5)
+ #define BNX2_PCI_ID_VAL5_RESERVED0_TE (0x3ffffffL<<6)
+ #define BNX2_PCI_ID_VAL5_PM_VERSION_XI (0x7L<<6)
+ #define BNX2_PCI_ID_VAL5_NO_SOFT_RESET_XI (1L<<9)
+ #define BNX2_PCI_ID_VAL5_RESERVED0_XI (0x3fffffL<<10)
+
+ #define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448
+ #define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8)
+ #define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST (1L<<9)
+ #define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS (0xfL<<16)
+ #define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX (0xffL<<24)
+
+ #define BNX2_PCI_ID_VAL6 0x0000044c
+ #define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0)
+ #define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8)
+ #define BNX2_PCI_ID_VAL6_BIST (0xffL<<16)
+ #define BNX2_PCI_ID_VAL6_RESERVED0 (0xffL<<24)
+
+ #define BNX2_PCI_MSI_DATA 0x00000450
+ #define BNX2_PCI_MSI_DATA_MSI_DATA (0xffffL<<0)
+
+ #define BNX2_PCI_MSI_ADDR_H 0x00000454
+ #define BNX2_PCI_MSI_ADDR_L 0x00000458
+ #define BNX2_PCI_MSI_ADDR_L_VAL (0x3fffffffL<<2)
+
+ #define BNX2_PCI_CFG_ACCESS_CMD 0x0000045c
+ #define BNX2_PCI_CFG_ACCESS_CMD_ADR (0x3fL<<2)
+ #define BNX2_PCI_CFG_ACCESS_CMD_RD_REQ (1L<<27)
+ #define BNX2_PCI_CFG_ACCESS_CMD_WR_REQ (0xfL<<28)
+
+ #define BNX2_PCI_CFG_ACCESS_DATA 0x00000460
+ #define BNX2_PCI_MSI_MASK 0x00000464
+ #define BNX2_PCI_MSI_MASK_MSI_MASK (0xffffffffL<<0)
+
+ #define BNX2_PCI_MSI_PEND 0x00000468
+ #define BNX2_PCI_MSI_PEND_MSI_PEND (0xffffffffL<<0)
+
+ #define BNX2_PCI_PM_DATA_C 0x0000046c
+ #define BNX2_PCI_PM_DATA_C_PM_DATA_8_PRG (0xffL<<0)
+ #define BNX2_PCI_PM_DATA_C_RESERVED0 (0xffffffL<<8)
+
+ #define BNX2_PCI_MSIX_CONTROL 0x000004c0
+ #define BNX2_PCI_MSIX_CONTROL_MSIX_TBL_SIZ (0x7ffL<<0)
+ #define BNX2_PCI_MSIX_CONTROL_RESERVED0 (0x1fffffL<<11)
+
+ #define BNX2_PCI_MSIX_TBL_OFF_BIR 0x000004c4
+ #define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_BIR (0x7L<<0)
+ #define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_OFF (0x1fffffffL<<3)
+
+ #define BNX2_PCI_MSIX_PBA_OFF_BIT 0x000004c8
+ #define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_BIR (0x7L<<0)
+ #define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_OFF (0x1fffffffL<<3)
+
+ #define BNX2_PCI_PCIE_CAPABILITY 0x000004d0
+ #define BNX2_PCI_PCIE_CAPABILITY_INTERRUPT_MSG_NUM (0x1fL<<0)
+ #define BNX2_PCI_PCIE_CAPABILITY_COMPLY_PCIE_1_1 (1L<<5)
+
+ #define BNX2_PCI_DEVICE_CAPABILITY 0x000004d4
+ #define BNX2_PCI_DEVICE_CAPABILITY_MAX_PL_SIZ_SUPPORTED (0x7L<<0)
+ #define BNX2_PCI_DEVICE_CAPABILITY_EXTENDED_TAG_SUPPORT (1L<<5)
+ #define BNX2_PCI_DEVICE_CAPABILITY_L0S_ACCEPTABLE_LATENCY (0x7L<<6)
+ #define BNX2_PCI_DEVICE_CAPABILITY_L1_ACCEPTABLE_LATENCY (0x7L<<9)
+ #define BNX2_PCI_DEVICE_CAPABILITY_ROLE_BASED_ERR_RPT (1L<<15)
+
+ #define BNX2_PCI_LINK_CAPABILITY 0x000004dc
+ #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED (0xfL<<0)
+ #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0001 (1L<<0)
+ #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0010 (1L<<0)
+ #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_WIDTH (0x1fL<<4)
+ #define BNX2_PCI_LINK_CAPABILITY_CLK_POWER_MGMT (1L<<9)
+ #define BNX2_PCI_LINK_CAPABILITY_ASPM_SUPPORT (0x3L<<10)
+ #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT (0x7L<<12)
+ #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_101 (5L<<12)
+ #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_110 (6L<<12)
+ #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT (0x7L<<15)
+ #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_001 (1L<<15)
+ #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_010 (2L<<15)
+ #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT (0x7L<<18)
+ #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_101 (5L<<18)
+ #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_110 (6L<<18)
+ #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT (0x7L<<21)
+ #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_001 (1L<<21)
+ #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_010 (2L<<21)
+ #define BNX2_PCI_LINK_CAPABILITY_PORT_NUM (0xffL<<24)
+
+ #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2 0x000004e4
+ #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_RANGE_SUPP (0xfL<<0)
+ #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_DISABL_SUPP (1L<<4)
+ #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_RESERVED (0x7ffffffL<<5)
+
+ #define BNX2_PCI_PCIE_LINK_CAPABILITY_2 0x000004e8
+ #define BNX2_PCI_PCIE_LINK_CAPABILITY_2_RESERVED (0xffffffffL<<0)
+
+ #define BNX2_PCI_GRC_WINDOW1_ADDR 0x00000610
+ #define BNX2_PCI_GRC_WINDOW1_ADDR_VALUE (0x1ffL<<13)
+
+ #define BNX2_PCI_GRC_WINDOW2_ADDR 0x00000614
+ #define BNX2_PCI_GRC_WINDOW2_ADDR_VALUE (0x1ffL<<13)
+
+ #define BNX2_PCI_GRC_WINDOW3_ADDR 0x00000618
+ #define BNX2_PCI_GRC_WINDOW3_ADDR_VALUE (0x1ffL<<13)
+
+ #define BNX2_MSIX_TABLE_ADDR 0x318000
+ #define BNX2_MSIX_PBA_ADDR 0x31c000
+
+ /*
+ * misc_reg definition
+ * offset: 0x800
+ */
+ #define BNX2_MISC_COMMAND 0x00000800
+ #define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0)
+ #define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1)
+ #define BNX2_MISC_COMMAND_SW_RESET (1L<<4)
+ #define BNX2_MISC_COMMAND_POR_RESET (1L<<5)
+ #define BNX2_MISC_COMMAND_HD_RESET (1L<<6)
+ #define BNX2_MISC_COMMAND_CMN_SW_RESET (1L<<7)
+ #define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8)
+ #define BNX2_MISC_COMMAND_CS16_ERR (1L<<9)
+ #define BNX2_MISC_COMMAND_CS16_ERR_LOC (0xfL<<12)
+ #define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16)
+ #define BNX2_MISC_COMMAND_POWERDOWN_EVENT (1L<<23)
+ #define BNX2_MISC_COMMAND_SW_SHUTDOWN (1L<<24)
+ #define BNX2_MISC_COMMAND_SHUTDOWN_EN (1L<<25)
+ #define BNX2_MISC_COMMAND_DINTEG_ATTN_EN (1L<<26)
+ #define BNX2_MISC_COMMAND_PCIE_LINK_IN_L23 (1L<<27)
+ #define BNX2_MISC_COMMAND_PCIE_DIS (1L<<28)
+
+ #define BNX2_MISC_CFG 0x00000804
+ #define BNX2_MISC_CFG_GRC_TMOUT (1L<<0)
+ #define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1)
+ #define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1)
+ #define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1)
+ #define BNX2_MISC_CFG_NVM_WR_EN_ALLOW (2L<<1)
+ #define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1)
+ #define BNX2_MISC_CFG_BIST_EN (1L<<3)
+ #define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4)
+ #define BNX2_MISC_CFG_RESERVED5_TE (1L<<5)
+ #define BNX2_MISC_CFG_RESERVED6_TE (1L<<6)
+ #define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7)
+ #define BNX2_MISC_CFG_LEDMODE (0x7L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY1_TE (1L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY2_TE (2L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY3_TE (3L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY4_TE (4L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY5_TE (5L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY6_TE (6L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY7_TE (7L<<8)
+ #define BNX2_MISC_CFG_MCP_GRC_TMOUT_TE (1L<<11)
+ #define BNX2_MISC_CFG_DBU_GRC_TMOUT_TE (1L<<12)
+ #define BNX2_MISC_CFG_LEDMODE_XI (0xfL<<8)
+ #define BNX2_MISC_CFG_LEDMODE_MAC_XI (0L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY1_XI (1L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY2_XI (2L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY3_XI (3L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_MAC2_XI (4L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY4_XI (5L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY5_XI (6L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY6_XI (7L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_MAC3_XI (8L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY7_XI (9L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY8_XI (10L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY9_XI (11L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_MAC4_XI (12L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY10_XI (13L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_PHY11_XI (14L<<8)
+ #define BNX2_MISC_CFG_LEDMODE_UNUSED_XI (15L<<8)
+ #define BNX2_MISC_CFG_PORT_SELECT_XI (1L<<13)
+ #define BNX2_MISC_CFG_PARITY_MODE_XI (1L<<14)
+
+ #define BNX2_MISC_ID 0x00000808
+ #define BNX2_MISC_ID_BOND_ID (0xfL<<0)
+ #define BNX2_MISC_ID_BOND_ID_X (0L<<0)
+ #define BNX2_MISC_ID_BOND_ID_C (3L<<0)
+ #define BNX2_MISC_ID_BOND_ID_S (12L<<0)
+ #define BNX2_MISC_ID_CHIP_METAL (0xffL<<4)
+ #define BNX2_MISC_ID_CHIP_REV (0xfL<<12)
+ #define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16)
+
+ #define BNX2_MISC_ENABLE_STATUS_BITS 0x0000080c
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE (1L<<1)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE (1L<<4)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE (1L<<5)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE (1L<<9)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE (1L<<12)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE (1L<<13)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE (1L<<15)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE (1L<<17)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE (1L<<18)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE (1L<<19)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE (1L<<21)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+ #define BNX2_MISC_ENABLE_STATUS_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
+
+ #define BNX2_MISC_ENABLE_SET_BITS 0x00000810
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE (1L<<1)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE (1L<<4)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE (1L<<5)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+ #define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+ #define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE (1L<<9)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE (1L<<12)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE (1L<<13)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE (1L<<15)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+ #define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE (1L<<17)
+ #define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE (1L<<18)
+ #define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE (1L<<19)
+ #define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+ #define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE (1L<<21)
+ #define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+ #define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+ #define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+ #define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25)
+ #define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26)
+ #define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27)
+ #define BNX2_MISC_ENABLE_SET_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+ #define BNX2_MISC_ENABLE_SET_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
+
+ #define BNX2_MISC_ENABLE_CLR_BITS 0x00000814
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE (1L<<1)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE (1L<<4)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE (1L<<5)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+ #define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE (1L<<9)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE (1L<<12)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE (1L<<13)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE (1L<<15)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE (1L<<17)
+ #define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE (1L<<18)
+ #define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE (1L<<19)
+ #define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+ #define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE (1L<<21)
+ #define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+ #define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+ #define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+ #define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25)
+ #define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26)
+ #define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+ #define BNX2_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
+
+ #define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED0_XI (0x7L<<8)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED1_XI (0xfL<<12)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_17_TE (1L<<17)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18_TE (1L<<18)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_19_TE (1L<<19)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_TE (0xfffL<<20)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_MGMT_XI (1L<<17)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED2_XI (0x3fL<<18)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_VCO_XI (0x7L<<24)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED3_XI (1L<<27)
+ #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_XI (0xfL<<28)
+
+ #define BNX2_MISC_SPIO 0x0000081c
+ #define BNX2_MISC_SPIO_VALUE (0xffL<<0)
+ #define BNX2_MISC_SPIO_SET (0xffL<<8)
+ #define BNX2_MISC_SPIO_CLR (0xffL<<16)
+ #define BNX2_MISC_SPIO_FLOAT (0xffL<<24)
+
+ #define BNX2_MISC_SPIO_INT 0x00000820
+ #define BNX2_MISC_SPIO_INT_INT_STATE_TE (0xfL<<0)
+ #define BNX2_MISC_SPIO_INT_OLD_VALUE_TE (0xfL<<8)
+ #define BNX2_MISC_SPIO_INT_OLD_SET_TE (0xfL<<16)
+ #define BNX2_MISC_SPIO_INT_OLD_CLR_TE (0xfL<<24)
+ #define BNX2_MISC_SPIO_INT_INT_STATE_XI (0xffL<<0)
+ #define BNX2_MISC_SPIO_INT_OLD_VALUE_XI (0xffL<<8)
+ #define BNX2_MISC_SPIO_INT_OLD_SET_XI (0xffL<<16)
+ #define BNX2_MISC_SPIO_INT_OLD_CLR_XI (0xffL<<24)
+
+ #define BNX2_MISC_CONFIG_LFSR 0x00000824
+ #define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0)
+
+ #define BNX2_MISC_LFSR_MASK_BITS 0x00000828
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE (1L<<1)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE (1L<<4)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE (1L<<5)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+ #define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+ #define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE (1L<<9)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE (1L<<12)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE (1L<<13)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE (1L<<15)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+ #define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE (1L<<17)
+ #define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE (1L<<18)
+ #define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE (1L<<19)
+ #define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+ #define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE (1L<<21)
+ #define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+ #define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+ #define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+ #define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25)
+ #define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26)
+ #define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27)
+ #define BNX2_MISC_LFSR_MASK_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
+ #define BNX2_MISC_LFSR_MASK_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
+
+ #define BNX2_MISC_ARB_REQ0 0x0000082c
+ #define BNX2_MISC_ARB_REQ1 0x00000830
+ #define BNX2_MISC_ARB_REQ2 0x00000834
+ #define BNX2_MISC_ARB_REQ3 0x00000838
+ #define BNX2_MISC_ARB_REQ4 0x0000083c
+ #define BNX2_MISC_ARB_FREE0 0x00000840
+ #define BNX2_MISC_ARB_FREE1 0x00000844
+ #define BNX2_MISC_ARB_FREE2 0x00000848
+ #define BNX2_MISC_ARB_FREE3 0x0000084c
+ #define BNX2_MISC_ARB_FREE4 0x00000850
+ #define BNX2_MISC_ARB_REQ_STATUS0 0x00000854
+ #define BNX2_MISC_ARB_REQ_STATUS1 0x00000858
+ #define BNX2_MISC_ARB_REQ_STATUS2 0x0000085c
+ #define BNX2_MISC_ARB_REQ_STATUS3 0x00000860
+ #define BNX2_MISC_ARB_REQ_STATUS4 0x00000864
+ #define BNX2_MISC_ARB_GNT0 0x00000868
+ #define BNX2_MISC_ARB_GNT0_0 (0x7L<<0)
+ #define BNX2_MISC_ARB_GNT0_1 (0x7L<<4)
+ #define BNX2_MISC_ARB_GNT0_2 (0x7L<<8)
+ #define BNX2_MISC_ARB_GNT0_3 (0x7L<<12)
+ #define BNX2_MISC_ARB_GNT0_4 (0x7L<<16)
+ #define BNX2_MISC_ARB_GNT0_5 (0x7L<<20)
+ #define BNX2_MISC_ARB_GNT0_6 (0x7L<<24)
+ #define BNX2_MISC_ARB_GNT0_7 (0x7L<<28)
+
+ #define BNX2_MISC_ARB_GNT1 0x0000086c
+ #define BNX2_MISC_ARB_GNT1_8 (0x7L<<0)
+ #define BNX2_MISC_ARB_GNT1_9 (0x7L<<4)
+ #define BNX2_MISC_ARB_GNT1_10 (0x7L<<8)
+ #define BNX2_MISC_ARB_GNT1_11 (0x7L<<12)
+ #define BNX2_MISC_ARB_GNT1_12 (0x7L<<16)
+ #define BNX2_MISC_ARB_GNT1_13 (0x7L<<20)
+ #define BNX2_MISC_ARB_GNT1_14 (0x7L<<24)
+ #define BNX2_MISC_ARB_GNT1_15 (0x7L<<28)
+
+ #define BNX2_MISC_ARB_GNT2 0x00000870
+ #define BNX2_MISC_ARB_GNT2_16 (0x7L<<0)
+ #define BNX2_MISC_ARB_GNT2_17 (0x7L<<4)
+ #define BNX2_MISC_ARB_GNT2_18 (0x7L<<8)
+ #define BNX2_MISC_ARB_GNT2_19 (0x7L<<12)
+ #define BNX2_MISC_ARB_GNT2_20 (0x7L<<16)
+ #define BNX2_MISC_ARB_GNT2_21 (0x7L<<20)
+ #define BNX2_MISC_ARB_GNT2_22 (0x7L<<24)
+ #define BNX2_MISC_ARB_GNT2_23 (0x7L<<28)
+
+ #define BNX2_MISC_ARB_GNT3 0x00000874
+ #define BNX2_MISC_ARB_GNT3_24 (0x7L<<0)
+ #define BNX2_MISC_ARB_GNT3_25 (0x7L<<4)
+ #define BNX2_MISC_ARB_GNT3_26 (0x7L<<8)
+ #define BNX2_MISC_ARB_GNT3_27 (0x7L<<12)
+ #define BNX2_MISC_ARB_GNT3_28 (0x7L<<16)
+ #define BNX2_MISC_ARB_GNT3_29 (0x7L<<20)
+ #define BNX2_MISC_ARB_GNT3_30 (0x7L<<24)
+ #define BNX2_MISC_ARB_GNT3_31 (0x7L<<28)
+
+ #define BNX2_MISC_RESERVED1 0x00000878
+ #define BNX2_MISC_RESERVED1_MISC_RESERVED1_VALUE (0x3fL<<0)
+
+ #define BNX2_MISC_RESERVED2 0x0000087c
+ #define BNX2_MISC_RESERVED2_PCIE_DIS (1L<<0)
+ #define BNX2_MISC_RESERVED2_LINK_IN_L23 (1L<<1)
+
+ #define BNX2_MISC_SM_ASF_CONTROL 0x00000880
+ #define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0)
+ #define BNX2_MISC_SM_ASF_CONTROL_TSC_EN (1L<<1)
+ #define BNX2_MISC_SM_ASF_CONTROL_WG_TO (1L<<2)
+ #define BNX2_MISC_SM_ASF_CONTROL_HB_TO (1L<<3)
+ #define BNX2_MISC_SM_ASF_CONTROL_PA_TO (1L<<4)
+ #define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5)
+ #define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6)
+ #define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7)
+ #define BNX2_MISC_SM_ASF_CONTROL_STRETCH_EN (1L<<8)
+ #define BNX2_MISC_SM_ASF_CONTROL_STRETCH_PULSE (1L<<9)
+ #define BNX2_MISC_SM_ASF_CONTROL_RES (0x3L<<10)
+ #define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12)
+ #define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13)
+ #define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14)
+ #define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15)
+ #define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x7fL<<16)
+ #define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x7fL<<23)
+ #define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30)
+ #define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31)
+
+ #define BNX2_MISC_SMB_IN 0x00000884
+ #define BNX2_MISC_SMB_IN_DAT_IN (0xffL<<0)
+ #define BNX2_MISC_SMB_IN_RDY (1L<<8)
+ #define BNX2_MISC_SMB_IN_DONE (1L<<9)
+ #define BNX2_MISC_SMB_IN_FIRSTBYTE (1L<<10)
+ #define BNX2_MISC_SMB_IN_STATUS (0x7L<<11)
+ #define BNX2_MISC_SMB_IN_STATUS_OK (0x0L<<11)
+ #define BNX2_MISC_SMB_IN_STATUS_PEC (0x1L<<11)
+ #define BNX2_MISC_SMB_IN_STATUS_OFLOW (0x2L<<11)
+ #define BNX2_MISC_SMB_IN_STATUS_STOP (0x3L<<11)
+ #define BNX2_MISC_SMB_IN_STATUS_TIMEOUT (0x4L<<11)
+
+ #define BNX2_MISC_SMB_OUT 0x00000888
+ #define BNX2_MISC_SMB_OUT_DAT_OUT (0xffL<<0)
+ #define BNX2_MISC_SMB_OUT_RDY (1L<<8)
+ #define BNX2_MISC_SMB_OUT_START (1L<<9)
+ #define BNX2_MISC_SMB_OUT_LAST (1L<<10)
+ #define BNX2_MISC_SMB_OUT_ACC_TYPE (1L<<11)
+ #define BNX2_MISC_SMB_OUT_ENB_PEC (1L<<12)
+ #define BNX2_MISC_SMB_OUT_GET_RX_LEN (1L<<13)
+ #define BNX2_MISC_SMB_OUT_SMB_READ_LEN (0x3fL<<14)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (6L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN (1L<<27)
+ #define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN (1L<<28)
+
+ #define BNX2_MISC_SMB_WATCHDOG 0x0000088c
+ #define BNX2_MISC_SMB_WATCHDOG_WATCHDOG (0xffffL<<0)
+
+ #define BNX2_MISC_SMB_HEARTBEAT 0x00000890
+ #define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT (0xffffL<<0)
+
+ #define BNX2_MISC_SMB_POLL_ASF 0x00000894
+ #define BNX2_MISC_SMB_POLL_ASF_POLL_ASF (0xffffL<<0)
+
+ #define BNX2_MISC_SMB_POLL_LEGACY 0x00000898
+ #define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY (0xffffL<<0)
+
+ #define BNX2_MISC_SMB_RETRAN 0x0000089c
+ #define BNX2_MISC_SMB_RETRAN_RETRAN (0xffL<<0)
+
+ #define BNX2_MISC_SMB_TIMESTAMP 0x000008a0
+ #define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP (0xffffffffL<<0)
+
+ #define BNX2_MISC_PERR_ENA0 0x000008a4
+ #define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC (1L<<0)
+ #define BNX2_MISC_PERR_ENA0_COM_MISC_REGF (1L<<1)
+ #define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD (1L<<2)
+ #define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC (1L<<3)
+ #define BNX2_MISC_PERR_ENA0_CP_MISC_REGF (1L<<4)
+ #define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD (1L<<5)
+ #define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM (1L<<6)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0 (1L<<7)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1 (1L<<8)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2 (1L<<9)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3 (1L<<10)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4 (1L<<11)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5 (1L<<12)
+ #define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL (1L<<13)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0 (1L<<14)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1 (1L<<15)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2 (1L<<16)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3 (1L<<17)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4 (1L<<18)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0 (1L<<19)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1 (1L<<20)
+ #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2 (1L<<21)
+ #define BNX2_MISC_PERR_ENA0_HC_MISC_DMA (1L<<22)
+ #define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF (1L<<23)
+ #define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD (1L<<24)
+ #define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX (1L<<25)
+ #define BNX2_MISC_PERR_ENA0_RBDC_MISC (1L<<26)
+ #define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB (1L<<27)
+ #define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR (1L<<28)
+ #define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29)
+ #define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30)
+ #define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31)
+ #define BNX2_MISC_PERR_ENA0_COM_DMAE_PERR_EN_XI (1L<<0)
+ #define BNX2_MISC_PERR_ENA0_CP_DMAE_PERR_EN_XI (1L<<1)
+ #define BNX2_MISC_PERR_ENA0_RPM_ACPIBEMEM_PERR_EN_XI (1L<<2)
+ #define BNX2_MISC_PERR_ENA0_CTX_USAGE_CNT_PERR_EN_XI (1L<<3)
+ #define BNX2_MISC_PERR_ENA0_CTX_PGTBL_PERR_EN_XI (1L<<4)
+ #define BNX2_MISC_PERR_ENA0_CTX_CACHE_PERR_EN_XI (1L<<5)
+ #define BNX2_MISC_PERR_ENA0_CTX_MIRROR_PERR_EN_XI (1L<<6)
+ #define BNX2_MISC_PERR_ENA0_COM_CTXC_PERR_EN_XI (1L<<7)
+ #define BNX2_MISC_PERR_ENA0_COM_SCPAD_PERR_EN_XI (1L<<8)
+ #define BNX2_MISC_PERR_ENA0_CP_CTXC_PERR_EN_XI (1L<<9)
+ #define BNX2_MISC_PERR_ENA0_CP_SCPAD_PERR_EN_XI (1L<<10)
+ #define BNX2_MISC_PERR_ENA0_RXP_RBUFC_PERR_EN_XI (1L<<11)
+ #define BNX2_MISC_PERR_ENA0_RXP_CTXC_PERR_EN_XI (1L<<12)
+ #define BNX2_MISC_PERR_ENA0_RXP_SCPAD_PERR_EN_XI (1L<<13)
+ #define BNX2_MISC_PERR_ENA0_TPAT_SCPAD_PERR_EN_XI (1L<<14)
+ #define BNX2_MISC_PERR_ENA0_TXP_CTXC_PERR_EN_XI (1L<<15)
+ #define BNX2_MISC_PERR_ENA0_TXP_SCPAD_PERR_EN_XI (1L<<16)
+ #define BNX2_MISC_PERR_ENA0_CS_TMEM_PERR_EN_XI (1L<<17)
+ #define BNX2_MISC_PERR_ENA0_MQ_CTX_PERR_EN_XI (1L<<18)
+ #define BNX2_MISC_PERR_ENA0_RPM_DFIFOMEM_PERR_EN_XI (1L<<19)
+ #define BNX2_MISC_PERR_ENA0_RPC_DFIFOMEM_PERR_EN_XI (1L<<20)
+ #define BNX2_MISC_PERR_ENA0_RBUF_PTRMEM_PERR_EN_XI (1L<<21)
+ #define BNX2_MISC_PERR_ENA0_RBUF_DATAMEM_PERR_EN_XI (1L<<22)
+ #define BNX2_MISC_PERR_ENA0_RV2P_P2IRAM_PERR_EN_XI (1L<<23)
+ #define BNX2_MISC_PERR_ENA0_RV2P_P1IRAM_PERR_EN_XI (1L<<24)
+ #define BNX2_MISC_PERR_ENA0_RV2P_CB1REGS_PERR_EN_XI (1L<<25)
+ #define BNX2_MISC_PERR_ENA0_RV2P_CB0REGS_PERR_EN_XI (1L<<26)
+ #define BNX2_MISC_PERR_ENA0_TPBUF_PERR_EN_XI (1L<<27)
+ #define BNX2_MISC_PERR_ENA0_THBUF_PERR_EN_XI (1L<<28)
+ #define BNX2_MISC_PERR_ENA0_TDMA_PERR_EN_XI (1L<<29)
+ #define BNX2_MISC_PERR_ENA0_TBDC_PERR_EN_XI (1L<<30)
+ #define BNX2_MISC_PERR_ENA0_TSCH_LR_PERR_EN_XI (1L<<31)
+
+ #define BNX2_MISC_PERR_ENA1 0x000008a8
+ #define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0)
+ #define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM (1L<<1)
+ #define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM (1L<<2)
+ #define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC (1L<<3)
+ #define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF (1L<<4)
+ #define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD (1L<<5)
+ #define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC (1L<<6)
+ #define BNX2_MISC_PERR_ENA1_TBDC_MISC (1L<<7)
+ #define BNX2_MISC_PERR_ENA1_TDMA_MISC (1L<<8)
+ #define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0 (1L<<9)
+ #define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1 (1L<<10)
+ #define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF (1L<<11)
+ #define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD (1L<<12)
+ #define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB (1L<<13)
+ #define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR (1L<<14)
+ #define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC (1L<<15)
+ #define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF (1L<<16)
+ #define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD (1L<<17)
+ #define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX (1L<<18)
+ #define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX (1L<<19)
+ #define BNX2_MISC_PERR_ENA1_UMP_MISC_RX (1L<<20)
+ #define BNX2_MISC_PERR_ENA1_UMP_MISC_TX (1L<<21)
+ #define BNX2_MISC_PERR_ENA1_RDMAQ_MISC (1L<<22)
+ #define BNX2_MISC_PERR_ENA1_CSQ_MISC (1L<<23)
+ #define BNX2_MISC_PERR_ENA1_CPQ_MISC (1L<<24)
+ #define BNX2_MISC_PERR_ENA1_MCPQ_MISC (1L<<25)
+ #define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC (1L<<26)
+ #define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC (1L<<27)
+ #define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC (1L<<28)
+ #define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29)
+ #define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30)
+ #define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31)
+ #define BNX2_MISC_PERR_ENA1_RBDC_PERR_EN_XI (1L<<0)
+ #define BNX2_MISC_PERR_ENA1_RDMA_DFIFO_PERR_EN_XI (1L<<2)
+ #define BNX2_MISC_PERR_ENA1_HC_STATS_PERR_EN_XI (1L<<3)
+ #define BNX2_MISC_PERR_ENA1_HC_MSIX_PERR_EN_XI (1L<<4)
+ #define BNX2_MISC_PERR_ENA1_HC_PRODUCSTB_PERR_EN_XI (1L<<5)
+ #define BNX2_MISC_PERR_ENA1_HC_CONSUMSTB_PERR_EN_XI (1L<<6)
+ #define BNX2_MISC_PERR_ENA1_TPATQ_PERR_EN_XI (1L<<7)
+ #define BNX2_MISC_PERR_ENA1_MCPQ_PERR_EN_XI (1L<<8)
+ #define BNX2_MISC_PERR_ENA1_TDMAQ_PERR_EN_XI (1L<<9)
+ #define BNX2_MISC_PERR_ENA1_TXPQ_PERR_EN_XI (1L<<10)
+ #define BNX2_MISC_PERR_ENA1_COMTQ_PERR_EN_XI (1L<<11)
+ #define BNX2_MISC_PERR_ENA1_COMQ_PERR_EN_XI (1L<<12)
+ #define BNX2_MISC_PERR_ENA1_RLUPQ_PERR_EN_XI (1L<<13)
+ #define BNX2_MISC_PERR_ENA1_RXPQ_PERR_EN_XI (1L<<14)
+ #define BNX2_MISC_PERR_ENA1_RV2PPQ_PERR_EN_XI (1L<<15)
+ #define BNX2_MISC_PERR_ENA1_RDMAQ_PERR_EN_XI (1L<<16)
+ #define BNX2_MISC_PERR_ENA1_TASQ_PERR_EN_XI (1L<<17)
+ #define BNX2_MISC_PERR_ENA1_TBDRQ_PERR_EN_XI (1L<<18)
+ #define BNX2_MISC_PERR_ENA1_TSCHQ_PERR_EN_XI (1L<<19)
+ #define BNX2_MISC_PERR_ENA1_COMXQ_PERR_EN_XI (1L<<20)
+ #define BNX2_MISC_PERR_ENA1_RXPCQ_PERR_EN_XI (1L<<21)
+ #define BNX2_MISC_PERR_ENA1_RV2PTQ_PERR_EN_XI (1L<<22)
+ #define BNX2_MISC_PERR_ENA1_RV2PMQ_PERR_EN_XI (1L<<23)
+ #define BNX2_MISC_PERR_ENA1_CPQ_PERR_EN_XI (1L<<24)
+ #define BNX2_MISC_PERR_ENA1_CSQ_PERR_EN_XI (1L<<25)
+ #define BNX2_MISC_PERR_ENA1_RLUP_CID_PERR_EN_XI (1L<<26)
+ #define BNX2_MISC_PERR_ENA1_RV2PCS_TMEM_PERR_EN_XI (1L<<27)
+ #define BNX2_MISC_PERR_ENA1_RV2PCSQ_PERR_EN_XI (1L<<28)
+ #define BNX2_MISC_PERR_ENA1_MQ_IDX_PERR_EN_XI (1L<<29)
+
+ #define BNX2_MISC_PERR_ENA2 0x000008ac
+ #define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0)
+ #define BNX2_MISC_PERR_ENA2_COMXQ_MISC (1L<<1)
+ #define BNX2_MISC_PERR_ENA2_COMTQ_MISC (1L<<2)
+ #define BNX2_MISC_PERR_ENA2_TSCHQ_MISC (1L<<3)
+ #define BNX2_MISC_PERR_ENA2_TBDRQ_MISC (1L<<4)
+ #define BNX2_MISC_PERR_ENA2_TXPQ_MISC (1L<<5)
+ #define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6)
+ #define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7)
+ #define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8)
+ #define BNX2_MISC_PERR_ENA2_TGT_FIFO_PERR_EN_XI (1L<<0)
+ #define BNX2_MISC_PERR_ENA2_UMP_TX_PERR_EN_XI (1L<<1)
+ #define BNX2_MISC_PERR_ENA2_UMP_RX_PERR_EN_XI (1L<<2)
+ #define BNX2_MISC_PERR_ENA2_MCP_ROM_PERR_EN_XI (1L<<3)
+ #define BNX2_MISC_PERR_ENA2_MCP_SCPAD_PERR_EN_XI (1L<<4)
+ #define BNX2_MISC_PERR_ENA2_HB_MEM_PERR_EN_XI (1L<<5)
+ #define BNX2_MISC_PERR_ENA2_PCIE_REPLAY_PERR_EN_XI (1L<<6)
+
+ #define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0
+ #define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0)
+ #define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12)
+ #define BNX2_MISC_DEBUG_VECTOR_SEL_1_XI (0xfffL<<15)
+
+ #define BNX2_MISC_VREG_CONTROL 0x000008b4
+ #define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_XI (0xfL<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS14_XI (0L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS12_XI (1L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS10_XI (2L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS8_XI (3L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS6_XI (4L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS4_XI (5L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS2_XI (6L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_NOM_XI (7L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS2_XI (8L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS4_XI (9L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS6_XI (10L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS8_XI (11L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS10_XI (12L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS12_XI (13L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS14_XI (14L<<0)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS16_XI (15L<<0)
+ #define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS14 (0L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS12 (1L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS10 (2L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS8 (3L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS6 (4L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS4 (5L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_PLUS2 (6L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_NOM (7L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS2 (8L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS4 (9L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS6 (10L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS8 (11L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS10 (12L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS12 (13L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS14 (14L<<4)
+ #define BNX2_MISC_VREG_CONTROL_2_5_MINUS16 (15L<<4)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT (0xfL<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS14 (0L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS12 (1L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS10 (2L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS8 (3L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS6 (4L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS4 (5L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS2 (6L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_NOM (7L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS2 (8L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS4 (9L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS6 (10L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS8 (11L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS10 (12L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS12 (13L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS14 (14L<<8)
+ #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS16 (15L<<8)
+
+ #define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8
+ #define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6)
+
+ #define BNX2_MISC_GP_HW_CTL0 0x000008bc
+ #define BNX2_MISC_GP_HW_CTL0_TX_DRIVE (1L<<0)
+ #define BNX2_MISC_GP_HW_CTL0_RMII_MODE (1L<<1)
+ #define BNX2_MISC_GP_HW_CTL0_RMII_CRSDV_SEL (1L<<2)
+ #define BNX2_MISC_GP_HW_CTL0_RVMII_MODE (1L<<3)
+ #define BNX2_MISC_GP_HW_CTL0_FLASH_SAMP_SCLK_NEGEDGE_TE (1L<<4)
+ #define BNX2_MISC_GP_HW_CTL0_HIDDEN_REVISION_ID_TE (1L<<5)
+ #define BNX2_MISC_GP_HW_CTL0_HC_CNTL_TMOUT_CTR_RST_TE (1L<<6)
+ #define BNX2_MISC_GP_HW_CTL0_RESERVED1_XI (0x7L<<4)
+ #define BNX2_MISC_GP_HW_CTL0_ENA_CORE_RST_ON_MAIN_PWR_GOING_AWAY (1L<<7)
+ #define BNX2_MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE (1L<<8)
+ #define BNX2_MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE (1L<<9)
+ #define BNX2_MISC_GP_HW_CTL0_LED_ACT_SEL_TE (1L<<10)
+ #define BNX2_MISC_GP_HW_CTL0_RESERVED2_XI (0x7L<<8)
+ #define BNX2_MISC_GP_HW_CTL0_UP1_DEF0 (1L<<11)
+ #define BNX2_MISC_GP_HW_CTL0_FIBER_MODE_DIS_DEF (1L<<12)
+ #define BNX2_MISC_GP_HW_CTL0_FORCE2500_DEF (1L<<13)
+ #define BNX2_MISC_GP_HW_CTL0_AUTODETECT_DIS_DEF (1L<<14)
+ #define BNX2_MISC_GP_HW_CTL0_PARALLEL_DETECT_DEF (1L<<15)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI (0xfL<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_3MA (0L<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P5MA (1L<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P0MA (3L<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P5MA (5L<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P0MA (7L<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_PWRDN (15L<<16)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE2DIS (1L<<20)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE1DIS (1L<<21)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT (0x3L<<22)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M6P (0L<<22)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M0P (1L<<22)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P0P (2L<<22)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P6P (3L<<22)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT (0x3L<<24)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M6P (0L<<24)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M0P (1L<<24)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P0P (2L<<24)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P6P (3L<<24)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ (0x3L<<26)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_240UA (0L<<26)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_160UA (1L<<26)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_400UA (2L<<26)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_320UA (3L<<26)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ (0x3L<<28)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_240UA (0L<<28)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_160UA (1L<<28)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_400UA (2L<<28)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_320UA (3L<<28)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ (0x3L<<30)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P57 (0L<<30)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P45 (1L<<30)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P62 (2L<<30)
+ #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P66 (3L<<30)
+
+ #define BNX2_MISC_GP_HW_CTL1 0x000008c0
+ #define BNX2_MISC_GP_HW_CTL1_1_ATTN_BTN_PRSNT_TE (1L<<0)
+ #define BNX2_MISC_GP_HW_CTL1_1_ATTN_IND_PRSNT_TE (1L<<1)
+ #define BNX2_MISC_GP_HW_CTL1_1_PWR_IND_PRSNT_TE (1L<<2)
+ #define BNX2_MISC_GP_HW_CTL1_0_PCIE_LOOPBACK_TE (1L<<3)
+ #define BNX2_MISC_GP_HW_CTL1_RESERVED_SOFT_XI (0xffffL<<0)
+ #define BNX2_MISC_GP_HW_CTL1_RESERVED_HARD_XI (0xffffL<<16)
+
+ #define BNX2_MISC_NEW_HW_CTL 0x000008c4
+ #define BNX2_MISC_NEW_HW_CTL_MAIN_POR_BYPASS (1L<<0)
+ #define BNX2_MISC_NEW_HW_CTL_RINGOSC_ENABLE (1L<<1)
+ #define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL0 (1L<<2)
+ #define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL1 (1L<<3)
+ #define BNX2_MISC_NEW_HW_CTL_RESERVED_SHARED (0xfffL<<4)
+ #define BNX2_MISC_NEW_HW_CTL_RESERVED_SPLIT (0xffffL<<16)
+
+ #define BNX2_MISC_NEW_CORE_CTL 0x000008c8
+ #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0)
+ #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1)
+ #define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE (1L<<16)
+ #define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2)
+ #define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16)
+
+ #define BNX2_MISC_ECO_HW_CTL 0x000008cc
+ #define BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN (1L<<0)
+ #define BNX2_MISC_ECO_HW_CTL_RESERVED_SOFT (0x7fffL<<1)
+ #define BNX2_MISC_ECO_HW_CTL_RESERVED_HARD (0xffffL<<16)
+
+ #define BNX2_MISC_ECO_CORE_CTL 0x000008d0
+ #define BNX2_MISC_ECO_CORE_CTL_RESERVED_SOFT (0xffffL<<0)
+ #define BNX2_MISC_ECO_CORE_CTL_RESERVED_HARD (0xffffL<<16)
+
+ #define BNX2_MISC_PPIO 0x000008d4
+ #define BNX2_MISC_PPIO_VALUE (0xfL<<0)
+ #define BNX2_MISC_PPIO_SET (0xfL<<8)
+ #define BNX2_MISC_PPIO_CLR (0xfL<<16)
+ #define BNX2_MISC_PPIO_FLOAT (0xfL<<24)
+
+ #define BNX2_MISC_PPIO_INT 0x000008d8
+ #define BNX2_MISC_PPIO_INT_INT_STATE (0xfL<<0)
+ #define BNX2_MISC_PPIO_INT_OLD_VALUE (0xfL<<8)
+ #define BNX2_MISC_PPIO_INT_OLD_SET (0xfL<<16)
+ #define BNX2_MISC_PPIO_INT_OLD_CLR (0xfL<<24)
+
+ #define BNX2_MISC_RESET_NUMS 0x000008dc
+ #define BNX2_MISC_RESET_NUMS_NUM_HARD_RESETS (0x7L<<0)
+ #define BNX2_MISC_RESET_NUMS_NUM_PCIE_RESETS (0x7L<<4)
+ #define BNX2_MISC_RESET_NUMS_NUM_PERSTB_RESETS (0x7L<<8)
+ #define BNX2_MISC_RESET_NUMS_NUM_CMN_RESETS (0x7L<<12)
+ #define BNX2_MISC_RESET_NUMS_NUM_PORT_RESETS (0x7L<<16)
+
+ #define BNX2_MISC_CS16_ERR 0x000008e0
+ #define BNX2_MISC_CS16_ERR_ENA_PCI (1L<<0)
+ #define BNX2_MISC_CS16_ERR_ENA_RDMA (1L<<1)
+ #define BNX2_MISC_CS16_ERR_ENA_TDMA (1L<<2)
+ #define BNX2_MISC_CS16_ERR_ENA_EMAC (1L<<3)
+ #define BNX2_MISC_CS16_ERR_ENA_CTX (1L<<4)
+ #define BNX2_MISC_CS16_ERR_ENA_TBDR (1L<<5)
+ #define BNX2_MISC_CS16_ERR_ENA_RBDC (1L<<6)
+ #define BNX2_MISC_CS16_ERR_ENA_COM (1L<<7)
+ #define BNX2_MISC_CS16_ERR_ENA_CP (1L<<8)
+ #define BNX2_MISC_CS16_ERR_STA_PCI (1L<<16)
+ #define BNX2_MISC_CS16_ERR_STA_RDMA (1L<<17)
+ #define BNX2_MISC_CS16_ERR_STA_TDMA (1L<<18)
+ #define BNX2_MISC_CS16_ERR_STA_EMAC (1L<<19)
+ #define BNX2_MISC_CS16_ERR_STA_CTX (1L<<20)
+ #define BNX2_MISC_CS16_ERR_STA_TBDR (1L<<21)
+ #define BNX2_MISC_CS16_ERR_STA_RBDC (1L<<22)
+ #define BNX2_MISC_CS16_ERR_STA_COM (1L<<23)
+ #define BNX2_MISC_CS16_ERR_STA_CP (1L<<24)
+
+ #define BNX2_MISC_SPIO_EVENT 0x000008e4
+ #define BNX2_MISC_SPIO_EVENT_ENABLE (0xffL<<0)
+
+ #define BNX2_MISC_PPIO_EVENT 0x000008e8
+ #define BNX2_MISC_PPIO_EVENT_ENABLE (0xfL<<0)
+
+ #define BNX2_MISC_DUAL_MEDIA_CTRL 0x000008ec
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID (0xffL<<0)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_X (0L<<0)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C (3L<<0)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S (12L<<0)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP (0x7L<<8)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN (1L<<11)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_SIGDET (1L<<12)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_SIGDET (1L<<13)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_SIGDET (1L<<14)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_SIGDET (1L<<15)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_LCPLL_RST (1L<<16)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_RST (1L<<17)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_RST (1L<<18)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_RST (1L<<19)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_RST (1L<<20)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL (0x7L<<21)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP (1L<<24)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE (1L<<25)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ (0xfL<<26)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER1_IDDQ (1L<<26)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER0_IDDQ (2L<<26)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY1_IDDQ (4L<<26)
+ #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY0_IDDQ (8L<<26)
+
+ #define BNX2_MISC_OTP_CMD1 0x000008f0
+ #define BNX2_MISC_OTP_CMD1_FMODE (0x7L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_IDLE (0L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_WRITE (1L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_INIT (2L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_SET (3L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_RST (4L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_VERIFY (5L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_RESERVED0 (6L<<0)
+ #define BNX2_MISC_OTP_CMD1_FMODE_RESERVED1 (7L<<0)
+ #define BNX2_MISC_OTP_CMD1_USEPINS (1L<<8)
+ #define BNX2_MISC_OTP_CMD1_PROGSEL (1L<<9)
+ #define BNX2_MISC_OTP_CMD1_PROGSTART (1L<<10)
+ #define BNX2_MISC_OTP_CMD1_PCOUNT (0x7L<<16)
+ #define BNX2_MISC_OTP_CMD1_PBYP (1L<<19)
+ #define BNX2_MISC_OTP_CMD1_VSEL (0xfL<<20)
+ #define BNX2_MISC_OTP_CMD1_TM (0x7L<<27)
+ #define BNX2_MISC_OTP_CMD1_SADBYP (1L<<30)
+ #define BNX2_MISC_OTP_CMD1_DEBUG (1L<<31)
+
+ #define BNX2_MISC_OTP_CMD2 0x000008f4
+ #define BNX2_MISC_OTP_CMD2_OTP_ROM_ADDR (0x3ffL<<0)
+ #define BNX2_MISC_OTP_CMD2_DOSEL (0x7fL<<16)
+ #define BNX2_MISC_OTP_CMD2_DOSEL_0 (0L<<16)
+ #define BNX2_MISC_OTP_CMD2_DOSEL_1 (1L<<16)
+ #define BNX2_MISC_OTP_CMD2_DOSEL_127 (127L<<16)
+
+ #define BNX2_MISC_OTP_STATUS 0x000008f8
+ #define BNX2_MISC_OTP_STATUS_DATA (0xffL<<0)
+ #define BNX2_MISC_OTP_STATUS_VALID (1L<<8)
+ #define BNX2_MISC_OTP_STATUS_BUSY (1L<<9)
+ #define BNX2_MISC_OTP_STATUS_BUSYSM (1L<<10)
+ #define BNX2_MISC_OTP_STATUS_DONE (1L<<11)
+
+ #define BNX2_MISC_OTP_SHIFT1_CMD 0x000008fc
+ #define BNX2_MISC_OTP_SHIFT1_CMD_RESET_MODE_N (1L<<0)
+ #define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_DONE (1L<<1)
+ #define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_START (1L<<2)
+ #define BNX2_MISC_OTP_SHIFT1_CMD_LOAD_DATA (1L<<3)
+ #define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_SELECT (0x1fL<<8)
+
+ #define BNX2_MISC_OTP_SHIFT1_DATA 0x00000900
+ #define BNX2_MISC_OTP_SHIFT2_CMD 0x00000904
+ #define BNX2_MISC_OTP_SHIFT2_CMD_RESET_MODE_N (1L<<0)
+ #define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_DONE (1L<<1)
+ #define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_START (1L<<2)
+ #define BNX2_MISC_OTP_SHIFT2_CMD_LOAD_DATA (1L<<3)
+ #define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_SELECT (0x1fL<<8)
+
+ #define BNX2_MISC_OTP_SHIFT2_DATA 0x00000908
+ #define BNX2_MISC_BIST_CS0 0x0000090c
+ #define BNX2_MISC_BIST_CS0_MBIST_EN (1L<<0)
+ #define BNX2_MISC_BIST_CS0_BIST_SETUP (0x3L<<1)
+ #define BNX2_MISC_BIST_CS0_MBIST_ASYNC_RESET (1L<<3)
+ #define BNX2_MISC_BIST_CS0_MBIST_DONE (1L<<8)
+ #define BNX2_MISC_BIST_CS0_MBIST_GO (1L<<9)
+ #define BNX2_MISC_BIST_CS0_BIST_OVERRIDE (1L<<31)
+
+ #define BNX2_MISC_BIST_MEMSTATUS0 0x00000910
+ #define BNX2_MISC_BIST_CS1 0x00000914
+ #define BNX2_MISC_BIST_CS1_MBIST_EN (1L<<0)
+ #define BNX2_MISC_BIST_CS1_BIST_SETUP (0x3L<<1)
+ #define BNX2_MISC_BIST_CS1_MBIST_ASYNC_RESET (1L<<3)
+ #define BNX2_MISC_BIST_CS1_MBIST_DONE (1L<<8)
+ #define BNX2_MISC_BIST_CS1_MBIST_GO (1L<<9)
+
+ #define BNX2_MISC_BIST_MEMSTATUS1 0x00000918
+ #define BNX2_MISC_BIST_CS2 0x0000091c
+ #define BNX2_MISC_BIST_CS2_MBIST_EN (1L<<0)
+ #define BNX2_MISC_BIST_CS2_BIST_SETUP (0x3L<<1)
+ #define BNX2_MISC_BIST_CS2_MBIST_ASYNC_RESET (1L<<3)
+ #define BNX2_MISC_BIST_CS2_MBIST_DONE (1L<<8)
+ #define BNX2_MISC_BIST_CS2_MBIST_GO (1L<<9)
+
+ #define BNX2_MISC_BIST_MEMSTATUS2 0x00000920
+ #define BNX2_MISC_BIST_CS3 0x00000924
+ #define BNX2_MISC_BIST_CS3_MBIST_EN (1L<<0)
+ #define BNX2_MISC_BIST_CS3_BIST_SETUP (0x3L<<1)
+ #define BNX2_MISC_BIST_CS3_MBIST_ASYNC_RESET (1L<<3)
+ #define BNX2_MISC_BIST_CS3_MBIST_DONE (1L<<8)
+ #define BNX2_MISC_BIST_CS3_MBIST_GO (1L<<9)
+
+ #define BNX2_MISC_BIST_MEMSTATUS3 0x00000928
+ #define BNX2_MISC_BIST_CS4 0x0000092c
+ #define BNX2_MISC_BIST_CS4_MBIST_EN (1L<<0)
+ #define BNX2_MISC_BIST_CS4_BIST_SETUP (0x3L<<1)
+ #define BNX2_MISC_BIST_CS4_MBIST_ASYNC_RESET (1L<<3)
+ #define BNX2_MISC_BIST_CS4_MBIST_DONE (1L<<8)
+ #define BNX2_MISC_BIST_CS4_MBIST_GO (1L<<9)
+
+ #define BNX2_MISC_BIST_MEMSTATUS4 0x00000930
+ #define BNX2_MISC_BIST_CS5 0x00000934
+ #define BNX2_MISC_BIST_CS5_MBIST_EN (1L<<0)
+ #define BNX2_MISC_BIST_CS5_BIST_SETUP (0x3L<<1)
+ #define BNX2_MISC_BIST_CS5_MBIST_ASYNC_RESET (1L<<3)
+ #define BNX2_MISC_BIST_CS5_MBIST_DONE (1L<<8)
+ #define BNX2_MISC_BIST_CS5_MBIST_GO (1L<<9)
+
+ #define BNX2_MISC_BIST_MEMSTATUS5 0x00000938
+ #define BNX2_MISC_MEM_TM0 0x0000093c
+ #define BNX2_MISC_MEM_TM0_PCIE_REPLAY_TM (0xfL<<0)
+ #define BNX2_MISC_MEM_TM0_MCP_SCPAD (0xfL<<8)
+ #define BNX2_MISC_MEM_TM0_UMP_TM (0xffL<<16)
+ #define BNX2_MISC_MEM_TM0_HB_MEM_TM (0xfL<<24)
+
+ #define BNX2_MISC_USPLL_CTRL 0x00000940
+ #define BNX2_MISC_USPLL_CTRL_PH_DET_DIS (1L<<0)
+ #define BNX2_MISC_USPLL_CTRL_FREQ_DET_DIS (1L<<1)
+ #define BNX2_MISC_USPLL_CTRL_LCPX (0x3fL<<2)
+ #define BNX2_MISC_USPLL_CTRL_RX (0x3L<<8)
+ #define BNX2_MISC_USPLL_CTRL_VC_EN (1L<<10)
+ #define BNX2_MISC_USPLL_CTRL_VCO_MG (0x3L<<11)
+ #define BNX2_MISC_USPLL_CTRL_KVCO_XF (0x7L<<13)
+ #define BNX2_MISC_USPLL_CTRL_KVCO_XS (0x7L<<16)
+ #define BNX2_MISC_USPLL_CTRL_TESTD_EN (1L<<19)
+ #define BNX2_MISC_USPLL_CTRL_TESTD_SEL (0x7L<<20)
+ #define BNX2_MISC_USPLL_CTRL_TESTA_EN (1L<<23)
+ #define BNX2_MISC_USPLL_CTRL_TESTA_SEL (0x3L<<24)
+ #define BNX2_MISC_USPLL_CTRL_ATTEN_FREF (1L<<26)
+ #define BNX2_MISC_USPLL_CTRL_DIGITAL_RST (1L<<27)
+ #define BNX2_MISC_USPLL_CTRL_ANALOG_RST (1L<<28)
+ #define BNX2_MISC_USPLL_CTRL_LOCK (1L<<29)
+
+ #define BNX2_MISC_PERR_STATUS0 0x00000944
+ #define BNX2_MISC_PERR_STATUS0_COM_DMAE_PERR (1L<<0)
+ #define BNX2_MISC_PERR_STATUS0_CP_DMAE_PERR (1L<<1)
+ #define BNX2_MISC_PERR_STATUS0_RPM_ACPIBEMEM_PERR (1L<<2)
+ #define BNX2_MISC_PERR_STATUS0_CTX_USAGE_CNT_PERR (1L<<3)
+ #define BNX2_MISC_PERR_STATUS0_CTX_PGTBL_PERR (1L<<4)
+ #define BNX2_MISC_PERR_STATUS0_CTX_CACHE_PERR (1L<<5)
+ #define BNX2_MISC_PERR_STATUS0_CTX_MIRROR_PERR (1L<<6)
+ #define BNX2_MISC_PERR_STATUS0_COM_CTXC_PERR (1L<<7)
+ #define BNX2_MISC_PERR_STATUS0_COM_SCPAD_PERR (1L<<8)
+ #define BNX2_MISC_PERR_STATUS0_CP_CTXC_PERR (1L<<9)
+ #define BNX2_MISC_PERR_STATUS0_CP_SCPAD_PERR (1L<<10)
+ #define BNX2_MISC_PERR_STATUS0_RXP_RBUFC_PERR (1L<<11)
+ #define BNX2_MISC_PERR_STATUS0_RXP_CTXC_PERR (1L<<12)
+ #define BNX2_MISC_PERR_STATUS0_RXP_SCPAD_PERR (1L<<13)
+ #define BNX2_MISC_PERR_STATUS0_TPAT_SCPAD_PERR (1L<<14)
+ #define BNX2_MISC_PERR_STATUS0_TXP_CTXC_PERR (1L<<15)
+ #define BNX2_MISC_PERR_STATUS0_TXP_SCPAD_PERR (1L<<16)
+ #define BNX2_MISC_PERR_STATUS0_CS_TMEM_PERR (1L<<17)
+ #define BNX2_MISC_PERR_STATUS0_MQ_CTX_PERR (1L<<18)
+ #define BNX2_MISC_PERR_STATUS0_RPM_DFIFOMEM_PERR (1L<<19)
+ #define BNX2_MISC_PERR_STATUS0_RPC_DFIFOMEM_PERR (1L<<20)
+ #define BNX2_MISC_PERR_STATUS0_RBUF_PTRMEM_PERR (1L<<21)
+ #define BNX2_MISC_PERR_STATUS0_RBUF_DATAMEM_PERR (1L<<22)
+ #define BNX2_MISC_PERR_STATUS0_RV2P_P2IRAM_PERR (1L<<23)
+ #define BNX2_MISC_PERR_STATUS0_RV2P_P1IRAM_PERR (1L<<24)
+ #define BNX2_MISC_PERR_STATUS0_RV2P_CB1REGS_PERR (1L<<25)
+ #define BNX2_MISC_PERR_STATUS0_RV2P_CB0REGS_PERR (1L<<26)
+ #define BNX2_MISC_PERR_STATUS0_TPBUF_PERR (1L<<27)
+ #define BNX2_MISC_PERR_STATUS0_THBUF_PERR (1L<<28)
+ #define BNX2_MISC_PERR_STATUS0_TDMA_PERR (1L<<29)
+ #define BNX2_MISC_PERR_STATUS0_TBDC_PERR (1L<<30)
+ #define BNX2_MISC_PERR_STATUS0_TSCH_LR_PERR (1L<<31)
+
+ #define BNX2_MISC_PERR_STATUS1 0x00000948
+ #define BNX2_MISC_PERR_STATUS1_RBDC_PERR (1L<<0)
+ #define BNX2_MISC_PERR_STATUS1_RDMA_DFIFO_PERR (1L<<2)
+ #define BNX2_MISC_PERR_STATUS1_HC_STATS_PERR (1L<<3)
+ #define BNX2_MISC_PERR_STATUS1_HC_MSIX_PERR (1L<<4)
+ #define BNX2_MISC_PERR_STATUS1_HC_PRODUCSTB_PERR (1L<<5)
+ #define BNX2_MISC_PERR_STATUS1_HC_CONSUMSTB_PERR (1L<<6)
+ #define BNX2_MISC_PERR_STATUS1_TPATQ_PERR (1L<<7)
+ #define BNX2_MISC_PERR_STATUS1_MCPQ_PERR (1L<<8)
+ #define BNX2_MISC_PERR_STATUS1_TDMAQ_PERR (1L<<9)
+ #define BNX2_MISC_PERR_STATUS1_TXPQ_PERR (1L<<10)
+ #define BNX2_MISC_PERR_STATUS1_COMTQ_PERR (1L<<11)
+ #define BNX2_MISC_PERR_STATUS1_COMQ_PERR (1L<<12)
+ #define BNX2_MISC_PERR_STATUS1_RLUPQ_PERR (1L<<13)
+ #define BNX2_MISC_PERR_STATUS1_RXPQ_PERR (1L<<14)
+ #define BNX2_MISC_PERR_STATUS1_RV2PPQ_PERR (1L<<15)
+ #define BNX2_MISC_PERR_STATUS1_RDMAQ_PERR (1L<<16)
+ #define BNX2_MISC_PERR_STATUS1_TASQ_PERR (1L<<17)
+ #define BNX2_MISC_PERR_STATUS1_TBDRQ_PERR (1L<<18)
+ #define BNX2_MISC_PERR_STATUS1_TSCHQ_PERR (1L<<19)
+ #define BNX2_MISC_PERR_STATUS1_COMXQ_PERR (1L<<20)
+ #define BNX2_MISC_PERR_STATUS1_RXPCQ_PERR (1L<<21)
+ #define BNX2_MISC_PERR_STATUS1_RV2PTQ_PERR (1L<<22)
+ #define BNX2_MISC_PERR_STATUS1_RV2PMQ_PERR (1L<<23)
+ #define BNX2_MISC_PERR_STATUS1_CPQ_PERR (1L<<24)
+ #define BNX2_MISC_PERR_STATUS1_CSQ_PERR (1L<<25)
+ #define BNX2_MISC_PERR_STATUS1_RLUP_CID_PERR (1L<<26)
+ #define BNX2_MISC_PERR_STATUS1_RV2PCS_TMEM_PERR (1L<<27)
+ #define BNX2_MISC_PERR_STATUS1_RV2PCSQ_PERR (1L<<28)
+ #define BNX2_MISC_PERR_STATUS1_MQ_IDX_PERR (1L<<29)
+
+ #define BNX2_MISC_PERR_STATUS2 0x0000094c
+ #define BNX2_MISC_PERR_STATUS2_TGT_FIFO_PERR (1L<<0)
+ #define BNX2_MISC_PERR_STATUS2_UMP_TX_PERR (1L<<1)
+ #define BNX2_MISC_PERR_STATUS2_UMP_RX_PERR (1L<<2)
+ #define BNX2_MISC_PERR_STATUS2_MCP_ROM_PERR (1L<<3)
+ #define BNX2_MISC_PERR_STATUS2_MCP_SCPAD_PERR (1L<<4)
+ #define BNX2_MISC_PERR_STATUS2_HB_MEM_PERR (1L<<5)
+ #define BNX2_MISC_PERR_STATUS2_PCIE_REPLAY_PERR (1L<<6)
+
+ #define BNX2_MISC_LCPLL_CTRL0 0x00000950
+ #define BNX2_MISC_LCPLL_CTRL0_OAC (0x7L<<0)
+ #define BNX2_MISC_LCPLL_CTRL0_OAC_NEGTWENTY (0L<<0)
+ #define BNX2_MISC_LCPLL_CTRL0_OAC_ZERO (1L<<0)
+ #define BNX2_MISC_LCPLL_CTRL0_OAC_TWENTY (3L<<0)
+ #define BNX2_MISC_LCPLL_CTRL0_OAC_FORTY (7L<<0)
+ #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL (0x7L<<3)
+ #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_360 (0L<<3)
+ #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_480 (1L<<3)
+ #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_600 (3L<<3)
+ #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_720 (7L<<3)
+ #define BNX2_MISC_LCPLL_CTRL0_BIAS_CTRL (0x3L<<6)
+ #define BNX2_MISC_LCPLL_CTRL0_PLL_OBSERVE (0x7L<<8)
+ #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL (0x3L<<11)
+ #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_0 (0L<<11)
+ #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_1 (1L<<11)
+ #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_2 (2L<<11)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLSEQSTART (1L<<13)
+ #define BNX2_MISC_LCPLL_CTRL0_RESERVED (1L<<14)
+ #define BNX2_MISC_LCPLL_CTRL0_CAPRETRY_EN (1L<<15)
+ #define BNX2_MISC_LCPLL_CTRL0_FREQMONITOR_EN (1L<<16)
+ #define BNX2_MISC_LCPLL_CTRL0_FREQDETRESTART_EN (1L<<17)
+ #define BNX2_MISC_LCPLL_CTRL0_FREQDETRETRY_EN (1L<<18)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE_EN (1L<<19)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE (1L<<20)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFPASS (1L<<21)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE_EN (1L<<22)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE (1L<<23)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS_EN (1L<<24)
+ #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS (1L<<25)
+ #define BNX2_MISC_LCPLL_CTRL0_CAPRESTART (1L<<26)
+ #define BNX2_MISC_LCPLL_CTRL0_CAPSELECTM_EN (1L<<27)
+
+ #define BNX2_MISC_LCPLL_CTRL1 0x00000954
+ #define BNX2_MISC_LCPLL_CTRL1_CAPSELECTM (0x1fL<<0)
+ #define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN_EN (1L<<5)
+ #define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN (1L<<6)
+ #define BNX2_MISC_LCPLL_CTRL1_SLOWDN_XOR (1L<<7)
+
+ #define BNX2_MISC_LCPLL_STATUS 0x00000958
+ #define BNX2_MISC_LCPLL_STATUS_FREQDONE_SM (1L<<0)
+ #define BNX2_MISC_LCPLL_STATUS_FREQPASS_SM (1L<<1)
+ #define BNX2_MISC_LCPLL_STATUS_PLLSEQDONE (1L<<2)
+ #define BNX2_MISC_LCPLL_STATUS_PLLSEQPASS (1L<<3)
+ #define BNX2_MISC_LCPLL_STATUS_PLLSTATE (0x7L<<4)
+ #define BNX2_MISC_LCPLL_STATUS_CAPSTATE (0x7L<<7)
+ #define BNX2_MISC_LCPLL_STATUS_CAPSELECT (0x1fL<<10)
+ #define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR (1L<<15)
+ #define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_0 (0L<<15)
+ #define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_1 (1L<<15)
+
+ #define BNX2_MISC_OSCFUNDS_CTRL 0x0000095c
+ #define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON (1L<<5)
+ #define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_OFF (0L<<5)
+ #define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_ON (1L<<5)
+ #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM (0x3L<<6)
+ #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_0 (0L<<6)
+ #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_1 (1L<<6)
+ #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_2 (2L<<6)
+ #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_3 (3L<<6)
+ #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ (0x3L<<8)
+ #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_0 (0L<<8)
+ #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_1 (1L<<8)
+ #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_2 (2L<<8)
+ #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_3 (3L<<8)
+ #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ (0x3L<<10)
+ #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_0 (0L<<10)
+ #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_1 (1L<<10)
+ #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_2 (2L<<10)
+ #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_3 (3L<<10)
+
+
+ /*
+ * nvm_reg definition
+ * offset: 0x6400
+ */
+ #define BNX2_NVM_COMMAND 0x00006400
+ #define BNX2_NVM_COMMAND_RST (1L<<0)
+ #define BNX2_NVM_COMMAND_DONE (1L<<3)
+ #define BNX2_NVM_COMMAND_DOIT (1L<<4)
+ #define BNX2_NVM_COMMAND_WR (1L<<5)
+ #define BNX2_NVM_COMMAND_ERASE (1L<<6)
+ #define BNX2_NVM_COMMAND_FIRST (1L<<7)
+ #define BNX2_NVM_COMMAND_LAST (1L<<8)
+ #define BNX2_NVM_COMMAND_WREN (1L<<16)
+ #define BNX2_NVM_COMMAND_WRDI (1L<<17)
+ #define BNX2_NVM_COMMAND_EWSR (1L<<18)
+ #define BNX2_NVM_COMMAND_WRSR (1L<<19)
+ #define BNX2_NVM_COMMAND_RD_ID (1L<<20)
+ #define BNX2_NVM_COMMAND_RD_STATUS (1L<<21)
+ #define BNX2_NVM_COMMAND_MODE_256 (1L<<22)
+
+ #define BNX2_NVM_STATUS 0x00006404
+ #define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0)
+ #define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4)
+ #define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_XI (0x1fL<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_IDLE_XI (0L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD0_XI (1L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD1_XI (2L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH0_XI (3L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH1_XI (4L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ADDR0_XI (5L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA0_XI (6L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA1_XI (7L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA2_XI (8L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA0_XI (9L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA1_XI (10L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA2_XI (11L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID0_XI (12L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID1_XI (13L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID2_XI (14L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID3_XI (15L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID4_XI (16L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CHECK_BUSY0_XI (17L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ST_WREN_XI (18L<<0)
+ #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WAIT_XI (19L<<0)
+
+ #define BNX2_NVM_WRITE 0x00006408
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG (0L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK (1L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA (2L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK (4L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI_XI (1L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO_XI (2L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B_XI (4L<<0)
+ #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK_XI (8L<<0)
+
+ #define BNX2_NVM_ADDR 0x0000640c
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG (0L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK (1L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA (2L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK (4L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI_XI (1L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO_XI (2L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B_XI (4L<<0)
+ #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK_XI (8L<<0)
+
+ #define BNX2_NVM_READ 0x00006410
+ #define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG (0L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_EECLK (1L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA (2L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_SCLK (4L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_SI_XI (1L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_SO_XI (2L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_CS_B_XI (4L<<0)
+ #define BNX2_NVM_READ_NVM_READ_VALUE_SCLK_XI (8L<<0)
+
+ #define BNX2_NVM_CFG1 0x00006414
+ #define BNX2_NVM_CFG1_FLASH_MODE (1L<<0)
+ #define BNX2_NVM_CFG1_BUFFER_MODE (1L<<1)
+ #define BNX2_NVM_CFG1_PASS_MODE (1L<<2)
+ #define BNX2_NVM_CFG1_BITBANG_MODE (1L<<3)
+ #define BNX2_NVM_CFG1_STATUS_BIT (0x7L<<4)
+ #define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4)
+ #define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4)
+ #define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7)
+ #define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11)
+ #define BNX2_NVM_CFG1_STRAP_CONTROL_0 (1L<<23)
+ #define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24)
+ #define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25)
+ #define BNX2_NVM_CFG1_FW_USTRAP_1 (1L<<26)
+ #define BNX2_NVM_CFG1_FW_USTRAP_0 (1L<<27)
+ #define BNX2_NVM_CFG1_FW_USTRAP_2 (1L<<28)
+ #define BNX2_NVM_CFG1_FW_USTRAP_3 (1L<<29)
+ #define BNX2_NVM_CFG1_FW_FLASH_TYPE_EN (1L<<30)
+ #define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31)
+
+ #define BNX2_NVM_CFG2 0x00006418
+ #define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0)
+ #define BNX2_NVM_CFG2_DUMMY (0xffL<<8)
+ #define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16)
+ #define BNX2_NVM_CFG2_READ_ID (0xffL<<24)
+
+ #define BNX2_NVM_CFG3 0x0000641c
+ #define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0)
+ #define BNX2_NVM_CFG3_WRITE_CMD (0xffL<<8)
+ #define BNX2_NVM_CFG3_BUFFER_WRITE_CMD (0xffL<<16)
+ #define BNX2_NVM_CFG3_READ_CMD (0xffL<<24)
+
+ #define BNX2_NVM_SW_ARB 0x00006420
+ #define BNX2_NVM_SW_ARB_ARB_REQ_SET0 (1L<<0)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_SET2 (1L<<2)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_SET3 (1L<<3)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_CLR0 (1L<<4)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6)
+ #define BNX2_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7)
+ #define BNX2_NVM_SW_ARB_ARB_ARB0 (1L<<8)
+ #define BNX2_NVM_SW_ARB_ARB_ARB1 (1L<<9)
+ #define BNX2_NVM_SW_ARB_ARB_ARB2 (1L<<10)
+ #define BNX2_NVM_SW_ARB_ARB_ARB3 (1L<<11)
+ #define BNX2_NVM_SW_ARB_REQ0 (1L<<12)
+ #define BNX2_NVM_SW_ARB_REQ1 (1L<<13)
+ #define BNX2_NVM_SW_ARB_REQ2 (1L<<14)
+ #define BNX2_NVM_SW_ARB_REQ3 (1L<<15)
+
+ #define BNX2_NVM_ACCESS_ENABLE 0x00006424
+ #define BNX2_NVM_ACCESS_ENABLE_EN (1L<<0)
+ #define BNX2_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
+
+ #define BNX2_NVM_WRITE1 0x00006428
+ #define BNX2_NVM_WRITE1_WREN_CMD (0xffL<<0)
+ #define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8)
+ #define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16)
+
+ #define BNX2_NVM_CFG4 0x0000642c
+ #define BNX2_NVM_CFG4_FLASH_SIZE (0x7L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_1MBIT (0L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_2MBIT (1L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_4MBIT (2L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_8MBIT (3L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_16MBIT (4L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_32MBIT (5L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_64MBIT (6L<<0)
+ #define BNX2_NVM_CFG4_FLASH_SIZE_128MBIT (7L<<0)
+ #define BNX2_NVM_CFG4_FLASH_VENDOR (1L<<3)
+ #define BNX2_NVM_CFG4_FLASH_VENDOR_ST (0L<<3)
+ #define BNX2_NVM_CFG4_FLASH_VENDOR_ATMEL (1L<<3)
+ #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC (0x3L<<4)
+ #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT8 (0L<<4)
+ #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT9 (1L<<4)
+ #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT10 (2L<<4)
+ #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT11 (3L<<4)
+ #define BNX2_NVM_CFG4_STATUS_BIT_POLARITY (1L<<6)
+ #define BNX2_NVM_CFG4_RESERVED (0x1ffffffL<<7)
+
+ #define BNX2_NVM_RECONFIG 0x00006430
+ #define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE (0xfL<<0)
+ #define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ST (0L<<0)
+ #define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ATMEL (1L<<0)
+ #define BNX2_NVM_RECONFIG_RECONFIG_STRAP_VALUE (0xfL<<4)
+ #define BNX2_NVM_RECONFIG_RESERVED (0x7fffffL<<8)
+ #define BNX2_NVM_RECONFIG_RECONFIG_DONE (1L<<31)
+
+
+
+ /*
+ * dma_reg definition
+ * offset: 0xc00
+ */
+ #define BNX2_DMA_COMMAND 0x00000c00
+ #define BNX2_DMA_COMMAND_ENABLE (1L<<0)
+
+ #define BNX2_DMA_STATUS 0x00000c04
+ #define BNX2_DMA_STATUS_PAR_ERROR_STATE (1L<<0)
+ #define BNX2_DMA_STATUS_READ_TRANSFERS_STAT (1L<<16)
+ #define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT (1L<<17)
+ #define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT (1L<<18)
+ #define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT (1L<<19)
+ #define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT (1L<<20)
+ #define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT (1L<<21)
+ #define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT (1L<<22)
+ #define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23)
+ #define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24)
+ #define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25)
+ #define BNX2_DMA_STATUS_GLOBAL_ERR_XI (1L<<0)
+ #define BNX2_DMA_STATUS_BME_XI (1L<<4)
+
+ #define BNX2_DMA_CONFIG 0x00000c08
+ #define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0)
+ #define BNX2_DMA_CONFIG_DATA_WORD_SWAP (1L<<1)
+ #define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP (1L<<4)
+ #define BNX2_DMA_CONFIG_CNTL_WORD_SWAP (1L<<5)
+ #define BNX2_DMA_CONFIG_ONE_DMA (1L<<6)
+ #define BNX2_DMA_CONFIG_CNTL_TWO_DMA (1L<<7)
+ #define BNX2_DMA_CONFIG_CNTL_FPGA_MODE (1L<<8)
+ #define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA (1L<<10)
+ #define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY (1L<<11)
+ #define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE (0xfL<<12)
+ #define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE (0xfL<<16)
+ #define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS (0x7L<<20)
+ #define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP (1L<<23)
+ #define BNX2_DMA_CONFIG_BIG_SIZE (0xfL<<24)
+ #define BNX2_DMA_CONFIG_BIG_SIZE_NONE (0x0L<<24)
+ #define BNX2_DMA_CONFIG_BIG_SIZE_64 (0x1L<<24)
+ #define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24)
+ #define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24)
+ #define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24)
+ #define BNX2_DMA_CONFIG_DAT_WBSWAP_MODE_XI (0x3L<<0)
+ #define BNX2_DMA_CONFIG_CTL_WBSWAP_MODE_XI (0x3L<<4)
+ #define BNX2_DMA_CONFIG_MAX_PL_XI (0x7L<<12)
+ #define BNX2_DMA_CONFIG_MAX_PL_128B_XI (0L<<12)
+ #define BNX2_DMA_CONFIG_MAX_PL_256B_XI (1L<<12)
+ #define BNX2_DMA_CONFIG_MAX_PL_512B_XI (2L<<12)
+ #define BNX2_DMA_CONFIG_MAX_PL_EN_XI (1L<<15)
+ #define BNX2_DMA_CONFIG_MAX_RRS_XI (0x7L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_128B_XI (0L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_256B_XI (1L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_512B_XI (2L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_1024B_XI (3L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_2048B_XI (4L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_4096B_XI (5L<<16)
+ #define BNX2_DMA_CONFIG_MAX_RRS_EN_XI (1L<<19)
+ #define BNX2_DMA_CONFIG_NO_64SWAP_EN_XI (1L<<31)
+
+ #define BNX2_DMA_BLACKOUT 0x00000c0c
+ #define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0)
+ #define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8)
+ #define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16)
+
+ #define BNX2_DMA_READ_MASTER_SETTING_0 0x00000c10
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_NO_SNOOP (1L<<0)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_RELAX_ORDER (1L<<1)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PRIORITY (1L<<2)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_TRAFFIC_CLASS (0x7L<<4)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PARAM_EN (1L<<7)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_NO_SNOOP (1L<<8)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_RELAX_ORDER (1L<<9)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PRIORITY (1L<<10)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_TRAFFIC_CLASS (0x7L<<12)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PARAM_EN (1L<<15)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_NO_SNOOP (1L<<16)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_RELAX_ORDER (1L<<17)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PRIORITY (1L<<18)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_TRAFFIC_CLASS (0x7L<<20)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PARAM_EN (1L<<23)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PRIORITY (1L<<26)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28)
+ #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31)
+
+ #define BNX2_DMA_READ_MASTER_SETTING_1 0x00000c14
+ #define BNX2_DMA_READ_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_COM_PRIORITY (1L<<2)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_COM_PARAM_EN (1L<<7)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_CP_PRIORITY (1L<<10)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12)
+ #define BNX2_DMA_READ_MASTER_SETTING_1_CP_PARAM_EN (1L<<15)
+
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0 0x00000c18
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_NO_SNOOP (1L<<0)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_RELAX_ORDER (1L<<1)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PRIORITY (1L<<2)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_CS_VLD (1L<<3)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_TRAFFIC_CLASS (0x7L<<4)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PARAM_EN (1L<<7)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_NO_SNOOP (1L<<8)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_RELAX_ORDER (1L<<9)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PRIORITY (1L<<10)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_CS_VLD (1L<<11)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_TRAFFIC_CLASS (0x7L<<12)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PARAM_EN (1L<<15)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PRIORITY (1L<<26)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_CS_VLD (1L<<27)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31)
+
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1 0x00000c1c
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PRIORITY (1L<<2)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_CS_VLD (1L<<3)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PARAM_EN (1L<<7)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PRIORITY (1L<<10)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_CS_VLD (1L<<11)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12)
+ #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PARAM_EN (1L<<15)
+
+ #define BNX2_DMA_ARBITER 0x00000c20
+ #define BNX2_DMA_ARBITER_NUM_READS (0x7L<<0)
+ #define BNX2_DMA_ARBITER_WR_ARB_MODE (1L<<4)
+ #define BNX2_DMA_ARBITER_WR_ARB_MODE_STRICT (0L<<4)
+ #define BNX2_DMA_ARBITER_WR_ARB_MODE_RND_RBN (1L<<4)
+ #define BNX2_DMA_ARBITER_RD_ARB_MODE (0x3L<<5)
+ #define BNX2_DMA_ARBITER_RD_ARB_MODE_STRICT (0L<<5)
+ #define BNX2_DMA_ARBITER_RD_ARB_MODE_RND_RBN (1L<<5)
+ #define BNX2_DMA_ARBITER_RD_ARB_MODE_WGT_RND_RBN (2L<<5)
+ #define BNX2_DMA_ARBITER_ALT_MODE_EN (1L<<8)
+ #define BNX2_DMA_ARBITER_RR_MODE (1L<<9)
+ #define BNX2_DMA_ARBITER_TIMER_MODE (1L<<10)
+ #define BNX2_DMA_ARBITER_OUSTD_READ_REQ (0xfL<<12)
+
+ #define BNX2_DMA_ARB_TIMERS 0x00000c24
+ #define BNX2_DMA_ARB_TIMERS_RD_DRR_WAIT_TIME (0xffL<<0)
+ #define BNX2_DMA_ARB_TIMERS_TM_MIN_TIMEOUT (0xffL<<12)
+ #define BNX2_DMA_ARB_TIMERS_TM_MAX_TIMEOUT (0xfffL<<20)
+
+ #define BNX2_DMA_DEBUG_VECT_PEEK 0x00000c2c
+ #define BNX2_DMA_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_DMA_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_DMA_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_DMA_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_DMA_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_DMA_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_DMA_TAG_RAM_00 0x00000c30
+ #define BNX2_DMA_TAG_RAM_00_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_00_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_00_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_00_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_00_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_00_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_00_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_00_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_00_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_00_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_00_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_00_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_00_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_00_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_01 0x00000c34
+ #define BNX2_DMA_TAG_RAM_01_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_01_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_01_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_01_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_01_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_01_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_01_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_01_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_01_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_01_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_01_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_01_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_01_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_01_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_02 0x00000c38
+ #define BNX2_DMA_TAG_RAM_02_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_02_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_02_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_02_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_02_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_02_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_02_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_02_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_02_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_02_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_02_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_02_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_02_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_02_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_03 0x00000c3c
+ #define BNX2_DMA_TAG_RAM_03_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_03_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_03_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_03_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_03_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_03_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_03_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_03_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_03_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_03_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_03_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_03_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_03_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_03_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_04 0x00000c40
+ #define BNX2_DMA_TAG_RAM_04_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_04_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_04_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_04_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_04_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_04_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_04_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_04_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_04_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_04_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_04_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_04_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_04_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_04_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_05 0x00000c44
+ #define BNX2_DMA_TAG_RAM_05_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_05_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_05_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_05_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_05_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_05_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_05_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_05_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_05_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_05_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_05_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_05_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_05_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_05_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_06 0x00000c48
+ #define BNX2_DMA_TAG_RAM_06_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_06_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_06_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_06_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_06_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_06_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_06_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_06_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_06_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_06_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_06_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_06_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_06_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_06_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_07 0x00000c4c
+ #define BNX2_DMA_TAG_RAM_07_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_07_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_07_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_07_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_07_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_07_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_07_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_07_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_07_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_07_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_07_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_07_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_07_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_07_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_08 0x00000c50
+ #define BNX2_DMA_TAG_RAM_08_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_08_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_08_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_08_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_08_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_08_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_08_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_08_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_08_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_08_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_08_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_08_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_08_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_08_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_09 0x00000c54
+ #define BNX2_DMA_TAG_RAM_09_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_09_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_09_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_09_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_09_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_09_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_09_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_09_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_09_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_09_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_09_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_09_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_09_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_09_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_10 0x00000c58
+ #define BNX2_DMA_TAG_RAM_10_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_10_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_10_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_10_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_10_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_10_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_10_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_10_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_10_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_10_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_10_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_10_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_10_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_10_VALID (1L<<10)
+
+ #define BNX2_DMA_TAG_RAM_11 0x00000c5c
+ #define BNX2_DMA_TAG_RAM_11_CHANNEL (0xfL<<0)
+ #define BNX2_DMA_TAG_RAM_11_MASTER (0x7L<<4)
+ #define BNX2_DMA_TAG_RAM_11_MASTER_CTX (0L<<4)
+ #define BNX2_DMA_TAG_RAM_11_MASTER_RBDC (1L<<4)
+ #define BNX2_DMA_TAG_RAM_11_MASTER_TBDC (2L<<4)
+ #define BNX2_DMA_TAG_RAM_11_MASTER_COM (3L<<4)
+ #define BNX2_DMA_TAG_RAM_11_MASTER_CP (4L<<4)
+ #define BNX2_DMA_TAG_RAM_11_MASTER_TDMA (5L<<4)
+ #define BNX2_DMA_TAG_RAM_11_SWAP (0x3L<<7)
+ #define BNX2_DMA_TAG_RAM_11_SWAP_CONFIG (0L<<7)
+ #define BNX2_DMA_TAG_RAM_11_SWAP_DATA (1L<<7)
+ #define BNX2_DMA_TAG_RAM_11_SWAP_CONTROL (2L<<7)
+ #define BNX2_DMA_TAG_RAM_11_FUNCTION (1L<<9)
+ #define BNX2_DMA_TAG_RAM_11_VALID (1L<<10)
+
+ #define BNX2_DMA_RCHAN_STAT_22 0x00000c60
+ #define BNX2_DMA_RCHAN_STAT_30 0x00000c64
+ #define BNX2_DMA_RCHAN_STAT_31 0x00000c68
+ #define BNX2_DMA_RCHAN_STAT_32 0x00000c6c
+ #define BNX2_DMA_RCHAN_STAT_40 0x00000c70
+ #define BNX2_DMA_RCHAN_STAT_41 0x00000c74
+ #define BNX2_DMA_RCHAN_STAT_42 0x00000c78
+ #define BNX2_DMA_RCHAN_STAT_50 0x00000c7c
+ #define BNX2_DMA_RCHAN_STAT_51 0x00000c80
+ #define BNX2_DMA_RCHAN_STAT_52 0x00000c84
+ #define BNX2_DMA_RCHAN_STAT_60 0x00000c88
+ #define BNX2_DMA_RCHAN_STAT_61 0x00000c8c
+ #define BNX2_DMA_RCHAN_STAT_62 0x00000c90
+ #define BNX2_DMA_RCHAN_STAT_70 0x00000c94
+ #define BNX2_DMA_RCHAN_STAT_71 0x00000c98
+ #define BNX2_DMA_RCHAN_STAT_72 0x00000c9c
+ #define BNX2_DMA_WCHAN_STAT_00 0x00000ca0
+ #define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+ #define BNX2_DMA_WCHAN_STAT_01 0x00000ca4
+ #define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+ #define BNX2_DMA_WCHAN_STAT_02 0x00000ca8
+ #define BNX2_DMA_WCHAN_STAT_02_LENGTH (0xffffL<<0)
+ #define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP (1L<<16)
+ #define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP (1L<<17)
+ #define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+ #define BNX2_DMA_WCHAN_STAT_10 0x00000cac
+ #define BNX2_DMA_WCHAN_STAT_11 0x00000cb0
+ #define BNX2_DMA_WCHAN_STAT_12 0x00000cb4
+ #define BNX2_DMA_WCHAN_STAT_20 0x00000cb8
+ #define BNX2_DMA_WCHAN_STAT_21 0x00000cbc
+ #define BNX2_DMA_WCHAN_STAT_22 0x00000cc0
+ #define BNX2_DMA_WCHAN_STAT_30 0x00000cc4
+ #define BNX2_DMA_WCHAN_STAT_31 0x00000cc8
+ #define BNX2_DMA_WCHAN_STAT_32 0x00000ccc
+ #define BNX2_DMA_WCHAN_STAT_40 0x00000cd0
+ #define BNX2_DMA_WCHAN_STAT_41 0x00000cd4
+ #define BNX2_DMA_WCHAN_STAT_42 0x00000cd8
+ #define BNX2_DMA_WCHAN_STAT_50 0x00000cdc
+ #define BNX2_DMA_WCHAN_STAT_51 0x00000ce0
+ #define BNX2_DMA_WCHAN_STAT_52 0x00000ce4
+ #define BNX2_DMA_WCHAN_STAT_60 0x00000ce8
+ #define BNX2_DMA_WCHAN_STAT_61 0x00000cec
+ #define BNX2_DMA_WCHAN_STAT_62 0x00000cf0
+ #define BNX2_DMA_WCHAN_STAT_70 0x00000cf4
+ #define BNX2_DMA_WCHAN_STAT_71 0x00000cf8
+ #define BNX2_DMA_WCHAN_STAT_72 0x00000cfc
+ #define BNX2_DMA_ARB_STAT_00 0x00000d00
+ #define BNX2_DMA_ARB_STAT_00_MASTER (0xffffL<<0)
+ #define BNX2_DMA_ARB_STAT_00_MASTER_ENC (0xffL<<16)
+ #define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR (0xffL<<24)
+
+ #define BNX2_DMA_ARB_STAT_01 0x00000d04
+ #define BNX2_DMA_ARB_STAT_01_LPR_RPTR (0xfL<<0)
+ #define BNX2_DMA_ARB_STAT_01_LPR_WPTR (0xfL<<4)
+ #define BNX2_DMA_ARB_STAT_01_LPB_RPTR (0xfL<<8)
+ #define BNX2_DMA_ARB_STAT_01_LPB_WPTR (0xfL<<12)
+ #define BNX2_DMA_ARB_STAT_01_HPR_RPTR (0xfL<<16)
+ #define BNX2_DMA_ARB_STAT_01_HPR_WPTR (0xfL<<20)
+ #define BNX2_DMA_ARB_STAT_01_HPB_RPTR (0xfL<<24)
+ #define BNX2_DMA_ARB_STAT_01_HPB_WPTR (0xfL<<28)
+
+ #define BNX2_DMA_FUSE_CTRL0_CMD 0x00000f00
+ #define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE (1L<<0)
+ #define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE (1L<<1)
+ #define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT (1L<<2)
+ #define BNX2_DMA_FUSE_CTRL0_CMD_LOAD (1L<<3)
+ #define BNX2_DMA_FUSE_CTRL0_CMD_SEL (0xfL<<8)
+
+ #define BNX2_DMA_FUSE_CTRL0_DATA 0x00000f04
+ #define BNX2_DMA_FUSE_CTRL1_CMD 0x00000f08
+ #define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE (1L<<0)
+ #define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE (1L<<1)
+ #define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT (1L<<2)
+ #define BNX2_DMA_FUSE_CTRL1_CMD_LOAD (1L<<3)
+ #define BNX2_DMA_FUSE_CTRL1_CMD_SEL (0xfL<<8)
+
+ #define BNX2_DMA_FUSE_CTRL1_DATA 0x00000f0c
+ #define BNX2_DMA_FUSE_CTRL2_CMD 0x00000f10
+ #define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE (1L<<0)
+ #define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE (1L<<1)
+ #define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT (1L<<2)
+ #define BNX2_DMA_FUSE_CTRL2_CMD_LOAD (1L<<3)
+ #define BNX2_DMA_FUSE_CTRL2_CMD_SEL (0xfL<<8)
+
+ #define BNX2_DMA_FUSE_CTRL2_DATA 0x00000f14
+
+
+ /*
+ * context_reg definition
+ * offset: 0x1000
+ */
+ #define BNX2_CTX_COMMAND 0x00001000
+ #define BNX2_CTX_COMMAND_ENABLED (1L<<0)
+ #define BNX2_CTX_COMMAND_DISABLE_USAGE_CNT (1L<<1)
+ #define BNX2_CTX_COMMAND_DISABLE_PLRU (1L<<2)
+ #define BNX2_CTX_COMMAND_DISABLE_COMBINE_READ (1L<<3)
+ #define BNX2_CTX_COMMAND_FLUSH_AHEAD (0x1fL<<8)
+ #define BNX2_CTX_COMMAND_MEM_INIT (1L<<13)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE (0xfL<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_256 (0L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_512 (1L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_1K (2L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_2K (3L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_4K (4L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_8K (5L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_16K (6L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_32K (7L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_64K (8L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_128K (9L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_256K (10L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_512K (11L<<16)
+ #define BNX2_CTX_COMMAND_PAGE_SIZE_1M (12L<<16)
+
+ #define BNX2_CTX_STATUS 0x00001004
+ #define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0)
+ #define BNX2_CTX_STATUS_READ_STAT (1L<<16)
+ #define BNX2_CTX_STATUS_WRITE_STAT (1L<<17)
+ #define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18)
+ #define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19)
+ #define BNX2_CTX_STATUS_EXT_READ_STAT (1L<<20)
+ #define BNX2_CTX_STATUS_EXT_WRITE_STAT (1L<<21)
+ #define BNX2_CTX_STATUS_MISS_STAT (1L<<22)
+ #define BNX2_CTX_STATUS_HIT_STAT (1L<<23)
+ #define BNX2_CTX_STATUS_DEAD_LOCK (1L<<24)
+ #define BNX2_CTX_STATUS_USAGE_CNT_ERR (1L<<25)
+ #define BNX2_CTX_STATUS_INVALID_PAGE (1L<<26)
+
+ #define BNX2_CTX_VIRT_ADDR 0x00001008
+ #define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6)
+
+ #define BNX2_CTX_PAGE_TBL 0x0000100c
+ #define BNX2_CTX_PAGE_TBL_PAGE_TBL (0x3fffL<<6)
+
+ #define BNX2_CTX_DATA_ADR 0x00001010
+ #define BNX2_CTX_DATA_ADR_DATA_ADR (0x7ffffL<<2)
+
+ #define BNX2_CTX_DATA 0x00001014
+ #define BNX2_CTX_LOCK 0x00001018
+ #define BNX2_CTX_LOCK_TYPE (0x7L<<0)
+ #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0)
+ #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0)
+ #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0)
+ #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0)
+ #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0)
+ #define BNX2_CTX_LOCK_TYPE_VOID_XI (0L<<0)
+ #define BNX2_CTX_LOCK_TYPE_PROTOCOL_XI (1L<<0)
+ #define BNX2_CTX_LOCK_TYPE_TX_XI (2L<<0)
+ #define BNX2_CTX_LOCK_TYPE_TIMER_XI (4L<<0)
+ #define BNX2_CTX_LOCK_TYPE_COMPLETE_XI (7L<<0)
+ #define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7)
+ #define BNX2_CTX_LOCK_GRANTED (1L<<26)
+ #define BNX2_CTX_LOCK_MODE (0x7L<<27)
+ #define BNX2_CTX_LOCK_MODE_UNLOCK (0x0L<<27)
+ #define BNX2_CTX_LOCK_MODE_IMMEDIATE (0x1L<<27)
+ #define BNX2_CTX_LOCK_MODE_SURE (0x2L<<27)
+ #define BNX2_CTX_LOCK_STATUS (1L<<30)
+ #define BNX2_CTX_LOCK_REQ (1L<<31)
+
+ #define BNX2_CTX_CTX_CTRL 0x0000101c
+ #define BNX2_CTX_CTX_CTRL_CTX_ADDR (0x7ffffL<<2)
+ #define BNX2_CTX_CTX_CTRL_MOD_USAGE_CNT (0x3L<<21)
+ #define BNX2_CTX_CTX_CTRL_NO_RAM_ACC (1L<<23)
+ #define BNX2_CTX_CTX_CTRL_PREFETCH_SIZE (0x3L<<24)
+ #define BNX2_CTX_CTX_CTRL_ATTR (1L<<26)
+ #define BNX2_CTX_CTX_CTRL_WRITE_REQ (1L<<30)
+ #define BNX2_CTX_CTX_CTRL_READ_REQ (1L<<31)
+
+ #define BNX2_CTX_CTX_DATA 0x00001020
+ #define BNX2_CTX_ACCESS_STATUS 0x00001040
+ #define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0)
+ #define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10)
+ #define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12)
+ #define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14)
+ #define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17)
+ #define BNX2_CTX_ACCESS_STATUS_CAMMASTERENCODED_XI (0x1fL<<0)
+ #define BNX2_CTX_ACCESS_STATUS_CACHEMASTERENCODED_XI (0x1fL<<5)
+ #define BNX2_CTX_ACCESS_STATUS_REQUEST_XI (0x3fffffL<<10)
+
+ #define BNX2_CTX_DBG_LOCK_STATUS 0x00001044
+ #define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0)
+ #define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22)
+
+ #define BNX2_CTX_CACHE_CTRL_STATUS 0x00001048
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RFIFO_OVERFLOW (1L<<0)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_INVALID_READ_COMP (1L<<1)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_FLUSH_START (1L<<6)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_FREE_ENTRY_CNT (0x3fL<<7)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_CACHE_ENTRY_NEEDED (0x3fL<<13)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN0_ACTIVE (1L<<19)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN1_ACTIVE (1L<<20)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN2_ACTIVE (1L<<21)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN3_ACTIVE (1L<<22)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN4_ACTIVE (1L<<23)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN5_ACTIVE (1L<<24)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN6_ACTIVE (1L<<25)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN7_ACTIVE (1L<<26)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN8_ACTIVE (1L<<27)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN9_ACTIVE (1L<<28)
+ #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN10_ACTIVE (1L<<29)
+
+ #define BNX2_CTX_CACHE_CTRL_SM_STATUS 0x0000104c
+ #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_DWC (0x7L<<0)
+ #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_WFIFOC (0x7L<<3)
+ #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RTAGC (0x7L<<6)
+ #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RFIFOC (0x7L<<9)
+ #define BNX2_CTX_CACHE_CTRL_SM_STATUS_INVALID_BLK_ADDR (0x7fffL<<16)
+
+ #define BNX2_CTX_CACHE_STATUS 0x00001050
+ #define BNX2_CTX_CACHE_STATUS_HELD_ENTRIES (0x3ffL<<0)
+ #define BNX2_CTX_CACHE_STATUS_MAX_HELD_ENTRIES (0x3ffL<<16)
+
+ #define BNX2_CTX_DMA_STATUS 0x00001054
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN0_STATUS (0x3L<<0)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN1_STATUS (0x3L<<2)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN2_STATUS (0x3L<<4)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN3_STATUS (0x3L<<6)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN4_STATUS (0x3L<<8)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN5_STATUS (0x3L<<10)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN6_STATUS (0x3L<<12)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN7_STATUS (0x3L<<14)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN8_STATUS (0x3L<<16)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN9_STATUS (0x3L<<18)
+ #define BNX2_CTX_DMA_STATUS_RD_CHAN10_STATUS (0x3L<<20)
+
+ #define BNX2_CTX_REP_STATUS 0x00001058
+ #define BNX2_CTX_REP_STATUS_ERROR_ENTRY (0x3ffL<<0)
+ #define BNX2_CTX_REP_STATUS_ERROR_CLIENT_ID (0x1fL<<10)
+ #define BNX2_CTX_REP_STATUS_USAGE_CNT_MAX_ERR (1L<<16)
+ #define BNX2_CTX_REP_STATUS_USAGE_CNT_MIN_ERR (1L<<17)
+ #define BNX2_CTX_REP_STATUS_USAGE_CNT_MISS_ERR (1L<<18)
+
+ #define BNX2_CTX_CKSUM_ERROR_STATUS 0x0000105c
+ #define BNX2_CTX_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+ #define BNX2_CTX_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
+ #define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080
+ #define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0)
+ #define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14)
+ #define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16)
+ #define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE_XI (1L<<14)
+ #define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE_XI (0x7L<<15)
+
+ #define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084
+ #define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088
+ #define BNX2_CTX_CHNL_LOCK_STATUS_3 0x0000108c
+ #define BNX2_CTX_CHNL_LOCK_STATUS_4 0x00001090
+ #define BNX2_CTX_CHNL_LOCK_STATUS_5 0x00001094
+ #define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098
+ #define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c
+ #define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0
+ #define BNX2_CTX_CHNL_LOCK_STATUS_9 0x000010a4
+
+ #define BNX2_CTX_CACHE_DATA 0x000010c4
+ #define BNX2_CTX_HOST_PAGE_TBL_CTRL 0x000010c8
+ #define BNX2_CTX_HOST_PAGE_TBL_CTRL_PAGE_TBL_ADDR (0x1ffL<<0)
+ #define BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ (1L<<30)
+ #define BNX2_CTX_HOST_PAGE_TBL_CTRL_READ_REQ (1L<<31)
+
+ #define BNX2_CTX_HOST_PAGE_TBL_DATA0 0x000010cc
+ #define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID (1L<<0)
+ #define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALUE (0xffffffL<<8)
+
+ #define BNX2_CTX_HOST_PAGE_TBL_DATA1 0x000010d0
+ #define BNX2_CTX_CAM_CTRL 0x000010d4
+ #define BNX2_CTX_CAM_CTRL_CAM_ADDR (0x3ffL<<0)
+ #define BNX2_CTX_CAM_CTRL_RESET (1L<<27)
+ #define BNX2_CTX_CAM_CTRL_INVALIDATE (1L<<28)
+ #define BNX2_CTX_CAM_CTRL_SEARCH (1L<<29)
+ #define BNX2_CTX_CAM_CTRL_WRITE_REQ (1L<<30)
+ #define BNX2_CTX_CAM_CTRL_READ_REQ (1L<<31)
+
+
+ /*
+ * emac_reg definition
+ * offset: 0x1400
+ */
+ #define BNX2_EMAC_MODE 0x00001400
+ #define BNX2_EMAC_MODE_RESET (1L<<0)
+ #define BNX2_EMAC_MODE_HALF_DUPLEX (1L<<1)
+ #define BNX2_EMAC_MODE_PORT (0x3L<<2)
+ #define BNX2_EMAC_MODE_PORT_NONE (0L<<2)
+ #define BNX2_EMAC_MODE_PORT_MII (1L<<2)
+ #define BNX2_EMAC_MODE_PORT_GMII (2L<<2)
+ #define BNX2_EMAC_MODE_PORT_MII_10M (3L<<2)
+ #define BNX2_EMAC_MODE_MAC_LOOP (1L<<4)
+ #define BNX2_EMAC_MODE_25G_MODE (1L<<5)
+ #define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7)
+ #define BNX2_EMAC_MODE_TX_BURST (1L<<8)
+ #define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9)
+ #define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10)
+ #define BNX2_EMAC_MODE_FORCE_LINK (1L<<11)
+ #define BNX2_EMAC_MODE_SERDES_MODE (1L<<12)
+ #define BNX2_EMAC_MODE_BOND_OVRD (1L<<13)
+ #define BNX2_EMAC_MODE_MPKT (1L<<18)
+ #define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19)
+ #define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20)
+
+ #define BNX2_EMAC_STATUS 0x00001404
+ #define BNX2_EMAC_STATUS_LINK (1L<<11)
+ #define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12)
+ #define BNX2_EMAC_STATUS_SERDES_AUTONEG_COMPLETE (1L<<13)
+ #define BNX2_EMAC_STATUS_SERDES_AUTONEG_CHANGE (1L<<14)
+ #define BNX2_EMAC_STATUS_SERDES_NXT_PG_CHANGE (1L<<16)
+ #define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0 (1L<<17)
+ #define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18)
+ #define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22)
+ #define BNX2_EMAC_STATUS_MI_INT (1L<<23)
+ #define BNX2_EMAC_STATUS_AP_ERROR (1L<<24)
+ #define BNX2_EMAC_STATUS_PARITY_ERROR_STATE (1L<<31)
+
+ #define BNX2_EMAC_ATTENTION_ENA 0x00001408
+ #define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11)
+ #define BNX2_EMAC_ATTENTION_ENA_AUTONEG_CHANGE (1L<<14)
+ #define BNX2_EMAC_ATTENTION_ENA_NXT_PG_CHANGE (1L<<16)
+ #define BNX2_EMAC_ATTENTION_ENA_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18)
+ #define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22)
+ #define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23)
+ #define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24)
+
+ #define BNX2_EMAC_LED 0x0000140c
+ #define BNX2_EMAC_LED_OVERRIDE (1L<<0)
+ #define BNX2_EMAC_LED_1000MB_OVERRIDE (1L<<1)
+ #define BNX2_EMAC_LED_100MB_OVERRIDE (1L<<2)
+ #define BNX2_EMAC_LED_10MB_OVERRIDE (1L<<3)
+ #define BNX2_EMAC_LED_TRAFFIC_OVERRIDE (1L<<4)
+ #define BNX2_EMAC_LED_BLNK_TRAFFIC (1L<<5)
+ #define BNX2_EMAC_LED_TRAFFIC (1L<<6)
+ #define BNX2_EMAC_LED_1000MB (1L<<7)
+ #define BNX2_EMAC_LED_100MB (1L<<8)
+ #define BNX2_EMAC_LED_10MB (1L<<9)
+ #define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10)
+ #define BNX2_EMAC_LED_2500MB (1L<<11)
+ #define BNX2_EMAC_LED_2500MB_OVERRIDE (1L<<12)
+ #define BNX2_EMAC_LED_ACTIVITY_SEL (0x3L<<17)
+ #define BNX2_EMAC_LED_ACTIVITY_SEL_0 (0L<<17)
+ #define BNX2_EMAC_LED_ACTIVITY_SEL_1 (1L<<17)
+ #define BNX2_EMAC_LED_ACTIVITY_SEL_2 (2L<<17)
+ #define BNX2_EMAC_LED_ACTIVITY_SEL_3 (3L<<17)
+ #define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19)
+ #define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31)
+
+ #define BNX2_EMAC_MAC_MATCH0 0x00001410
+ #define BNX2_EMAC_MAC_MATCH1 0x00001414
+ #define BNX2_EMAC_MAC_MATCH2 0x00001418
+ #define BNX2_EMAC_MAC_MATCH3 0x0000141c
+ #define BNX2_EMAC_MAC_MATCH4 0x00001420
+ #define BNX2_EMAC_MAC_MATCH5 0x00001424
+ #define BNX2_EMAC_MAC_MATCH6 0x00001428
+ #define BNX2_EMAC_MAC_MATCH7 0x0000142c
+ #define BNX2_EMAC_MAC_MATCH8 0x00001430
+ #define BNX2_EMAC_MAC_MATCH9 0x00001434
+ #define BNX2_EMAC_MAC_MATCH10 0x00001438
+ #define BNX2_EMAC_MAC_MATCH11 0x0000143c
+ #define BNX2_EMAC_MAC_MATCH12 0x00001440
+ #define BNX2_EMAC_MAC_MATCH13 0x00001444
+ #define BNX2_EMAC_MAC_MATCH14 0x00001448
+ #define BNX2_EMAC_MAC_MATCH15 0x0000144c
+ #define BNX2_EMAC_MAC_MATCH16 0x00001450
+ #define BNX2_EMAC_MAC_MATCH17 0x00001454
+ #define BNX2_EMAC_MAC_MATCH18 0x00001458
+ #define BNX2_EMAC_MAC_MATCH19 0x0000145c
+ #define BNX2_EMAC_MAC_MATCH20 0x00001460
+ #define BNX2_EMAC_MAC_MATCH21 0x00001464
+ #define BNX2_EMAC_MAC_MATCH22 0x00001468
+ #define BNX2_EMAC_MAC_MATCH23 0x0000146c
+ #define BNX2_EMAC_MAC_MATCH24 0x00001470
+ #define BNX2_EMAC_MAC_MATCH25 0x00001474
+ #define BNX2_EMAC_MAC_MATCH26 0x00001478
+ #define BNX2_EMAC_MAC_MATCH27 0x0000147c
+ #define BNX2_EMAC_MAC_MATCH28 0x00001480
+ #define BNX2_EMAC_MAC_MATCH29 0x00001484
+ #define BNX2_EMAC_MAC_MATCH30 0x00001488
+ #define BNX2_EMAC_MAC_MATCH31 0x0000148c
+ #define BNX2_EMAC_BACKOFF_SEED 0x00001498
+ #define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED (0x3ffL<<0)
+
+ #define BNX2_EMAC_RX_MTU_SIZE 0x0000149c
+ #define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE (0xffffL<<0)
+ #define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31)
+
+ #define BNX2_EMAC_SERDES_CNTL 0x000014a4
+ #define BNX2_EMAC_SERDES_CNTL_RXR (0x7L<<0)
+ #define BNX2_EMAC_SERDES_CNTL_RXG (0x3L<<3)
+ #define BNX2_EMAC_SERDES_CNTL_RXCKSEL (1L<<6)
+ #define BNX2_EMAC_SERDES_CNTL_TXBIAS (0x7L<<7)
+ #define BNX2_EMAC_SERDES_CNTL_BGMAX (1L<<10)
+ #define BNX2_EMAC_SERDES_CNTL_BGMIN (1L<<11)
+ #define BNX2_EMAC_SERDES_CNTL_TXMODE (1L<<12)
+ #define BNX2_EMAC_SERDES_CNTL_TXEDGE (1L<<13)
+ #define BNX2_EMAC_SERDES_CNTL_SERDES_MODE (1L<<14)
+ #define BNX2_EMAC_SERDES_CNTL_PLLTEST (1L<<15)
+ #define BNX2_EMAC_SERDES_CNTL_CDET_EN (1L<<16)
+ #define BNX2_EMAC_SERDES_CNTL_TBI_LBK (1L<<17)
+ #define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK (1L<<18)
+ #define BNX2_EMAC_SERDES_CNTL_REV_PHASE (1L<<19)
+ #define BNX2_EMAC_SERDES_CNTL_REGCTL12 (0x3L<<20)
+ #define BNX2_EMAC_SERDES_CNTL_REGCTL25 (0x3L<<22)
+
+ #define BNX2_EMAC_SERDES_STATUS 0x000014a8
+ #define BNX2_EMAC_SERDES_STATUS_RX_STAT (0xffL<<0)
+ #define BNX2_EMAC_SERDES_STATUS_COMMA_DET (1L<<8)
+
+ #define BNX2_EMAC_MDIO_COMM 0x000014ac
+ #define BNX2_EMAC_MDIO_COMM_DATA (0xffffL<<0)
+ #define BNX2_EMAC_MDIO_COMM_REG_ADDR (0x1fL<<16)
+ #define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_22_XI (1L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_45_XI (1L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_READ_22_XI (2L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_READ_INC_45_XI (2L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26)
+ #define BNX2_EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26)
+ #define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28)
+ #define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29)
+ #define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30)
+
+ #define BNX2_EMAC_MDIO_STATUS 0x000014b0
+ #define BNX2_EMAC_MDIO_STATUS_LINK (1L<<0)
+ #define BNX2_EMAC_MDIO_STATUS_10MB (1L<<1)
+
+ #define BNX2_EMAC_MDIO_MODE 0x000014b4
+ #define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE (1L<<1)
+ #define BNX2_EMAC_MDIO_MODE_AUTO_POLL (1L<<4)
+ #define BNX2_EMAC_MDIO_MODE_BIT_BANG (1L<<8)
+ #define BNX2_EMAC_MDIO_MODE_MDIO (1L<<9)
+ #define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10)
+ #define BNX2_EMAC_MDIO_MODE_MDC (1L<<11)
+ #define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12)
+ #define BNX2_EMAC_MDIO_MODE_EXT_MDINT (1L<<13)
+ #define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16)
+ #define BNX2_EMAC_MDIO_MODE_CLOCK_CNT_XI (0x3fL<<16)
+ #define BNX2_EMAC_MDIO_MODE_CLAUSE_45_XI (1L<<31)
+
+ #define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8
+ #define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0)
+
+ #define BNX2_EMAC_TX_MODE 0x000014bc
+ #define BNX2_EMAC_TX_MODE_RESET (1L<<0)
+ #define BNX2_EMAC_TX_MODE_CS16_TEST (1L<<2)
+ #define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3)
+ #define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4)
+ #define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5)
+ #define BNX2_EMAC_TX_MODE_LONG_PAUSE (1L<<6)
+ #define BNX2_EMAC_TX_MODE_LINK_AWARE (1L<<7)
+
+ #define BNX2_EMAC_TX_STATUS 0x000014c0
+ #define BNX2_EMAC_TX_STATUS_XOFFED (1L<<0)
+ #define BNX2_EMAC_TX_STATUS_XOFF_SENT (1L<<1)
+ #define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2)
+ #define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3)
+ #define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4)
+ #define BNX2_EMAC_TX_STATUS_CS16_ERROR (1L<<5)
+
+ #define BNX2_EMAC_TX_LENGTHS 0x000014c4
+ #define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0)
+ #define BNX2_EMAC_TX_LENGTHS_IPG (0xfL<<8)
+ #define BNX2_EMAC_TX_LENGTHS_IPG_CRS (0x3L<<12)
+
+ #define BNX2_EMAC_RX_MODE 0x000014c8
+ #define BNX2_EMAC_RX_MODE_RESET (1L<<0)
+ #define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2)
+ #define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3)
+ #define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4)
+ #define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5)
+ #define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6)
+ #define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7)
+ #define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8)
+ #define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9)
+ #define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10)
+ #define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11)
+ #define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12)
+
+ #define BNX2_EMAC_RX_STATUS 0x000014cc
+ #define BNX2_EMAC_RX_STATUS_FFED (1L<<0)
+ #define BNX2_EMAC_RX_STATUS_FF_RECEIVED (1L<<1)
+ #define BNX2_EMAC_RX_STATUS_N_RECEIVED (1L<<2)
+
+ #define BNX2_EMAC_MULTICAST_HASH0 0x000014d0
+ #define BNX2_EMAC_MULTICAST_HASH1 0x000014d4
+ #define BNX2_EMAC_MULTICAST_HASH2 0x000014d8
+ #define BNX2_EMAC_MULTICAST_HASH3 0x000014dc
+ #define BNX2_EMAC_MULTICAST_HASH4 0x000014e0
+ #define BNX2_EMAC_MULTICAST_HASH5 0x000014e4
+ #define BNX2_EMAC_MULTICAST_HASH6 0x000014e8
+ #define BNX2_EMAC_MULTICAST_HASH7 0x000014ec
+ #define BNX2_EMAC_CKSUM_ERROR_STATUS 0x000014f0
+ #define BNX2_EMAC_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+ #define BNX2_EMAC_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
+ #define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500
+ #define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508
+ #define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS 0x0000150c
+ #define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS 0x00001510
+ #define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS 0x00001514
+ #define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS 0x00001518
+ #define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS 0x0000151c
+ #define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS 0x00001520
+ #define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED 0x00001524
+ #define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED 0x00001528
+ #define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED 0x0000152c
+ #define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED 0x00001530
+ #define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG 0x00001534
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS 0x00001538
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS 0x0000153c
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS 0x00001540
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x00001544
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001548
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554
+ #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001558
+ #define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c
+ #define BNX2_EMAC_RXMAC_DEBUG1 0x00001560
+ #define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE (1L<<1)
+ #define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC (1L<<2)
+ #define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR (1L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR (1L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA (1L<<5)
+ #define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START (1L<<6)
+ #define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT (0xffffL<<7)
+ #define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME (0xffL<<23)
+
+ #define BNX2_EMAC_RXMAC_DEBUG2 0x00001564
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE (0x7L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE (0x0L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD (0x1L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA (0x2L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP (0x3L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT (0x4L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP (0x5L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP (0x6L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC (0x7L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE (0xfL<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE (0x0L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0 (0x1L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1 (0x2L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2 (0x3L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3 (0x4L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT (0x5L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT (0x6L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS (0x7L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST (0x8L<<3)
+ #define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN (0xffL<<7)
+ #define BNX2_EMAC_RXMAC_DEBUG2_FALSEC (1L<<15)
+ #define BNX2_EMAC_RXMAC_DEBUG2_TAGGED (1L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE (1L<<18)
+ #define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE (0L<<18)
+ #define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED (1L<<18)
+ #define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER (0xfL<<19)
+ #define BNX2_EMAC_RXMAC_DEBUG2_QUANTA (0x1fL<<23)
+
+ #define BNX2_EMAC_RXMAC_DEBUG3 0x00001568
+ #define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR (0xffffL<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR (0xffffL<<16)
+
+ #define BNX2_EMAC_RXMAC_DEBUG4 0x0000156c
+ #define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD (0xffffL<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE (0x3fL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE (0x0L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3 (0xaL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1 (0xeL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2 (0xfL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK (0x10L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC (0x11L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2 (0x12L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3 (0x13L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1 (0x14L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2 (0x15L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3 (0x16L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE (0x17L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC (0x18L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE (0x19L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD (0x1aL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC (0x1bL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH (0x1cL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF (0x1dL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON (0x1eL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED (0x1fL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED (0x20L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE (0x21L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL (0x22L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1 (0x23L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2 (0x24L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3 (0x25L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE (0x26L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE (0x27L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL (0x28L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE (0x29L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP (0x2aL<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT (1L<<22)
+ #define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23)
+ #define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24)
+ #define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25)
+ #define BNX2_EMAC_RXMAC_DEBUG4_SFD_FOUND (1L<<26)
+ #define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27)
+ #define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28)
+
+ #define BNX2_EMAC_RXMAC_DEBUG5 0x00001570
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM (0x7L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE (0L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF (1L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT (2L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC (3L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE (4L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL (5L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT (6L<<0)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1 (0x7L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW (0x0L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT (0x1L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF (0x2L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF (0x3L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF (0x4L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF (0x6L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF (0x7L<<4)
+ #define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED (1L<<7)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0 (0x7L<<8)
+ #define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL (1L<<11)
+ #define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE (1L<<12)
+ #define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA (1L<<13)
+ #define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT (1L<<14)
+ #define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT (1L<<15)
+ #define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE (0x3L<<16)
+ #define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19)
+ #define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20)
+
+ #define BNX2_EMAC_RX_STAT_FALSECARRIERERRORS 0x00001574
+ #define BNX2_EMAC_RX_STAT_AC0 0x00001580
+ #define BNX2_EMAC_RX_STAT_AC1 0x00001584
+ #define BNX2_EMAC_RX_STAT_AC2 0x00001588
+ #define BNX2_EMAC_RX_STAT_AC3 0x0000158c
+ #define BNX2_EMAC_RX_STAT_AC4 0x00001590
+ #define BNX2_EMAC_RX_STAT_AC5 0x00001594
+ #define BNX2_EMAC_RX_STAT_AC6 0x00001598
+ #define BNX2_EMAC_RX_STAT_AC7 0x0000159c
+ #define BNX2_EMAC_RX_STAT_AC8 0x000015a0
+ #define BNX2_EMAC_RX_STAT_AC9 0x000015a4
+ #define BNX2_EMAC_RX_STAT_AC10 0x000015a8
+ #define BNX2_EMAC_RX_STAT_AC11 0x000015ac
+ #define BNX2_EMAC_RX_STAT_AC12 0x000015b0
+ #define BNX2_EMAC_RX_STAT_AC13 0x000015b4
+ #define BNX2_EMAC_RX_STAT_AC14 0x000015b8
+ #define BNX2_EMAC_RX_STAT_AC15 0x000015bc
+ #define BNX2_EMAC_RX_STAT_AC16 0x000015c0
+ #define BNX2_EMAC_RX_STAT_AC17 0x000015c4
+ #define BNX2_EMAC_RX_STAT_AC18 0x000015c8
+ #define BNX2_EMAC_RX_STAT_AC19 0x000015cc
+ #define BNX2_EMAC_RX_STAT_AC20 0x000015d0
+ #define BNX2_EMAC_RX_STAT_AC21 0x000015d4
+ #define BNX2_EMAC_RX_STAT_AC22 0x000015d8
+ #define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc
+ #define BNX2_EMAC_RX_STAT_AC_28 0x000015f4
+ #define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600
+ #define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608
+ #define BNX2_EMAC_TX_STAT_OUTXONSENT 0x0000160c
+ #define BNX2_EMAC_TX_STAT_OUTXOFFSENT 0x00001610
+ #define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE 0x00001614
+ #define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES 0x00001618
+ #define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES 0x0000161c
+ #define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS 0x00001620
+ #define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS 0x00001624
+ #define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS 0x00001628
+ #define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS 0x0000162c
+ #define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS 0x00001630
+ #define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS 0x00001634
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS 0x00001638
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x0000163c
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001640
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c
+ #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001650
+ #define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654
+ #define BNX2_EMAC_TXMAC_DEBUG0 0x00001658
+ #define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE (0xfL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE (0x0L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0 (0x1L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0 (0x4L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1 (0x5L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2 (0x6L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3 (0x7L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0 (0x8L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1 (0x9L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE (1L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC (1L<<5)
+ #define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER (0xfL<<6)
+ #define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE (1L<<10)
+ #define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION (1L<<11)
+ #define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER (1L<<12)
+ #define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED (1L<<13)
+ #define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE (1L<<14)
+ #define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME (0xfL<<15)
+ #define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME (0xffL<<19)
+
+ #define BNX2_EMAC_TXMAC_DEBUG2 0x00001660
+ #define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF (0x3ffL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT (0xffffL<<10)
+ #define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT (0x1fL<<26)
+ #define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT (1L<<31)
+
+ #define BNX2_EMAC_TXMAC_DEBUG3 0x00001664
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE (0xfL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE (0x0L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1 (0x1L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2 (0x2L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD (0x3L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA (0x4L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1 (0x5L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2 (0x6L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT (0x7L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB (0x8L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG (0x9L<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM (0xaL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM (0xbL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM (0xcL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT (0xdL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF (0xeL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE (0x7L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE (0x0L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT (0x1L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI (0x2L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC (0x3L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2 (0x4L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3 (0x5L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC (0x6L<<4)
+ #define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE (1L<<7)
+ #define BNX2_EMAC_TXMAC_DEBUG3_XOFF (1L<<8)
+ #define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER (0xfL<<9)
+ #define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER (0x1fL<<13)
+
+ #define BNX2_EMAC_TXMAC_DEBUG4 0x00001668
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER (0xffffL<<0)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE (0xfL<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16)
+ #define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20)
+ #define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21)
+ #define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22)
+ #define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER (1L<<23)
+ #define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND (1L<<24)
+ #define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING (1L<<25)
+ #define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC (1L<<26)
+ #define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING (1L<<27)
+ #define BNX2_EMAC_TXMAC_DEBUG4_COL_IN (1L<<28)
+ #define BNX2_EMAC_TXMAC_DEBUG4_BURSTING (1L<<29)
+ #define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE (1L<<30)
+ #define BNX2_EMAC_TXMAC_DEBUG4_GO (1L<<31)
+
+ #define BNX2_EMAC_TX_STAT_AC0 0x00001680
+ #define BNX2_EMAC_TX_STAT_AC1 0x00001684
+ #define BNX2_EMAC_TX_STAT_AC2 0x00001688
+ #define BNX2_EMAC_TX_STAT_AC3 0x0000168c
+ #define BNX2_EMAC_TX_STAT_AC4 0x00001690
+ #define BNX2_EMAC_TX_STAT_AC5 0x00001694
+ #define BNX2_EMAC_TX_STAT_AC6 0x00001698
+ #define BNX2_EMAC_TX_STAT_AC7 0x0000169c
+ #define BNX2_EMAC_TX_STAT_AC8 0x000016a0
+ #define BNX2_EMAC_TX_STAT_AC9 0x000016a4
+ #define BNX2_EMAC_TX_STAT_AC10 0x000016a8
+ #define BNX2_EMAC_TX_STAT_AC11 0x000016ac
+ #define BNX2_EMAC_TX_STAT_AC12 0x000016b0
+ #define BNX2_EMAC_TX_STAT_AC13 0x000016b4
+ #define BNX2_EMAC_TX_STAT_AC14 0x000016b8
+ #define BNX2_EMAC_TX_STAT_AC15 0x000016bc
+ #define BNX2_EMAC_TX_STAT_AC16 0x000016c0
+ #define BNX2_EMAC_TX_STAT_AC17 0x000016c4
+ #define BNX2_EMAC_TX_STAT_AC18 0x000016c8
+ #define BNX2_EMAC_TX_STAT_AC19 0x000016cc
+ #define BNX2_EMAC_TX_STAT_AC20 0x000016d0
+ #define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8
+ #define BNX2_EMAC_TX_RATE_LIMIT_CTRL 0x000016fc
+ #define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_INC (0x7fL<<0)
+ #define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_NUM (0x7fL<<16)
+ #define BNX2_EMAC_TX_RATE_LIMIT_CTRL_RATE_LIMITER_EN (1L<<31)
+
+
+ /*
+ * rpm_reg definition
+ * offset: 0x1800
+ */
+ #define BNX2_RPM_COMMAND 0x00001800
+ #define BNX2_RPM_COMMAND_ENABLED (1L<<0)
+ #define BNX2_RPM_COMMAND_OVERRUN_ABORT (1L<<4)
+
+ #define BNX2_RPM_STATUS 0x00001804
+ #define BNX2_RPM_STATUS_MBUF_WAIT (1L<<0)
+ #define BNX2_RPM_STATUS_FREE_WAIT (1L<<1)
+
+ #define BNX2_RPM_CONFIG 0x00001808
+ #define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM (1L<<0)
+ #define BNX2_RPM_CONFIG_ACPI_ENA (1L<<1)
+ #define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2)
+ #define BNX2_RPM_CONFIG_MP_KEEP (1L<<3)
+ #define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4)
+ #define BNX2_RPM_CONFIG_DISABLE_WOL_ASSERT (1L<<30)
+ #define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31)
+
+ #define BNX2_RPM_MGMT_PKT_CTRL 0x0000180c
+ #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_SORT (0xfL<<0)
+ #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_RULE (0xfL<<4)
+ #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_DISCARD_EN (1L<<30)
+ #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_EN (1L<<31)
+
+ #define BNX2_RPM_VLAN_MATCH0 0x00001810
+ #define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0)
+
+ #define BNX2_RPM_VLAN_MATCH1 0x00001814
+ #define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE (0xfffL<<0)
+
+ #define BNX2_RPM_VLAN_MATCH2 0x00001818
+ #define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE (0xfffL<<0)
+
+ #define BNX2_RPM_VLAN_MATCH3 0x0000181c
+ #define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE (0xfffL<<0)
+
+ #define BNX2_RPM_SORT_USER0 0x00001820
+ #define BNX2_RPM_SORT_USER0_PM_EN (0xffffL<<0)
+ #define BNX2_RPM_SORT_USER0_BC_EN (1L<<16)
+ #define BNX2_RPM_SORT_USER0_MC_EN (1L<<17)
+ #define BNX2_RPM_SORT_USER0_MC_HSH_EN (1L<<18)
+ #define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19)
+ #define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20)
+ #define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24)
+ #define BNX2_RPM_SORT_USER0_VLAN_NOTMATCH (1L<<25)
+ #define BNX2_RPM_SORT_USER0_ENA (1L<<31)
+
+ #define BNX2_RPM_SORT_USER1 0x00001824
+ #define BNX2_RPM_SORT_USER1_PM_EN (0xffffL<<0)
+ #define BNX2_RPM_SORT_USER1_BC_EN (1L<<16)
+ #define BNX2_RPM_SORT_USER1_MC_EN (1L<<17)
+ #define BNX2_RPM_SORT_USER1_MC_HSH_EN (1L<<18)
+ #define BNX2_RPM_SORT_USER1_PROM_EN (1L<<19)
+ #define BNX2_RPM_SORT_USER1_VLAN_EN (0xfL<<20)
+ #define BNX2_RPM_SORT_USER1_PROM_VLAN (1L<<24)
+ #define BNX2_RPM_SORT_USER1_ENA (1L<<31)
+
+ #define BNX2_RPM_SORT_USER2 0x00001828
+ #define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0)
+ #define BNX2_RPM_SORT_USER2_BC_EN (1L<<16)
+ #define BNX2_RPM_SORT_USER2_MC_EN (1L<<17)
+ #define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18)
+ #define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19)
+ #define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20)
+ #define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24)
+ #define BNX2_RPM_SORT_USER2_ENA (1L<<31)
+
+ #define BNX2_RPM_SORT_USER3 0x0000182c
+ #define BNX2_RPM_SORT_USER3_PM_EN (0xffffL<<0)
+ #define BNX2_RPM_SORT_USER3_BC_EN (1L<<16)
+ #define BNX2_RPM_SORT_USER3_MC_EN (1L<<17)
+ #define BNX2_RPM_SORT_USER3_MC_HSH_EN (1L<<18)
+ #define BNX2_RPM_SORT_USER3_PROM_EN (1L<<19)
+ #define BNX2_RPM_SORT_USER3_VLAN_EN (0xfL<<20)
+ #define BNX2_RPM_SORT_USER3_PROM_VLAN (1L<<24)
+ #define BNX2_RPM_SORT_USER3_ENA (1L<<31)
+
+ #define BNX2_RPM_STAT_L2_FILTER_DISCARDS 0x00001840
+ #define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS 0x00001844
+ #define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848
+ #define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c
+ #define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0 0x00001854
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1 0x00001858
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2 0x0000185c
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3 0x00001860
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4 0x00001864
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5 0x00001868
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6 0x0000186c
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7 0x00001870
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN (0xffL<<0)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER (0xffL<<16)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN_TYPE (1L<<30)
+ #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_EN (1L<<31)
+
+ #define BNX2_RPM_STAT_AC0 0x00001880
+ #define BNX2_RPM_STAT_AC1 0x00001884
+ #define BNX2_RPM_STAT_AC2 0x00001888
+ #define BNX2_RPM_STAT_AC3 0x0000188c
+ #define BNX2_RPM_STAT_AC4 0x00001890
+ #define BNX2_RPM_RC_CNTL_16 0x000018e0
+ #define BNX2_RPM_RC_CNTL_16_OFFSET (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_16_CLASS (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_16_PRIORITY (1L<<11)
+ #define BNX2_RPM_RC_CNTL_16_P4 (1L<<12)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_START (0L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_IP (1L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP (2L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_UDP (3L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_DATA (4L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP_UDP (5L<<13)
+ #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_ICMPV6 (6L<<13)
+ #define BNX2_RPM_RC_CNTL_16_COMP (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_16_COMP_EQUAL (0L<<16)
+ #define BNX2_RPM_RC_CNTL_16_COMP_NEQUAL (1L<<16)
+ #define BNX2_RPM_RC_CNTL_16_COMP_GREATER (2L<<16)
+ #define BNX2_RPM_RC_CNTL_16_COMP_LESS (3L<<16)
+ #define BNX2_RPM_RC_CNTL_16_MAP (1L<<18)
+ #define BNX2_RPM_RC_CNTL_16_SBIT (1L<<19)
+ #define BNX2_RPM_RC_CNTL_16_CMDSEL (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_16_DISCARD (1L<<25)
+ #define BNX2_RPM_RC_CNTL_16_MASK (1L<<26)
+ #define BNX2_RPM_RC_CNTL_16_P1 (1L<<27)
+ #define BNX2_RPM_RC_CNTL_16_P2 (1L<<28)
+ #define BNX2_RPM_RC_CNTL_16_P3 (1L<<29)
+ #define BNX2_RPM_RC_CNTL_16_NBIT (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_16 0x000018e4
+ #define BNX2_RPM_RC_VALUE_MASK_16_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_16_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_17 0x000018e8
+ #define BNX2_RPM_RC_CNTL_17_OFFSET (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_17_CLASS (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_17_PRIORITY (1L<<11)
+ #define BNX2_RPM_RC_CNTL_17_P4 (1L<<12)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_START (0L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_IP (1L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP (2L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_UDP (3L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_DATA (4L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP_UDP (5L<<13)
+ #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_ICMPV6 (6L<<13)
+ #define BNX2_RPM_RC_CNTL_17_COMP (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_17_COMP_EQUAL (0L<<16)
+ #define BNX2_RPM_RC_CNTL_17_COMP_NEQUAL (1L<<16)
+ #define BNX2_RPM_RC_CNTL_17_COMP_GREATER (2L<<16)
+ #define BNX2_RPM_RC_CNTL_17_COMP_LESS (3L<<16)
+ #define BNX2_RPM_RC_CNTL_17_MAP (1L<<18)
+ #define BNX2_RPM_RC_CNTL_17_SBIT (1L<<19)
+ #define BNX2_RPM_RC_CNTL_17_CMDSEL (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_17_DISCARD (1L<<25)
+ #define BNX2_RPM_RC_CNTL_17_MASK (1L<<26)
+ #define BNX2_RPM_RC_CNTL_17_P1 (1L<<27)
+ #define BNX2_RPM_RC_CNTL_17_P2 (1L<<28)
+ #define BNX2_RPM_RC_CNTL_17_P3 (1L<<29)
+ #define BNX2_RPM_RC_CNTL_17_NBIT (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_17 0x000018ec
+ #define BNX2_RPM_RC_VALUE_MASK_17_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_17_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_18 0x000018f0
+ #define BNX2_RPM_RC_CNTL_18_OFFSET (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_18_CLASS (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_18_PRIORITY (1L<<11)
+ #define BNX2_RPM_RC_CNTL_18_P4 (1L<<12)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_START (0L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_IP (1L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP (2L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_UDP (3L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_DATA (4L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP_UDP (5L<<13)
+ #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_ICMPV6 (6L<<13)
+ #define BNX2_RPM_RC_CNTL_18_COMP (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_18_COMP_EQUAL (0L<<16)
+ #define BNX2_RPM_RC_CNTL_18_COMP_NEQUAL (1L<<16)
+ #define BNX2_RPM_RC_CNTL_18_COMP_GREATER (2L<<16)
+ #define BNX2_RPM_RC_CNTL_18_COMP_LESS (3L<<16)
+ #define BNX2_RPM_RC_CNTL_18_MAP (1L<<18)
+ #define BNX2_RPM_RC_CNTL_18_SBIT (1L<<19)
+ #define BNX2_RPM_RC_CNTL_18_CMDSEL (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_18_DISCARD (1L<<25)
+ #define BNX2_RPM_RC_CNTL_18_MASK (1L<<26)
+ #define BNX2_RPM_RC_CNTL_18_P1 (1L<<27)
+ #define BNX2_RPM_RC_CNTL_18_P2 (1L<<28)
+ #define BNX2_RPM_RC_CNTL_18_P3 (1L<<29)
+ #define BNX2_RPM_RC_CNTL_18_NBIT (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_18 0x000018f4
+ #define BNX2_RPM_RC_VALUE_MASK_18_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_18_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_19 0x000018f8
+ #define BNX2_RPM_RC_CNTL_19_OFFSET (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_19_CLASS (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_19_PRIORITY (1L<<11)
+ #define BNX2_RPM_RC_CNTL_19_P4 (1L<<12)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_START (0L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_IP (1L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP (2L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_UDP (3L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_DATA (4L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP_UDP (5L<<13)
+ #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_ICMPV6 (6L<<13)
+ #define BNX2_RPM_RC_CNTL_19_COMP (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_19_COMP_EQUAL (0L<<16)
+ #define BNX2_RPM_RC_CNTL_19_COMP_NEQUAL (1L<<16)
+ #define BNX2_RPM_RC_CNTL_19_COMP_GREATER (2L<<16)
+ #define BNX2_RPM_RC_CNTL_19_COMP_LESS (3L<<16)
+ #define BNX2_RPM_RC_CNTL_19_MAP (1L<<18)
+ #define BNX2_RPM_RC_CNTL_19_SBIT (1L<<19)
+ #define BNX2_RPM_RC_CNTL_19_CMDSEL (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_19_DISCARD (1L<<25)
+ #define BNX2_RPM_RC_CNTL_19_MASK (1L<<26)
+ #define BNX2_RPM_RC_CNTL_19_P1 (1L<<27)
+ #define BNX2_RPM_RC_CNTL_19_P2 (1L<<28)
+ #define BNX2_RPM_RC_CNTL_19_P3 (1L<<29)
+ #define BNX2_RPM_RC_CNTL_19_NBIT (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_19 0x000018fc
+ #define BNX2_RPM_RC_VALUE_MASK_19_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_19_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_0 0x00001900
+ #define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_0_PRIORITY (1L<<11)
+ #define BNX2_RPM_RC_CNTL_0_P4 (1L<<12)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START (0L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP (1L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP_UDP (5L<<13)
+ #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_ICMPV6 (6L<<13)
+ #define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16)
+ #define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16)
+ #define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16)
+ #define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16)
+ #define BNX2_RPM_RC_CNTL_0_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19)
+ #define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20)
+ #define BNX2_RPM_RC_CNTL_0_MAP (1L<<24)
+ #define BNX2_RPM_RC_CNTL_0_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25)
+ #define BNX2_RPM_RC_CNTL_0_MASK (1L<<26)
+ #define BNX2_RPM_RC_CNTL_0_P1 (1L<<27)
+ #define BNX2_RPM_RC_CNTL_0_P2 (1L<<28)
+ #define BNX2_RPM_RC_CNTL_0_P3 (1L<<29)
+ #define BNX2_RPM_RC_CNTL_0_NBIT (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_0 0x00001904
+ #define BNX2_RPM_RC_VALUE_MASK_0_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_0_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_1 0x00001908
+ #define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_1_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_1_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_1_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_1_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_1_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_1_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_1_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_1_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_1_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_1_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_1_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_1_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_1_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_1_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_1_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_1_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_1_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_1_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c
+ #define BNX2_RPM_RC_VALUE_MASK_1_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_1_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_2 0x00001910
+ #define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_2_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_2_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_2_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_2_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_2_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_2_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_2_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_2_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_2_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_2_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_2_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_2_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_2_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_2_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_2_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_2_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_2_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_2_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_2 0x00001914
+ #define BNX2_RPM_RC_VALUE_MASK_2_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_2_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_3 0x00001918
+ #define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_3_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_3_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_3_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_3_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_3_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_3_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_3_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_3_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_3_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_3_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_3_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_3_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_3_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_3_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_3_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_3_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_3_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_3_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c
+ #define BNX2_RPM_RC_VALUE_MASK_3_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_3_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_4 0x00001920
+ #define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_4_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_4_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_4_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_4_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_4_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_4_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_4_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_4_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_4_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_4_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_4_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_4_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_4_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_4_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_4_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_4_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_4_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_4_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_4 0x00001924
+ #define BNX2_RPM_RC_VALUE_MASK_4_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_4_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_5 0x00001928
+ #define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_5_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_5_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_5_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_5_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_5_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_5_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_5_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_5_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_5_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_5_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_5_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_5_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_5_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_5_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_5_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_5_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_5_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_5_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c
+ #define BNX2_RPM_RC_VALUE_MASK_5_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_5_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_6 0x00001930
+ #define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_6_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_6_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_6_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_6_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_6_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_6_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_6_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_6_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_6_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_6_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_6_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_6_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_6_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_6_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_6_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_6_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_6_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_6_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_6 0x00001934
+ #define BNX2_RPM_RC_VALUE_MASK_6_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_6_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_7 0x00001938
+ #define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_7_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_7_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_7_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_7_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_7_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_7_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_7_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_7_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_7_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_7_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_7_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_7_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_7_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_7_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_7_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_7_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_7_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_7_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c
+ #define BNX2_RPM_RC_VALUE_MASK_7_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_7_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_8 0x00001940
+ #define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_8_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_8_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_8_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_8_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_8_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_8_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_8_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_8_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_8_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_8_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_8_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_8_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_8_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_8_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_8_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_8_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_8_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_8_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_8 0x00001944
+ #define BNX2_RPM_RC_VALUE_MASK_8_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_8_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_9 0x00001948
+ #define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_9_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_9_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_9_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_9_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_9_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_9_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_9_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_9_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_9_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_9_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_9_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_9_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_9_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_9_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_9_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_9_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_9_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_9_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c
+ #define BNX2_RPM_RC_VALUE_MASK_9_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_9_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_10 0x00001950
+ #define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_10_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_10_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_10_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_10_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_10_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_10_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_10_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_10_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_10_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_10_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_10_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_10_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_10_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_10_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_10_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_10_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_10_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_10_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_10 0x00001954
+ #define BNX2_RPM_RC_VALUE_MASK_10_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_10_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_11 0x00001958
+ #define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_11_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_11_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_11_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_11_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_11_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_11_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_11_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_11_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_11_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_11_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_11_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_11_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_11_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_11_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_11_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_11_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_11_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_11_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c
+ #define BNX2_RPM_RC_VALUE_MASK_11_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_11_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_12 0x00001960
+ #define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_12_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_12_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_12_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_12_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_12_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_12_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_12_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_12_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_12_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_12_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_12_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_12_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_12_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_12_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_12_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_12_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_12_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_12_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_12 0x00001964
+ #define BNX2_RPM_RC_VALUE_MASK_12_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_12_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_13 0x00001968
+ #define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_13_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_13_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_13_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_13_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_13_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_13_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_13_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_13_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_13_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_13_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_13_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_13_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_13_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_13_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_13_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_13_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_13_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_13_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c
+ #define BNX2_RPM_RC_VALUE_MASK_13_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_13_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_14 0x00001970
+ #define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_14_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_14_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_14_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_14_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_14_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_14_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_14_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_14_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_14_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_14_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_14_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_14_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_14_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_14_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_14_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_14_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_14_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_14_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_14 0x00001974
+ #define BNX2_RPM_RC_VALUE_MASK_14_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_14_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CNTL_15 0x00001978
+ #define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0)
+ #define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19)
+ #define BNX2_RPM_RC_CNTL_15_OFFSET_XI (0xffL<<0)
+ #define BNX2_RPM_RC_CNTL_15_CLASS_XI (0x7L<<8)
+ #define BNX2_RPM_RC_CNTL_15_PRIORITY_XI (1L<<11)
+ #define BNX2_RPM_RC_CNTL_15_P4_XI (1L<<12)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_XI (0x7L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_START_XI (0L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_IP_XI (1L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_XI (2L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_UDP_XI (3L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_DATA_XI (4L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_UDP_XI (5L<<13)
+ #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_ICMPV6_XI (6L<<13)
+ #define BNX2_RPM_RC_CNTL_15_COMP_XI (0x3L<<16)
+ #define BNX2_RPM_RC_CNTL_15_COMP_EQUAL_XI (0L<<16)
+ #define BNX2_RPM_RC_CNTL_15_COMP_NEQUAL_XI (1L<<16)
+ #define BNX2_RPM_RC_CNTL_15_COMP_GREATER_XI (2L<<16)
+ #define BNX2_RPM_RC_CNTL_15_COMP_LESS_XI (3L<<16)
+ #define BNX2_RPM_RC_CNTL_15_MAP_XI (1L<<18)
+ #define BNX2_RPM_RC_CNTL_15_SBIT_XI (1L<<19)
+ #define BNX2_RPM_RC_CNTL_15_CMDSEL_XI (0x1fL<<20)
+ #define BNX2_RPM_RC_CNTL_15_DISCARD_XI (1L<<25)
+ #define BNX2_RPM_RC_CNTL_15_MASK_XI (1L<<26)
+ #define BNX2_RPM_RC_CNTL_15_P1_XI (1L<<27)
+ #define BNX2_RPM_RC_CNTL_15_P2_XI (1L<<28)
+ #define BNX2_RPM_RC_CNTL_15_P3_XI (1L<<29)
+ #define BNX2_RPM_RC_CNTL_15_NBIT_XI (1L<<30)
+
+ #define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c
+ #define BNX2_RPM_RC_VALUE_MASK_15_VALUE (0xffffL<<0)
+ #define BNX2_RPM_RC_VALUE_MASK_15_MASK (0xffffL<<16)
+
+ #define BNX2_RPM_RC_CONFIG 0x00001980
+ #define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0)
+ #define BNX2_RPM_RC_CONFIG_RULE_ENABLE_XI (0xfffffL<<0)
+ #define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24)
+ #define BNX2_RPM_RC_CONFIG_KNUM_OVERWRITE (1L<<31)
+
+ #define BNX2_RPM_DEBUG0 0x00001984
+ #define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0)
+ #define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD (1L<<16)
+ #define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD (1L<<17)
+ #define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD (1L<<18)
+ #define BNX2_RPM_DEBUG0_T_IP_OFST_VLD (1L<<19)
+ #define BNX2_RPM_DEBUG0_IP_MORE_FRGMT (1L<<20)
+ #define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR (1L<<21)
+ #define BNX2_RPM_DEBUG0_LLC_SNAP (1L<<22)
+ #define BNX2_RPM_DEBUG0_FM_STARTED (1L<<23)
+ #define BNX2_RPM_DEBUG0_DONE (1L<<24)
+ #define BNX2_RPM_DEBUG0_WAIT_4_DONE (1L<<25)
+ #define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM (1L<<26)
+ #define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM (1L<<27)
+ #define BNX2_RPM_DEBUG0_IGNORE_VLAN (1L<<28)
+ #define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE (1L<<31)
+
+ #define BNX2_RPM_DEBUG1 0x00001988
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST (0xffffL<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE (0L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL (1L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC (2L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP (4L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP (8L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START (16L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP (32L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP (64L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP (128L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH (256L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP (512L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD (1024L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA (2048L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY (0x2000L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT (0x4000L<<0)
+ #define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT (0x8000L<<0)
+ #define BNX2_RPM_DEBUG1_HDR_BCNT (0x7ffL<<16)
+ #define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D (1L<<28)
+ #define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2 (1L<<29)
+ #define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1 (1L<<30)
+ #define BNX2_RPM_DEBUG1_EOF_0XTRA_WD (1L<<31)
+
+ #define BNX2_RPM_DEBUG2 0x0000198c
+ #define BNX2_RPM_DEBUG2_CMD_HIT_VEC (0xffffL<<0)
+ #define BNX2_RPM_DEBUG2_IP_BCNT (0xffL<<16)
+ #define BNX2_RPM_DEBUG2_THIS_CMD_M4 (1L<<24)
+ #define BNX2_RPM_DEBUG2_THIS_CMD_M3 (1L<<25)
+ #define BNX2_RPM_DEBUG2_THIS_CMD_M2 (1L<<26)
+ #define BNX2_RPM_DEBUG2_THIS_CMD_M1 (1L<<27)
+ #define BNX2_RPM_DEBUG2_IPIPE_EMPTY (1L<<28)
+ #define BNX2_RPM_DEBUG2_FM_DISCARD (1L<<29)
+ #define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2 (1L<<30)
+ #define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1 (1L<<31)
+
+ #define BNX2_RPM_DEBUG3 0x00001990
+ #define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR (0x1ffL<<0)
+ #define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT (1L<<9)
+ #define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT (1L<<10)
+ #define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT (1L<<11)
+ #define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ (1L<<12)
+ #define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ (1L<<13)
+ #define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL (1L<<14)
+ #define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP (1L<<15)
+ #define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT (0xfL<<16)
+ #define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL (1L<<21)
+ #define BNX2_RPM_DEBUG3_DROP_NXT_VLD (1L<<22)
+ #define BNX2_RPM_DEBUG3_DROP_NXT (1L<<23)
+ #define BNX2_RPM_DEBUG3_FTQ_FSM (0x3L<<24)
+ #define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE (0x0L<<24)
+ #define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK (0x1L<<24)
+ #define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE (0x2L<<24)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM (0x3L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF (0x0L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF (0x1L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA (0x2L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA (0x3L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF (0x4L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK (0x5L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD (0x6L<<26)
+ #define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE (0x7L<<26)
+ #define BNX2_RPM_DEBUG3_MBFREE_FSM (1L<<29)
+ #define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE (0L<<29)
+ #define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK (1L<<29)
+ #define BNX2_RPM_DEBUG3_MBALLOC_FSM (1L<<30)
+ #define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF (0x0L<<30)
+ #define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF (0x1L<<30)
+ #define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR (1L<<31)
+
+ #define BNX2_RPM_DEBUG4 0x00001994
+ #define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER (0x1ffffffL<<0)
+ #define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE (0x7L<<25)
+ #define BNX2_RPM_DEBUG4_MBWRITE_FSM (0x7L<<28)
+ #define BNX2_RPM_DEBUG4_DFIFO_EMPTY (1L<<31)
+
+ #define BNX2_RPM_DEBUG5 0x00001998
+ #define BNX2_RPM_DEBUG5_RDROP_WPTR (0x1fL<<0)
+ #define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR (0x1fL<<5)
+ #define BNX2_RPM_DEBUG5_RDROP_MC_RPTR (0x1fL<<10)
+ #define BNX2_RPM_DEBUG5_RDROP_RC_RPTR (0x1fL<<15)
+ #define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY (1L<<20)
+ #define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY (1L<<21)
+ #define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR (1L<<22)
+ #define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT (1L<<23)
+ #define BNX2_RPM_DEBUG5_HOLDREG_DISCARD (1L<<24)
+ #define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL (1L<<25)
+ #define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY (1L<<26)
+ #define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY (1L<<27)
+ #define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY (1L<<28)
+ #define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY (1L<<29)
+ #define BNX2_RPM_DEBUG5_HOLDREG_FULL_T (1L<<30)
+ #define BNX2_RPM_DEBUG5_HOLDREG_RD (1L<<31)
+
+ #define BNX2_RPM_DEBUG6 0x0000199c
+ #define BNX2_RPM_DEBUG6_ACPI_VEC (0xffffL<<0)
+ #define BNX2_RPM_DEBUG6_VEC (0xffffL<<16)
+
+ #define BNX2_RPM_DEBUG7 0x000019a0
+ #define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC (0xffffffffL<<0)
+
+ #define BNX2_RPM_DEBUG8 0x000019a4
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM (0xfL<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE (0L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR (1L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR (2L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR (3L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF (4L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA (5L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR (6L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR (7L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR (8L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR (9L<<0)
+ #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF (10L<<0)
+ #define BNX2_RPM_DEBUG8_COMPARE_AT_W0 (1L<<4)
+ #define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA (1L<<5)
+ #define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT (1L<<6)
+ #define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3 (1L<<7)
+ #define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2 (1L<<8)
+ #define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES (1L<<9)
+ #define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES (1L<<10)
+ #define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES (1L<<11)
+ #define BNX2_RPM_DEBUG8_EOF_DET (1L<<12)
+ #define BNX2_RPM_DEBUG8_SOF_DET (1L<<13)
+ #define BNX2_RPM_DEBUG8_WAIT_4_SOF (1L<<14)
+ #define BNX2_RPM_DEBUG8_ALL_DONE (1L<<15)
+ #define BNX2_RPM_DEBUG8_THBUF_ADDR (0x7fL<<16)
+ #define BNX2_RPM_DEBUG8_BYTE_CTR (0xffL<<24)
+
+ #define BNX2_RPM_DEBUG9 0x000019a8
+ #define BNX2_RPM_DEBUG9_OUTFIFO_COUNT (0x7L<<0)
+ #define BNX2_RPM_DEBUG9_RDE_ACPI_RDY (1L<<3)
+ #define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT (0x7L<<4)
+ #define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED (1L<<28)
+ #define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29)
+ #define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30)
+ #define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31)
+ #define BNX2_RPM_DEBUG9_BEMEM_R_XI (0x1fL<<0)
+ #define BNX2_RPM_DEBUG9_EO_XI (1L<<5)
+ #define BNX2_RPM_DEBUG9_AEOF_DE_XI (1L<<6)
+ #define BNX2_RPM_DEBUG9_SO_XI (1L<<7)
+ #define BNX2_RPM_DEBUG9_WD64_CT_XI (0x1fL<<8)
+ #define BNX2_RPM_DEBUG9_EOF_VLDBYTE_XI (0x7L<<13)
+ #define BNX2_RPM_DEBUG9_ACPI_RDE_PAT_ID_XI (0xfL<<16)
+ #define BNX2_RPM_DEBUG9_CALCRC_RESULT_XI (0x3ffL<<20)
+ #define BNX2_RPM_DEBUG9_DATA_IN_VL_XI (1L<<30)
+ #define BNX2_RPM_DEBUG9_CALCRC_BUFFER_VLD_XI (1L<<31)
+
+ #define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0
+ #define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4
+ #define BNX2_RPM_ACPI_DBG_BUF_W02 0x000019c8
+ #define BNX2_RPM_ACPI_DBG_BUF_W03 0x000019cc
+ #define BNX2_RPM_ACPI_DBG_BUF_W10 0x000019d0
+ #define BNX2_RPM_ACPI_DBG_BUF_W11 0x000019d4
+ #define BNX2_RPM_ACPI_DBG_BUF_W12 0x000019d8
+ #define BNX2_RPM_ACPI_DBG_BUF_W13 0x000019dc
+ #define BNX2_RPM_ACPI_DBG_BUF_W20 0x000019e0
+ #define BNX2_RPM_ACPI_DBG_BUF_W21 0x000019e4
+ #define BNX2_RPM_ACPI_DBG_BUF_W22 0x000019e8
+ #define BNX2_RPM_ACPI_DBG_BUF_W23 0x000019ec
+ #define BNX2_RPM_ACPI_DBG_BUF_W30 0x000019f0
+ #define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4
+ #define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8
+ #define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc
+ #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL 0x00001a00
+ #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_BYTE_ADDRESS (0xffffL<<0)
+ #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_DEBUGRD (1L<<28)
+ #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_MODE (1L<<29)
+ #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_INIT (1L<<30)
+ #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_WR (1L<<31)
+
+ #define BNX2_RPM_ACPI_PATTERN_CTRL 0x00001a04
+ #define BNX2_RPM_ACPI_PATTERN_CTRL_PATTERN_ID (0xfL<<0)
+ #define BNX2_RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR (1L<<30)
+ #define BNX2_RPM_ACPI_PATTERN_CTRL_WR (1L<<31)
+
+ #define BNX2_RPM_ACPI_DATA 0x00001a08
+ #define BNX2_RPM_ACPI_DATA_PATTERN_BE (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_LEN0 0x00001a0c
+ #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN3 (0xffL<<0)
+ #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN2 (0xffL<<8)
+ #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN1 (0xffL<<16)
+ #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN0 (0xffL<<24)
+
+ #define BNX2_RPM_ACPI_PATTERN_LEN1 0x00001a10
+ #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN7 (0xffL<<0)
+ #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN6 (0xffL<<8)
+ #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN5 (0xffL<<16)
+ #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN4 (0xffL<<24)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC0 0x00001a18
+ #define BNX2_RPM_ACPI_PATTERN_CRC0_PATTERN_CRC0 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC1 0x00001a1c
+ #define BNX2_RPM_ACPI_PATTERN_CRC1_PATTERN_CRC1 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC2 0x00001a20
+ #define BNX2_RPM_ACPI_PATTERN_CRC2_PATTERN_CRC2 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC3 0x00001a24
+ #define BNX2_RPM_ACPI_PATTERN_CRC3_PATTERN_CRC3 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC4 0x00001a28
+ #define BNX2_RPM_ACPI_PATTERN_CRC4_PATTERN_CRC4 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC5 0x00001a2c
+ #define BNX2_RPM_ACPI_PATTERN_CRC5_PATTERN_CRC5 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC6 0x00001a30
+ #define BNX2_RPM_ACPI_PATTERN_CRC6_PATTERN_CRC6 (0xffffffffL<<0)
+
+ #define BNX2_RPM_ACPI_PATTERN_CRC7 0x00001a34
+ #define BNX2_RPM_ACPI_PATTERN_CRC7_PATTERN_CRC7 (0xffffffffL<<0)
+
+
+ /*
+ * rlup_reg definition
+ * offset: 0x2000
+ */
+ #define BNX2_RLUP_RSS_CONFIG 0x0000201c
+ #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_XI (0x3L<<0)
+ #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI (0L<<0)
+ #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI (1L<<0)
+ #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_IP_ONLY_XI (2L<<0)
+ #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_RES_XI (3L<<0)
+ #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_XI (0x3L<<2)
+ #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI (0L<<2)
+ #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI (1L<<2)
+ #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_IP_ONLY_XI (2L<<2)
+ #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_RES_XI (3L<<2)
+
+ #define BNX2_RLUP_RSS_COMMAND 0x00002048
+ #define BNX2_RLUP_RSS_COMMAND_RSS_IND_TABLE_ADDR (0xfUL<<0)
+ #define BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK (0xffUL<<4)
+ #define BNX2_RLUP_RSS_COMMAND_WRITE (1UL<<12)
+ #define BNX2_RLUP_RSS_COMMAND_READ (1UL<<13)
+ #define BNX2_RLUP_RSS_COMMAND_HASH_MASK (0x7UL<<14)
+
+ #define BNX2_RLUP_RSS_DATA 0x0000204c
+
+
+ /*
+ * rbuf_reg definition
+ * offset: 0x200000
+ */
+ #define BNX2_RBUF_COMMAND 0x00200000
+ #define BNX2_RBUF_COMMAND_ENABLED (1L<<0)
+ #define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1)
+ #define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2)
+ #define BNX2_RBUF_COMMAND_PKT_OFFSET_OVFL (1L<<3)
+ #define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4)
+ #define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5)
+ #define BNX2_RBUF_COMMAND_EN_PRI_CHNGE_TE (1L<<6)
+ #define BNX2_RBUF_COMMAND_CU_ISOLATE_XI (1L<<5)
+ #define BNX2_RBUF_COMMAND_EN_PRI_CHANGE_XI (1L<<6)
+ #define BNX2_RBUF_COMMAND_GRC_ENDIAN_CONV_DIS_XI (1L<<7)
+
+ #define BNX2_RBUF_STATUS1 0x00200004
+ #define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0)
+
+ #define BNX2_RBUF_STATUS2 0x00200008
+ #define BNX2_RBUF_STATUS2_FREE_TAIL (0x1ffL<<0)
+ #define BNX2_RBUF_STATUS2_FREE_HEAD (0x1ffL<<16)
+
+ #define BNX2_RBUF_CONFIG 0x0020000c
+ #define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0)
+ #define BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 31 / 1000) + 54)
+ #define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16)
+ #define BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 39 / 1000) + 66)
+ #define BNX2_RBUF_CONFIG_VAL(mtu) \
+ (BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) | \
+ (BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) << 16))
+
+ #define BNX2_RBUF_FW_BUF_ALLOC 0x00200010
+ #define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7)
+ #define BNX2_RBUF_FW_BUF_ALLOC_TYPE (1L<<16)
+ #define BNX2_RBUF_FW_BUF_ALLOC_ALLOC_REQ (1L<<31)
+
+ #define BNX2_RBUF_FW_BUF_FREE 0x00200014
+ #define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0)
+ #define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7)
+ #define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16)
+ #define BNX2_RBUF_FW_BUF_FREE_TYPE (1L<<25)
+ #define BNX2_RBUF_FW_BUF_FREE_FREE_REQ (1L<<31)
+
+ #define BNX2_RBUF_FW_BUF_SEL 0x00200018
+ #define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0)
+ #define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7)
+ #define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16)
+ #define BNX2_RBUF_FW_BUF_SEL_SEL_REQ (1L<<31)
+
+ #define BNX2_RBUF_CONFIG2 0x0020001c
+ #define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0)
+ #define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 4 / 1000) + 5)
+ #define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16)
+ #define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 2 / 100) + 30)
+ #define BNX2_RBUF_CONFIG2_VAL(mtu) \
+ (BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) | \
+ (BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) << 16))
+
+ #define BNX2_RBUF_CONFIG3 0x00200020
+ #define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0)
+ #define BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 12 / 1000) + 18)
+ #define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16)
+ #define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 2 / 100) + 30)
+ #define BNX2_RBUF_CONFIG3_VAL(mtu) \
+ (BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) | \
+ (BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) << 16))
+
+ #define BNX2_RBUF_PKT_DATA 0x00208000
+ #define BNX2_RBUF_CLIST_DATA 0x00210000
+ #define BNX2_RBUF_BUF_DATA 0x00220000
+
+
+ /*
+ * rv2p_reg definition
+ * offset: 0x2800
+ */
+ #define BNX2_RV2P_COMMAND 0x00002800
+ #define BNX2_RV2P_COMMAND_ENABLED (1L<<0)
+ #define BNX2_RV2P_COMMAND_PROC1_INTRPT (1L<<1)
+ #define BNX2_RV2P_COMMAND_PROC2_INTRPT (1L<<2)
+ #define BNX2_RV2P_COMMAND_ABORT0 (1L<<4)
+ #define BNX2_RV2P_COMMAND_ABORT1 (1L<<5)
+ #define BNX2_RV2P_COMMAND_ABORT2 (1L<<6)
+ #define BNX2_RV2P_COMMAND_ABORT3 (1L<<7)
+ #define BNX2_RV2P_COMMAND_ABORT4 (1L<<8)
+ #define BNX2_RV2P_COMMAND_ABORT5 (1L<<9)
+ #define BNX2_RV2P_COMMAND_PROC1_RESET (1L<<16)
+ #define BNX2_RV2P_COMMAND_PROC2_RESET (1L<<17)
+ #define BNX2_RV2P_COMMAND_CTXIF_RESET (1L<<18)
+
+ #define BNX2_RV2P_STATUS 0x00002804
+ #define BNX2_RV2P_STATUS_ALWAYS_0 (1L<<0)
+ #define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT (1L<<8)
+ #define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT (1L<<9)
+ #define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT (1L<<10)
+ #define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT (1L<<11)
+ #define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT (1L<<12)
+ #define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT (1L<<13)
+
+ #define BNX2_RV2P_CONFIG 0x00002808
+ #define BNX2_RV2P_CONFIG_STALL_PROC1 (1L<<0)
+ #define BNX2_RV2P_CONFIG_STALL_PROC2 (1L<<1)
+ #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0 (1L<<8)
+ #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1 (1L<<9)
+ #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2 (1L<<10)
+ #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3 (1L<<11)
+ #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4 (1L<<12)
+ #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5 (1L<<13)
+ #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0 (1L<<16)
+ #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1 (1L<<17)
+ #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2 (1L<<18)
+ #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3 (1L<<19)
+ #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4 (1L<<20)
+ #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5 (1L<<21)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE (0xfL<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_256 (0L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_512 (1L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_1K (2L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_2K (3L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_4K (4L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_8K (5L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_16K (6L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_32K (7L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_64K (8L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_128K (9L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_256K (10L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_512K (11L<<24)
+ #define BNX2_RV2P_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+ #define BNX2_RV2P_GEN_BFR_ADDR_0 0x00002810
+ #define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE (0xffffL<<16)
+
+ #define BNX2_RV2P_GEN_BFR_ADDR_1 0x00002814
+ #define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE (0xffffL<<16)
+
+ #define BNX2_RV2P_GEN_BFR_ADDR_2 0x00002818
+ #define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE (0xffffL<<16)
+
+ #define BNX2_RV2P_GEN_BFR_ADDR_3 0x0000281c
+ #define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE (0xffffL<<16)
+
+ #define BNX2_RV2P_INSTR_HIGH 0x00002830
+ #define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0)
+
+ #define BNX2_RV2P_INSTR_LOW 0x00002834
+ #define BNX2_RV2P_INSTR_LOW_LOW (0xffffffffL<<0)
+
+ #define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838
+ #define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0)
+ #define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31)
+
+ #define BNX2_RV2P_PROC2_ADDR_CMD 0x0000283c
+ #define BNX2_RV2P_PROC2_ADDR_CMD_ADD (0x3ffL<<0)
+ #define BNX2_RV2P_PROC2_ADDR_CMD_RDWR (1L<<31)
+
+ #define BNX2_RV2P_PROC1_GRC_DEBUG 0x00002840
+ #define BNX2_RV2P_PROC2_GRC_DEBUG 0x00002844
+ #define BNX2_RV2P_GRC_PROC_DEBUG 0x00002848
+ #define BNX2_RV2P_DEBUG_VECT_PEEK 0x0000284c
+ #define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_RV2P_MPFE_PFE_CTL 0x00002afc
+ #define BNX2_RV2P_MPFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+ #define BNX2_RV2P_MPFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+ #define BNX2_RV2P_MPFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+ #define BNX2_RV2P_RV2PPQ 0x00002b40
+ #define BNX2_RV2P_PFTQ_CMD 0x00002b78
+ #define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_RV2P_PFTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_RV2P_PFTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_RV2P_PFTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_RV2P_PFTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_RV2P_PFTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_RV2P_PFTQ_CMD_POP (1L<<30)
+ #define BNX2_RV2P_PFTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_RV2P_PFTQ_CTL 0x00002b7c
+ #define BNX2_RV2P_PFTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_RV2P_PFTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_RV2P_RV2PTQ 0x00002b80
+ #define BNX2_RV2P_TFTQ_CMD 0x00002bb8
+ #define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_RV2P_TFTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_RV2P_TFTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_RV2P_TFTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_RV2P_TFTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_RV2P_TFTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_RV2P_TFTQ_CMD_POP (1L<<30)
+ #define BNX2_RV2P_TFTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_RV2P_TFTQ_CTL 0x00002bbc
+ #define BNX2_RV2P_TFTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_RV2P_TFTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_RV2P_RV2PMQ 0x00002bc0
+ #define BNX2_RV2P_MFTQ_CMD 0x00002bf8
+ #define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_RV2P_MFTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_RV2P_MFTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_RV2P_MFTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_RV2P_MFTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_RV2P_MFTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_RV2P_MFTQ_CMD_POP (1L<<30)
+ #define BNX2_RV2P_MFTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_RV2P_MFTQ_CTL 0x00002bfc
+ #define BNX2_RV2P_MFTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_RV2P_MFTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+ /*
+ * mq_reg definition
+ * offset: 0x3c00
+ */
+ #define BNX2_MQ_COMMAND 0x00003c00
+ #define BNX2_MQ_COMMAND_ENABLED (1L<<0)
+ #define BNX2_MQ_COMMAND_INIT (1L<<1)
+ #define BNX2_MQ_COMMAND_OVERFLOW (1L<<4)
+ #define BNX2_MQ_COMMAND_WR_ERROR (1L<<5)
+ #define BNX2_MQ_COMMAND_RD_ERROR (1L<<6)
+ #define BNX2_MQ_COMMAND_IDB_CFG_ERROR (1L<<7)
+ #define BNX2_MQ_COMMAND_IDB_OVERFLOW (1L<<10)
+ #define BNX2_MQ_COMMAND_NO_BIN_ERROR (1L<<11)
+ #define BNX2_MQ_COMMAND_NO_MAP_ERROR (1L<<12)
+
+ #define BNX2_MQ_STATUS 0x00003c04
+ #define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16)
+ #define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17)
+ #define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18)
+ #define BNX2_MQ_STATUS_IDB_OFLOW_STAT (1L<<19)
+
+ #define BNX2_MQ_CONFIG 0x00003c08
+ #define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0)
+ #define BNX2_MQ_CONFIG_HALT_DIS (1L<<1)
+ #define BNX2_MQ_CONFIG_BIN_MQ_MODE (1L<<2)
+ #define BNX2_MQ_CONFIG_DIS_IDB_DROP (1L<<3)
+ #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4)
+ #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4)
+ #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4)
+ #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K (2L<<4)
+ #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K (3L<<4)
+ #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K (4L<<4)
+ #define BNX2_MQ_CONFIG_MAX_DEPTH (0x7fL<<8)
+ #define BNX2_MQ_CONFIG_CUR_DEPTH (0x7fL<<20)
+
+ #define BNX2_MQ_ENQUEUE1 0x00003c0c
+ #define BNX2_MQ_ENQUEUE1_OFFSET (0x3fL<<2)
+ #define BNX2_MQ_ENQUEUE1_CID (0x3fffL<<8)
+ #define BNX2_MQ_ENQUEUE1_BYTE_MASK (0xfL<<24)
+ #define BNX2_MQ_ENQUEUE1_KNL_MODE (1L<<28)
+
+ #define BNX2_MQ_ENQUEUE2 0x00003c10
+ #define BNX2_MQ_BAD_WR_ADDR 0x00003c14
+ #define BNX2_MQ_BAD_RD_ADDR 0x00003c18
+ #define BNX2_MQ_KNL_BYP_WIND_START 0x00003c1c
+ #define BNX2_MQ_KNL_BYP_WIND_START_VALUE (0xfffffL<<12)
+
+ #define BNX2_MQ_KNL_WIND_END 0x00003c20
+ #define BNX2_MQ_KNL_WIND_END_VALUE (0xffffffL<<8)
+
+ #define BNX2_MQ_KNL_WRITE_MASK1 0x00003c24
+ #define BNX2_MQ_KNL_TX_MASK1 0x00003c28
+ #define BNX2_MQ_KNL_CMD_MASK1 0x00003c2c
+ #define BNX2_MQ_KNL_COND_ENQUEUE_MASK1 0x00003c30
+ #define BNX2_MQ_KNL_RX_V2P_MASK1 0x00003c34
+ #define BNX2_MQ_KNL_WRITE_MASK2 0x00003c38
+ #define BNX2_MQ_KNL_TX_MASK2 0x00003c3c
+ #define BNX2_MQ_KNL_CMD_MASK2 0x00003c40
+ #define BNX2_MQ_KNL_COND_ENQUEUE_MASK2 0x00003c44
+ #define BNX2_MQ_KNL_RX_V2P_MASK2 0x00003c48
+ #define BNX2_MQ_KNL_BYP_WRITE_MASK1 0x00003c4c
+ #define BNX2_MQ_KNL_BYP_TX_MASK1 0x00003c50
+ #define BNX2_MQ_KNL_BYP_CMD_MASK1 0x00003c54
+ #define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1 0x00003c58
+ #define BNX2_MQ_KNL_BYP_RX_V2P_MASK1 0x00003c5c
+ #define BNX2_MQ_KNL_BYP_WRITE_MASK2 0x00003c60
+ #define BNX2_MQ_KNL_BYP_TX_MASK2 0x00003c64
+ #define BNX2_MQ_KNL_BYP_CMD_MASK2 0x00003c68
+ #define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2 0x00003c6c
+ #define BNX2_MQ_KNL_BYP_RX_V2P_MASK2 0x00003c70
+ #define BNX2_MQ_MEM_WR_ADDR 0x00003c74
+ #define BNX2_MQ_MEM_WR_ADDR_VALUE (0x3fL<<0)
+
+ #define BNX2_MQ_MEM_WR_DATA0 0x00003c78
+ #define BNX2_MQ_MEM_WR_DATA0_VALUE (0xffffffffL<<0)
+
+ #define BNX2_MQ_MEM_WR_DATA1 0x00003c7c
+ #define BNX2_MQ_MEM_WR_DATA1_VALUE (0xffffffffL<<0)
+
+ #define BNX2_MQ_MEM_WR_DATA2 0x00003c80
+ #define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0)
+ #define BNX2_MQ_MEM_WR_DATA2_VALUE_XI (0x7fffffffL<<0)
+
+ #define BNX2_MQ_MEM_RD_ADDR 0x00003c84
+ #define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0)
+
+ #define BNX2_MQ_MEM_RD_DATA0 0x00003c88
+ #define BNX2_MQ_MEM_RD_DATA0_VALUE (0xffffffffL<<0)
+
+ #define BNX2_MQ_MEM_RD_DATA1 0x00003c8c
+ #define BNX2_MQ_MEM_RD_DATA1_VALUE (0xffffffffL<<0)
+
+ #define BNX2_MQ_MEM_RD_DATA2 0x00003c90
+ #define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0)
+ #define BNX2_MQ_MEM_RD_DATA2_VALUE_XI (0x7fffffffL<<0)
+
+ #define BNX2_MQ_MAP_L2_3 0x00003d2c
+ #define BNX2_MQ_MAP_L2_3_MQ_OFFSET (0xffL<<0)
+ #define BNX2_MQ_MAP_L2_3_SZ (0x3L<<8)
+ #define BNX2_MQ_MAP_L2_3_CTX_OFFSET (0x2ffL<<10)
+ #define BNX2_MQ_MAP_L2_3_BIN_OFFSET (0x7L<<23)
+ #define BNX2_MQ_MAP_L2_3_ARM (0x3L<<26)
+ #define BNX2_MQ_MAP_L2_3_ENA (0x1L<<31)
+ #define BNX2_MQ_MAP_L2_3_DEFAULT 0x82004646
+
+ #define BNX2_MQ_MAP_L2_5 0x00003d34
+ #define BNX2_MQ_MAP_L2_5_ARM (0x3L<<26)
+
+ /*
+ * tsch_reg definition
+ * offset: 0x4c00
+ */
+ #define BNX2_TSCH_TSS_CFG 0x00004c1c
+ #define BNX2_TSCH_TSS_CFG_TSS_START_CID (0x7ffL<<8)
+ #define BNX2_TSCH_TSS_CFG_NUM_OF_TSS_CON (0xfL<<24)
+
+
+
+ /*
+ * tbdr_reg definition
+ * offset: 0x5000
+ */
+ #define BNX2_TBDR_COMMAND 0x00005000
+ #define BNX2_TBDR_COMMAND_ENABLE (1L<<0)
+ #define BNX2_TBDR_COMMAND_SOFT_RST (1L<<1)
+ #define BNX2_TBDR_COMMAND_MSTR_ABORT (1L<<4)
+
+ #define BNX2_TBDR_STATUS 0x00005004
+ #define BNX2_TBDR_STATUS_DMA_WAIT (1L<<0)
+ #define BNX2_TBDR_STATUS_FTQ_WAIT (1L<<1)
+ #define BNX2_TBDR_STATUS_FIFO_OVERFLOW (1L<<2)
+ #define BNX2_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3)
+ #define BNX2_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4)
+ #define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5)
+ #define BNX2_TBDR_STATUS_BURST_CNT (1L<<6)
+
+ #define BNX2_TBDR_CONFIG 0x00005008
+ #define BNX2_TBDR_CONFIG_MAX_BDS (0xffL<<0)
+ #define BNX2_TBDR_CONFIG_SWAP_MODE (1L<<8)
+ #define BNX2_TBDR_CONFIG_PRIORITY (1L<<9)
+ #define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE (0xfL<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24)
+ #define BNX2_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+ #define BNX2_TBDR_DEBUG_VECT_PEEK 0x0000500c
+ #define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_TBDR_CKSUM_ERROR_STATUS 0x00005010
+ #define BNX2_TBDR_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+ #define BNX2_TBDR_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
+ #define BNX2_TBDR_TBDRQ 0x000053c0
+ #define BNX2_TBDR_FTQ_CMD 0x000053f8
+ #define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_TBDR_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_TBDR_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_TBDR_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_TBDR_FTQ_CMD_POP (1L<<30)
+ #define BNX2_TBDR_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_TBDR_FTQ_CTL 0x000053fc
+ #define BNX2_TBDR_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_TBDR_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+ /*
+ * tdma_reg definition
+ * offset: 0x5c00
+ */
+ #define BNX2_TDMA_COMMAND 0x00005c00
+ #define BNX2_TDMA_COMMAND_ENABLED (1L<<0)
+ #define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4)
+ #define BNX2_TDMA_COMMAND_CS16_ERR (1L<<5)
+ #define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
+ #define BNX2_TDMA_COMMAND_MASK_CS1 (1L<<20)
+ #define BNX2_TDMA_COMMAND_MASK_CS2 (1L<<21)
+ #define BNX2_TDMA_COMMAND_MASK_CS3 (1L<<22)
+ #define BNX2_TDMA_COMMAND_MASK_CS4 (1L<<23)
+ #define BNX2_TDMA_COMMAND_FORCE_ILOCK_CKERR (1L<<24)
+ #define BNX2_TDMA_COMMAND_OFIFO_CLR (1L<<30)
+ #define BNX2_TDMA_COMMAND_IFIFO_CLR (1L<<31)
+
+ #define BNX2_TDMA_STATUS 0x00005c04
+ #define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0)
+ #define BNX2_TDMA_STATUS_PAYLOAD_WAIT (1L<<1)
+ #define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2)
+ #define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3)
+ #define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16)
+ #define BNX2_TDMA_STATUS_BURST_CNT (1L<<17)
+ #define BNX2_TDMA_STATUS_MAX_IFIFO_DEPTH (0x3fL<<20)
+ #define BNX2_TDMA_STATUS_OFIFO_OVERFLOW (1L<<30)
+ #define BNX2_TDMA_STATUS_IFIFO_OVERFLOW (1L<<31)
+
+ #define BNX2_TDMA_CONFIG 0x00005c08
+ #define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0)
+ #define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1)
+ #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN (0x3L<<2)
+ #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_0 (0L<<2)
+ #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_1 (1L<<2)
+ #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_2 (2L<<2)
+ #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_3 (3L<<2)
+ #define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4)
+ #define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4)
+ #define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4)
+ #define BNX2_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4)
+ #define BNX2_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4)
+ #define BNX2_TDMA_CONFIG_LINE_SZ (0xfL<<8)
+ #define BNX2_TDMA_CONFIG_LINE_SZ_64 (0L<<8)
+ #define BNX2_TDMA_CONFIG_LINE_SZ_128 (4L<<8)
+ #define BNX2_TDMA_CONFIG_LINE_SZ_256 (6L<<8)
+ #define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8)
+ #define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15)
+ #define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16)
+ #define BNX2_TDMA_CONFIG_CMPL_ENTRY (1L<<17)
+ #define BNX2_TDMA_CONFIG_OFIFO_CMP (1L<<19)
+ #define BNX2_TDMA_CONFIG_OFIFO_CMP_3 (0L<<19)
+ #define BNX2_TDMA_CONFIG_OFIFO_CMP_2 (1L<<19)
+ #define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_XI (0x7L<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_0_XI (0L<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_4_XI (1L<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_8_XI (2L<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_16_XI (3L<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_32_XI (4L<<20)
+ #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_64_XI (5L<<20)
+ #define BNX2_TDMA_CONFIG_FIFO_CMP_EN_XI (1L<<23)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_XI (0x7L<<24)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_512_XI (0L<<24)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_1024_XI (1L<<24)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_2048_XI (2L<<24)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_4096_XI (3L<<24)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_8192_XI (4L<<24)
+ #define BNX2_TDMA_CONFIG_BYTES_OST_16384_XI (5L<<24)
+ #define BNX2_TDMA_CONFIG_HC_BYPASS_XI (1L<<27)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_XI (0x7L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_128_XI (0L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_256_XI (1L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_512_XI (2L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_1024_XI (3L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_2048_XI (4L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_4096_XI (5L<<28)
+ #define BNX2_TDMA_CONFIG_LCL_MRRS_EN_XI (1L<<31)
+
+ #define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c
+ #define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3)
+
+ #define BNX2_TDMA_DBG_WATCHDOG 0x00005c10
+ #define BNX2_TDMA_DBG_TRIGGER 0x00005c14
+ #define BNX2_TDMA_DMAD_FSM 0x00005c80
+ #define BNX2_TDMA_DMAD_FSM_BD_INVLD (1L<<0)
+ #define BNX2_TDMA_DMAD_FSM_PUSH (0xfL<<4)
+ #define BNX2_TDMA_DMAD_FSM_ARB_TBDC (0x3L<<8)
+ #define BNX2_TDMA_DMAD_FSM_ARB_CTX (1L<<12)
+ #define BNX2_TDMA_DMAD_FSM_DR_INTF (1L<<16)
+ #define BNX2_TDMA_DMAD_FSM_DMAD (0x7L<<20)
+ #define BNX2_TDMA_DMAD_FSM_BD (0xfL<<24)
+
+ #define BNX2_TDMA_DMAD_STATUS 0x00005c84
+ #define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY (0x3L<<0)
+ #define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY (0x3L<<4)
+ #define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY (0x3L<<8)
+ #define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM (0xfL<<12)
+
+ #define BNX2_TDMA_DR_INTF_FSM 0x00005c88
+ #define BNX2_TDMA_DR_INTF_FSM_L2_COMP (0x3L<<0)
+ #define BNX2_TDMA_DR_INTF_FSM_TPATQ (0x7L<<4)
+ #define BNX2_TDMA_DR_INTF_FSM_TPBUF (0x3L<<8)
+ #define BNX2_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12)
+ #define BNX2_TDMA_DR_INTF_FSM_DMAD (0x7L<<16)
+
+ #define BNX2_TDMA_DR_INTF_STATUS 0x00005c8c
+ #define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0)
+ #define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4)
+ #define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8)
+ #define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12)
+ #define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16)
+
+ #define BNX2_TDMA_PUSH_FSM 0x00005c90
+ #define BNX2_TDMA_BD_IF_DEBUG 0x00005c94
+ #define BNX2_TDMA_DMAD_IF_DEBUG 0x00005c98
+ #define BNX2_TDMA_CTX_IF_DEBUG 0x00005c9c
+ #define BNX2_TDMA_TPBUF_IF_DEBUG 0x00005ca0
+ #define BNX2_TDMA_DR_IF_DEBUG 0x00005ca4
+ #define BNX2_TDMA_TPATQ_IF_DEBUG 0x00005ca8
+ #define BNX2_TDMA_TDMA_ILOCK_CKSUM 0x00005cac
+ #define BNX2_TDMA_TDMA_ILOCK_CKSUM_CALCULATED (0xffffL<<0)
+ #define BNX2_TDMA_TDMA_ILOCK_CKSUM_EXPECTED (0xffffL<<16)
+
+ #define BNX2_TDMA_TDMA_PCIE_CKSUM 0x00005cb0
+ #define BNX2_TDMA_TDMA_PCIE_CKSUM_CALCULATED (0xffffL<<0)
+ #define BNX2_TDMA_TDMA_PCIE_CKSUM_EXPECTED (0xffffL<<16)
+
+ #define BNX2_TDMA_TDMAQ 0x00005fc0
+ #define BNX2_TDMA_FTQ_CMD 0x00005ff8
+ #define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_TDMA_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_TDMA_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_TDMA_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_TDMA_FTQ_CMD_POP (1L<<30)
+ #define BNX2_TDMA_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_TDMA_FTQ_CTL 0x00005ffc
+ #define BNX2_TDMA_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_TDMA_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_TDMA_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_TDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+ /*
+ * hc_reg definition
+ * offset: 0x6800
+ */
+ #define BNX2_HC_COMMAND 0x00006800
+ #define BNX2_HC_COMMAND_ENABLE (1L<<0)
+ #define BNX2_HC_COMMAND_SKIP_ABORT (1L<<4)
+ #define BNX2_HC_COMMAND_COAL_NOW (1L<<16)
+ #define BNX2_HC_COMMAND_COAL_NOW_WO_INT (1L<<17)
+ #define BNX2_HC_COMMAND_STATS_NOW (1L<<18)
+ #define BNX2_HC_COMMAND_FORCE_INT (0x3L<<19)
+ #define BNX2_HC_COMMAND_FORCE_INT_NULL (0L<<19)
+ #define BNX2_HC_COMMAND_FORCE_INT_HIGH (1L<<19)
+ #define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19)
+ #define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19)
+ #define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21)
+ #define BNX2_HC_COMMAND_MAIN_PWR_INT (1L<<22)
+ #define BNX2_HC_COMMAND_COAL_ON_NEXT_EVENT (1L<<27)
+
+ #define BNX2_HC_STATUS 0x00006804
+ #define BNX2_HC_STATUS_MASTER_ABORT (1L<<0)
+ #define BNX2_HC_STATUS_PARITY_ERROR_STATE (1L<<1)
+ #define BNX2_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16)
+ #define BNX2_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17)
+ #define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18)
+ #define BNX2_HC_STATUS_NUM_INT_GEN_STAT (1L<<19)
+ #define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20)
+ #define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT (1L<<23)
+ #define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT (1L<<24)
+ #define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT (1L<<25)
+
+ #define BNX2_HC_CONFIG 0x00006808
+ #define BNX2_HC_CONFIG_COLLECT_STATS (1L<<0)
+ #define BNX2_HC_CONFIG_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_CONFIG_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_CONFIG_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_CONFIG_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5)
+ #define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6)
+ #define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8)
+ #define BNX2_HC_CONFIG_PER_MODE (1L<<16)
+ #define BNX2_HC_CONFIG_ONE_SHOT (1L<<17)
+ #define BNX2_HC_CONFIG_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_CONFIG_SET_MASK_AT_RD (1L<<19)
+ #define BNX2_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC (0x7L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_64B (0L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_128B (1L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_256B (2L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_512B (3L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24)
+ #define BNX2_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24)
+ #define BNX2_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29)
+ #define BNX2_HC_CONFIG_UNMASK_ALL (1L<<30)
+ #define BNX2_HC_CONFIG_TX_SEL (1L<<31)
+
+ #define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c
+ #define BNX2_HC_STATUS_ADDR_L 0x00006810
+ #define BNX2_HC_STATUS_ADDR_H 0x00006814
+ #define BNX2_HC_STATISTICS_ADDR_L 0x00006818
+ #define BNX2_HC_STATISTICS_ADDR_H 0x0000681c
+ #define BNX2_HC_TX_QUICK_CONS_TRIP 0x00006820
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP 0x00006824
+ #define BNX2_HC_COMP_PROD_TRIP_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP 0x00006828
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS 0x0000682c
+ #define BNX2_HC_RX_TICKS_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS 0x00006830
+ #define BNX2_HC_TX_TICKS_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS 0x00006834
+ #define BNX2_HC_COM_TICKS_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS 0x00006838
+ #define BNX2_HC_CMD_TICKS_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS 0x0000683c
+ #define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_STAT_COLLECT_TICKS 0x00006840
+ #define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4)
+
+ #define BNX2_HC_STATS_TICKS 0x00006844
+ #define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8)
+
+ #define BNX2_HC_STATS_INTERRUPT_STATUS 0x00006848
+ #define BNX2_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0)
+ #define BNX2_HC_STATS_INTERRUPT_STATUS_INT_STATUS (0x1ffL<<16)
+
+ #define BNX2_HC_STAT_MEM_DATA 0x0000684c
+ #define BNX2_HC_STAT_GEN_SEL_0 0x00006850
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3 (3L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4 (4L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5 (5L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6 (6L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7 (7L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8 (8L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9 (9L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10 (10L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11 (11L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0 (12L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1 (13L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2 (14L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3 (15L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4 (16L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5 (17L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6 (18L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7 (19L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0 (20L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1 (21L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2 (22L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3 (23L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4 (24L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5 (25L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6 (26L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7 (27L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8 (28L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9 (29L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10 (30L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11 (31L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0 (32L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1 (33L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2 (34L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3 (35L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0 (36L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1 (37L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2 (38L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3 (39L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4 (40L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5 (41L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6 (42L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7 (43L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0 (44L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1 (45L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2 (46L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3 (47L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4 (48L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5 (49L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6 (50L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7 (51L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT (52L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT (53L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS (54L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN (55L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR (56L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK (59L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK (60L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK (61L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT (62L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT (63L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT (64L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT (65L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT (75L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT (76L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT (77L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT (78L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT (79L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT (80L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT (81L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT (82L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT (83L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT (84L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT (85L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT (86L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT (87L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT (88L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT (89L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT (90L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT (91L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT (92L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT (93L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT (94L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64 (95L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64 (96L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS (97L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS (98L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT (99L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT (100L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT (101L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT (102L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT (103L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT (104L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT (105L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT (106L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT (107L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT (108L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT (109L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT (110L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT (111L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT (112L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT (113L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT (114L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0 (115L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1 (116L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2 (117L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3 (118L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4 (119L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5 (120L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS (121L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS (122L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT (127L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_XI (0xffL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UMP_RX_FRAME_DROP_XI (52L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S0_XI (57L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S1_XI (58L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S2_XI (85L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S3_XI (86L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S4_XI (87L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S5_XI (88L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S6_XI (89L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S7_XI (90L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S8_XI (91L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S9_XI (92L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S10_XI (93L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MQ_IDB_OFLOW_XI (94L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_RD_CNT_XI (123L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_WR_CNT_XI (124L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_HITS_XI (125L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_MISSES_XI (126L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC1_XI (128L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC1_XI (129L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC1_XI (130L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC1_XI (131L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC1_XI (132L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC1_XI (133L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC2_XI (134L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC2_XI (135L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC2_XI (136L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC2_XI (137L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC2_XI (138L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC2_XI (139L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC3_XI (140L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC3_XI (141L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC3_XI (142L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC3_XI (143L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC3_XI (144L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC3_XI (145L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC4_XI (146L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC4_XI (147L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC4_XI (148L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC4_XI (149L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC4_XI (150L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC4_XI (151L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC5_XI (152L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC5_XI (153L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC5_XI (154L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC5_XI (155L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC5_XI (156L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC5_XI (157L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC6_XI (158L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC6_XI (159L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC6_XI (160L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC6_XI (161L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC6_XI (162L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC6_XI (163L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC7_XI (164L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC7_XI (165L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC7_XI (166L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC7_XI (167L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC7_XI (168L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC7_XI (169L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC8_XI (170L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC8_XI (171L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC8_XI (172L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC8_XI (173L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC8_XI (174L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC8_XI (175L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_CMD_CNT_XI (176L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_SLOT_CNT_XI (177L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI (178L<<0)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1_XI (0xffL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2_XI (0xffL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3_XI (0xffL<<24)
+
+ #define BNX2_HC_STAT_GEN_SEL_1 0x00006854
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4_XI (0xffL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5_XI (0xffL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6_XI (0xffL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7_XI (0xffL<<24)
+
+ #define BNX2_HC_STAT_GEN_SEL_2 0x00006858
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8_XI (0xffL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9_XI (0xffL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10_XI (0xffL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11_XI (0xffL<<24)
+
+ #define BNX2_HC_STAT_GEN_SEL_3 0x0000685c
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12_XI (0xffL<<0)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13_XI (0xffL<<8)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14_XI (0xffL<<16)
+ #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15_XI (0xffL<<24)
+
+ #define BNX2_HC_STAT_GEN_STAT0 0x00006888
+ #define BNX2_HC_STAT_GEN_STAT1 0x0000688c
+ #define BNX2_HC_STAT_GEN_STAT2 0x00006890
+ #define BNX2_HC_STAT_GEN_STAT3 0x00006894
+ #define BNX2_HC_STAT_GEN_STAT4 0x00006898
+ #define BNX2_HC_STAT_GEN_STAT5 0x0000689c
+ #define BNX2_HC_STAT_GEN_STAT6 0x000068a0
+ #define BNX2_HC_STAT_GEN_STAT7 0x000068a4
+ #define BNX2_HC_STAT_GEN_STAT8 0x000068a8
+ #define BNX2_HC_STAT_GEN_STAT9 0x000068ac
+ #define BNX2_HC_STAT_GEN_STAT10 0x000068b0
+ #define BNX2_HC_STAT_GEN_STAT11 0x000068b4
+ #define BNX2_HC_STAT_GEN_STAT12 0x000068b8
+ #define BNX2_HC_STAT_GEN_STAT13 0x000068bc
+ #define BNX2_HC_STAT_GEN_STAT14 0x000068c0
+ #define BNX2_HC_STAT_GEN_STAT15 0x000068c4
+ #define BNX2_HC_STAT_GEN_STAT_AC0 0x000068c8
+ #define BNX2_HC_STAT_GEN_STAT_AC1 0x000068cc
+ #define BNX2_HC_STAT_GEN_STAT_AC2 0x000068d0
+ #define BNX2_HC_STAT_GEN_STAT_AC3 0x000068d4
+ #define BNX2_HC_STAT_GEN_STAT_AC4 0x000068d8
+ #define BNX2_HC_STAT_GEN_STAT_AC5 0x000068dc
+ #define BNX2_HC_STAT_GEN_STAT_AC6 0x000068e0
+ #define BNX2_HC_STAT_GEN_STAT_AC7 0x000068e4
+ #define BNX2_HC_STAT_GEN_STAT_AC8 0x000068e8
+ #define BNX2_HC_STAT_GEN_STAT_AC9 0x000068ec
+ #define BNX2_HC_STAT_GEN_STAT_AC10 0x000068f0
+ #define BNX2_HC_STAT_GEN_STAT_AC11 0x000068f4
+ #define BNX2_HC_STAT_GEN_STAT_AC12 0x000068f8
+ #define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc
+ #define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900
+ #define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904
+ #define BNX2_HC_STAT_GEN_STAT_AC 0x000068c8
+ #define BNX2_HC_VIS 0x00006908
+ #define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_START (1L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST (2L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64 (3L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32 (4L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE (5L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_DMA (6L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL (7L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW (8L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH (9L<<0)
+ #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA (10L<<0)
+ #define BNX2_HC_VIS_DMA_STAT_STATE (0xfL<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_IDLE (0L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM (1L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA (2L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP (3L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_COMP (4L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM (5L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA (6L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1 (7L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2 (8L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_WAIT (9L<<8)
+ #define BNX2_HC_VIS_DMA_STAT_STATE_ABORT (15L<<8)
+ #define BNX2_HC_VIS_DMA_MSI_STATE (0x7L<<12)
+ #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE (0x3L<<15)
+ #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE (0L<<15)
+ #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT (1L<<15)
+ #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START (2L<<15)
+
+ #define BNX2_HC_VIS_1 0x0000690c
+ #define BNX2_HC_VIS_1_HW_INTACK_STATE (1L<<4)
+ #define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE (0L<<4)
+ #define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT (1L<<4)
+ #define BNX2_HC_VIS_1_SW_INTACK_STATE (1L<<5)
+ #define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE (0L<<5)
+ #define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT (1L<<5)
+ #define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE (1L<<6)
+ #define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE (0L<<6)
+ #define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT (1L<<6)
+ #define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE (1L<<7)
+ #define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE (0L<<7)
+ #define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT (1L<<7)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE (0xfL<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE (0L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA (1L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE (2L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN (3L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT (4L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE (5L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN (6L<<17)
+ #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT (7L<<17)
+ #define BNX2_HC_VIS_1_RAM_WR_ARB_STATE (0x3L<<21)
+ #define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL (0L<<21)
+ #define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR (1L<<21)
+ #define BNX2_HC_VIS_1_INT_GEN_STATE (1L<<23)
+ #define BNX2_HC_VIS_1_INT_GEN_STATE_DLE (0L<<23)
+ #define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT (1L<<23)
+ #define BNX2_HC_VIS_1_STAT_CHAN_ID (0x7L<<24)
+ #define BNX2_HC_VIS_1_INT_B (1L<<27)
+
+ #define BNX2_HC_DEBUG_VECT_PEEK 0x00006910
+ #define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_HC_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_HC_COALESCE_NOW 0x00006914
+ #define BNX2_HC_COALESCE_NOW_COAL_NOW (0x1ffL<<1)
+ #define BNX2_HC_COALESCE_NOW_COAL_NOW_WO_INT (0x1ffL<<11)
+ #define BNX2_HC_COALESCE_NOW_COAL_ON_NXT_EVENT (0x1ffL<<21)
+
+ #define BNX2_HC_MSIX_BIT_VECTOR 0x00006918
+ #define BNX2_HC_MSIX_BIT_VECTOR_VAL (0x1ffL<<0)
+
+ #define BNX2_HC_SB_CONFIG_1 0x00006a00
+ #define BNX2_HC_SB_CONFIG_1_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_1_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_1_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_1_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_1_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_1_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_1_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_1_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_1 0x00006a04
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_1_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_1 0x00006a08
+ #define BNX2_HC_COMP_PROD_TRIP_1_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_1_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_1 0x00006a0c
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_1_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_1 0x00006a10
+ #define BNX2_HC_RX_TICKS_1_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_1_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_1 0x00006a14
+ #define BNX2_HC_TX_TICKS_1_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_1_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_1 0x00006a18
+ #define BNX2_HC_COM_TICKS_1_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_1_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_1 0x00006a1c
+ #define BNX2_HC_CMD_TICKS_1_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_1_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_1 0x00006a20
+ #define BNX2_HC_PERIODIC_TICKS_1_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_1_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_2 0x00006a24
+ #define BNX2_HC_SB_CONFIG_2_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_2_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_2_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_2_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_2_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_2_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_2_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_2_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_2 0x00006a28
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_2_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_2 0x00006a2c
+ #define BNX2_HC_COMP_PROD_TRIP_2_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_2_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_2 0x00006a30
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_2_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_2 0x00006a34
+ #define BNX2_HC_RX_TICKS_2_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_2_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_2 0x00006a38
+ #define BNX2_HC_TX_TICKS_2_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_2_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_2 0x00006a3c
+ #define BNX2_HC_COM_TICKS_2_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_2_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_2 0x00006a40
+ #define BNX2_HC_CMD_TICKS_2_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_2_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_2 0x00006a44
+ #define BNX2_HC_PERIODIC_TICKS_2_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_2_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_3 0x00006a48
+ #define BNX2_HC_SB_CONFIG_3_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_3_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_3_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_3_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_3_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_3_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_3_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_3_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_3 0x00006a4c
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_3_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_3 0x00006a50
+ #define BNX2_HC_COMP_PROD_TRIP_3_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_3_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_3 0x00006a54
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_3_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_3 0x00006a58
+ #define BNX2_HC_RX_TICKS_3_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_3_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_3 0x00006a5c
+ #define BNX2_HC_TX_TICKS_3_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_3_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_3 0x00006a60
+ #define BNX2_HC_COM_TICKS_3_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_3_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_3 0x00006a64
+ #define BNX2_HC_CMD_TICKS_3_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_3_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_3 0x00006a68
+ #define BNX2_HC_PERIODIC_TICKS_3_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_3_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_4 0x00006a6c
+ #define BNX2_HC_SB_CONFIG_4_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_4_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_4_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_4_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_4_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_4_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_4_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_4_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_4 0x00006a70
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_4_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_4 0x00006a74
+ #define BNX2_HC_COMP_PROD_TRIP_4_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_4_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_4 0x00006a78
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_4_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_4 0x00006a7c
+ #define BNX2_HC_RX_TICKS_4_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_4_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_4 0x00006a80
+ #define BNX2_HC_TX_TICKS_4_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_4_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_4 0x00006a84
+ #define BNX2_HC_COM_TICKS_4_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_4_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_4 0x00006a88
+ #define BNX2_HC_CMD_TICKS_4_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_4_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_4 0x00006a8c
+ #define BNX2_HC_PERIODIC_TICKS_4_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_4_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_5 0x00006a90
+ #define BNX2_HC_SB_CONFIG_5_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_5_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_5_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_5_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_5_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_5_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_5_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_5_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_5 0x00006a94
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_5_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_5 0x00006a98
+ #define BNX2_HC_COMP_PROD_TRIP_5_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_5_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_5 0x00006a9c
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_5_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_5 0x00006aa0
+ #define BNX2_HC_RX_TICKS_5_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_5_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_5 0x00006aa4
+ #define BNX2_HC_TX_TICKS_5_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_5_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_5 0x00006aa8
+ #define BNX2_HC_COM_TICKS_5_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_5_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_5 0x00006aac
+ #define BNX2_HC_CMD_TICKS_5_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_5_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_5 0x00006ab0
+ #define BNX2_HC_PERIODIC_TICKS_5_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_5_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_6 0x00006ab4
+ #define BNX2_HC_SB_CONFIG_6_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_6_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_6_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_6_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_6_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_6_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_6_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_6_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_6 0x00006ab8
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_6_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_6 0x00006abc
+ #define BNX2_HC_COMP_PROD_TRIP_6_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_6_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_6 0x00006ac0
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_6_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_6 0x00006ac4
+ #define BNX2_HC_RX_TICKS_6_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_6_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_6 0x00006ac8
+ #define BNX2_HC_TX_TICKS_6_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_6_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_6 0x00006acc
+ #define BNX2_HC_COM_TICKS_6_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_6_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_6 0x00006ad0
+ #define BNX2_HC_CMD_TICKS_6_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_6_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_6 0x00006ad4
+ #define BNX2_HC_PERIODIC_TICKS_6_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_6_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_7 0x00006ad8
+ #define BNX2_HC_SB_CONFIG_7_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_7_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_7_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_7_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_7_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_7_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_7_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_7_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_7 0x00006adc
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_7_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_7 0x00006ae0
+ #define BNX2_HC_COMP_PROD_TRIP_7_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_7_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_7 0x00006ae4
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_7_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_7 0x00006ae8
+ #define BNX2_HC_RX_TICKS_7_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_7_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_7 0x00006aec
+ #define BNX2_HC_TX_TICKS_7_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_7_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_7 0x00006af0
+ #define BNX2_HC_COM_TICKS_7_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_7_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_7 0x00006af4
+ #define BNX2_HC_CMD_TICKS_7_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_7_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_7 0x00006af8
+ #define BNX2_HC_PERIODIC_TICKS_7_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_7_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_8 0x00006afc
+ #define BNX2_HC_SB_CONFIG_8_RX_TMR_MODE (1L<<1)
+ #define BNX2_HC_SB_CONFIG_8_TX_TMR_MODE (1L<<2)
+ #define BNX2_HC_SB_CONFIG_8_COM_TMR_MODE (1L<<3)
+ #define BNX2_HC_SB_CONFIG_8_CMD_TMR_MODE (1L<<4)
+ #define BNX2_HC_SB_CONFIG_8_PER_MODE (1L<<16)
+ #define BNX2_HC_SB_CONFIG_8_ONE_SHOT (1L<<17)
+ #define BNX2_HC_SB_CONFIG_8_USE_INT_PARAM (1L<<18)
+ #define BNX2_HC_SB_CONFIG_8_PER_COLLECT_LIMIT (0xfL<<20)
+
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_8 0x00006b00
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_8_INT (0xffL<<16)
+
+ #define BNX2_HC_COMP_PROD_TRIP_8 0x00006b04
+ #define BNX2_HC_COMP_PROD_TRIP_8_VALUE (0xffL<<0)
+ #define BNX2_HC_COMP_PROD_TRIP_8_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_8 0x00006b08
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_8_INT (0xffL<<16)
+
+ #define BNX2_HC_RX_TICKS_8 0x00006b0c
+ #define BNX2_HC_RX_TICKS_8_VALUE (0x3ffL<<0)
+ #define BNX2_HC_RX_TICKS_8_INT (0x3ffL<<16)
+
+ #define BNX2_HC_TX_TICKS_8 0x00006b10
+ #define BNX2_HC_TX_TICKS_8_VALUE (0x3ffL<<0)
+ #define BNX2_HC_TX_TICKS_8_INT (0x3ffL<<16)
+
+ #define BNX2_HC_COM_TICKS_8 0x00006b14
+ #define BNX2_HC_COM_TICKS_8_VALUE (0x3ffL<<0)
+ #define BNX2_HC_COM_TICKS_8_INT (0x3ffL<<16)
+
+ #define BNX2_HC_CMD_TICKS_8 0x00006b18
+ #define BNX2_HC_CMD_TICKS_8_VALUE (0x3ffL<<0)
+ #define BNX2_HC_CMD_TICKS_8_INT (0x3ffL<<16)
+
+ #define BNX2_HC_PERIODIC_TICKS_8 0x00006b1c
+ #define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS (0xffffL<<0)
+ #define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS (0xffffL<<16)
+
+ #define BNX2_HC_SB_CONFIG_SIZE (BNX2_HC_SB_CONFIG_2 - BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_COMP_PROD_TRIP_OFF (BNX2_HC_COMP_PROD_TRIP_1 - \
+ BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_COM_TICKS_OFF (BNX2_HC_COM_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_CMD_TICKS_OFF (BNX2_HC_CMD_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_TX_QUICK_CONS_TRIP_OFF (BNX2_HC_TX_QUICK_CONS_TRIP_1 - \
+ BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_TX_TICKS_OFF (BNX2_HC_TX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_RX_QUICK_CONS_TRIP_OFF (BNX2_HC_RX_QUICK_CONS_TRIP_1 - \
+ BNX2_HC_SB_CONFIG_1)
+ #define BNX2_HC_RX_TICKS_OFF (BNX2_HC_RX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+
+
+ /*
+ * txp_reg definition
+ * offset: 0x40000
+ */
+ #define BNX2_TXP_CPU_MODE 0x00045000
+ #define BNX2_TXP_CPU_MODE_LOCAL_RST (1L<<0)
+ #define BNX2_TXP_CPU_MODE_STEP_ENA (1L<<1)
+ #define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+ #define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+ #define BNX2_TXP_CPU_MODE_MSG_BIT1 (1L<<6)
+ #define BNX2_TXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+ #define BNX2_TXP_CPU_MODE_SOFT_HALT (1L<<10)
+ #define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+ #define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+ #define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+ #define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+ #define BNX2_TXP_CPU_STATE 0x00045004
+ #define BNX2_TXP_CPU_STATE_BREAKPOINT (1L<<0)
+ #define BNX2_TXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+ #define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+ #define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+ #define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+ #define BNX2_TXP_CPU_STATE_BAD_PC_HALTED (1L<<6)
+ #define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+ #define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+ #define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10)
+ #define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12)
++#define BNX2_TXP_CPU_STATE_INTERRUPT (1L<<12)
+ #define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+ #define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+ #define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+ #define BNX2_TXP_CPU_EVENT_MASK 0x00045008
+ #define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+ #define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+ #define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+ #define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+ #define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+ #define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+ #define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+ #define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+ #define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+ #define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+ #define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+ #define BNX2_TXP_CPU_PROGRAM_COUNTER 0x0004501c
+ #define BNX2_TXP_CPU_INSTRUCTION 0x00045020
+ #define BNX2_TXP_CPU_DATA_ACCESS 0x00045024
+ #define BNX2_TXP_CPU_INTERRUPT_ENABLE 0x00045028
+ #define BNX2_TXP_CPU_INTERRUPT_VECTOR 0x0004502c
+ #define BNX2_TXP_CPU_INTERRUPT_SAVED_PC 0x00045030
+ #define BNX2_TXP_CPU_HW_BREAKPOINT 0x00045034
+ #define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+ #define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK 0x00045038
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_TXP_CPU_LAST_BRANCH_ADDR 0x00045048
+ #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+ #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+ #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+ #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+ #define BNX2_TXP_CPU_REG_FILE 0x00045200
+ #define BNX2_TXP_TXPQ 0x000453c0
+ #define BNX2_TXP_FTQ_CMD 0x000453f8
+ #define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_TXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_TXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_TXP_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_TXP_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_TXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_TXP_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_TXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_TXP_FTQ_CMD_POP (1L<<30)
+ #define BNX2_TXP_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_TXP_FTQ_CTL 0x000453fc
+ #define BNX2_TXP_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_TXP_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_TXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_TXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_TXP_SCRATCH 0x00060000
+
+
+ /*
+ * tpat_reg definition
+ * offset: 0x80000
+ */
+ #define BNX2_TPAT_CPU_MODE 0x00085000
+ #define BNX2_TPAT_CPU_MODE_LOCAL_RST (1L<<0)
+ #define BNX2_TPAT_CPU_MODE_STEP_ENA (1L<<1)
+ #define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+ #define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+ #define BNX2_TPAT_CPU_MODE_MSG_BIT1 (1L<<6)
+ #define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA (1L<<7)
+ #define BNX2_TPAT_CPU_MODE_SOFT_HALT (1L<<10)
+ #define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+ #define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+ #define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+ #define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+ #define BNX2_TPAT_CPU_STATE 0x00085004
+ #define BNX2_TPAT_CPU_STATE_BREAKPOINT (1L<<0)
+ #define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED (1L<<2)
+ #define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+ #define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+ #define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+ #define BNX2_TPAT_CPU_STATE_BAD_PC_HALTED (1L<<6)
+ #define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7)
+ #define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+ #define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10)
+ #define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12)
++#define BNX2_TPAT_CPU_STATE_INTERRUPT (1L<<12)
+ #define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+ #define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15)
+ #define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31)
+
+ #define BNX2_TPAT_CPU_EVENT_MASK 0x00085008
+ #define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+ #define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+ #define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+ #define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+ #define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+ #define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+ #define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+ #define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+ #define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+ #define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+ #define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+ #define BNX2_TPAT_CPU_PROGRAM_COUNTER 0x0008501c
+ #define BNX2_TPAT_CPU_INSTRUCTION 0x00085020
+ #define BNX2_TPAT_CPU_DATA_ACCESS 0x00085024
+ #define BNX2_TPAT_CPU_INTERRUPT_ENABLE 0x00085028
+ #define BNX2_TPAT_CPU_INTERRUPT_VECTOR 0x0008502c
+ #define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC 0x00085030
+ #define BNX2_TPAT_CPU_HW_BREAKPOINT 0x00085034
+ #define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+ #define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK 0x00085038
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR 0x00085048
+ #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+ #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+ #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+ #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+ #define BNX2_TPAT_CPU_REG_FILE 0x00085200
+ #define BNX2_TPAT_TPATQ 0x000853c0
+ #define BNX2_TPAT_FTQ_CMD 0x000853f8
+ #define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_TPAT_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_TPAT_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_TPAT_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_TPAT_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_TPAT_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_TPAT_FTQ_CMD_POP (1L<<30)
+ #define BNX2_TPAT_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_TPAT_FTQ_CTL 0x000853fc
+ #define BNX2_TPAT_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_TPAT_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_TPAT_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_TPAT_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_TPAT_SCRATCH 0x000a0000
+
+
+ /*
+ * rxp_reg definition
+ * offset: 0xc0000
+ */
+ #define BNX2_RXP_CPU_MODE 0x000c5000
+ #define BNX2_RXP_CPU_MODE_LOCAL_RST (1L<<0)
+ #define BNX2_RXP_CPU_MODE_STEP_ENA (1L<<1)
+ #define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+ #define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+ #define BNX2_RXP_CPU_MODE_MSG_BIT1 (1L<<6)
+ #define BNX2_RXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+ #define BNX2_RXP_CPU_MODE_SOFT_HALT (1L<<10)
+ #define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+ #define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+ #define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+ #define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+ #define BNX2_RXP_CPU_STATE 0x000c5004
+ #define BNX2_RXP_CPU_STATE_BREAKPOINT (1L<<0)
+ #define BNX2_RXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+ #define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+ #define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+ #define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+ #define BNX2_RXP_CPU_STATE_BAD_PC_HALTED (1L<<6)
+ #define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+ #define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+ #define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10)
+ #define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12)
++#define BNX2_RXP_CPU_STATE_INTERRUPT (1L<<12)
+ #define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+ #define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+ #define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+ #define BNX2_RXP_CPU_EVENT_MASK 0x000c5008
+ #define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+ #define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+ #define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+ #define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+ #define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+ #define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+ #define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+ #define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+ #define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+ #define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+ #define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+ #define BNX2_RXP_CPU_PROGRAM_COUNTER 0x000c501c
+ #define BNX2_RXP_CPU_INSTRUCTION 0x000c5020
+ #define BNX2_RXP_CPU_DATA_ACCESS 0x000c5024
+ #define BNX2_RXP_CPU_INTERRUPT_ENABLE 0x000c5028
+ #define BNX2_RXP_CPU_INTERRUPT_VECTOR 0x000c502c
+ #define BNX2_RXP_CPU_INTERRUPT_SAVED_PC 0x000c5030
+ #define BNX2_RXP_CPU_HW_BREAKPOINT 0x000c5034
+ #define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+ #define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK 0x000c5038
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_RXP_CPU_LAST_BRANCH_ADDR 0x000c5048
+ #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+ #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+ #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+ #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+ #define BNX2_RXP_CPU_REG_FILE 0x000c5200
+ #define BNX2_RXP_PFE_PFE_CTL 0x000c537c
+ #define BNX2_RXP_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+ #define BNX2_RXP_PFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+ #define BNX2_RXP_PFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+ #define BNX2_RXP_RXPCQ 0x000c5380
+ #define BNX2_RXP_CFTQ_CMD 0x000c53b8
+ #define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_RXP_CFTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_RXP_CFTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_RXP_CFTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_RXP_CFTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_RXP_CFTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_RXP_CFTQ_CMD_POP (1L<<30)
+ #define BNX2_RXP_CFTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_RXP_CFTQ_CTL 0x000c53bc
+ #define BNX2_RXP_CFTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_RXP_CFTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_RXP_RXPQ 0x000c53c0
+ #define BNX2_RXP_FTQ_CMD 0x000c53f8
+ #define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_RXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_RXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_RXP_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_RXP_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_RXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_RXP_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_RXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_RXP_FTQ_CMD_POP (1L<<30)
+ #define BNX2_RXP_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_RXP_FTQ_CTL 0x000c53fc
+ #define BNX2_RXP_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_RXP_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_RXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_RXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_RXP_SCRATCH 0x000e0000
+ #define BNX2_RXP_SCRATCH_RXP_FLOOD 0x000e0024
+ #define BNX2_RXP_SCRATCH_RSS_TBL_SZ 0x000e0038
+ #define BNX2_RXP_SCRATCH_RSS_TBL 0x000e003c
+ #define BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES 128
+
+
+ /*
+ * com_reg definition
+ * offset: 0x100000
+ */
+ #define BNX2_COM_CKSUM_ERROR_STATUS 0x00100000
+ #define BNX2_COM_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+ #define BNX2_COM_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
+ #define BNX2_COM_CPU_MODE 0x00105000
+ #define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0)
+ #define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1)
+ #define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+ #define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+ #define BNX2_COM_CPU_MODE_MSG_BIT1 (1L<<6)
+ #define BNX2_COM_CPU_MODE_INTERRUPT_ENA (1L<<7)
+ #define BNX2_COM_CPU_MODE_SOFT_HALT (1L<<10)
+ #define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+ #define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+ #define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+ #define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+ #define BNX2_COM_CPU_STATE 0x00105004
+ #define BNX2_COM_CPU_STATE_BREAKPOINT (1L<<0)
+ #define BNX2_COM_CPU_STATE_BAD_INST_HALTED (1L<<2)
+ #define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+ #define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+ #define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+ #define BNX2_COM_CPU_STATE_BAD_PC_HALTED (1L<<6)
+ #define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7)
+ #define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+ #define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10)
+ #define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12)
++#define BNX2_COM_CPU_STATE_INTERRUPT (1L<<12)
+ #define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+ #define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15)
+ #define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31)
+
+ #define BNX2_COM_CPU_EVENT_MASK 0x00105008
+ #define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+ #define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+ #define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+ #define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+ #define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+ #define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+ #define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+ #define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+ #define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+ #define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+ #define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+ #define BNX2_COM_CPU_PROGRAM_COUNTER 0x0010501c
+ #define BNX2_COM_CPU_INSTRUCTION 0x00105020
+ #define BNX2_COM_CPU_DATA_ACCESS 0x00105024
+ #define BNX2_COM_CPU_INTERRUPT_ENABLE 0x00105028
+ #define BNX2_COM_CPU_INTERRUPT_VECTOR 0x0010502c
+ #define BNX2_COM_CPU_INTERRUPT_SAVED_PC 0x00105030
+ #define BNX2_COM_CPU_HW_BREAKPOINT 0x00105034
+ #define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+ #define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK 0x00105038
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_COM_CPU_LAST_BRANCH_ADDR 0x00105048
+ #define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+ #define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+ #define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+ #define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+ #define BNX2_COM_CPU_REG_FILE 0x00105200
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL 0x001052bc
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+ #define BNX2_COM_COMTQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+ #define BNX2_COM_COMXQ 0x00105340
+ #define BNX2_COM_COMXQ_FTQ_CMD 0x00105378
+ #define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_COM_COMXQ_FTQ_CMD_POP (1L<<30)
+ #define BNX2_COM_COMXQ_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_COM_COMXQ_FTQ_CTL 0x0010537c
+ #define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_COM_COMTQ 0x00105380
+ #define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8
+ #define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_COM_COMTQ_FTQ_CMD_POP (1L<<30)
+ #define BNX2_COM_COMTQ_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_COM_COMTQ_FTQ_CTL 0x001053bc
+ #define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_COM_COMQ 0x001053c0
+ #define BNX2_COM_COMQ_FTQ_CMD 0x001053f8
+ #define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_COM_COMQ_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_COM_COMQ_FTQ_CMD_POP (1L<<30)
+ #define BNX2_COM_COMQ_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_COM_COMQ_FTQ_CTL 0x001053fc
+ #define BNX2_COM_COMQ_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_COM_SCRATCH 0x00120000
+
+ #define BNX2_FW_RX_LOW_LATENCY 0x00120058
+ #define BNX2_FW_RX_DROP_COUNT 0x00120084
+
+
+ /*
+ * cp_reg definition
+ * offset: 0x180000
+ */
+ #define BNX2_CP_CKSUM_ERROR_STATUS 0x00180000
+ #define BNX2_CP_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0)
+ #define BNX2_CP_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16)
+
+ #define BNX2_CP_CPU_MODE 0x00185000
+ #define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0)
+ #define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1)
+ #define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+ #define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+ #define BNX2_CP_CPU_MODE_MSG_BIT1 (1L<<6)
+ #define BNX2_CP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+ #define BNX2_CP_CPU_MODE_SOFT_HALT (1L<<10)
+ #define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+ #define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+ #define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+ #define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+ #define BNX2_CP_CPU_STATE 0x00185004
+ #define BNX2_CP_CPU_STATE_BREAKPOINT (1L<<0)
+ #define BNX2_CP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+ #define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+ #define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+ #define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+ #define BNX2_CP_CPU_STATE_BAD_PC_HALTED (1L<<6)
+ #define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7)
+ #define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+ #define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10)
+ #define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12)
++#define BNX2_CP_CPU_STATE_INTERRUPT (1L<<12)
+ #define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+ #define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+ #define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+ #define BNX2_CP_CPU_EVENT_MASK 0x00185008
+ #define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+ #define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+ #define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+ #define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+ #define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+ #define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+ #define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+ #define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+ #define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+ #define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+ #define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+ #define BNX2_CP_CPU_PROGRAM_COUNTER 0x0018501c
+ #define BNX2_CP_CPU_INSTRUCTION 0x00185020
+ #define BNX2_CP_CPU_DATA_ACCESS 0x00185024
+ #define BNX2_CP_CPU_INTERRUPT_ENABLE 0x00185028
+ #define BNX2_CP_CPU_INTERRUPT_VECTOR 0x0018502c
+ #define BNX2_CP_CPU_INTERRUPT_SAVED_PC 0x00185030
+ #define BNX2_CP_CPU_HW_BREAKPOINT 0x00185034
+ #define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+ #define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK 0x00185038
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_CP_CPU_LAST_BRANCH_ADDR 0x00185048
+ #define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+ #define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+ #define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+ #define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+ #define BNX2_CP_CPU_REG_FILE 0x00185200
+ #define BNX2_CP_CPQ_PFE_PFE_CTL 0x001853bc
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12)
+ #define BNX2_CP_CPQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16)
+
+ #define BNX2_CP_CPQ 0x001853c0
+ #define BNX2_CP_CPQ_FTQ_CMD 0x001853f8
+ #define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_CP_CPQ_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_CP_CPQ_FTQ_CMD_POP (1L<<30)
+ #define BNX2_CP_CPQ_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_CP_CPQ_FTQ_CTL 0x001853fc
+ #define BNX2_CP_CPQ_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_CP_SCRATCH 0x001a0000
+
+ #define BNX2_FW_MAX_ISCSI_CONN 0x001a0080
+
+
+ /*
+ * mcp_reg definition
+ * offset: 0x140000
+ */
+ #define BNX2_MCP_MCP_CONTROL 0x00140080
+ #define BNX2_MCP_MCP_CONTROL_SMBUS_SEL (1L<<30)
+ #define BNX2_MCP_MCP_CONTROL_MCP_ISOLATE (1L<<31)
+
+ #define BNX2_MCP_MCP_ATTENTION_STATUS 0x00140084
+ #define BNX2_MCP_MCP_ATTENTION_STATUS_DRV_DOORBELL (1L<<29)
+ #define BNX2_MCP_MCP_ATTENTION_STATUS_WATCHDOG_TIMEOUT (1L<<30)
+ #define BNX2_MCP_MCP_ATTENTION_STATUS_CPU_EVENT (1L<<31)
+
+ #define BNX2_MCP_MCP_HEARTBEAT_CONTROL 0x00140088
+ #define BNX2_MCP_MCP_HEARTBEAT_CONTROL_MCP_HEARTBEAT_ENABLE (1L<<31)
+
+ #define BNX2_MCP_MCP_HEARTBEAT_STATUS 0x0014008c
+ #define BNX2_MCP_MCP_HEARTBEAT_STATUS_MCP_HEARTBEAT_PERIOD (0x7ffL<<0)
+ #define BNX2_MCP_MCP_HEARTBEAT_STATUS_VALID (1L<<31)
+
+ #define BNX2_MCP_MCP_HEARTBEAT 0x00140090
+ #define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_COUNT (0x3fffffffL<<0)
+ #define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_INC (1L<<30)
+ #define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_RESET (1L<<31)
+
+ #define BNX2_MCP_WATCHDOG_RESET 0x00140094
+ #define BNX2_MCP_WATCHDOG_RESET_WATCHDOG_RESET (1L<<31)
+
+ #define BNX2_MCP_WATCHDOG_CONTROL 0x00140098
+ #define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_TIMEOUT (0xfffffffL<<0)
+ #define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ATTN (1L<<29)
+ #define BNX2_MCP_WATCHDOG_CONTROL_MCP_RST_ENABLE (1L<<30)
+ #define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ENABLE (1L<<31)
+
+ #define BNX2_MCP_ACCESS_LOCK 0x0014009c
+ #define BNX2_MCP_ACCESS_LOCK_LOCK (1L<<31)
+
+ #define BNX2_MCP_TOE_ID 0x001400a0
+ #define BNX2_MCP_TOE_ID_FUNCTION_ID (1L<<31)
+
+ #define BNX2_MCP_MAILBOX_CFG 0x001400a4
+ #define BNX2_MCP_MAILBOX_CFG_MAILBOX_OFFSET (0x3fffL<<0)
+ #define BNX2_MCP_MAILBOX_CFG_MAILBOX_SIZE (0xfffL<<20)
+
+ #define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC 0x001400a8
+ #define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_OFFSET (0x3fffL<<0)
+ #define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_SIZE (0xfffL<<20)
+
+ #define BNX2_MCP_MCP_DOORBELL 0x001400ac
+ #define BNX2_MCP_MCP_DOORBELL_MCP_DOORBELL (1L<<31)
+
+ #define BNX2_MCP_DRIVER_DOORBELL 0x001400b0
+ #define BNX2_MCP_DRIVER_DOORBELL_DRIVER_DOORBELL (1L<<31)
+
+ #define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC 0x001400b4
+ #define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC_DRIVER_DOORBELL (1L<<31)
+
+ #define BNX2_MCP_CPU_MODE 0x00145000
+ #define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0)
+ #define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1)
+ #define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+ #define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+ #define BNX2_MCP_CPU_MODE_MSG_BIT1 (1L<<6)
+ #define BNX2_MCP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+ #define BNX2_MCP_CPU_MODE_SOFT_HALT (1L<<10)
+ #define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+ #define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+ #define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+ #define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+ #define BNX2_MCP_CPU_STATE 0x00145004
+ #define BNX2_MCP_CPU_STATE_BREAKPOINT (1L<<0)
+ #define BNX2_MCP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+ #define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+ #define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+ #define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+ #define BNX2_MCP_CPU_STATE_BAD_PC_HALTED (1L<<6)
+ #define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7)
+ #define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+ #define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10)
+ #define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
++#define BNX2_MCP_CPU_STATE_INTERRUPT (1L<<12)
+ #define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+ #define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+ #define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+ #define BNX2_MCP_CPU_EVENT_MASK 0x00145008
+ #define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+ #define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+ #define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+ #define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+ #define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+ #define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+ #define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+ #define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+ #define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+ #define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+ #define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+ #define BNX2_MCP_CPU_PROGRAM_COUNTER 0x0014501c
+ #define BNX2_MCP_CPU_INSTRUCTION 0x00145020
+ #define BNX2_MCP_CPU_DATA_ACCESS 0x00145024
+ #define BNX2_MCP_CPU_INTERRUPT_ENABLE 0x00145028
+ #define BNX2_MCP_CPU_INTERRUPT_VECTOR 0x0014502c
+ #define BNX2_MCP_CPU_INTERRUPT_SAVED_PC 0x00145030
+ #define BNX2_MCP_CPU_HW_BREAKPOINT 0x00145034
+ #define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+ #define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK 0x00145038
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+ #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+ #define BNX2_MCP_CPU_LAST_BRANCH_ADDR 0x00145048
+ #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+ #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+ #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+ #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+ #define BNX2_MCP_CPU_REG_FILE 0x00145200
+ #define BNX2_MCP_MCPQ 0x001453c0
+ #define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8
+ #define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET (1L<<25)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA (1L<<26)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA (1L<<28)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_POP (1L<<30)
+ #define BNX2_MCP_MCPQ_FTQ_CMD_BUSY (1L<<31)
+
+ #define BNX2_MCP_MCPQ_FTQ_CTL 0x001453fc
+ #define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE (1L<<0)
+ #define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW (1L<<1)
+ #define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+ #define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+ #define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+ #define BNX2_MCP_ROM 0x00150000
+ #define BNX2_MCP_SCRATCH 0x00160000
+ #define BNX2_MCP_STATE_P1 0x0016f9c8
+ #define BNX2_MCP_STATE_P0 0x0016fdc8
+ #define BNX2_MCP_STATE_P1_5708 0x001699c8
+ #define BNX2_MCP_STATE_P0_5708 0x00169dc8
+
+ #define BNX2_SHM_HDR_SIGNATURE BNX2_MCP_SCRATCH
+ #define BNX2_SHM_HDR_SIGNATURE_SIG_MASK 0xffff0000
+ #define BNX2_SHM_HDR_SIGNATURE_SIG 0x53530000
+ #define BNX2_SHM_HDR_SIGNATURE_VER_MASK 0x000000ff
+ #define BNX2_SHM_HDR_SIGNATURE_VER_ONE 0x00000001
+
+ #define BNX2_SHM_HDR_ADDR_0 BNX2_MCP_SCRATCH + 4
+ #define BNX2_SHM_HDR_ADDR_1 BNX2_MCP_SCRATCH + 8
+
+
+ #define NUM_MC_HASH_REGISTERS 8
+
+
+ /* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0. */
+ #define PHY_BCM5706_PHY_ID 0x00206160
+
+ #define PHY_ID(id) ((id) & 0xfffffff0)
+ #define PHY_REV_ID(id) ((id) & 0xf)
+
+ /* 5708 Serdes PHY registers */
+
+ #define BCM5708S_BMCR_FORCE_2500 0x20
+
+ #define BCM5708S_UP1 0xb
+
+ #define BCM5708S_UP1_2G5 0x1
+
+ #define BCM5708S_BLK_ADDR 0x1f
+
+ #define BCM5708S_BLK_ADDR_DIG 0x0000
+ #define BCM5708S_BLK_ADDR_DIG3 0x0002
+ #define BCM5708S_BLK_ADDR_TX_MISC 0x0005
+
+ /* Digital Block */
+ #define BCM5708S_1000X_CTL1 0x10
+
+ #define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001
+ #define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010
+
+ #define BCM5708S_1000X_CTL2 0x11
+
+ #define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001
+
+ #define BCM5708S_1000X_STAT1 0x14
+
+ #define BCM5708S_1000X_STAT1_SGMII 0x0001
+ #define BCM5708S_1000X_STAT1_LINK 0x0002
+ #define BCM5708S_1000X_STAT1_FD 0x0004
+ #define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018
+ #define BCM5708S_1000X_STAT1_SPEED_10 0x0000
+ #define BCM5708S_1000X_STAT1_SPEED_100 0x0008
+ #define BCM5708S_1000X_STAT1_SPEED_1G 0x0010
+ #define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018
+ #define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020
+ #define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040
+
+ /* Digital3 Block */
+ #define BCM5708S_DIG_3_0 0x10
+
+ #define BCM5708S_DIG_3_0_USE_IEEE 0x0001
+
+ /* Tx/Misc Block */
+ #define BCM5708S_TX_ACTL1 0x15
+
+ #define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30
+
+ #define BCM5708S_TX_ACTL3 0x17
+
+ #define MII_BNX2_DSP_RW_PORT 0x15
+ #define MII_BNX2_DSP_ADDRESS 0x17
+ #define MII_BNX2_DSP_EXPAND_REG 0x0f00
+ #define MII_EXPAND_REG1 (MII_BNX2_DSP_EXPAND_REG | 1)
+ #define MII_EXPAND_REG1_RUDI_C 0x20
+ #define MII_EXPAND_SERDES_CTL (MII_BNX2_DSP_EXPAND_REG | 3)
+
+ #define MII_BNX2_MISC_SHADOW 0x1c
+ #define MISC_SHDW_AN_DBG 0x6800
+ #define MISC_SHDW_AN_DBG_NOSYNC 0x0002
+ #define MISC_SHDW_AN_DBG_RUDI_INVALID 0x0100
+ #define MISC_SHDW_MODE_CTL 0x7c00
+ #define MISC_SHDW_MODE_CTL_SIG_DET 0x0010
+
+ #define MII_BNX2_BLK_ADDR 0x1f
+ #define MII_BNX2_BLK_ADDR_IEEE0 0x0000
+ #define MII_BNX2_BLK_ADDR_GP_STATUS 0x8120
+ #define MII_BNX2_GP_TOP_AN_STATUS1 0x1b
+ #define MII_BNX2_GP_TOP_AN_SPEED_MSK 0x3f00
+ #define MII_BNX2_GP_TOP_AN_SPEED_10 0x0000
+ #define MII_BNX2_GP_TOP_AN_SPEED_100 0x0100
+ #define MII_BNX2_GP_TOP_AN_SPEED_1G 0x0200
+ #define MII_BNX2_GP_TOP_AN_SPEED_2_5G 0x0300
+ #define MII_BNX2_GP_TOP_AN_SPEED_1GKV 0x0d00
+ #define MII_BNX2_GP_TOP_AN_FD 0x8
+ #define MII_BNX2_BLK_ADDR_SERDES_DIG 0x8300
+ #define MII_BNX2_SERDES_DIG_1000XCTL1 0x10
+ #define MII_BNX2_SD_1000XCTL1_FIBER 0x01
+ #define MII_BNX2_SD_1000XCTL1_AUTODET 0x10
+ #define MII_BNX2_SERDES_DIG_MISC1 0x18
+ #define MII_BNX2_SD_MISC1_FORCE_MSK 0xf
+ #define MII_BNX2_SD_MISC1_FORCE_2_5G 0x0
+ #define MII_BNX2_SD_MISC1_FORCE 0x10
+ #define MII_BNX2_BLK_ADDR_OVER1G 0x8320
+ #define MII_BNX2_OVER1G_UP1 0x19
+ #define MII_BNX2_BLK_ADDR_BAM_NXTPG 0x8350
+ #define MII_BNX2_BAM_NXTPG_CTL 0x10
+ #define MII_BNX2_NXTPG_CTL_BAM 0x1
+ #define MII_BNX2_NXTPG_CTL_T2 0x2
+ #define MII_BNX2_BLK_ADDR_CL73_USERB0 0x8370
+ #define MII_BNX2_CL73_BAM_CTL1 0x12
+ #define MII_BNX2_CL73_BAM_EN 0x8000
+ #define MII_BNX2_CL73_BAM_STA_MGR_EN 0x4000
+ #define MII_BNX2_CL73_BAM_NP_AFT_BP_EN 0x2000
+ #define MII_BNX2_BLK_ADDR_AER 0xffd0
+ #define MII_BNX2_AER_AER 0x1e
+ #define MII_BNX2_AER_AER_AN_MMD 0x3800
+ #define MII_BNX2_BLK_ADDR_COMBO_IEEEB0 0xffe0
+
+ #define MIN_ETHERNET_PACKET_SIZE 60
+ #define MAX_ETHERNET_PACKET_SIZE 1514
+ #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
+
+ #define BNX2_RX_COPY_THRESH 128
+
+ #define BNX2_MISC_ENABLE_DEFAULT 0x17ffffff
+
+ #define BNX2_START_UNICAST_ADDRESS_INDEX 4
+ #define BNX2_END_UNICAST_ADDRESS_INDEX 7
+ #define BNX2_MAX_UNICAST_ADDRESSES (BNX2_END_UNICAST_ADDRESS_INDEX - \
+ BNX2_START_UNICAST_ADDRESS_INDEX + 1)
+
+ #define DMA_READ_CHANS 5
+ #define DMA_WRITE_CHANS 3
+
+ /* Use CPU native page size up to 16K for the ring sizes. */
+ #if (PAGE_SHIFT > 14)
+ #define BCM_PAGE_BITS 14
+ #else
+ #define BCM_PAGE_BITS PAGE_SHIFT
+ #endif
+ #define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS)
+
+ #define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
+ #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+
+ #define MAX_RX_RINGS 8
+ #define MAX_RX_PG_RINGS 32
+ #define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
+ #define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
+ #define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
+ #define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS)
+
+ #define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
+ (MAX_TX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+ #define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
+
+ #define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \
+ (MAX_RX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+ #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
+ #define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
+
+ #define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
+ #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
+
+ /* Context size. */
+ #define CTX_SHIFT 7
+ #define CTX_SIZE (1 << CTX_SHIFT)
+ #define CTX_MASK (CTX_SIZE - 1)
+ #define GET_CID_ADDR(_cid) ((_cid) << CTX_SHIFT)
+ #define GET_CID(_cid_addr) ((_cid_addr) >> CTX_SHIFT)
+
+ #define PHY_CTX_SHIFT 6
+ #define PHY_CTX_SIZE (1 << PHY_CTX_SHIFT)
+ #define PHY_CTX_MASK (PHY_CTX_SIZE - 1)
+ #define GET_PCID_ADDR(_pcid) ((_pcid) << PHY_CTX_SHIFT)
+ #define GET_PCID(_pcid_addr) ((_pcid_addr) >> PHY_CTX_SHIFT)
+
+ #define MB_KERNEL_CTX_SHIFT 8
+ #define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT)
+ #define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1)
+ #define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT))
+
+ #define MAX_CID_CNT 0x4000
+ #define MAX_CID_ADDR (GET_CID_ADDR(MAX_CID_CNT))
+ #define INVALID_CID_ADDR 0xffffffff
+
+ #define TX_CID 16
+ #define TX_TSS_CID 32
+ #define RX_CID 0
+ #define RX_RSS_CID 4
+ #define RX_MAX_RSS_RINGS 7
+ #define RX_MAX_RINGS (RX_MAX_RSS_RINGS + 1)
+ #define TX_MAX_TSS_RINGS 7
+ #define TX_MAX_RINGS (TX_MAX_TSS_RINGS + 1)
+
+ #define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID)
+ #define MB_RX_CID_ADDR MB_GET_CID_ADDR(RX_CID)
+
+ struct sw_bd {
+ struct sk_buff *skb;
+ struct l2_fhdr *desc;
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+ };
+
+ struct sw_pg {
+ struct page *page;
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+ };
+
+ struct sw_tx_bd {
+ struct sk_buff *skb;
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+ unsigned short is_gso;
+ unsigned short nr_frags;
+ };
+
+ #define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
+ #define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
+ #define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
+ #define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT)
+ #define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
+
+ /* Buffered flash (Atmel: AT45DB011B) specific information */
+ #define SEEPROM_PAGE_BITS 2
+ #define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS)
+ #define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1)
+ #define SEEPROM_PAGE_SIZE 4
+ #define SEEPROM_TOTAL_SIZE 65536
+
+ #define BUFFERED_FLASH_PAGE_BITS 9
+ #define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS)
+ #define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1)
+ #define BUFFERED_FLASH_PAGE_SIZE 264
+ #define BUFFERED_FLASH_TOTAL_SIZE 0x21000
+
+ #define SAIFUN_FLASH_PAGE_BITS 8
+ #define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS)
+ #define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1)
+ #define SAIFUN_FLASH_PAGE_SIZE 256
+ #define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536
+
+ #define ST_MICRO_FLASH_PAGE_BITS 8
+ #define ST_MICRO_FLASH_PHY_PAGE_SIZE (1 << ST_MICRO_FLASH_PAGE_BITS)
+ #define ST_MICRO_FLASH_BYTE_ADDR_MASK (ST_MICRO_FLASH_PHY_PAGE_SIZE-1)
+ #define ST_MICRO_FLASH_PAGE_SIZE 256
+ #define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536
+
+ #define BCM5709_FLASH_PAGE_BITS 8
+ #define BCM5709_FLASH_PHY_PAGE_SIZE (1 << BCM5709_FLASH_PAGE_BITS)
+ #define BCM5709_FLASH_BYTE_ADDR_MASK (BCM5709_FLASH_PHY_PAGE_SIZE-1)
+ #define BCM5709_FLASH_PAGE_SIZE 256
+
+ #define NVRAM_TIMEOUT_COUNT 30000
+
+
+ #define FLASH_STRAP_MASK (BNX2_NVM_CFG1_FLASH_MODE | \
+ BNX2_NVM_CFG1_BUFFER_MODE | \
+ BNX2_NVM_CFG1_PROTECT_MODE | \
+ BNX2_NVM_CFG1_FLASH_SIZE)
+
+ #define FLASH_BACKUP_STRAP_MASK (0xf << 26)
+
+ struct flash_spec {
+ u32 strapping;
+ u32 config1;
+ u32 config2;
+ u32 config3;
+ u32 write1;
+ u32 flags;
+ #define BNX2_NV_BUFFERED 0x00000001
+ #define BNX2_NV_TRANSLATE 0x00000002
+ #define BNX2_NV_WREN 0x00000004
+ u32 page_bits;
+ u32 page_size;
+ u32 addr_mask;
+ u32 total_size;
+ u8 *name;
+ };
+
+ #define BNX2_MAX_MSIX_HW_VEC 9
+ #define BNX2_MAX_MSIX_VEC 9
+ #ifdef BCM_CNIC
+ #define BNX2_MIN_MSIX_VEC 2
+ #else
+ #define BNX2_MIN_MSIX_VEC 1
+ #endif
+
+
+ struct bnx2_irq {
+ irq_handler_t handler;
+ unsigned int vector;
+ u8 requested;
+ char name[IFNAMSIZ + 2];
+ };
+
+ struct bnx2_tx_ring_info {
+ u32 tx_prod_bseq;
+ u16 tx_prod;
+ u32 tx_bidx_addr;
+ u32 tx_bseq_addr;
+
+ struct tx_bd *tx_desc_ring;
+ struct sw_tx_bd *tx_buf_ring;
+
+ u16 tx_cons;
+ u16 hw_tx_cons;
+
+ dma_addr_t tx_desc_mapping;
+ };
+
+ struct bnx2_rx_ring_info {
+ u32 rx_prod_bseq;
+ u16 rx_prod;
+ u16 rx_cons;
+
+ u32 rx_bidx_addr;
+ u32 rx_bseq_addr;
+ u32 rx_pg_bidx_addr;
+
+ u16 rx_pg_prod;
+ u16 rx_pg_cons;
+
+ struct sw_bd *rx_buf_ring;
+ struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
+ struct sw_pg *rx_pg_ring;
+ struct rx_bd *rx_pg_desc_ring[MAX_RX_PG_RINGS];
+
+ dma_addr_t rx_desc_mapping[MAX_RX_RINGS];
+ dma_addr_t rx_pg_desc_mapping[MAX_RX_PG_RINGS];
+ };
+
+ struct bnx2_napi {
+ struct napi_struct napi ____cacheline_aligned;
+ struct bnx2 *bp;
+ union {
+ struct status_block *msi;
+ struct status_block_msix *msix;
+ } status_blk;
+ u16 *hw_tx_cons_ptr;
+ u16 *hw_rx_cons_ptr;
+ u32 last_status_idx;
+ u32 int_num;
+
+ #ifdef BCM_CNIC
+ u32 cnic_tag;
+ int cnic_present;
+ #endif
+
+ struct bnx2_rx_ring_info rx_ring;
+ struct bnx2_tx_ring_info tx_ring;
+ };
+
+ struct bnx2 {
+ /* Fields used in the tx and intr/napi performance paths are grouped */
+ /* together in the beginning of the structure. */
+ void __iomem *regview;
+
+ struct net_device *dev;
+ struct pci_dev *pdev;
+
+ atomic_t intr_sem;
+
+ u32 flags;
+ #define BNX2_FLAG_PCIX 0x00000001
+ #define BNX2_FLAG_PCI_32BIT 0x00000002
+ #define BNX2_FLAG_MSIX_CAP 0x00000004
+ #define BNX2_FLAG_NO_WOL 0x00000008
+ #define BNX2_FLAG_USING_MSI 0x00000020
+ #define BNX2_FLAG_ASF_ENABLE 0x00000040
+ #define BNX2_FLAG_MSI_CAP 0x00000080
+ #define BNX2_FLAG_ONE_SHOT_MSI 0x00000100
+ #define BNX2_FLAG_PCIE 0x00000200
+ #define BNX2_FLAG_USING_MSIX 0x00000400
+ #define BNX2_FLAG_USING_MSI_OR_MSIX (BNX2_FLAG_USING_MSI | \
+ BNX2_FLAG_USING_MSIX)
+ #define BNX2_FLAG_JUMBO_BROKEN 0x00000800
+ #define BNX2_FLAG_CAN_KEEP_VLAN 0x00001000
+ #define BNX2_FLAG_BROKEN_STATS 0x00002000
+ #define BNX2_FLAG_AER_ENABLED 0x00004000
+
+ struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC];
+
+ u32 rx_buf_use_size; /* useable size */
+ u32 rx_buf_size; /* with alignment */
+ u32 rx_copy_thresh;
+ u32 rx_jumbo_thresh;
+ u32 rx_max_ring_idx;
+ u32 rx_max_pg_ring_idx;
+
+ /* TX constants */
+ int tx_ring_size;
+ u32 tx_wake_thresh;
+
+ #ifdef BCM_CNIC
+ struct cnic_ops __rcu *cnic_ops;
+ void *cnic_data;
+ #endif
+
+ /* End of fields used in the performance code paths. */
+
+ unsigned int current_interval;
+ #define BNX2_TIMER_INTERVAL HZ
+ #define BNX2_SERDES_AN_TIMEOUT (HZ / 3)
+ #define BNX2_SERDES_FORCED_TIMEOUT (HZ / 10)
+
+ struct timer_list timer;
+ struct work_struct reset_task;
+
+ /* Used to synchronize phy accesses. */
+ spinlock_t phy_lock;
+ spinlock_t indirect_lock;
+
+ u32 phy_flags;
+ #define BNX2_PHY_FLAG_SERDES 0x00000001
+ #define BNX2_PHY_FLAG_CRC_FIX 0x00000002
+ #define BNX2_PHY_FLAG_PARALLEL_DETECT 0x00000004
+ #define BNX2_PHY_FLAG_2_5G_CAPABLE 0x00000008
+ #define BNX2_PHY_FLAG_INT_MODE_MASK 0x00000300
+ #define BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING 0x00000100
+ #define BNX2_PHY_FLAG_INT_MODE_LINK_READY 0x00000200
+ #define BNX2_PHY_FLAG_DIS_EARLY_DAC 0x00000400
+ #define BNX2_PHY_FLAG_REMOTE_PHY_CAP 0x00000800
+ #define BNX2_PHY_FLAG_FORCED_DOWN 0x00001000
+ #define BNX2_PHY_FLAG_NO_PARALLEL 0x00002000
+
+ u32 mii_bmcr;
+ u32 mii_bmsr;
+ u32 mii_bmsr1;
+ u32 mii_adv;
+ u32 mii_lpa;
+ u32 mii_up1;
+
+ u32 chip_id;
+ /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
+ #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
+ #define CHIP_NUM_5706 0x57060000
+ #define CHIP_NUM_5708 0x57080000
+ #define CHIP_NUM_5709 0x57090000
+
+ #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
+ #define CHIP_REV_Ax 0x00000000
+ #define CHIP_REV_Bx 0x00001000
+ #define CHIP_REV_Cx 0x00002000
+
+ #define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0)
+ #define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f)
+
+ #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0)
+ #define CHIP_ID_5706_A0 0x57060000
+ #define CHIP_ID_5706_A1 0x57060010
+ #define CHIP_ID_5706_A2 0x57060020
+ #define CHIP_ID_5708_A0 0x57080000
+ #define CHIP_ID_5708_B0 0x57081000
+ #define CHIP_ID_5708_B1 0x57081010
+ #define CHIP_ID_5709_A0 0x57090000
+ #define CHIP_ID_5709_A1 0x57090010
+
+ #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
+
+ /* A serdes chip will have the first bit of the bond id set. */
+ #define CHIP_BOND_ID_SERDES_BIT 0x01
+
+ u32 phy_addr;
+ u32 phy_id;
+
+ u16 bus_speed_mhz;
+ u8 wol;
+
+ u8 pad;
+
+ u16 fw_wr_seq;
+ u16 fw_drv_pulse_wr_seq;
+
+ int rx_max_ring;
+ int rx_ring_size;
+
+ int rx_max_pg_ring;
+ int rx_pg_ring_size;
+
+ u16 tx_quick_cons_trip;
+ u16 tx_quick_cons_trip_int;
+ u16 rx_quick_cons_trip;
+ u16 rx_quick_cons_trip_int;
+ u16 comp_prod_trip;
+ u16 comp_prod_trip_int;
+ u16 tx_ticks;
+ u16 tx_ticks_int;
+ u16 com_ticks;
+ u16 com_ticks_int;
+ u16 cmd_ticks;
+ u16 cmd_ticks_int;
+ u16 rx_ticks;
+ u16 rx_ticks_int;
+
+ u32 stats_ticks;
+
+ dma_addr_t status_blk_mapping;
+
+ struct statistics_block *stats_blk;
+ struct statistics_block *temp_stats_blk;
+ dma_addr_t stats_blk_mapping;
+
+ int ctx_pages;
+ void *ctx_blk[4];
+ dma_addr_t ctx_blk_mapping[4];
+
+ u32 hc_cmd;
+ u32 rx_mode;
+
+ u16 req_line_speed;
+ u8 req_duplex;
+
+ u8 phy_port;
+ u8 link_up;
+
+ u16 line_speed;
+ u8 duplex;
+ u8 flow_ctrl; /* actual flow ctrl settings */
+ /* may be different from */
+ /* req_flow_ctrl if autoneg */
+ u32 advertising;
+
+ u8 req_flow_ctrl; /* flow ctrl advertisement */
+ /* settings or forced */
+ /* settings */
+ u8 autoneg;
+ #define AUTONEG_SPEED 1
+ #define AUTONEG_FLOW_CTRL 2
+
+ u8 loopback;
+ #define MAC_LOOPBACK 1
+ #define PHY_LOOPBACK 2
+
+ u8 serdes_an_pending;
+
+ u8 mac_addr[8];
+
+ u32 shmem_base;
+
+ char fw_version[32];
+
+ int pm_cap;
+ int pcix_cap;
+
+ const struct flash_spec *flash_info;
+ u32 flash_size;
+
+ int status_stats_size;
+
+ struct bnx2_irq irq_tbl[BNX2_MAX_MSIX_VEC];
+ int irq_nvecs;
+
+ u8 num_tx_rings;
+ u8 num_rx_rings;
+
+ u32 leds_save;
+ u32 idle_chk_status_idx;
+
+ #ifdef BCM_CNIC
+ struct mutex cnic_lock;
+ struct cnic_eth_dev cnic_eth_dev;
+ #endif
+
+ const struct firmware *mips_firmware;
+ const struct firmware *rv2p_firmware;
+ };
+
+ #define REG_RD(bp, offset) \
+ readl(bp->regview + offset)
+
+ #define REG_WR(bp, offset, val) \
+ writel(val, bp->regview + offset)
+
+ #define REG_WR16(bp, offset, val) \
+ writew(val, bp->regview + offset)
+
+ struct cpu_reg {
+ u32 mode;
+ u32 mode_value_halt;
+ u32 mode_value_sstep;
+
+ u32 state;
+ u32 state_value_clear;
+
+ u32 gpr0;
+ u32 evmask;
+ u32 pc;
+ u32 inst;
+ u32 bp;
+
+ u32 spad_base;
+
+ u32 mips_view_base;
+ };
+
+ struct bnx2_fw_file_section {
+ __be32 addr;
+ __be32 len;
+ __be32 offset;
+ };
+
+ struct bnx2_mips_fw_file_entry {
+ __be32 start_addr;
+ struct bnx2_fw_file_section text;
+ struct bnx2_fw_file_section data;
+ struct bnx2_fw_file_section rodata;
+ };
+
+ struct bnx2_rv2p_fw_file_entry {
+ struct bnx2_fw_file_section rv2p;
+ __be32 fixup[8];
+ };
+
+ struct bnx2_mips_fw_file {
+ struct bnx2_mips_fw_file_entry com;
+ struct bnx2_mips_fw_file_entry cp;
+ struct bnx2_mips_fw_file_entry rxp;
+ struct bnx2_mips_fw_file_entry tpat;
+ struct bnx2_mips_fw_file_entry txp;
+ };
+
+ struct bnx2_rv2p_fw_file {
+ struct bnx2_rv2p_fw_file_entry proc1;
+ struct bnx2_rv2p_fw_file_entry proc2;
+ };
+
+ #define RV2P_P1_FIXUP_PAGE_SIZE_IDX 0
+ #define RV2P_BD_PAGE_SIZE_MSK 0xffff
+ #define RV2P_BD_PAGE_SIZE ((BCM_PAGE_SIZE / 16) - 1)
+
+ #define RV2P_PROC1 0
+ #define RV2P_PROC2 1
+
+
+ /* This value (in milliseconds) determines the frequency of the driver
+ * issuing the PULSE message code. The firmware monitors this periodic
+ * pulse to determine when to switch to an OS-absent mode. */
+ #define BNX2_DRV_PULSE_PERIOD_MS 250
+
+ /* This value (in milliseconds) determines how long the driver should
+ * wait for an acknowledgement from the firmware before timing out. Once
+ * the firmware has timed out, the driver will assume there is no firmware
+ * running and there won't be any firmware-driver synchronization during a
+ * driver reset. */
+ #define BNX2_FW_ACK_TIME_OUT_MS 1000
+
+
+ #define BNX2_DRV_RESET_SIGNATURE 0x00000000
+ #define BNX2_DRV_RESET_SIGNATURE_MAGIC 0x4841564b /* HAVK */
+ //#define DRV_RESET_SIGNATURE_MAGIC 0x47495352 /* RSIG */
+
+ #define BNX2_DRV_MB 0x00000004
+ #define BNX2_DRV_MSG_CODE 0xff000000
+ #define BNX2_DRV_MSG_CODE_RESET 0x01000000
+ #define BNX2_DRV_MSG_CODE_UNLOAD 0x02000000
+ #define BNX2_DRV_MSG_CODE_SHUTDOWN 0x03000000
+ #define BNX2_DRV_MSG_CODE_SUSPEND_WOL 0x04000000
+ #define BNX2_DRV_MSG_CODE_FW_TIMEOUT 0x05000000
+ #define BNX2_DRV_MSG_CODE_PULSE 0x06000000
+ #define BNX2_DRV_MSG_CODE_DIAG 0x07000000
+ #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000
+ #define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN 0x0b000000
+ #define BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE 0x0d000000
+ #define BNX2_DRV_MSG_CODE_CMD_SET_LINK 0x10000000
+
+ #define BNX2_DRV_MSG_DATA 0x00ff0000
+ #define BNX2_DRV_MSG_DATA_WAIT0 0x00010000
+ #define BNX2_DRV_MSG_DATA_WAIT1 0x00020000
+ #define BNX2_DRV_MSG_DATA_WAIT2 0x00030000
+ #define BNX2_DRV_MSG_DATA_WAIT3 0x00040000
+
+ #define BNX2_DRV_MSG_SEQ 0x0000ffff
+
+ #define BNX2_FW_MB 0x00000008
+ #define BNX2_FW_MSG_ACK 0x0000ffff
+ #define BNX2_FW_MSG_STATUS_MASK 0x00ff0000
+ #define BNX2_FW_MSG_STATUS_OK 0x00000000
+ #define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000
+
+ #define BNX2_LINK_STATUS 0x0000000c
+ #define BNX2_LINK_STATUS_INIT_VALUE 0xffffffff
+ #define BNX2_LINK_STATUS_LINK_UP 0x1
+ #define BNX2_LINK_STATUS_LINK_DOWN 0x0
+ #define BNX2_LINK_STATUS_SPEED_MASK 0x1e
+ #define BNX2_LINK_STATUS_AN_INCOMPLETE (0<<1)
+ #define BNX2_LINK_STATUS_10HALF (1<<1)
+ #define BNX2_LINK_STATUS_10FULL (2<<1)
+ #define BNX2_LINK_STATUS_100HALF (3<<1)
+ #define BNX2_LINK_STATUS_100BASE_T4 (4<<1)
+ #define BNX2_LINK_STATUS_100FULL (5<<1)
+ #define BNX2_LINK_STATUS_1000HALF (6<<1)
+ #define BNX2_LINK_STATUS_1000FULL (7<<1)
+ #define BNX2_LINK_STATUS_2500HALF (8<<1)
+ #define BNX2_LINK_STATUS_2500FULL (9<<1)
+ #define BNX2_LINK_STATUS_AN_ENABLED (1<<5)
+ #define BNX2_LINK_STATUS_AN_COMPLETE (1<<6)
+ #define BNX2_LINK_STATUS_PARALLEL_DET (1<<7)
+ #define BNX2_LINK_STATUS_RESERVED (1<<8)
+ #define BNX2_LINK_STATUS_PARTNER_AD_1000FULL (1<<9)
+ #define BNX2_LINK_STATUS_PARTNER_AD_1000HALF (1<<10)
+ #define BNX2_LINK_STATUS_PARTNER_AD_100BT4 (1<<11)
+ #define BNX2_LINK_STATUS_PARTNER_AD_100FULL (1<<12)
+ #define BNX2_LINK_STATUS_PARTNER_AD_100HALF (1<<13)
+ #define BNX2_LINK_STATUS_PARTNER_AD_10FULL (1<<14)
+ #define BNX2_LINK_STATUS_PARTNER_AD_10HALF (1<<15)
+ #define BNX2_LINK_STATUS_TX_FC_ENABLED (1<<16)
+ #define BNX2_LINK_STATUS_RX_FC_ENABLED (1<<17)
+ #define BNX2_LINK_STATUS_PARTNER_SYM_PAUSE_CAP (1<<18)
+ #define BNX2_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP (1<<19)
+ #define BNX2_LINK_STATUS_SERDES_LINK (1<<20)
+ #define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21)
+ #define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22)
+ #define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED (1<<31)
+
+ #define BNX2_DRV_PULSE_MB 0x00000010
+ #define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff
+
+ /* Indicate to the firmware not to go into the
+ * OS absent when it is not getting driver pulse.
+ * This is used for debugging. */
+ #define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000
+
+ #define BNX2_DRV_MB_ARG0 0x00000014
+ #define BNX2_NETLINK_SET_LINK_SPEED_10HALF (1<<0)
+ #define BNX2_NETLINK_SET_LINK_SPEED_10FULL (1<<1)
+ #define BNX2_NETLINK_SET_LINK_SPEED_10 \
+ (BNX2_NETLINK_SET_LINK_SPEED_10HALF | \
+ BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+ #define BNX2_NETLINK_SET_LINK_SPEED_100HALF (1<<2)
+ #define BNX2_NETLINK_SET_LINK_SPEED_100FULL (1<<3)
+ #define BNX2_NETLINK_SET_LINK_SPEED_100 \
+ (BNX2_NETLINK_SET_LINK_SPEED_100HALF | \
+ BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+ #define BNX2_NETLINK_SET_LINK_SPEED_1GHALF (1<<4)
+ #define BNX2_NETLINK_SET_LINK_SPEED_1GFULL (1<<5)
+ #define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF (1<<6)
+ #define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL (1<<7)
+ #define BNX2_NETLINK_SET_LINK_SPEED_10GHALF (1<<8)
+ #define BNX2_NETLINK_SET_LINK_SPEED_10GFULL (1<<9)
+ #define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG (1<<10)
+ #define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE (1<<11)
+ #define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE (1<<12)
+ #define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE (1<<13)
+ #define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED (1<<14)
+ #define BNX2_NETLINK_SET_LINK_PHY_RESET (1<<15)
+
+ #define BNX2_DEV_INFO_SIGNATURE 0x00000020
+ #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900
+ #define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00
+ #define BNX2_DEV_INFO_FEATURE_CFG_VALID 0x01
+ #define BNX2_DEV_INFO_SECONDARY_PORT 0x80
+ #define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE 0x40
+
+ #define BNX2_SHARED_HW_CFG_PART_NUM 0x00000024
+
+ #define BNX2_SHARED_HW_CFG_POWER_DISSIPATED 0x00000034
+ #define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK 0xff000000
+ #define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK 0xff0000
+ #define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK 0xff00
+ #define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK 0xff
+
+ #define BNX2_SHARED_HW_CFG POWER_CONSUMED 0x00000038
+ #define BNX2_SHARED_HW_CFG_CONFIG 0x0000003c
+ #define BNX2_SHARED_HW_CFG_DESIGN_NIC 0
+ #define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1
+ #define BNX2_SHARED_HW_CFG_PHY_COPPER 0
+ #define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2
+ #define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20
+ #define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40
+ #define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8
+ #define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300
+ #define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0
+ #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100
+ #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200
+ #define BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX 0x8000
+
+ #define BNX2_SHARED_HW_CFG_CONFIG2 0x00000040
+ #define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK 0x00fff000
+
+ #define BNX2_DEV_INFO_BC_REV 0x0000004c
+
+ #define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050
+ #define BNX2_PORT_HW_CFG_UPPERMAC_MASK 0xffff
+
+ #define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
+ #define BNX2_PORT_HW_CFG_CONFIG 0x00000058
+ #define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff
+ #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000
+ #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000
+ #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000
+ #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000
+
+ #define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
+ #define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c
+ #define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER 0x00000070
+ #define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER 0x00000074
+ #define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER 0x00000078
+ #define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER 0x0000007c
+
+ #define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2 0x000000b4
+
+ #define BNX2_DEV_INFO_FORMAT_REV 0x000000c4
+ #define BNX2_DEV_INFO_FORMAT_REV_MASK 0xff000000
+ #define BNX2_DEV_INFO_FORMAT_REV_ID ('A' << 24)
+
+ #define BNX2_SHARED_FEATURE 0x000000c8
+ #define BNX2_SHARED_FEATURE_MASK 0xffffffff
+
+ #define BNX2_PORT_FEATURE 0x000000d8
+ #define BNX2_PORT2_FEATURE 0x00000014c
+ #define BNX2_PORT_FEATURE_WOL_ENABLED 0x01000000
+ #define BNX2_PORT_FEATURE_MBA_ENABLED 0x02000000
+ #define BNX2_PORT_FEATURE_ASF_ENABLED 0x04000000
+ #define BNX2_PORT_FEATURE_IMD_ENABLED 0x08000000
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_MASK 0xf
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED 0x0
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_64K 0x1
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_128K 0x2
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_256K 0x3
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_512K 0x4
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_1M 0x5
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_2M 0x6
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_4M 0x7
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_8M 0x8
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_16M 0x9
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_32M 0xa
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_64M 0xb
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_128M 0xc
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_256M 0xd
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_512M 0xe
+ #define BNX2_PORT_FEATURE_BAR1_SIZE_1G 0xf
+
+ #define BNX2_PORT_FEATURE_WOL 0xdc
+ #define BNX2_PORT2_FEATURE_WOL 0x150
+ #define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS 4
+ #define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK 0x30
+ #define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE 0
+ #define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC 0x10
+ #define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI 0x20
+ #define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x30
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK 0xf
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG 0
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF 1
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL 2
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF 5
+ #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL 6
+ #define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000 0x40
+ #define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400
+ #define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP 0x800
+
+ #define BNX2_PORT_FEATURE_MBA 0xe0
+ #define BNX2_PORT2_FEATURE_MBA 0x154
+ #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS 0
+ #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x3
+ #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0
+ #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 1
+ #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 2
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS 2
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG 0
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF 0x4
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL 0x8
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF 0xc
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL 0x10
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF 0x14
+ #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL 0x18
+ #define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x40
+ #define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S 0
+ #define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x80
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS 8
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0xff00
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K 0x100
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x200
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x300
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x400
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x500
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x600
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x700
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x800
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x900
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0xa00
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0xb00
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0xc00
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0xd00
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0xe00
+ #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0xf00
+ #define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS 16
+ #define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0xf0000
+ #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS 20
+ #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x300000
+ #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0
+ #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x100000
+ #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x200000
+ #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x300000
+
+ #define BNX2_PORT_FEATURE_IMD 0xe4
+ #define BNX2_PORT2_FEATURE_IMD 0x158
+ #define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT 0
+ #define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE 1
+
+ #define BNX2_PORT_FEATURE_VLAN 0xe8
+ #define BNX2_PORT2_FEATURE_VLAN 0x15c
+ #define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff
+ #define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000
+
+ #define BNX2_MFW_VER_PTR 0x00000014c
+
+ #define BNX2_BC_STATE_RESET_TYPE 0x000001c0
+ #define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254
+ #define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff
+ #define BNX2_BC_STATE_RESET_TYPE_NONE (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00010000)
+ #define BNX2_BC_STATE_RESET_TYPE_PCI (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00020000)
+ #define BNX2_BC_STATE_RESET_TYPE_VAUX (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00030000)
+ #define BNX2_BC_STATE_RESET_TYPE_DRV_MASK DRV_MSG_CODE
+ #define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_RESET)
+ #define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_UNLOAD)
+ #define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_SHUTDOWN)
+ #define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_WOL)
+ #define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_DIAG)
+ #define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ (msg))
+
+ #define BNX2_BC_STATE 0x000001c4
+ #define BNX2_BC_STATE_ERR_MASK 0x0000ff00
+ #define BNX2_BC_STATE_SIGN 0x42530000
+ #define BNX2_BC_STATE_SIGN_MASK 0xffff0000
+ #define BNX2_BC_STATE_BC1_START (BNX2_BC_STATE_SIGN | 0x1)
+ #define BNX2_BC_STATE_GET_NVM_CFG1 (BNX2_BC_STATE_SIGN | 0x2)
+ #define BNX2_BC_STATE_PROG_BAR (BNX2_BC_STATE_SIGN | 0x3)
+ #define BNX2_BC_STATE_INIT_VID (BNX2_BC_STATE_SIGN | 0x4)
+ #define BNX2_BC_STATE_GET_NVM_CFG2 (BNX2_BC_STATE_SIGN | 0x5)
+ #define BNX2_BC_STATE_APPLY_WKARND (BNX2_BC_STATE_SIGN | 0x6)
+ #define BNX2_BC_STATE_LOAD_BC2 (BNX2_BC_STATE_SIGN | 0x7)
+ #define BNX2_BC_STATE_GOING_BC2 (BNX2_BC_STATE_SIGN | 0x8)
+ #define BNX2_BC_STATE_GOING_DIAG (BNX2_BC_STATE_SIGN | 0x9)
+ #define BNX2_BC_STATE_RT_FINAL_INIT (BNX2_BC_STATE_SIGN | 0x81)
+ #define BNX2_BC_STATE_RT_WKARND (BNX2_BC_STATE_SIGN | 0x82)
+ #define BNX2_BC_STATE_RT_DRV_PULSE (BNX2_BC_STATE_SIGN | 0x83)
+ #define BNX2_BC_STATE_RT_FIOEVTS (BNX2_BC_STATE_SIGN | 0x84)
+ #define BNX2_BC_STATE_RT_DRV_CMD (BNX2_BC_STATE_SIGN | 0x85)
+ #define BNX2_BC_STATE_RT_LOW_POWER (BNX2_BC_STATE_SIGN | 0x86)
+ #define BNX2_BC_STATE_RT_SET_WOL (BNX2_BC_STATE_SIGN | 0x87)
+ #define BNX2_BC_STATE_RT_OTHER_FW (BNX2_BC_STATE_SIGN | 0x88)
+ #define BNX2_BC_STATE_RT_GOING_D3 (BNX2_BC_STATE_SIGN | 0x89)
+ #define BNX2_BC_STATE_ERR_BAD_VERSION (BNX2_BC_STATE_SIGN | 0x0100)
+ #define BNX2_BC_STATE_ERR_BAD_BC2_CRC (BNX2_BC_STATE_SIGN | 0x0200)
+ #define BNX2_BC_STATE_ERR_BC1_LOOP (BNX2_BC_STATE_SIGN | 0x0300)
+ #define BNX2_BC_STATE_ERR_UNKNOWN_CMD (BNX2_BC_STATE_SIGN | 0x0400)
+ #define BNX2_BC_STATE_ERR_DRV_DEAD (BNX2_BC_STATE_SIGN | 0x0500)
+ #define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600)
+ #define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700)
+
+ #define BNX2_BC_STATE_CONDITION 0x000001c8
+ #define BNX2_CONDITION_MFW_RUN_UNKNOWN 0x00000000
+ #define BNX2_CONDITION_MFW_RUN_IPMI 0x00002000
+ #define BNX2_CONDITION_MFW_RUN_UMP 0x00004000
+ #define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000
+ #define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000
+ #define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000
+
+ #define BNX2_BC_STATE_DEBUG_CMD 0x1dc
+ #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000
+ #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000
+ #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff
+ #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff
+
+ #define BNX2_FW_EVT_CODE_MB 0x354
+ #define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000
+ #define BNX2_FW_EVT_CODE_LINK_EVENT 0x00000001
+
+ #define BNX2_DRV_ACK_CAP_MB 0x364
+ #define BNX2_DRV_ACK_CAP_SIGNATURE 0x35450000
+ #define BNX2_CAPABILITY_SIGNATURE_MASK 0xFFFF0000
+
+ #define BNX2_FW_CAP_MB 0x368
+ #define BNX2_FW_CAP_SIGNATURE 0xaa550000
+ #define BNX2_FW_ACK_DRV_SIGNATURE 0x52500000
+ #define BNX2_FW_CAP_SIGNATURE_MASK 0xffff0000
+ #define BNX2_FW_CAP_REMOTE_PHY_CAPABLE 0x00000001
+ #define BNX2_FW_CAP_REMOTE_PHY_PRESENT 0x00000002
+ #define BNX2_FW_CAP_MFW_CAN_KEEP_VLAN 0x00000008
+ #define BNX2_FW_CAP_BC_CAN_KEEP_VLAN 0x00000010
+ #define BNX2_FW_CAP_CAN_KEEP_VLAN (BNX2_FW_CAP_BC_CAN_KEEP_VLAN | \
+ BNX2_FW_CAP_MFW_CAN_KEEP_VLAN)
+
+ #define BNX2_RPHY_SIGNATURE 0x36c
+ #define BNX2_RPHY_LOAD_SIGNATURE 0x5a5a5a5a
+
+ #define BNX2_RPHY_FLAGS 0x370
+ #define BNX2_RPHY_SERDES_LINK 0x374
+ #define BNX2_RPHY_COPPER_LINK 0x378
+
+ #define BNX2_ISCSI_INITIATOR 0x3dc
+ #define BNX2_ISCSI_INITIATOR_EN 0x00080000
+
+ #define BNX2_ISCSI_MAX_CONN 0x3e4
+ #define BNX2_ISCSI_MAX_CONN_MASK 0xffff0000
+ #define BNX2_ISCSI_MAX_CONN_SHIFT 16
+
+ #define HOST_VIEW_SHMEM_BASE 0x167c00
+
+ #define DP_SHMEM_LINE(bp, offset) \
+ netdev_err(bp->dev, "DEBUG: %08x: %08x %08x %08x %08x\n", \
+ offset, \
+ bnx2_shmem_rd(bp, offset), \
+ bnx2_shmem_rd(bp, offset + 4), \
+ bnx2_shmem_rd(bp, offset + 8), \
+ bnx2_shmem_rd(bp, offset + 12))
+
+ #endif
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /*
+ drivers/net/tulip/21142.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ DC21143 manual "21143 PCI/CardBus 10/100Mb/s Ethernet LAN Controller
+ Hardware Reference Manual" is currently available at :
+ http://developer.intel.com/design/network/manuals/278074.htm
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+ #include <linux/delay.h>
+ #include "tulip.h"
+
+
+ static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };
+ u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
+ static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+
+
+ /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
+ of available transceivers. */
+ void t21142_media_task(struct work_struct *work)
+ {
+ struct tulip_private *tp =
+ container_of(work, struct tulip_private, media_work);
+ struct net_device *dev = tp->dev;
+ void __iomem *ioaddr = tp->base_addr;
+ int csr12 = ioread32(ioaddr + CSR12);
+ int next_tick = 60*HZ;
+ int new_csr6 = 0;
+ int csr14 = ioread32(ioaddr + CSR14);
+
+ /* CSR12[LS10,LS100] are not reliable during autonegotiation */
+ if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000)
+ csr12 |= 6;
+ if (tulip_debug > 2)
+ dev_info(&dev->dev, "21143 negotiation status %08x, %s\n",
+ csr12, medianame[dev->if_port]);
+ if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+ if (tulip_check_duplex(dev) < 0) {
+ netif_carrier_off(dev);
+ next_tick = 3*HZ;
+ } else {
+ netif_carrier_on(dev);
+ next_tick = 60*HZ;
+ }
+ } else if (tp->nwayset) {
+ /* Don't screw up a negotiated session! */
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "Using NWay-set %s media, csr12 %08x\n",
+ medianame[dev->if_port], csr12);
+ } else if (tp->medialock) {
+ ;
+ } else if (dev->if_port == 3) {
+ if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "No 21143 100baseTx link beat, %08x, trying NWay\n",
+ csr12);
+ t21142_start_nway(dev);
+ next_tick = 3*HZ;
+ }
+ } else if ((csr12 & 0x7000) != 0x5000) {
+ /* Negotiation failed. Search media types. */
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "21143 negotiation failed, status %08x\n",
+ csr12);
+ if (!(csr12 & 4)) { /* 10mbps link beat good. */
+ new_csr6 = 0x82420000;
+ dev->if_port = 0;
+ iowrite32(0, ioaddr + CSR13);
+ iowrite32(0x0003FFFF, ioaddr + CSR14);
+ iowrite16(t21142_csr15[dev->if_port], ioaddr + CSR15);
+ iowrite32(t21142_csr13[dev->if_port], ioaddr + CSR13);
+ } else {
+ /* Select 100mbps port to check for link beat. */
+ new_csr6 = 0x83860000;
+ dev->if_port = 3;
+ iowrite32(0, ioaddr + CSR13);
+ iowrite32(0x0003FFFF, ioaddr + CSR14);
+ iowrite16(8, ioaddr + CSR15);
+ iowrite32(1, ioaddr + CSR13);
+ }
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "Testing new 21143 media %s\n",
+ medianame[dev->if_port]);
+ if (new_csr6 != (tp->csr6 & ~0x00D5)) {
+ tp->csr6 &= 0x00D5;
+ tp->csr6 |= new_csr6;
+ iowrite32(0x0301, ioaddr + CSR12);
+ tulip_restart_rxtx(tp);
+ }
+ next_tick = 3*HZ;
+ }
+
+ /* mod_timer synchronizes us with potential add_timer calls
+ * from interrupts.
+ */
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ }
+
+
+ void t21142_start_nway(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int csr14 = ((tp->sym_advertise & 0x0780) << 9) |
+ ((tp->sym_advertise & 0x0020) << 1) | 0xffbf;
+
+ dev->if_port = 0;
+ tp->nway = tp->mediasense = 1;
+ tp->nwayset = tp->lpar = 0;
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Restarting 21143 autonegotiation, csr14=%08x\n",
+ csr14);
+ iowrite32(0x0001, ioaddr + CSR13);
+ udelay(100);
+ iowrite32(csr14, ioaddr + CSR14);
+ tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0);
+ iowrite32(tp->csr6, ioaddr + CSR6);
+ if (tp->mtable && tp->mtable->csr15dir) {
+ iowrite32(tp->mtable->csr15dir, ioaddr + CSR15);
+ iowrite32(tp->mtable->csr15val, ioaddr + CSR15);
+ } else
+ iowrite16(0x0008, ioaddr + CSR15);
+ iowrite32(0x1301, ioaddr + CSR12); /* Trigger NWAY. */
+ }
+
+
+
+ void t21142_lnk_change(struct net_device *dev, int csr5)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int csr12 = ioread32(ioaddr + CSR12);
+ int csr14 = ioread32(ioaddr + CSR14);
+
+ /* CSR12[LS10,LS100] are not reliable during autonegotiation */
+ if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000)
+ csr12 |= 6;
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "21143 link status interrupt %08x, CSR5 %x, %08x\n",
+ csr12, csr5, csr14);
+
+ /* If NWay finished and we have a negotiated partner capability. */
+ if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) {
+ int setup_done = 0;
+ int negotiated = tp->sym_advertise & (csr12 >> 16);
+ tp->lpar = csr12 >> 16;
+ tp->nwayset = 1;
+ /* If partner cannot negotiate, it is 10Mbps Half Duplex */
+ if (!(csr12 & 0x8000)) dev->if_port = 0;
+ else if (negotiated & 0x0100) dev->if_port = 5;
+ else if (negotiated & 0x0080) dev->if_port = 3;
+ else if (negotiated & 0x0040) dev->if_port = 4;
+ else if (negotiated & 0x0020) dev->if_port = 0;
+ else {
+ tp->nwayset = 0;
+ if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180))
+ dev->if_port = 3;
+ }
+ tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0;
+
+ if (tulip_debug > 1) {
+ if (tp->nwayset)
+ dev_info(&dev->dev,
+ "Switching to %s based on link negotiation %04x & %04x = %04x\n",
+ medianame[dev->if_port],
+ tp->sym_advertise, tp->lpar,
+ negotiated);
+ else
+ dev_info(&dev->dev,
+ "Autonegotiation failed, using %s, link beat status %04x\n",
+ medianame[dev->if_port], csr12);
+ }
+
+ if (tp->mtable) {
+ int i;
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == dev->if_port) {
+ int startup = ! ((tp->chip_id == DC21143 && (tp->revision == 48 || tp->revision == 65)));
+ tp->cur_index = i;
+ tulip_select_media(dev, startup);
+ setup_done = 1;
+ break;
+ }
+ }
+ if ( ! setup_done) {
+ tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff);
+ if (tp->full_duplex)
+ tp->csr6 |= 0x0200;
+ iowrite32(1, ioaddr + CSR13);
+ }
+ #if 0 /* Restart shouldn't be needed. */
+ iowrite32(tp->csr6 | RxOn, ioaddr + CSR6);
+ if (tulip_debug > 2)
+ netdev_dbg(dev, " Restarting Tx and Rx, CSR5 is %08x\n",
+ ioread32(ioaddr + CSR5));
+ #endif
+ tulip_start_rxtx(tp);
+ if (tulip_debug > 2)
+ netdev_dbg(dev, " Setting CSR6 %08x/%x CSR12 %08x\n",
+ tp->csr6, ioread32(ioaddr + CSR6),
+ ioread32(ioaddr + CSR12));
+ } else if ((tp->nwayset && (csr5 & 0x08000000) &&
+ (dev->if_port == 3 || dev->if_port == 5) &&
+ (csr12 & 2) == 2) ||
+ (tp->nway && (csr5 & (TPLnkFail)))) {
+ /* Link blew? Maybe restart NWay. */
+ del_timer_sync(&tp->timer);
+ t21142_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ } else if (dev->if_port == 3 || dev->if_port == 5) {
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "21143 %s link beat %s\n",
+ medianame[dev->if_port],
+ (csr12 & 2) ? "failed" : "good");
+ if ((csr12 & 2) && ! tp->medialock) {
+ del_timer_sync(&tp->timer);
+ t21142_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ } else if (dev->if_port == 5)
+ iowrite32(csr14 & ~0x080, ioaddr + CSR14);
+ } else if (dev->if_port == 0 || dev->if_port == 4) {
+ if ((csr12 & 4) == 0)
+ dev_info(&dev->dev, "21143 10baseT link beat good\n");
+ } else if (!(csr12 & 4)) { /* 10mbps link beat good. */
+ if (tulip_debug)
+ dev_info(&dev->dev, "21143 10mbps sensed media\n");
+ dev->if_port = 0;
+ } else if (tp->nwayset) {
+ if (tulip_debug)
+ dev_info(&dev->dev, "21143 using NWay-set %s, csr6 %08x\n",
+ medianame[dev->if_port], tp->csr6);
+ } else { /* 100mbps link beat good. */
+ if (tulip_debug)
+ dev_info(&dev->dev, "21143 100baseTx sensed media\n");
+ dev->if_port = 3;
+ tp->csr6 = 0x838E0000 | (tp->csr6 & 0x20ff);
+ iowrite32(0x0003FF7F, ioaddr + CSR14);
+ iowrite32(0x0301, ioaddr + CSR12);
+ tulip_restart_rxtx(tp);
+ }
+ }
+
+
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
+ /*
+ drivers/net/tulip/eeprom.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bug reports to http://bugzilla.kernel.org/.
+ */
+
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include "tulip.h"
+ #include <linux/init.h>
+ #include <asm/unaligned.h>
+
+
+
+ /* Serial EEPROM section. */
+ /* The main routine to parse the very complicated SROM structure.
+ Search www.digital.com for "21X4 SROM" to get details.
+ This code is very complex, and will require changes to support
+ additional cards, so I'll be verbose about what is going on.
+ */
+
+ /* Known cards that have old-style EEPROMs. */
+ static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
+ {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
+ 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
+ {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
+ 0x0000, 0x009E, /* 10baseT */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0903, 0x006D, /* 100baseTx */
+ 0x0905, 0x006D, /* 100baseTx-FD */ }},
+ {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
+ 0x0107, 0x8021, /* 100baseFx */
+ 0x0108, 0x8021, /* 100baseFx-FD */
+ 0x0100, 0x009E, /* 10baseT */
+ 0x0104, 0x009E, /* 10baseT-FD */
+ 0x0103, 0x006D, /* 100baseTx */
+ 0x0105, 0x006D, /* 100baseTx-FD */ }},
+ {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
+ 0x1001, 0x009E, /* 10base2, CSR12 0x10*/
+ 0x0000, 0x009E, /* 10baseT */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
+ 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
+ {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
+ 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */
+ 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */
+ 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
+ 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
+ 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
+ }},
+ {"NetWinder", 0x00, 0x10, 0x57,
+ /* Default media = MII
+ * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1
+ */
+ { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
+ },
+ {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset */
+ 0x0000, /* 0 == high offset, 0 == gap */
+ 0x0800, /* Default Autoselect */
+ 0x8001, /* 1 leaf, extended type, bogus len */
+ 0x0003, /* Type 3 (MII), PHY #0 */
+ 0x0400, /* 0 init instr, 4 reset instr */
+ 0x0801, /* Set control mode, GP0 output */
+ 0x0000, /* Drive GP0 Low (RST is active low) */
+ 0x0800, /* control mode, GP0 input (undriven) */
+ 0x0000, /* clear control mode */
+ 0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX */
+ 0x01e0, /* Advertise all above */
+ 0x5000, /* FDX all above */
+ 0x1800, /* Set fast TTM in 100bt modes */
+ 0x0000, /* PHY cannot be unplugged */
+ }},
+ {NULL}};
+
+
+ static const char *block_name[] __devinitdata = {
+ "21140 non-MII",
+ "21140 MII PHY",
+ "21142 Serial PHY",
+ "21142 MII PHY",
+ "21143 SYM PHY",
+ "21143 reset method"
+ };
+
+
+ /**
+ * tulip_build_fake_mediatable - Build a fake mediatable entry.
+ * @tp: Ptr to the tulip private data.
+ *
+ * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
+ * srom and can not be handled under the fixup routine. These cards
+ * still need a valid mediatable entry for correct csr12 setup and
+ * mii handling.
+ *
+ * Since this is currently a parisc-linux specific function, the
+ * #ifdef __hppa__ should completely optimize this function away for
+ * non-parisc hardware.
+ */
+ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
+ {
+ #ifdef CONFIG_GSC
+ if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
+ static unsigned char leafdata[] =
+ { 0x01, /* phy number */
+ 0x02, /* gpr setup sequence length */
+ 0x02, 0x00, /* gpr setup sequence */
+ 0x02, /* phy reset sequence length */
+ 0x01, 0x00, /* phy reset sequence */
+ 0x00, 0x78, /* media capabilities */
+ 0x00, 0xe0, /* nway advertisement */
+ 0x00, 0x05, /* fdx bit map */
+ 0x00, 0x06 /* ttm bit map */
+ };
+
+ tp->mtable = kmalloc(sizeof(struct mediatable) +
+ sizeof(struct medialeaf), GFP_KERNEL);
+
+ if (tp->mtable == NULL)
+ return; /* Horrible, impossible failure. */
+
+ tp->mtable->defaultmedia = 0x800;
+ tp->mtable->leafcount = 1;
+ tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
+ tp->mtable->has_nonmii = 0;
+ tp->mtable->has_reset = 0;
+ tp->mtable->has_mii = 1;
+ tp->mtable->csr15dir = tp->mtable->csr15val = 0;
+ tp->mtable->mleaf[0].type = 1;
+ tp->mtable->mleaf[0].media = 11;
+ tp->mtable->mleaf[0].leafdata = &leafdata[0];
+ tp->flags |= HAS_PHY_IRQ;
+ tp->csr12_shadow = -1;
+ }
+ #endif
+ }
+
+ void __devinit tulip_parse_eeprom(struct net_device *dev)
+ {
+ /*
+ dev is not registered at this point, so logging messages can't
+ use dev_<level> or netdev_<level> but dev->name is good via a
+ hack in the caller
+ */
+
+ /* The last media info list parsed, for multiport boards. */
+ static struct mediatable *last_mediatable;
+ static unsigned char *last_ee_data;
+ static int controller_index;
+ struct tulip_private *tp = netdev_priv(dev);
+ unsigned char *ee_data = tp->eeprom;
+ int i;
+
+ tp->mtable = NULL;
+ /* Detect an old-style (SA only) EEPROM layout:
+ memcmp(eedata, eedata+16, 8). */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ break;
+ if (i >= 8) {
+ if (ee_data[0] == 0xff) {
+ if (last_mediatable) {
+ controller_index++;
+ pr_info("%s: Controller %d of multiport board\n",
+ dev->name, controller_index);
+ tp->mtable = last_mediatable;
+ ee_data = last_ee_data;
+ goto subsequent_board;
+ } else
+ pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
+ dev->name);
+ return;
+ }
+ /* Do a fix-up based on the vendor half of the station address prefix. */
+ for (i = 0; eeprom_fixups[i].name; i++) {
+ if (dev->dev_addr[0] == eeprom_fixups[i].addr0 &&
+ dev->dev_addr[1] == eeprom_fixups[i].addr1 &&
+ dev->dev_addr[2] == eeprom_fixups[i].addr2) {
+ if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
+ i++; /* An Accton EN1207, not an outlaw Maxtech. */
+ memcpy(ee_data + 26, eeprom_fixups[i].newtable,
+ sizeof(eeprom_fixups[i].newtable));
+ pr_info("%s: Old format EEPROM on '%s' board. Using substitute media control info\n",
+ dev->name, eeprom_fixups[i].name);
+ break;
+ }
+ }
+ if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
+ pr_info("%s: Old style EEPROM with no media selection information\n",
+ dev->name);
+ return;
+ }
+ }
+
+ controller_index = 0;
+ if (ee_data[19] > 1) { /* Multiport board. */
+ last_ee_data = ee_data;
+ }
+ subsequent_board:
+
+ if (ee_data[27] == 0) { /* No valid media table. */
+ tulip_build_fake_mediatable(tp);
+ } else {
+ unsigned char *p = (void *)ee_data + ee_data[27];
+ unsigned char csr12dir = 0;
+ int count, new_advertise = 0;
+ struct mediatable *mtable;
+ u16 media = get_u16(p);
+
+ p += 2;
+ if (tp->flags & CSR12_IN_SROM)
+ csr12dir = *p++;
+ count = *p++;
+
+ /* there is no phy information, don't even try to build mtable */
+ if (count == 0) {
+ if (tulip_debug > 0)
+ pr_warn("%s: no phy info, aborting mtable build\n",
+ dev->name);
+ return;
+ }
+
+ mtable = kmalloc(sizeof(struct mediatable) +
+ count * sizeof(struct medialeaf),
+ GFP_KERNEL);
+ if (mtable == NULL)
+ return; /* Horrible, impossible failure. */
+ last_mediatable = tp->mtable = mtable;
+ mtable->defaultmedia = media;
+ mtable->leafcount = count;
+ mtable->csr12dir = csr12dir;
+ mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
+ mtable->csr15dir = mtable->csr15val = 0;
+
+ pr_info("%s: EEPROM default media type %s\n",
+ dev->name,
+ media & 0x0800 ? "Autosense"
+ : medianame[media & MEDIA_MASK]);
+ for (i = 0; i < count; i++) {
+ struct medialeaf *leaf = &mtable->mleaf[i];
+
+ if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
+ leaf->type = 0;
+ leaf->media = p[0] & 0x3f;
+ leaf->leafdata = p;
+ if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */
+ mtable->has_mii = 1;
+ p += 4;
+ } else {
+ leaf->type = p[1];
+ if (p[1] == 0x05) {
+ mtable->has_reset = i;
+ leaf->media = p[2] & 0x0f;
+ } else if (tp->chip_id == DM910X && p[1] == 0x80) {
+ /* Hack to ignore Davicom delay period block */
+ mtable->leafcount--;
+ count--;
+ i--;
+ leaf->leafdata = p + 2;
+ p += (p[0] & 0x3f) + 1;
+ continue;
+ } else if (p[1] & 1) {
+ int gpr_len, reset_len;
+
+ mtable->has_mii = 1;
+ leaf->media = 11;
+ gpr_len=p[3]*2;
+ reset_len=p[4+gpr_len]*2;
+ new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
+ } else {
+ mtable->has_nonmii = 1;
+ leaf->media = p[2] & MEDIA_MASK;
+ /* Davicom's media number for 100BaseTX is strange */
+ if (tp->chip_id == DM910X && leaf->media == 1)
+ leaf->media = 3;
+ switch (leaf->media) {
+ case 0: new_advertise |= 0x0020; break;
+ case 4: new_advertise |= 0x0040; break;
+ case 3: new_advertise |= 0x0080; break;
+ case 5: new_advertise |= 0x0100; break;
+ case 6: new_advertise |= 0x0200; break;
+ }
+ if (p[1] == 2 && leaf->media == 0) {
+ if (p[2] & 0x40) {
+ u32 base15 = get_unaligned((u16*)&p[7]);
+ mtable->csr15dir =
+ (get_unaligned((u16*)&p[9])<<16) + base15;
+ mtable->csr15val =
+ (get_unaligned((u16*)&p[11])<<16) + base15;
+ } else {
+ mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
+ mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
+ }
+ }
+ }
+ leaf->leafdata = p + 2;
+ p += (p[0] & 0x3f) + 1;
+ }
+ if (tulip_debug > 1 && leaf->media == 11) {
+ unsigned char *bp = leaf->leafdata;
+ pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n",
+ dev->name,
+ bp[0], bp[1], bp[2 + bp[1]*2],
+ bp[5 + bp[2 + bp[1]*2]*2],
+ bp[4 + bp[2 + bp[1]*2]*2]);
+ }
+ pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n",
+ dev->name,
+ i, medianame[leaf->media & 15], leaf->media,
+ leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
+ leaf->type);
+ }
+ if (new_advertise)
+ tp->sym_advertise = new_advertise;
+ }
+ }
+ /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
+
+ /* EEPROM_Ctrl bits. */
+ #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
+ #define EE_CS 0x01 /* EEPROM chip select. */
+ #define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */
+ #define EE_WRITE_0 0x01
+ #define EE_WRITE_1 0x05
+ #define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */
+ #define EE_ENB (0x4800 | EE_CS)
+
+ /* Delay between EEPROM clock transitions.
+ Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
+ We add a bus turn-around to insure that this remains true. */
+ #define eeprom_delay() ioread32(ee_addr)
+
+ /* The EEPROM commands include the alway-set leading bit. */
+ #define EE_READ_CMD (6)
+
+ /* Note: this routine returns extra data bits for size detection. */
+ int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
+ {
+ int i;
+ unsigned retval = 0;
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ee_addr = tp->base_addr + CSR9;
+ int read_cmd = location | (EE_READ_CMD << addr_len);
+
+ /* If location is past the end of what we can address, don't
+ * read some other location (ie truncate). Just return zero.
+ */
+ if (location > (1 << addr_len) - 1)
+ return 0;
+
+ iowrite32(EE_ENB & ~EE_CS, ee_addr);
+ iowrite32(EE_ENB, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ iowrite32(EE_ENB | dataval, ee_addr);
+ eeprom_delay();
+ iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ }
+ iowrite32(EE_ENB, ee_addr);
+ eeprom_delay();
+
+ for (i = 16; i > 0; i--) {
+ iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ iowrite32(EE_ENB, ee_addr);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ iowrite32(EE_ENB & ~EE_CS, ee_addr);
+ return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
+ }
+
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
+ /*
+ drivers/net/tulip/interrupt.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
-
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+ #include <linux/pci.h>
+ #include "tulip.h"
+ #include <linux/etherdevice.h>
+
+ int tulip_rx_copybreak;
+ unsigned int tulip_max_interrupt_work;
+
+ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+ #define MIT_SIZE 15
+ #define MIT_TABLE 15 /* We use 0 or max */
+
+ static unsigned int mit_table[MIT_SIZE+1] =
+ {
+ /* CRS11 21143 hardware Mitigation Control Interrupt
+ We use only RX mitigation we other techniques for
+ TX intr. mitigation.
+
+ 31 Cycle Size (timer control)
+ 30:27 TX timer in 16 * Cycle size
+ 26:24 TX No pkts before Int.
+ 23:20 RX timer in Cycle size
+ 19:17 RX No pkts before Int.
+ 16 Continues Mode (CM)
+ */
+
+ 0x0, /* IM disabled */
+ 0x80150000, /* RX time = 1, RX pkts = 2, CM = 1 */
+ 0x80150000,
+ 0x80270000,
+ 0x80370000,
+ 0x80490000,
+ 0x80590000,
+ 0x80690000,
+ 0x807B0000,
+ 0x808B0000,
+ 0x809D0000,
+ 0x80AD0000,
+ 0x80BD0000,
+ 0x80CF0000,
+ 0x80DF0000,
+ // 0x80FF0000 /* RX time = 16, RX pkts = 7, CM = 1 */
+ 0x80F10000 /* RX time = 16, RX pkts = 0, CM = 1 */
+ };
+ #endif
+
+
+ int tulip_refill_rx(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int entry;
+ int refilled = 0;
+
+ /* Refill the Rx ring buffers. */
+ for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
+ entry = tp->dirty_rx % RX_RING_SIZE;
+ if (tp->rx_buffers[entry].skb == NULL) {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+
+ skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ);
+ if (skb == NULL)
+ break;
+
+ mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ,
+ PCI_DMA_FROMDEVICE);
+ tp->rx_buffers[entry].mapping = mapping;
+
+ skb->dev = dev; /* Mark as being used by this device. */
+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping);
+ refilled++;
+ }
+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned);
+ }
+ if(tp->chip_id == LC82C168) {
+ if(((ioread32(tp->base_addr + CSR5)>>17)&0x07) == 4) {
+ /* Rx stopped due to out of buffers,
+ * restart it
+ */
+ iowrite32(0x01, tp->base_addr + CSR2);
+ }
+ }
+ return refilled;
+ }
+
+ #ifdef CONFIG_TULIP_NAPI
+
+ void oom_timer(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+ napi_schedule(&tp->napi);
+ }
+
+ int tulip_poll(struct napi_struct *napi, int budget)
+ {
+ struct tulip_private *tp = container_of(napi, struct tulip_private, napi);
+ struct net_device *dev = tp->dev;
+ int entry = tp->cur_rx % RX_RING_SIZE;
+ int work_done = 0;
+ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+ int received = 0;
+ #endif
+
+ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+
+ /* that one buffer is needed for mit activation; or might be a
+ bug in the ring buffer code; check later -- JHS*/
+
+ if (budget >=RX_RING_SIZE) budget--;
+ #endif
+
+ if (tulip_debug > 4)
+ netdev_dbg(dev, " In tulip_rx(), entry %d %08x\n",
+ entry, tp->rx_ring[entry].status);
+
+ do {
+ if (ioread32(tp->base_addr + CSR5) == 0xffffffff) {
+ netdev_dbg(dev, " In tulip_poll(), hardware disappeared\n");
+ break;
+ }
+ /* Acknowledge current RX interrupt sources. */
+ iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5);
+
+
+ /* If we own the next entry, it is a new packet. Send it up. */
+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
+ s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+ short pkt_len;
+
+ if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
+ break;
+
+ if (tulip_debug > 5)
+ netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n",
+ entry, status);
+
+ if (++work_done >= budget)
+ goto not_done;
+
+ /*
+ * Omit the four octet CRC from the length.
+ * (May not be considered valid until we have
+ * checked status for RxLengthOver2047 bits)
+ */
+ pkt_len = ((status >> 16) & 0x7ff) - 4;
+
+ /*
+ * Maximum pkt_len is 1518 (1514 + vlan header)
+ * Anything higher than this is always invalid
+ * regardless of RxLengthOver2047 bits
+ */
+
+ if ((status & (RxLengthOver2047 |
+ RxDescCRCError |
+ RxDescCollisionSeen |
+ RxDescRunt |
+ RxDescDescErr |
+ RxWholePkt)) != RxWholePkt ||
+ pkt_len > 1518) {
+ if ((status & (RxLengthOver2047 |
+ RxWholePkt)) != RxWholePkt) {
+ /* Ingore earlier buffers. */
+ if ((status & 0xffff) != 0x7fff) {
+ if (tulip_debug > 1)
+ dev_warn(&dev->dev,
+ "Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
+ status);
+ dev->stats.rx_length_errors++;
+ }
+ } else {
+ /* There was a fatal error. */
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "Receive error, Rx status %08x\n",
+ status);
+ dev->stats.rx_errors++; /* end of a packet.*/
+ if (pkt_len > 1518 ||
+ (status & RxDescRunt))
+ dev->stats.rx_length_errors++;
+
+ if (status & 0x0004)
+ dev->stats.rx_frame_errors++;
+ if (status & 0x0002)
+ dev->stats.rx_crc_errors++;
+ if (status & 0x0001)
+ dev->stats.rx_fifo_errors++;
+ }
+ } else {
+ struct sk_buff *skb;
+
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < tulip_rx_copybreak &&
+ (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+ pci_dma_sync_single_for_cpu(tp->pdev,
+ tp->rx_buffers[entry].mapping,
+ pkt_len, PCI_DMA_FROMDEVICE);
+ #if ! defined(__alpha__)
+ skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+ pkt_len);
+ skb_put(skb, pkt_len);
+ #else
+ memcpy(skb_put(skb, pkt_len),
+ tp->rx_buffers[entry].skb->data,
+ pkt_len);
+ #endif
+ pci_dma_sync_single_for_device(tp->pdev,
+ tp->rx_buffers[entry].mapping,
+ pkt_len, PCI_DMA_FROMDEVICE);
+ } else { /* Pass up the skb already on the Rx ring. */
+ char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
+ pkt_len);
+
+ #ifndef final_version
+ if (tp->rx_buffers[entry].mapping !=
+ le32_to_cpu(tp->rx_ring[entry].buffer1)) {
+ dev_err(&dev->dev,
+ "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %08llx %p / %p\n",
+ le32_to_cpu(tp->rx_ring[entry].buffer1),
+ (unsigned long long)tp->rx_buffers[entry].mapping,
+ skb->head, temp);
+ }
+ #endif
+
+ pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+
+ tp->rx_buffers[entry].skb = NULL;
+ tp->rx_buffers[entry].mapping = 0;
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+
+ netif_receive_skb(skb);
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+ }
+ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+ received++;
+ #endif
+
+ entry = (++tp->cur_rx) % RX_RING_SIZE;
+ if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
+ tulip_refill_rx(dev);
+
+ }
+
+ /* New ack strategy... irq does not ack Rx any longer
+ hopefully this helps */
+
+ /* Really bad things can happen here... If new packet arrives
+ * and an irq arrives (tx or just due to occasionally unset
+ * mask), it will be acked by irq handler, but new thread
+ * is not scheduled. It is major hole in design.
+ * No idea how to fix this if "playing with fire" will fail
+ * tomorrow (night 011029). If it will not fail, we won
+ * finally: amount of IO did not increase at all. */
+ } while ((ioread32(tp->base_addr + CSR5) & RxIntr));
+
+ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+
+ /* We use this simplistic scheme for IM. It's proven by
+ real life installations. We can have IM enabled
+ continuesly but this would cause unnecessary latency.
+ Unfortunely we can't use all the NET_RX_* feedback here.
+ This would turn on IM for devices that is not contributing
+ to backlog congestion with unnecessary latency.
+
+ We monitor the device RX-ring and have:
+
+ HW Interrupt Mitigation either ON or OFF.
+
+ ON: More then 1 pkt received (per intr.) OR we are dropping
+ OFF: Only 1 pkt received
+
+ Note. We only use min and max (0, 15) settings from mit_table */
+
+
+ if( tp->flags & HAS_INTR_MITIGATION) {
+ if( received > 1 ) {
+ if( ! tp->mit_on ) {
+ tp->mit_on = 1;
+ iowrite32(mit_table[MIT_TABLE], tp->base_addr + CSR11);
+ }
+ }
+ else {
+ if( tp->mit_on ) {
+ tp->mit_on = 0;
+ iowrite32(0, tp->base_addr + CSR11);
+ }
+ }
+ }
+
+ #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
+
+ tulip_refill_rx(dev);
+
+ /* If RX ring is not full we are out of memory. */
+ if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+ goto oom;
+
+ /* Remove us from polling list and enable RX intr. */
+
+ napi_complete(napi);
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7);
+
+ /* The last op happens after poll completion. Which means the following:
+ * 1. it can race with disabling irqs in irq handler
+ * 2. it can race with dise/enabling irqs in other poll threads
+ * 3. if an irq raised after beginning loop, it will be immediately
+ * triggered here.
+ *
+ * Summarizing: the logic results in some redundant irqs both
+ * due to races in masking and due to too late acking of already
+ * processed irqs. But it must not result in losing events.
+ */
+
+ return work_done;
+
+ not_done:
+ if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
+ tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+ tulip_refill_rx(dev);
+
+ if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+ goto oom;
+
+ return work_done;
+
+ oom: /* Executed with RX ints disabled */
+
+ /* Start timer, stop polling, but do not enable rx interrupts. */
+ mod_timer(&tp->oom_timer, jiffies+1);
+
+ /* Think: timer_pending() was an explicit signature of bug.
+ * Timer can be pending now but fired and completed
+ * before we did napi_complete(). See? We would lose it. */
+
+ /* remove ourselves from the polling list */
+ napi_complete(napi);
+
+ return work_done;
+ }
+
+ #else /* CONFIG_TULIP_NAPI */
+
+ static int tulip_rx(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int entry = tp->cur_rx % RX_RING_SIZE;
+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+ int received = 0;
+
+ if (tulip_debug > 4)
+ netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n",
+ entry, tp->rx_ring[entry].status);
+ /* If we own the next entry, it is a new packet. Send it up. */
+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
+ s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+ short pkt_len;
+
+ if (tulip_debug > 5)
+ netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n",
+ entry, status);
+ if (--rx_work_limit < 0)
+ break;
+
+ /*
+ Omit the four octet CRC from the length.
+ (May not be considered valid until we have
+ checked status for RxLengthOver2047 bits)
+ */
+ pkt_len = ((status >> 16) & 0x7ff) - 4;
+ /*
+ Maximum pkt_len is 1518 (1514 + vlan header)
+ Anything higher than this is always invalid
+ regardless of RxLengthOver2047 bits
+ */
+
+ if ((status & (RxLengthOver2047 |
+ RxDescCRCError |
+ RxDescCollisionSeen |
+ RxDescRunt |
+ RxDescDescErr |
+ RxWholePkt)) != RxWholePkt ||
+ pkt_len > 1518) {
+ if ((status & (RxLengthOver2047 |
+ RxWholePkt)) != RxWholePkt) {
+ /* Ingore earlier buffers. */
+ if ((status & 0xffff) != 0x7fff) {
+ if (tulip_debug > 1)
+ netdev_warn(dev,
+ "Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
+ status);
+ dev->stats.rx_length_errors++;
+ }
+ } else {
+ /* There was a fatal error. */
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "Receive error, Rx status %08x\n",
+ status);
+ dev->stats.rx_errors++; /* end of a packet.*/
+ if (pkt_len > 1518 ||
+ (status & RxDescRunt))
+ dev->stats.rx_length_errors++;
+ if (status & 0x0004)
+ dev->stats.rx_frame_errors++;
+ if (status & 0x0002)
+ dev->stats.rx_crc_errors++;
+ if (status & 0x0001)
+ dev->stats.rx_fifo_errors++;
+ }
+ } else {
+ struct sk_buff *skb;
+
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < tulip_rx_copybreak &&
+ (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+ pci_dma_sync_single_for_cpu(tp->pdev,
+ tp->rx_buffers[entry].mapping,
+ pkt_len, PCI_DMA_FROMDEVICE);
+ #if ! defined(__alpha__)
+ skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+ pkt_len);
+ skb_put(skb, pkt_len);
+ #else
+ memcpy(skb_put(skb, pkt_len),
+ tp->rx_buffers[entry].skb->data,
+ pkt_len);
+ #endif
+ pci_dma_sync_single_for_device(tp->pdev,
+ tp->rx_buffers[entry].mapping,
+ pkt_len, PCI_DMA_FROMDEVICE);
+ } else { /* Pass up the skb already on the Rx ring. */
+ char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
+ pkt_len);
+
+ #ifndef final_version
+ if (tp->rx_buffers[entry].mapping !=
+ le32_to_cpu(tp->rx_ring[entry].buffer1)) {
+ dev_err(&dev->dev,
+ "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %Lx %p / %p\n",
+ le32_to_cpu(tp->rx_ring[entry].buffer1),
+ (long long)tp->rx_buffers[entry].mapping,
+ skb->head, temp);
+ }
+ #endif
+
+ pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+
+ tp->rx_buffers[entry].skb = NULL;
+ tp->rx_buffers[entry].mapping = 0;
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+
+ netif_rx(skb);
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+ }
+ received++;
+ entry = (++tp->cur_rx) % RX_RING_SIZE;
+ }
+ return received;
+ }
+ #endif /* CONFIG_TULIP_NAPI */
+
+ static inline unsigned int phy_interrupt (struct net_device *dev)
+ {
+ #ifdef __hppa__
+ struct tulip_private *tp = netdev_priv(dev);
+ int csr12 = ioread32(tp->base_addr + CSR12) & 0xff;
+
+ if (csr12 != tp->csr12_shadow) {
+ /* ack interrupt */
+ iowrite32(csr12 | 0x02, tp->base_addr + CSR12);
+ tp->csr12_shadow = csr12;
+ /* do link change stuff */
+ spin_lock(&tp->lock);
+ tulip_check_duplex(dev);
+ spin_unlock(&tp->lock);
+ /* clear irq ack bit */
+ iowrite32(csr12 & ~0x02, tp->base_addr + CSR12);
+
+ return 1;
+ }
+ #endif
+
+ return 0;
+ }
+
+ /* The interrupt handler does all of the Rx thread work and cleans up
+ after the Tx thread. */
+ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
+ {
+ struct net_device *dev = (struct net_device *)dev_instance;
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int csr5;
+ int missed;
+ int rx = 0;
+ int tx = 0;
+ int oi = 0;
+ int maxrx = RX_RING_SIZE;
+ int maxtx = TX_RING_SIZE;
+ int maxoi = TX_RING_SIZE;
+ #ifdef CONFIG_TULIP_NAPI
+ int rxd = 0;
+ #else
+ int entry;
+ #endif
+ unsigned int work_count = tulip_max_interrupt_work;
+ unsigned int handled = 0;
+
+ /* Let's see whether the interrupt really is for us */
+ csr5 = ioread32(ioaddr + CSR5);
+
+ if (tp->flags & HAS_PHY_IRQ)
+ handled = phy_interrupt (dev);
+
+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
+ return IRQ_RETVAL(handled);
+
+ tp->nir++;
+
+ do {
+
+ #ifdef CONFIG_TULIP_NAPI
+
+ if (!rxd && (csr5 & (RxIntr | RxNoBuf))) {
+ rxd++;
+ /* Mask RX intrs and add the device to poll list. */
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
+ napi_schedule(&tp->napi);
+
+ if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
+ break;
+ }
+
+ /* Acknowledge the interrupt sources we handle here ASAP
+ the poll function does Rx and RxNoBuf acking */
+
+ iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5);
+
+ #else
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5);
+
+
+ if (csr5 & (RxIntr | RxNoBuf)) {
+ rx += tulip_rx(dev);
+ tulip_refill_rx(dev);
+ }
+
+ #endif /* CONFIG_TULIP_NAPI */
+
+ if (tulip_debug > 4)
+ netdev_dbg(dev, "interrupt csr5=%#8.8x new csr5=%#8.8x\n",
+ csr5, ioread32(ioaddr + CSR5));
+
+
+ if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
+ unsigned int dirty_tx;
+
+ spin_lock(&tp->lock);
+
+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
+ dirty_tx++) {
+ int entry = dirty_tx % TX_RING_SIZE;
+ int status = le32_to_cpu(tp->tx_ring[entry].status);
+
+ if (status < 0)
+ break; /* It still has not been Txed */
+
+ /* Check for Rx filter setup frames. */
+ if (tp->tx_buffers[entry].skb == NULL) {
+ /* test because dummy frames not mapped */
+ if (tp->tx_buffers[entry].mapping)
+ pci_unmap_single(tp->pdev,
+ tp->tx_buffers[entry].mapping,
+ sizeof(tp->setup_frame),
+ PCI_DMA_TODEVICE);
+ continue;
+ }
+
+ if (status & 0x8000) {
+ /* There was an major error, log it. */
+ #ifndef final_version
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Transmit error, Tx status %08x\n",
+ status);
+ #endif
+ dev->stats.tx_errors++;
+ if (status & 0x4104)
+ dev->stats.tx_aborted_errors++;
+ if (status & 0x0C00)
+ dev->stats.tx_carrier_errors++;
+ if (status & 0x0200)
+ dev->stats.tx_window_errors++;
+ if (status & 0x0002)
+ dev->stats.tx_fifo_errors++;
+ if ((status & 0x0080) && tp->full_duplex == 0)
+ dev->stats.tx_heartbeat_errors++;
+ } else {
+ dev->stats.tx_bytes +=
+ tp->tx_buffers[entry].skb->len;
+ dev->stats.collisions += (status >> 3) & 15;
+ dev->stats.tx_packets++;
+ }
+
+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
+ tp->tx_buffers[entry].skb->len,
+ PCI_DMA_TODEVICE);
+
+ /* Free the original skb. */
+ dev_kfree_skb_irq(tp->tx_buffers[entry].skb);
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ tx++;
+ }
+
+ #ifndef final_version
+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
+ dev_err(&dev->dev,
+ "Out-of-sync dirty pointer, %d vs. %d\n",
+ dirty_tx, tp->cur_tx);
+ dirty_tx += TX_RING_SIZE;
+ }
+ #endif
+
+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2)
+ netif_wake_queue(dev);
+
+ tp->dirty_tx = dirty_tx;
+ if (csr5 & TxDied) {
+ if (tulip_debug > 2)
+ dev_warn(&dev->dev,
+ "The transmitter stopped. CSR5 is %x, CSR6 %x, new CSR6 %x\n",
+ csr5, ioread32(ioaddr + CSR6),
+ tp->csr6);
+ tulip_restart_rxtx(tp);
+ }
+ spin_unlock(&tp->lock);
+ }
+
+ /* Log errors. */
+ if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */
+ if (csr5 == 0xffffffff)
+ break;
+ if (csr5 & TxJabber)
+ dev->stats.tx_errors++;
+ if (csr5 & TxFIFOUnderflow) {
+ if ((tp->csr6 & 0xC000) != 0xC000)
+ tp->csr6 += 0x4000; /* Bump up the Tx threshold */
+ else
+ tp->csr6 |= 0x00200000; /* Store-n-forward. */
+ /* Restart the transmit process. */
+ tulip_restart_rxtx(tp);
+ iowrite32(0, ioaddr + CSR1);
+ }
+ if (csr5 & (RxDied | RxNoBuf)) {
+ if (tp->flags & COMET_MAC_ADDR) {
+ iowrite32(tp->mc_filter[0], ioaddr + 0xAC);
+ iowrite32(tp->mc_filter[1], ioaddr + 0xB0);
+ }
+ }
+ if (csr5 & RxDied) { /* Missed a Rx frame. */
+ dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+ dev->stats.rx_errors++;
+ tulip_start_rxtx(tp);
+ }
+ /*
+ * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this
+ * call is ever done under the spinlock
+ */
+ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
+ if (tp->link_change)
+ (tp->link_change)(dev, csr5);
+ }
+ if (csr5 & SystemError) {
+ int error = (csr5 >> 23) & 7;
+ /* oops, we hit a PCI error. The code produced corresponds
+ * to the reason:
+ * 0 - parity error
+ * 1 - master abort
+ * 2 - target abort
+ * Note that on parity error, we should do a software reset
+ * of the chip to get it back into a sane state (according
+ * to the 21142/3 docs that is).
+ * -- rmk
+ */
+ dev_err(&dev->dev,
+ "(%lu) System Error occurred (%d)\n",
+ tp->nir, error);
+ }
+ /* Clear all error sources, included undocumented ones! */
+ iowrite32(0x0800f7ba, ioaddr + CSR5);
+ oi++;
+ }
+ if (csr5 & TimerInt) {
+
+ if (tulip_debug > 2)
+ dev_err(&dev->dev,
+ "Re-enabling interrupts, %08x\n",
+ csr5);
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+ tp->ttimer = 0;
+ oi++;
+ }
+ if (tx > maxtx || rx > maxrx || oi > maxoi) {
+ if (tulip_debug > 1)
+ dev_warn(&dev->dev, "Too much work during an interrupt, csr5=0x%08x. (%lu) (%d,%d,%d)\n",
+ csr5, tp->nir, tx, rx, oi);
+
+ /* Acknowledge all interrupt sources. */
+ iowrite32(0x8001ffff, ioaddr + CSR5);
+ if (tp->flags & HAS_INTR_MITIGATION) {
+ /* Josip Loncaric at ICASE did extensive experimentation
+ to develop a good interrupt mitigation setting.*/
+ iowrite32(0x8b240000, ioaddr + CSR11);
+ } else if (tp->chip_id == LC82C168) {
+ /* the LC82C168 doesn't have a hw timer.*/
+ iowrite32(0x00, ioaddr + CSR7);
+ mod_timer(&tp->timer, RUN_AT(HZ/50));
+ } else {
+ /* Mask all interrupting sources, set timer to
+ re-enable. */
+ iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
+ iowrite32(0x0012, ioaddr + CSR11);
+ }
+ break;
+ }
+
+ work_count--;
+ if (work_count == 0)
+ break;
+
+ csr5 = ioread32(ioaddr + CSR5);
+
+ #ifdef CONFIG_TULIP_NAPI
+ if (rxd)
+ csr5 &= ~RxPollInt;
+ } while ((csr5 & (TxNoBuf |
+ TxDied |
+ TxIntr |
+ TimerInt |
+ /* Abnormal intr. */
+ RxDied |
+ TxFIFOUnderflow |
+ TxJabber |
+ TPLnkFail |
+ SystemError )) != 0);
+ #else
+ } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
+
+ tulip_refill_rx(dev);
+
+ /* check if the card is in suspend mode */
+ entry = tp->dirty_rx % RX_RING_SIZE;
+ if (tp->rx_buffers[entry].skb == NULL) {
+ if (tulip_debug > 1)
+ dev_warn(&dev->dev,
+ "in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n",
+ tp->nir, tp->cur_rx, tp->ttimer, rx);
+ if (tp->chip_id == LC82C168) {
+ iowrite32(0x00, ioaddr + CSR7);
+ mod_timer(&tp->timer, RUN_AT(HZ/50));
+ } else {
+ if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) {
+ if (tulip_debug > 1)
+ dev_warn(&dev->dev,
+ "in rx suspend mode: (%lu) set timer\n",
+ tp->nir);
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt,
+ ioaddr + CSR7);
+ iowrite32(TimerInt, ioaddr + CSR5);
+ iowrite32(12, ioaddr + CSR11);
+ tp->ttimer = 1;
+ }
+ }
+ }
+ #endif /* CONFIG_TULIP_NAPI */
+
+ if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
+ dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+ }
+
+ if (tulip_debug > 4)
+ netdev_dbg(dev, "exiting interrupt, csr5=%#04x\n",
+ ioread32(ioaddr + CSR5));
+
+ return IRQ_HANDLED;
+ }
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /*
+ drivers/net/tulip/media.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+ #include <linux/kernel.h>
+ #include <linux/mii.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+ #include "tulip.h"
+
+
+ /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+ "overclocking" issues or future 66Mhz PCI. */
+ #define mdio_delay() ioread32(mdio_addr)
+
+ /* Read and write the MII registers using software-generated serial
+ MDIO protocol. It is just different enough from the EEPROM protocol
+ to not share code. The maxium data clock rate is 2.5 Mhz. */
+ #define MDIO_SHIFT_CLK 0x10000
+ #define MDIO_DATA_WRITE0 0x00000
+ #define MDIO_DATA_WRITE1 0x20000
+ #define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */
+ #define MDIO_ENB_IN 0x40000
+ #define MDIO_DATA_READ 0x80000
+
+ static const unsigned char comet_miireg2offset[32] = {
+ 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC, 0, 0,0,0,0, 0,0,0,0,
+ 0,0xD0,0,0, 0,0,0,0, 0,0,0,0, 0, 0xD4, 0xD8, 0xDC, };
+
+
+ /* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol.
+ See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management functions")
+ or DP83840A data sheet for more details.
+ */
+
+ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int i;
+ int read_cmd = (0xf6 << 10) | ((phy_id & 0x1f) << 5) | location;
+ int retval = 0;
+ void __iomem *ioaddr = tp->base_addr;
+ void __iomem *mdio_addr = ioaddr + CSR9;
+ unsigned long flags;
+
+ if (location & ~0x1f)
+ return 0xffff;
+
+ if (tp->chip_id == COMET && phy_id == 30) {
+ if (comet_miireg2offset[location])
+ return ioread32(ioaddr + comet_miireg2offset[location]);
+ return 0xffff;
+ }
+
+ spin_lock_irqsave(&tp->mii_lock, flags);
+ if (tp->chip_id == LC82C168) {
+ iowrite32(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
+ ioread32(ioaddr + 0xA0);
+ ioread32(ioaddr + 0xA0);
+ for (i = 1000; i >= 0; --i) {
+ barrier();
+ if ( ! ((retval = ioread32(ioaddr + 0xA0)) & 0x80000000))
+ break;
+ }
+ spin_unlock_irqrestore(&tp->mii_lock, flags);
+ return retval & 0xffff;
+ }
+
+ /* Establish sync by sending at least 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+
+ iowrite32(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ iowrite32(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ retval = (retval << 1) | ((ioread32(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+
+ spin_unlock_irqrestore(&tp->mii_lock, flags);
+ return (retval>>1) & 0xffff;
+ }
+
+ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int i;
+ int cmd = (0x5002 << 16) | ((phy_id & 0x1f) << 23) | (location<<18) | (val & 0xffff);
+ void __iomem *ioaddr = tp->base_addr;
+ void __iomem *mdio_addr = ioaddr + CSR9;
+ unsigned long flags;
+
+ if (location & ~0x1f)
+ return;
+
+ if (tp->chip_id == COMET && phy_id == 30) {
+ if (comet_miireg2offset[location])
+ iowrite32(val, ioaddr + comet_miireg2offset[location]);
+ return;
+ }
+
+ spin_lock_irqsave(&tp->mii_lock, flags);
+ if (tp->chip_id == LC82C168) {
+ iowrite32(cmd, ioaddr + 0xA0);
+ for (i = 1000; i >= 0; --i) {
+ barrier();
+ if ( ! (ioread32(ioaddr + 0xA0) & 0x80000000))
+ break;
+ }
+ spin_unlock_irqrestore(&tp->mii_lock, flags);
+ return;
+ }
+
+ /* Establish sync by sending 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ iowrite32(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ iowrite32(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+
+ spin_unlock_irqrestore(&tp->mii_lock, flags);
+ }
+
+
+ /* Set up the transceiver control registers for the selected media type. */
+ void tulip_select_media(struct net_device *dev, int startup)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ struct mediatable *mtable = tp->mtable;
+ u32 new_csr6;
+ int i;
+
+ if (mtable) {
+ struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
+ unsigned char *p = mleaf->leafdata;
+ switch (mleaf->type) {
+ case 0: /* 21140 non-MII xcvr. */
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Using a 21140 non-MII transceiver with control setting %02x\n",
+ p[1]);
+ dev->if_port = p[0];
+ if (startup)
+ iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ iowrite32(p[1], ioaddr + CSR12);
+ new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
+ break;
+ case 2: case 4: {
+ u16 setup[5];
+ u32 csr13val, csr14val, csr15dir, csr15val;
+ for (i = 0; i < 5; i++)
+ setup[i] = get_u16(&p[i*2 + 1]);
+
+ dev->if_port = p[0] & MEDIA_MASK;
+ if (tulip_media_cap[dev->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+
+ if (startup && mtable->has_reset) {
+ struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+ unsigned char *rst = rleaf->leafdata;
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Resetting the transceiver\n");
+ for (i = 0; i < rst[0]; i++)
+ iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+ }
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "21143 non-MII %s transceiver control %04x/%04x\n",
+ medianame[dev->if_port],
+ setup[0], setup[1]);
+ if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */
+ csr13val = setup[0];
+ csr14val = setup[1];
+ csr15dir = (setup[3]<<16) | setup[2];
+ csr15val = (setup[4]<<16) | setup[2];
+ iowrite32(0, ioaddr + CSR13);
+ iowrite32(csr14val, ioaddr + CSR14);
+ iowrite32(csr15dir, ioaddr + CSR15); /* Direction */
+ iowrite32(csr15val, ioaddr + CSR15); /* Data */
+ iowrite32(csr13val, ioaddr + CSR13);
+ } else {
+ csr13val = 1;
+ csr14val = 0;
+ csr15dir = (setup[0]<<16) | 0x0008;
+ csr15val = (setup[1]<<16) | 0x0008;
+ if (dev->if_port <= 4)
+ csr14val = t21142_csr14[dev->if_port];
+ if (startup) {
+ iowrite32(0, ioaddr + CSR13);
+ iowrite32(csr14val, ioaddr + CSR14);
+ }
+ iowrite32(csr15dir, ioaddr + CSR15); /* Direction */
+ iowrite32(csr15val, ioaddr + CSR15); /* Data */
+ if (startup) iowrite32(csr13val, ioaddr + CSR13);
+ }
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Setting CSR15 to %08x/%08x\n",
+ csr15dir, csr15val);
+ if (mleaf->type == 4)
+ new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
+ else
+ new_csr6 = 0x82420000;
+ break;
+ }
+ case 1: case 3: {
+ int phy_num = p[0];
+ int init_length = p[1];
+ u16 *misc_info, tmp_info;
+
+ dev->if_port = 11;
+ new_csr6 = 0x020E0000;
+ if (mleaf->type == 3) { /* 21142 */
+ u16 *init_sequence = (u16*)(p+2);
+ u16 *reset_sequence = &((u16*)(p+3))[init_length];
+ int reset_length = p[2 + init_length*2];
+ misc_info = reset_sequence + reset_length;
+ if (startup) {
+ int timeout = 10; /* max 1 ms */
+ for (i = 0; i < reset_length; i++)
+ iowrite32(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
+
+ /* flush posted writes */
+ ioread32(ioaddr + CSR15);
+
+ /* Sect 3.10.3 in DP83840A.pdf (p39) */
+ udelay(500);
+
+ /* Section 4.2 in DP83840A.pdf (p43) */
+ /* and IEEE 802.3 "22.2.4.1.1 Reset" */
+ while (timeout-- &&
+ (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET))
+ udelay(100);
+ }
+ for (i = 0; i < init_length; i++)
+ iowrite32(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
+
+ ioread32(ioaddr + CSR15); /* flush posted writes */
+ } else {
+ u8 *init_sequence = p + 2;
+ u8 *reset_sequence = p + 3 + init_length;
+ int reset_length = p[2 + init_length];
+ misc_info = (u16*)(reset_sequence + reset_length);
+ if (startup) {
+ int timeout = 10; /* max 1 ms */
+ iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ for (i = 0; i < reset_length; i++)
+ iowrite32(reset_sequence[i], ioaddr + CSR12);
+
+ /* flush posted writes */
+ ioread32(ioaddr + CSR12);
+
+ /* Sect 3.10.3 in DP83840A.pdf (p39) */
+ udelay(500);
+
+ /* Section 4.2 in DP83840A.pdf (p43) */
+ /* and IEEE 802.3 "22.2.4.1.1 Reset" */
+ while (timeout-- &&
+ (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET))
+ udelay(100);
+ }
+ for (i = 0; i < init_length; i++)
+ iowrite32(init_sequence[i], ioaddr + CSR12);
+
+ ioread32(ioaddr + CSR12); /* flush posted writes */
+ }
+
+ tmp_info = get_u16(&misc_info[1]);
+ if (tmp_info)
+ tp->advertising[phy_num] = tmp_info | 1;
+ if (tmp_info && startup < 2) {
+ if (tp->mii_advertise == 0)
+ tp->mii_advertise = tp->advertising[phy_num];
+ if (tulip_debug > 1)
+ netdev_dbg(dev, " Advertising %04x on MII %d\n",
+ tp->mii_advertise,
+ tp->phys[phy_num]);
+ tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise);
+ }
+ break;
+ }
+ case 5: case 6: {
+ u16 setup[5];
+
+ new_csr6 = 0; /* FIXME */
+
+ for (i = 0; i < 5; i++)
+ setup[i] = get_u16(&p[i*2 + 1]);
+
+ if (startup && mtable->has_reset) {
+ struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+ unsigned char *rst = rleaf->leafdata;
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Resetting the transceiver\n");
+ for (i = 0; i < rst[0]; i++)
+ iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+ }
+
+ break;
+ }
+ default:
+ netdev_dbg(dev, " Invalid media table selection %d\n",
+ mleaf->type);
+ new_csr6 = 0x020E0000;
+ }
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Using media type %s, CSR12 is %02x\n",
+ medianame[dev->if_port],
+ ioread32(ioaddr + CSR12) & 0xff);
+ } else if (tp->chip_id == LC82C168) {
+ if (startup && ! tp->medialock)
+ dev->if_port = tp->mii_cnt ? 11 : 0;
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "PNIC PHY status is %3.3x, media %s\n",
+ ioread32(ioaddr + 0xB8),
+ medianame[dev->if_port]);
+ if (tp->mii_cnt) {
+ new_csr6 = 0x810C0000;
+ iowrite32(0x0001, ioaddr + CSR15);
+ iowrite32(0x0201B07A, ioaddr + 0xB8);
+ } else if (startup) {
+ /* Start with 10mbps to do autonegotiation. */
+ iowrite32(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ iowrite32(0x0001B078, ioaddr + 0xB8);
+ iowrite32(0x0201B078, ioaddr + 0xB8);
+ } else if (dev->if_port == 3 || dev->if_port == 5) {
+ iowrite32(0x33, ioaddr + CSR12);
+ new_csr6 = 0x01860000;
+ /* Trigger autonegotiation. */
+ iowrite32(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
+ } else {
+ iowrite32(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ iowrite32(0x1F078, ioaddr + 0xB8);
+ }
+ } else { /* Unknown chip type with no media table. */
+ if (tp->default_port == 0)
+ dev->if_port = tp->mii_cnt ? 11 : 3;
+ if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+ new_csr6 = 0x020E0000;
+ } else if (tulip_media_cap[dev->if_port] & MediaIsFx) {
+ new_csr6 = 0x02860000;
+ } else
+ new_csr6 = 0x03860000;
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "No media description table, assuming %s transceiver, CSR12 %02x\n",
+ medianame[dev->if_port],
+ ioread32(ioaddr + CSR12));
+ }
+
+ tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
+
+ mdelay(1);
+ }
+
+ /*
+ Check the MII negotiated duplex and change the CSR6 setting if
+ required.
+ Return 0 if everything is OK.
+ Return < 0 if the transceiver is missing or has no link beat.
+ */
+ int tulip_check_duplex(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ unsigned int bmsr, lpa, negotiated, new_csr6;
+
+ bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
+ lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA);
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "MII status %04x, Link partner report %04x\n",
+ bmsr, lpa);
+ if (bmsr == 0xffff)
+ return -2;
+ if ((bmsr & BMSR_LSTATUS) == 0) {
+ int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
+ if ((new_bmsr & BMSR_LSTATUS) == 0) {
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "No link beat on the MII interface, status %04x\n",
+ new_bmsr);
+ return -1;
+ }
+ }
+ negotiated = lpa & tp->advertising[0];
+ tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated);
+
+ new_csr6 = tp->csr6;
+
+ if (negotiated & LPA_100) new_csr6 &= ~TxThreshold;
+ else new_csr6 |= TxThreshold;
+ if (tp->full_duplex) new_csr6 |= FullDuplex;
+ else new_csr6 &= ~FullDuplex;
+
+ if (new_csr6 != tp->csr6) {
+ tp->csr6 = new_csr6;
+ tulip_restart_rxtx(tp);
+
+ if (tulip_debug > 0)
+ dev_info(&dev->dev,
+ "Setting %s-duplex based on MII#%d link partner capability of %04x\n",
+ tp->full_duplex ? "full" : "half",
+ tp->phys[0], lpa);
+ return 1;
+ }
+
+ return 0;
+ }
+
+ void __devinit tulip_find_mii (struct net_device *dev, int board_idx)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int phyn, phy_idx = 0;
+ int mii_reg0;
+ int mii_advert;
+ unsigned int to_advert, new_bmcr, ane_switch;
+
+ /* Find the connected MII xcvrs.
+ Doing this in open() would allow detecting external xcvrs later,
+ but takes much time. */
+ for (phyn = 1; phyn <= 32 && phy_idx < sizeof (tp->phys); phyn++) {
+ int phy = phyn & 0x1f;
+ int mii_status = tulip_mdio_read (dev, phy, MII_BMSR);
+ if ((mii_status & 0x8301) == 0x8001 ||
+ ((mii_status & BMSR_100BASE4) == 0 &&
+ (mii_status & 0x7800) != 0)) {
+ /* preserve Becker logic, gain indentation level */
+ } else {
+ continue;
+ }
+
+ mii_reg0 = tulip_mdio_read (dev, phy, MII_BMCR);
+ mii_advert = tulip_mdio_read (dev, phy, MII_ADVERTISE);
+ ane_switch = 0;
+
+ /* if not advertising at all, gen an
+ * advertising value from the capability
+ * bits in BMSR
+ */
+ if ((mii_advert & ADVERTISE_ALL) == 0) {
+ unsigned int tmpadv = tulip_mdio_read (dev, phy, MII_BMSR);
+ mii_advert = ((tmpadv >> 6) & 0x3e0) | 1;
+ }
+
+ if (tp->mii_advertise) {
+ tp->advertising[phy_idx] =
+ to_advert = tp->mii_advertise;
+ } else if (tp->advertising[phy_idx]) {
+ to_advert = tp->advertising[phy_idx];
+ } else {
+ tp->advertising[phy_idx] =
+ tp->mii_advertise =
+ to_advert = mii_advert;
+ }
+
+ tp->phys[phy_idx++] = phy;
+
+ pr_info("tulip%d: MII transceiver #%d config %04x status %04x advertising %04x\n",
+ board_idx, phy, mii_reg0, mii_status, mii_advert);
+
+ /* Fixup for DLink with miswired PHY. */
+ if (mii_advert != to_advert) {
+ pr_debug("tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n",
+ board_idx, to_advert, phy, mii_advert);
+ tulip_mdio_write (dev, phy, 4, to_advert);
+ }
+
+ /* Enable autonegotiation: some boards default to off. */
+ if (tp->default_port == 0) {
+ new_bmcr = mii_reg0 | BMCR_ANENABLE;
+ if (new_bmcr != mii_reg0) {
+ new_bmcr |= BMCR_ANRESTART;
+ ane_switch = 1;
+ }
+ }
+ /* ...or disable nway, if forcing media */
+ else {
+ new_bmcr = mii_reg0 & ~BMCR_ANENABLE;
+ if (new_bmcr != mii_reg0)
+ ane_switch = 1;
+ }
+
+ /* clear out bits we never want at this point */
+ new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE |
+ BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK |
+ BMCR_RESET);
+
+ if (tp->full_duplex)
+ new_bmcr |= BMCR_FULLDPLX;
+ if (tulip_media_cap[tp->default_port] & MediaIs100)
+ new_bmcr |= BMCR_SPEED100;
+
+ if (new_bmcr != mii_reg0) {
+ /* some phys need the ANE switch to
+ * happen before forced media settings
+ * will "take." However, we write the
+ * same value twice in order not to
+ * confuse the sane phys.
+ */
+ if (ane_switch) {
+ tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
+ udelay (10);
+ }
+ tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
+ }
+ }
+ tp->mii_cnt = phy_idx;
+ if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
+ pr_info("tulip%d: ***WARNING***: No MII transceiver found!\n",
+ board_idx);
+ tp->phys[0] = 1;
+ }
+ }
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /*
+ drivers/net/tulip/pnic.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+ #include <linux/jiffies.h>
+ #include "tulip.h"
+
+
+ void pnic_do_nway(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ u32 phy_reg = ioread32(ioaddr + 0xB8);
+ u32 new_csr6 = tp->csr6 & ~0x40C40200;
+
+ if (phy_reg & 0x78000000) { /* Ignore baseT4 */
+ if (phy_reg & 0x20000000) dev->if_port = 5;
+ else if (phy_reg & 0x40000000) dev->if_port = 3;
+ else if (phy_reg & 0x10000000) dev->if_port = 4;
+ else if (phy_reg & 0x08000000) dev->if_port = 0;
+ tp->nwayset = 1;
+ new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000;
+ iowrite32(0x32 | (dev->if_port & 1), ioaddr + CSR12);
+ if (dev->if_port & 1)
+ iowrite32(0x1F868, ioaddr + 0xB8);
+ if (phy_reg & 0x30000000) {
+ tp->full_duplex = 1;
+ new_csr6 |= 0x00000200;
+ }
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "PNIC autonegotiated status %08x, %s\n",
+ phy_reg, medianame[dev->if_port]);
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ /* Restart Tx */
+ tulip_restart_rxtx(tp);
+ dev->trans_start = jiffies;
+ }
+ }
+ }
+
+ void pnic_lnk_change(struct net_device *dev, int csr5)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int phy_reg = ioread32(ioaddr + 0xB8);
+
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "PNIC link changed state %08x, CSR5 %08x\n",
+ phy_reg, csr5);
+ if (ioread32(ioaddr + CSR5) & TPLnkFail) {
+ iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
+ /* If we use an external MII, then we mustn't use the
+ * internal negotiation.
+ */
+ if (tulip_media_cap[dev->if_port] & MediaIsMII)
+ return;
+ if (! tp->nwayset || time_after(jiffies, dev_trans_start(dev) + 1*HZ)) {
+ tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
+ iowrite32(tp->csr6, ioaddr + CSR6);
+ iowrite32(0x30, ioaddr + CSR12);
+ iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+ dev->trans_start = jiffies;
+ }
+ } else if (ioread32(ioaddr + CSR5) & TPLnkPass) {
+ if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+ spin_lock(&tp->lock);
+ tulip_check_duplex(dev);
+ spin_unlock(&tp->lock);
+ } else {
+ pnic_do_nway(dev);
+ }
+ iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
+ }
+ }
+
+ void pnic_timer(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int next_tick = 60*HZ;
+
+ if(!ioread32(ioaddr + CSR7)) {
+ /* the timer was called due to a work overflow
+ * in the interrupt handler. Skip the connection
+ * checks, the nic is definitively speaking with
+ * his link partner.
+ */
+ goto too_good_connection;
+ }
+
+ if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+ spin_lock_irq(&tp->lock);
+ if (tulip_check_duplex(dev) > 0)
+ next_tick = 3*HZ;
+ spin_unlock_irq(&tp->lock);
+ } else {
+ int csr12 = ioread32(ioaddr + CSR12);
+ int new_csr6 = tp->csr6 & ~0x40C40200;
+ int phy_reg = ioread32(ioaddr + 0xB8);
+ int csr5 = ioread32(ioaddr + CSR5);
+
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "PNIC timer PHY status %08x, %s CSR5 %08x\n",
+ phy_reg, medianame[dev->if_port], csr5);
+ if (phy_reg & 0x04000000) { /* Remote link fault */
+ iowrite32(0x0201F078, ioaddr + 0xB8);
+ next_tick = 1*HZ;
+ tp->nwayset = 0;
+ } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */
+ pnic_do_nway(dev);
+ next_tick = 60*HZ;
+ } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "%s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n",
+ medianame[dev->if_port],
+ csr12,
+ ioread32(ioaddr + CSR5),
+ ioread32(ioaddr + 0xB8));
+ next_tick = 3*HZ;
+ if (tp->medialock) {
+ } else if (tp->nwayset && (dev->if_port & 1)) {
+ next_tick = 1*HZ;
+ } else if (dev->if_port == 0) {
+ dev->if_port = 3;
+ iowrite32(0x33, ioaddr + CSR12);
+ new_csr6 = 0x01860000;
+ iowrite32(0x1F868, ioaddr + 0xB8);
+ } else {
+ dev->if_port = 0;
+ iowrite32(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ iowrite32(0x1F078, ioaddr + 0xB8);
+ }
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ /* Restart Tx */
+ tulip_restart_rxtx(tp);
+ dev->trans_start = jiffies;
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "Changing PNIC configuration to %s %s-duplex, CSR6 %08x\n",
+ medianame[dev->if_port],
+ tp->full_duplex ? "full" : "half",
+ new_csr6);
+ }
+ }
+ }
+ too_good_connection:
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ if(!ioread32(ioaddr + CSR7)) {
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "sw timer wakeup\n");
+ disable_irq(dev->irq);
+ tulip_refill_rx(dev);
+ enable_irq(dev->irq);
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+ }
+ }
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /*
+ drivers/net/tulip/pnic2.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+ Modified to hep support PNIC_II by Kevin B. Hendricks
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+
+ /* Understanding the PNIC_II - everything is this file is based
+ * on the PNIC_II_PDF datasheet which is sorely lacking in detail
+ *
+ * As I understand things, here are the registers and bits that
+ * explain the masks and constants used in this file that are
+ * either different from the 21142/3 or important for basic operation.
+ *
+ *
+ * CSR 6 (mask = 0xfe3bd1fd of bits not to change)
+ * -----
+ * Bit 24 - SCR
+ * Bit 23 - PCS
+ * Bit 22 - TTM (Trasmit Threshold Mode)
+ * Bit 18 - Port Select
+ * Bit 13 - Start - 1, Stop - 0 Transmissions
+ * Bit 11:10 - Loop Back Operation Mode
+ * Bit 9 - Full Duplex mode (Advertise 10BaseT-FD is CSR14<7> is set)
+ * Bit 1 - Start - 1, Stop - 0 Receive
+ *
+ *
+ * CSR 14 (mask = 0xfff0ee39 of bits not to change)
+ * ------
+ * Bit 19 - PAUSE-Pause
+ * Bit 18 - Advertise T4
+ * Bit 17 - Advertise 100baseTx-FD
+ * Bit 16 - Advertise 100baseTx-HD
+ * Bit 12 - LTE - Link Test Enable
+ * Bit 7 - ANE - Auto Negotiate Enable
+ * Bit 6 - HDE - Advertise 10baseT-HD
+ * Bit 2 - Reset to Power down - kept as 1 for normal operation
+ * Bit 1 - Loop Back enable for 10baseT MCC
+ *
+ *
+ * CSR 12
+ * ------
+ * Bit 25 - Partner can do T4
+ * Bit 24 - Partner can do 100baseTx-FD
+ * Bit 23 - Partner can do 100baseTx-HD
+ * Bit 22 - Partner can do 10baseT-FD
+ * Bit 21 - Partner can do 10baseT-HD
+ * Bit 15 - LPN is 1 if all above bits are valid other wise 0
+ * Bit 14:12 - autonegotiation state (write 001 to start autonegotiate)
+ * Bit 3 - Autopolarity state
+ * Bit 2 - LS10B - link state of 10baseT 0 - good, 1 - failed
+ * Bit 1 - LS100B - link state of 100baseT 0 - good, 1 - failed
+ *
+ *
+ * Data Port Selection Info
+ *-------------------------
+ *
+ * CSR14<7> CSR6<18> CSR6<22> CSR6<23> CSR6<24> MODE/PORT
+ * 1 0 0 (X) 0 (X) 1 NWAY
+ * 0 0 1 0 (X) 0 10baseT
+ * 0 1 0 1 1 (X) 100baseT
+ *
+ *
+ */
+
+
+
+ #include "tulip.h"
+ #include <linux/delay.h>
+
+
+ void pnic2_timer(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int next_tick = 60*HZ;
+
+ if (tulip_debug > 3)
+ dev_info(&dev->dev, "PNIC2 negotiation status %08x\n",
+ ioread32(ioaddr + CSR12));
+
+ if (next_tick) {
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ }
+ }
+
+
+ void pnic2_start_nway(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int csr14;
+ int csr12;
+
+ /* set up what to advertise during the negotiation */
+
+ /* load in csr14 and mask off bits not to touch
+ * comment at top of file explains mask value
+ */
+ csr14 = (ioread32(ioaddr + CSR14) & 0xfff0ee39);
+
+ /* bit 17 - advetise 100baseTx-FD */
+ if (tp->sym_advertise & 0x0100) csr14 |= 0x00020000;
+
+ /* bit 16 - advertise 100baseTx-HD */
+ if (tp->sym_advertise & 0x0080) csr14 |= 0x00010000;
+
+ /* bit 6 - advertise 10baseT-HD */
+ if (tp->sym_advertise & 0x0020) csr14 |= 0x00000040;
+
+ /* Now set bit 12 Link Test Enable, Bit 7 Autonegotiation Enable
+ * and bit 0 Don't PowerDown 10baseT
+ */
+ csr14 |= 0x00001184;
+
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Restarting PNIC2 autonegotiation, csr14=%08x\n",
+ csr14);
+
+ /* tell pnic2_lnk_change we are doing an nway negotiation */
+ dev->if_port = 0;
+ tp->nway = tp->mediasense = 1;
+ tp->nwayset = tp->lpar = 0;
+
+ /* now we have to set up csr6 for NWAY state */
+
+ tp->csr6 = ioread32(ioaddr + CSR6);
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "On Entry to Nway, csr6=%08x\n", tp->csr6);
+
+ /* mask off any bits not to touch
+ * comment at top of file explains mask value
+ */
+ tp->csr6 = tp->csr6 & 0xfe3bd1fd;
+
+ /* don't forget that bit 9 is also used for advertising */
+ /* advertise 10baseT-FD for the negotiation (bit 9) */
+ if (tp->sym_advertise & 0x0040) tp->csr6 |= 0x00000200;
+
+ /* set bit 24 for nway negotiation mode ...
+ * see Data Port Selection comment at top of file
+ * and "Stop" - reset both Transmit (bit 13) and Receive (bit 1)
+ */
+ tp->csr6 |= 0x01000000;
+ iowrite32(csr14, ioaddr + CSR14);
+ iowrite32(tp->csr6, ioaddr + CSR6);
+ udelay(100);
+
+ /* all set up so now force the negotiation to begin */
+
+ /* read in current values and mask off all but the
+ * Autonegotiation bits 14:12. Writing a 001 to those bits
+ * should start the autonegotiation
+ */
+ csr12 = (ioread32(ioaddr + CSR12) & 0xffff8fff);
+ csr12 |= 0x1000;
+ iowrite32(csr12, ioaddr + CSR12);
+ }
+
+
+
+ void pnic2_lnk_change(struct net_device *dev, int csr5)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int csr14;
+
+ /* read the staus register to find out what is up */
+ int csr12 = ioread32(ioaddr + CSR12);
+
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "PNIC2 link status interrupt %08x, CSR5 %x, %08x\n",
+ csr12, csr5, ioread32(ioaddr + CSR14));
+
+ /* If NWay finished and we have a negotiated partner capability.
+ * check bits 14:12 for bit pattern 101 - all is good
+ */
+ if (tp->nway && !tp->nwayset) {
+
+ /* we did an auto negotiation */
+
+ if ((csr12 & 0x7000) == 0x5000) {
+
+ /* negotiation ended successfully */
+
+ /* get the link partners reply and mask out all but
+ * bits 24-21 which show the partners capabilities
+ * and match those to what we advertised
+ *
+ * then begin to interpret the results of the negotiation.
+ * Always go in this order : (we are ignoring T4 for now)
+ * 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD
+ */
+
+ int negotiated = ((csr12 >> 16) & 0x01E0) & tp->sym_advertise;
+ tp->lpar = (csr12 >> 16);
+ tp->nwayset = 1;
+
+ if (negotiated & 0x0100) dev->if_port = 5;
+ else if (negotiated & 0x0080) dev->if_port = 3;
+ else if (negotiated & 0x0040) dev->if_port = 4;
+ else if (negotiated & 0x0020) dev->if_port = 0;
+ else {
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "funny autonegotiate result csr12 %08x advertising %04x\n",
+ csr12, tp->sym_advertise);
+ tp->nwayset = 0;
+ /* so check if 100baseTx link state is okay */
+ if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180))
+ dev->if_port = 3;
+ }
+
+ /* now record the duplex that was negotiated */
+ tp->full_duplex = 0;
+ if ((dev->if_port == 4) || (dev->if_port == 5))
+ tp->full_duplex = 1;
+
+ if (tulip_debug > 1) {
+ if (tp->nwayset)
+ dev_info(&dev->dev,
+ "Switching to %s based on link negotiation %04x & %04x = %04x\n",
+ medianame[dev->if_port],
+ tp->sym_advertise, tp->lpar,
+ negotiated);
+ }
+
+ /* remember to turn off bit 7 - autonegotiate
+ * enable so we can properly end nway mode and
+ * set duplex (ie. use csr6<9> again)
+ */
+ csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f);
+ iowrite32(csr14,ioaddr + CSR14);
+
+
+ /* now set the data port and operating mode
+ * (see the Data Port Selection comments at
+ * the top of the file
+ */
+
+ /* get current csr6 and mask off bits not to touch */
+ /* see comment at top of file */
+
+ tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd);
+
+ /* so if using if_port 3 or 5 then select the 100baseT
+ * port else select the 10baseT port.
+ * See the Data Port Selection table at the top
+ * of the file which was taken from the PNIC_II.PDF
+ * datasheet
+ */
+ if (dev->if_port & 1) tp->csr6 |= 0x01840000;
+ else tp->csr6 |= 0x00400000;
+
+ /* now set the full duplex bit appropriately */
+ if (tp->full_duplex) tp->csr6 |= 0x00000200;
+
+ iowrite32(1, ioaddr + CSR13);
+
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "Setting CSR6 %08x/%x CSR12 %08x\n",
+ tp->csr6,
+ ioread32(ioaddr + CSR6),
+ ioread32(ioaddr + CSR12));
+
+ /* now the following actually writes out the
+ * new csr6 values
+ */
+ tulip_start_rxtx(tp);
+
+ return;
+
+ } else {
+ dev_info(&dev->dev,
+ "Autonegotiation failed, using %s, link beat status %04x\n",
+ medianame[dev->if_port], csr12);
+
+ /* remember to turn off bit 7 - autonegotiate
+ * enable so we don't forget
+ */
+ csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f);
+ iowrite32(csr14,ioaddr + CSR14);
+
+ /* what should we do when autonegotiate fails?
+ * should we try again or default to baseline
+ * case. I just don't know.
+ *
+ * for now default to some baseline case
+ */
+
+ dev->if_port = 0;
+ tp->nway = 0;
+ tp->nwayset = 1;
+
+ /* set to 10baseTx-HD - see Data Port Selection
+ * comment given at the top of the file
+ */
+ tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd);
+ tp->csr6 |= 0x00400000;
+
+ tulip_restart_rxtx(tp);
+
+ return;
+
+ }
+ }
+
+ if ((tp->nwayset && (csr5 & 0x08000000) &&
+ (dev->if_port == 3 || dev->if_port == 5) &&
+ (csr12 & 2) == 2) || (tp->nway && (csr5 & (TPLnkFail)))) {
+
+ /* Link blew? Maybe restart NWay. */
+
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "Ugh! Link blew?\n");
+
+ del_timer_sync(&tp->timer);
+ pnic2_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+
+ return;
+ }
+
+
+ if (dev->if_port == 3 || dev->if_port == 5) {
+
+ /* we are at 100mb and a potential link change occurred */
+
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "PNIC2 %s link beat %s\n",
+ medianame[dev->if_port],
+ (csr12 & 2) ? "failed" : "good");
+
+ /* check 100 link beat */
+
+ tp->nway = 0;
+ tp->nwayset = 1;
+
+ /* if failed then try doing an nway to get in sync */
+ if ((csr12 & 2) && ! tp->medialock) {
+ del_timer_sync(&tp->timer);
+ pnic2_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ }
+
+ return;
+ }
+
+ if (dev->if_port == 0 || dev->if_port == 4) {
+
+ /* we are at 10mb and a potential link change occurred */
+
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "PNIC2 %s link beat %s\n",
+ medianame[dev->if_port],
+ (csr12 & 4) ? "failed" : "good");
+
+
+ tp->nway = 0;
+ tp->nwayset = 1;
+
+ /* if failed, try doing an nway to get in sync */
+ if ((csr12 & 4) && ! tp->medialock) {
+ del_timer_sync(&tp->timer);
+ pnic2_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ }
+
+ return;
+ }
+
+
+ if (tulip_debug > 1)
+ dev_info(&dev->dev, "PNIC2 Link Change Default?\n");
+
+ /* if all else fails default to trying 10baseT-HD */
+ dev->if_port = 0;
+
+ /* make sure autonegotiate enable is off */
+ csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f);
+ iowrite32(csr14,ioaddr + CSR14);
+
+ /* set to 10baseTx-HD - see Data Port Selection
+ * comment given at the top of the file
+ */
+ tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd);
+ tp->csr6 |= 0x00400000;
+
+ tulip_restart_rxtx(tp);
+ }
+
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /*
+ drivers/net/tulip/timer.c
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+
+ #include "tulip.h"
+
+
+ void tulip_media_task(struct work_struct *work)
+ {
+ struct tulip_private *tp =
+ container_of(work, struct tulip_private, media_work);
+ struct net_device *dev = tp->dev;
+ void __iomem *ioaddr = tp->base_addr;
+ u32 csr12 = ioread32(ioaddr + CSR12);
+ int next_tick = 2*HZ;
+ unsigned long flags;
+
+ if (tulip_debug > 2) {
+ netdev_dbg(dev, "Media selection tick, %s, status %08x mode %08x SIA %08x %08x %08x %08x\n",
+ medianame[dev->if_port],
+ ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR6),
+ csr12, ioread32(ioaddr + CSR13),
+ ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15));
+ }
+ switch (tp->chip_id) {
+ case DC21140:
+ case DC21142:
+ case MX98713:
+ case COMPEX9881:
+ case DM910X:
+ default: {
+ struct medialeaf *mleaf;
+ unsigned char *p;
+ if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */
+ /* Not much that can be done.
+ Assume this a generic MII or SYM transceiver. */
+ next_tick = 60*HZ;
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "network media monitor CSR6 %08x CSR12 0x%02x\n",
+ ioread32(ioaddr + CSR6),
+ csr12 & 0xff);
+ break;
+ }
+ mleaf = &tp->mtable->mleaf[tp->cur_index];
+ p = mleaf->leafdata;
+ switch (mleaf->type) {
+ case 0: case 4: {
+ /* Type 0 serial or 4 SYM transceiver. Check the link beat bit. */
+ int offset = mleaf->type == 4 ? 5 : 2;
+ s8 bitnum = p[offset];
+ if (p[offset+1] & 0x80) {
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Transceiver monitor tick CSR12=%#02x, no media sense\n",
+ csr12);
+ if (mleaf->type == 4) {
+ if (mleaf->media == 3 && (csr12 & 0x02))
+ goto select_next_media;
+ }
+ break;
+ }
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "Transceiver monitor tick: CSR12=%#02x bit %d is %d, expecting %d\n",
+ csr12, (bitnum >> 1) & 7,
+ (csr12 & (1 << ((bitnum >> 1) & 7))) != 0,
+ (bitnum >= 0));
+ /* Check that the specified bit has the proper value. */
+ if ((bitnum < 0) !=
+ ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) {
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "Link beat detected for %s\n",
+ medianame[mleaf->media & MEDIA_MASK]);
+ if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */
+ goto actually_mii;
+ netif_carrier_on(dev);
+ break;
+ }
+ netif_carrier_off(dev);
+ if (tp->medialock)
+ break;
+ select_next_media:
+ if (--tp->cur_index < 0) {
+ /* We start again, but should instead look for default. */
+ tp->cur_index = tp->mtable->leafcount - 1;
+ }
+ dev->if_port = tp->mtable->mleaf[tp->cur_index].media;
+ if (tulip_media_cap[dev->if_port] & MediaIsFD)
+ goto select_next_media; /* Skip FD entries. */
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "No link beat on media %s, trying transceiver type %s\n",
+ medianame[mleaf->media & MEDIA_MASK],
+ medianame[tp->mtable->mleaf[tp->cur_index].media]);
+ tulip_select_media(dev, 0);
+ /* Restart the transmit process. */
+ tulip_restart_rxtx(tp);
+ next_tick = (24*HZ)/10;
+ break;
+ }
+ case 1: case 3: /* 21140, 21142 MII */
+ actually_mii:
+ if (tulip_check_duplex(dev) < 0) {
+ netif_carrier_off(dev);
+ next_tick = 3*HZ;
+ } else {
+ netif_carrier_on(dev);
+ next_tick = 60*HZ;
+ }
+ break;
+ case 2: /* 21142 serial block has no link beat. */
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+
+ spin_lock_irqsave(&tp->lock, flags);
+ if (tp->timeout_recovery) {
+ tulip_tx_timeout_complete(tp, ioaddr);
+ tp->timeout_recovery = 0;
+ }
+ spin_unlock_irqrestore(&tp->lock, flags);
+
+ /* mod_timer synchronizes us with potential add_timer calls
+ * from interrupts.
+ */
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ }
+
+
+ void mxic_timer(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int next_tick = 60*HZ;
+
+ if (tulip_debug > 3) {
+ dev_info(&dev->dev, "MXIC negotiation status %08x\n",
+ ioread32(ioaddr + CSR12));
+ }
+ if (next_tick) {
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ }
+ }
+
+
+ void comet_timer(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+ int next_tick = 60*HZ;
+
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Comet link status %04x partner capability %04x\n",
+ tulip_mdio_read(dev, tp->phys[0], 1),
+ tulip_mdio_read(dev, tp->phys[0], 5));
+ /* mod_timer synchronizes us with potential add_timer calls
+ * from interrupts.
+ */
+ if (tulip_check_duplex(dev) < 0)
+ { netif_carrier_off(dev); }
+ else
+ { netif_carrier_on(dev); }
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ }
+
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /*
+ drivers/net/tulip/tulip.h
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+ #ifndef __NET_TULIP_H__
+ #define __NET_TULIP_H__
+
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/spinlock.h>
+ #include <linux/netdevice.h>
+ #include <linux/ethtool.h>
+ #include <linux/timer.h>
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/unaligned.h>
+
+
+
+ /* undefine, or define to various debugging levels (>4 == obscene levels) */
+ #define TULIP_DEBUG 1
+
+ #ifdef CONFIG_TULIP_MMIO
+ #define TULIP_BAR 1 /* CBMA */
+ #else
+ #define TULIP_BAR 0 /* CBIO */
+ #endif
+
+
+
+ struct tulip_chip_table {
+ char *chip_name;
+ int io_size;
+ int valid_intrs; /* CSR7 interrupt enable settings */
+ int flags;
+ void (*media_timer) (unsigned long);
+ work_func_t media_task;
+ };
+
+
+ enum tbl_flag {
+ HAS_MII = 0x00001,
+ HAS_MEDIA_TABLE = 0x00002,
+ CSR12_IN_SROM = 0x00004,
+ ALWAYS_CHECK_MII = 0x00008,
+ HAS_ACPI = 0x00010,
+ MC_HASH_ONLY = 0x00020, /* Hash-only multicast filter. */
+ HAS_PNICNWAY = 0x00080,
+ HAS_NWAY = 0x00040, /* Uses internal NWay xcvr. */
+ HAS_INTR_MITIGATION = 0x00100,
+ IS_ASIX = 0x00200,
+ HAS_8023X = 0x00400,
+ COMET_MAC_ADDR = 0x00800,
+ HAS_PCI_MWI = 0x01000,
+ HAS_PHY_IRQ = 0x02000,
+ HAS_SWAPPED_SEEPROM = 0x04000,
+ NEEDS_FAKE_MEDIA_TABLE = 0x08000,
+ COMET_PM = 0x10000,
+ };
+
+
+ /* chip types. careful! order is VERY IMPORTANT here, as these
+ * are used throughout the driver as indices into arrays */
+ /* Note 21142 == 21143. */
+ enum chips {
+ DC21040 = 0,
+ DC21041 = 1,
+ DC21140 = 2,
+ DC21142 = 3, DC21143 = 3,
+ LC82C168,
+ MX98713,
+ MX98715,
+ MX98725,
+ AX88140,
+ PNIC2,
+ COMET,
+ COMPEX9881,
+ I21145,
+ DM910X,
+ CONEXANT,
+ };
+
+
+ enum MediaIs {
+ MediaIsFD = 1,
+ MediaAlwaysFD = 2,
+ MediaIsMII = 4,
+ MediaIsFx = 8,
+ MediaIs100 = 16
+ };
+
+
+ /* Offsets to the Command and Status Registers, "CSRs". All accesses
+ must be longword instructions and quadword aligned. */
+ enum tulip_offsets {
+ CSR0 = 0,
+ CSR1 = 0x08,
+ CSR2 = 0x10,
+ CSR3 = 0x18,
+ CSR4 = 0x20,
+ CSR5 = 0x28,
+ CSR6 = 0x30,
+ CSR7 = 0x38,
+ CSR8 = 0x40,
+ CSR9 = 0x48,
+ CSR10 = 0x50,
+ CSR11 = 0x58,
+ CSR12 = 0x60,
+ CSR13 = 0x68,
+ CSR14 = 0x70,
+ CSR15 = 0x78,
+ CSR18 = 0x88,
+ CSR19 = 0x8c,
+ CSR20 = 0x90,
+ CSR27 = 0xAC,
+ CSR28 = 0xB0,
+ };
+
+ /* register offset and bits for CFDD PCI config reg */
+ enum pci_cfg_driver_reg {
+ CFDD = 0x40,
+ CFDD_Sleep = (1 << 31),
+ CFDD_Snooze = (1 << 30),
+ };
+
+ #define RxPollInt (RxIntr|RxNoBuf|RxDied|RxJabber)
+
+ /* The bits in the CSR5 status registers, mostly interrupt sources. */
+ enum status_bits {
+ TimerInt = 0x800,
+ SystemError = 0x2000,
+ TPLnkFail = 0x1000,
+ TPLnkPass = 0x10,
+ NormalIntr = 0x10000,
+ AbnormalIntr = 0x8000,
+ RxJabber = 0x200,
+ RxDied = 0x100,
+ RxNoBuf = 0x80,
+ RxIntr = 0x40,
+ TxFIFOUnderflow = 0x20,
+ RxErrIntr = 0x10,
+ TxJabber = 0x08,
+ TxNoBuf = 0x04,
+ TxDied = 0x02,
+ TxIntr = 0x01,
+ };
+
+ /* bit mask for CSR5 TX/RX process state */
+ #define CSR5_TS 0x00700000
+ #define CSR5_RS 0x000e0000
+
+ enum tulip_mode_bits {
+ TxThreshold = (1 << 22),
+ FullDuplex = (1 << 9),
+ TxOn = 0x2000,
+ AcceptBroadcast = 0x0100,
+ AcceptAllMulticast = 0x0080,
+ AcceptAllPhys = 0x0040,
+ AcceptRunt = 0x0008,
+ RxOn = 0x0002,
+ RxTx = (TxOn | RxOn),
+ };
+
+
+ enum tulip_busconfig_bits {
+ MWI = (1 << 24),
+ MRL = (1 << 23),
+ MRM = (1 << 21),
+ CALShift = 14,
+ BurstLenShift = 8,
+ };
+
+
+ /* The Tulip Rx and Tx buffer descriptors. */
+ struct tulip_rx_desc {
+ __le32 status;
+ __le32 length;
+ __le32 buffer1;
+ __le32 buffer2;
+ };
+
+
+ struct tulip_tx_desc {
+ __le32 status;
+ __le32 length;
+ __le32 buffer1;
+ __le32 buffer2; /* We use only buffer 1. */
+ };
+
+
+ enum desc_status_bits {
+ DescOwned = 0x80000000,
+ DescWholePkt = 0x60000000,
+ DescEndPkt = 0x40000000,
+ DescStartPkt = 0x20000000,
+ DescEndRing = 0x02000000,
+ DescUseLink = 0x01000000,
+
+ /*
+ * Error summary flag is logical or of 'CRC Error', 'Collision Seen',
+ * 'Frame Too Long', 'Runt' and 'Descriptor Error' flags generated
+ * within tulip chip.
+ */
+ RxDescErrorSummary = 0x8000,
+ RxDescCRCError = 0x0002,
+ RxDescCollisionSeen = 0x0040,
+
+ /*
+ * 'Frame Too Long' flag is set if packet length including CRC exceeds
+ * 1518. However, a full sized VLAN tagged frame is 1522 bytes
+ * including CRC.
+ *
+ * The tulip chip does not block oversized frames, and if this flag is
+ * set on a receive descriptor it does not indicate the frame has been
+ * truncated. The receive descriptor also includes the actual length.
+ * Therefore we can safety ignore this flag and check the length
+ * ourselves.
+ */
+ RxDescFrameTooLong = 0x0080,
+ RxDescRunt = 0x0800,
+ RxDescDescErr = 0x4000,
+ RxWholePkt = 0x00000300,
+ /*
+ * Top three bits of 14 bit frame length (status bits 27-29) should
+ * never be set as that would make frame over 2047 bytes. The Receive
+ * Watchdog flag (bit 4) may indicate the length is over 2048 and the
+ * length field is invalid.
+ */
+ RxLengthOver2047 = 0x38000010
+ };
+
+
+ enum t21143_csr6_bits {
+ csr6_sc = (1<<31),
+ csr6_ra = (1<<30),
+ csr6_ign_dest_msb = (1<<26),
+ csr6_mbo = (1<<25),
+ csr6_scr = (1<<24), /* scramble mode flag: can't be set */
+ csr6_pcs = (1<<23), /* Enables PCS functions (symbol mode requires csr6_ps be set) default is set */
+ csr6_ttm = (1<<22), /* Transmit Threshold Mode, set for 10baseT, 0 for 100BaseTX */
+ csr6_sf = (1<<21), /* Store and forward. If set ignores TR bits */
+ csr6_hbd = (1<<19), /* Heart beat disable. Disables SQE function in 10baseT */
+ csr6_ps = (1<<18), /* Port Select. 0 (defualt) = 10baseT, 1 = 100baseTX: can't be set */
+ csr6_ca = (1<<17), /* Collision Offset Enable. If set uses special algorithm in low collision situations */
+ csr6_trh = (1<<15), /* Transmit Threshold high bit */
+ csr6_trl = (1<<14), /* Transmit Threshold low bit */
+
+ /***************************************************************
+ * This table shows transmit threshold values based on media *
+ * and these two registers (from PNIC1 & 2 docs) Note: this is *
+ * all meaningless if sf is set. *
+ ***************************************************************/
+
+ /***********************************
+ * (trh,trl) * 100BaseTX * 10BaseT *
+ ***********************************
+ * (0,0) * 128 * 72 *
+ * (0,1) * 256 * 96 *
+ * (1,0) * 512 * 128 *
+ * (1,1) * 1024 * 160 *
+ ***********************************/
+
+ csr6_fc = (1<<12), /* Forces a collision in next transmission (for testing in loopback mode) */
+ csr6_om_int_loop = (1<<10), /* internal (FIFO) loopback flag */
+ csr6_om_ext_loop = (1<<11), /* external (PMD) loopback flag */
+ /* set both and you get (PHY) loopback */
+ csr6_fd = (1<<9), /* Full duplex mode, disables hearbeat, no loopback */
+ csr6_pm = (1<<7), /* Pass All Multicast */
+ csr6_pr = (1<<6), /* Promiscuous mode */
+ csr6_sb = (1<<5), /* Start(1)/Stop(0) backoff counter */
+ csr6_if = (1<<4), /* Inverse Filtering, rejects only addresses in address table: can't be set */
+ csr6_pb = (1<<3), /* Pass Bad Frames, (1) causes even bad frames to be passed on */
+ csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */
+ csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */
+
+ csr6_mask_capture = (csr6_sc | csr6_ca),
+ csr6_mask_defstate = (csr6_mask_capture | csr6_mbo),
+ csr6_mask_hdcap = (csr6_mask_defstate | csr6_hbd | csr6_ps),
+ csr6_mask_hdcaptt = (csr6_mask_hdcap | csr6_trh | csr6_trl),
+ csr6_mask_fullcap = (csr6_mask_hdcaptt | csr6_fd),
+ csr6_mask_fullpromisc = (csr6_pr | csr6_pm),
+ csr6_mask_filters = (csr6_hp | csr6_ho | csr6_if),
+ csr6_mask_100bt = (csr6_scr | csr6_pcs | csr6_hbd),
+ };
+
+ enum tulip_comet_csr13_bits {
+ /* The LINKOFFE and LINKONE work in conjunction with LSCE, i.e. they
+ * determine which link status transition wakes up if LSCE is
+ * enabled */
+ comet_csr13_linkoffe = (1 << 17),
+ comet_csr13_linkone = (1 << 16),
+ comet_csr13_wfre = (1 << 10),
+ comet_csr13_mpre = (1 << 9),
+ comet_csr13_lsce = (1 << 8),
+ comet_csr13_wfr = (1 << 2),
+ comet_csr13_mpr = (1 << 1),
+ comet_csr13_lsc = (1 << 0),
+ };
+
+ enum tulip_comet_csr18_bits {
+ comet_csr18_pmes_sticky = (1 << 24),
+ comet_csr18_pm_mode = (1 << 19),
+ comet_csr18_apm_mode = (1 << 18),
+ comet_csr18_d3a = (1 << 7)
+ };
+
+ enum tulip_comet_csr20_bits {
+ comet_csr20_pmes = (1 << 15),
+ };
+
+ /* Keep the ring sizes a power of two for efficiency.
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+
+ #define TX_RING_SIZE 32
+ #define RX_RING_SIZE 128
+ #define MEDIA_MASK 31
+
+ /* The receiver on the DC21143 rev 65 can fail to close the last
+ * receive descriptor in certain circumstances (see errata) when
+ * using MWI. This can only occur if the receive buffer ends on
+ * a cache line boundary, so the "+ 4" below ensures it doesn't.
+ */
+ #define PKT_BUF_SZ (1536 + 4) /* Size of each temporary Rx buffer. */
+
+ #define TULIP_MIN_CACHE_LINE 8 /* in units of 32-bit words */
+
+ #if defined(__sparc__) || defined(__hppa__)
+ /* The UltraSparc PCI controllers will disconnect at every 64-byte
+ * crossing anyways so it makes no sense to tell Tulip to burst
+ * any more than that.
+ */
+ #define TULIP_MAX_CACHE_LINE 16 /* in units of 32-bit words */
+ #else
+ #define TULIP_MAX_CACHE_LINE 32 /* in units of 32-bit words */
+ #endif
+
+
+ /* Ring-wrap flag in length field, use for last ring entry.
+ 0x01000000 means chain on buffer2 address,
+ 0x02000000 means use the ring start address in CSR2/3.
+ Note: Some work-alike chips do not function correctly in chained mode.
+ The ASIX chip works only in chained mode.
+ Thus we indicates ring mode, but always write the 'next' field for
+ chained mode as well.
+ */
+ #define DESC_RING_WRAP 0x02000000
+
+
+ #define EEPROM_SIZE 512 /* 2 << EEPROM_ADDRLEN */
+
+
+ #define RUN_AT(x) (jiffies + (x))
+
+ #define get_u16(ptr) get_unaligned_le16((ptr))
+
+ struct medialeaf {
+ u8 type;
+ u8 media;
+ unsigned char *leafdata;
+ };
+
+
+ struct mediatable {
+ u16 defaultmedia;
+ u8 leafcount;
+ u8 csr12dir; /* General purpose pin directions. */
+ unsigned has_mii:1;
+ unsigned has_nonmii:1;
+ unsigned has_reset:6;
+ u32 csr15dir;
+ u32 csr15val; /* 21143 NWay setting. */
+ struct medialeaf mleaf[0];
+ };
+
+
+ struct mediainfo {
+ struct mediainfo *next;
+ int info_type;
+ int index;
+ unsigned char *info;
+ };
+
+ struct ring_info {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+ };
+
+
+ struct tulip_private {
+ const char *product_name;
+ struct net_device *next_module;
+ struct tulip_rx_desc *rx_ring;
+ struct tulip_tx_desc *tx_ring;
+ dma_addr_t rx_ring_dma;
+ dma_addr_t tx_ring_dma;
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct ring_info tx_buffers[TX_RING_SIZE];
+ /* The addresses of receive-in-place skbuffs. */
+ struct ring_info rx_buffers[RX_RING_SIZE];
+ u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */
+ int chip_id;
+ int revision;
+ int flags;
+ struct napi_struct napi;
+ struct timer_list timer; /* Media selection timer. */
+ struct timer_list oom_timer; /* Out of memory timer. */
+ u32 mc_filter[2];
+ spinlock_t lock;
+ spinlock_t mii_lock;
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+
+ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+ int mit_on;
+ #endif
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int full_duplex_lock:1;
+ unsigned int fake_addr:1; /* Multiport board faked address. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
+ unsigned int media2:4; /* Secondary monitored media port. */
+ unsigned int medialock:1; /* Don't sense media type. */
+ unsigned int mediasense:1; /* Media sensing in progress. */
+ unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */
+ unsigned int timeout_recovery:1;
+ unsigned int csr0; /* CSR0 setting. */
+ unsigned int csr6; /* Current CSR6 control settings. */
+ unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */
+ void (*link_change) (struct net_device * dev, int csr5);
+ struct ethtool_wolinfo wolinfo; /* WOL settings */
+ u16 sym_advertise, mii_advertise; /* NWay capabilities advertised. */
+ u16 lpar; /* 21143 Link partner ability. */
+ u16 advertising[4];
+ signed char phys[4], mii_cnt; /* MII device addresses. */
+ struct mediatable *mtable;
+ int cur_index; /* Current media index. */
+ int saved_if_port;
+ struct pci_dev *pdev;
+ int ttimer;
+ int susp_rx;
+ unsigned long nir;
+ void __iomem *base_addr;
+ int csr12_shadow;
+ int pad0; /* Used for 8-byte alignment */
+ struct work_struct media_work;
+ struct net_device *dev;
+ };
+
+
+ struct eeprom_fixup {
+ char *name;
+ unsigned char addr0;
+ unsigned char addr1;
+ unsigned char addr2;
+ u16 newtable[32]; /* Max length below. */
+ };
+
+
+ /* 21142.c */
+ extern u16 t21142_csr14[];
+ void t21142_media_task(struct work_struct *work);
+ void t21142_start_nway(struct net_device *dev);
+ void t21142_lnk_change(struct net_device *dev, int csr5);
+
+
+ /* PNIC2.c */
+ void pnic2_lnk_change(struct net_device *dev, int csr5);
+ void pnic2_timer(unsigned long data);
+ void pnic2_start_nway(struct net_device *dev);
+ void pnic2_lnk_change(struct net_device *dev, int csr5);
+
+ /* eeprom.c */
+ void tulip_parse_eeprom(struct net_device *dev);
+ int tulip_read_eeprom(struct net_device *dev, int location, int addr_len);
+
+ /* interrupt.c */
+ extern unsigned int tulip_max_interrupt_work;
+ extern int tulip_rx_copybreak;
+ irqreturn_t tulip_interrupt(int irq, void *dev_instance);
+ int tulip_refill_rx(struct net_device *dev);
+ #ifdef CONFIG_TULIP_NAPI
+ int tulip_poll(struct napi_struct *napi, int budget);
+ #endif
+
+
+ /* media.c */
+ int tulip_mdio_read(struct net_device *dev, int phy_id, int location);
+ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int value);
+ void tulip_select_media(struct net_device *dev, int startup);
+ int tulip_check_duplex(struct net_device *dev);
+ void tulip_find_mii (struct net_device *dev, int board_idx);
+
+ /* pnic.c */
+ void pnic_do_nway(struct net_device *dev);
+ void pnic_lnk_change(struct net_device *dev, int csr5);
+ void pnic_timer(unsigned long data);
+
+ /* timer.c */
+ void tulip_media_task(struct work_struct *work);
+ void mxic_timer(unsigned long data);
+ void comet_timer(unsigned long data);
+
+ /* tulip_core.c */
+ extern int tulip_debug;
+ extern const char * const medianame[];
+ extern const char tulip_media_cap[];
+ extern struct tulip_chip_table tulip_tbl[];
+ void oom_timer(unsigned long data);
+ extern u8 t21040_csr13[];
+
+ static inline void tulip_start_rxtx(struct tulip_private *tp)
+ {
+ void __iomem *ioaddr = tp->base_addr;
+ iowrite32(tp->csr6 | RxTx, ioaddr + CSR6);
+ barrier();
+ (void) ioread32(ioaddr + CSR6); /* mmio sync */
+ }
+
+ static inline void tulip_stop_rxtx(struct tulip_private *tp)
+ {
+ void __iomem *ioaddr = tp->base_addr;
+ u32 csr6 = ioread32(ioaddr + CSR6);
+
+ if (csr6 & RxTx) {
+ unsigned i=1300/10;
+ iowrite32(csr6 & ~RxTx, ioaddr + CSR6);
+ barrier();
+ /* wait until in-flight frame completes.
+ * Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin)
+ * Typically expect this loop to end in < 50 us on 100BT.
+ */
+ while (--i && (ioread32(ioaddr + CSR5) & (CSR5_TS|CSR5_RS)))
+ udelay(10);
+
+ if (!i)
+ netdev_dbg(tp->dev, "tulip_stop_rxtx() failed (CSR5 0x%x CSR6 0x%x)\n",
+ ioread32(ioaddr + CSR5),
+ ioread32(ioaddr + CSR6));
+ }
+ }
+
+ static inline void tulip_restart_rxtx(struct tulip_private *tp)
+ {
+ tulip_stop_rxtx(tp);
+ udelay(5);
+ tulip_start_rxtx(tp);
+ }
+
+ static inline void tulip_tx_timeout_complete(struct tulip_private *tp, void __iomem *ioaddr)
+ {
+ /* Stop and restart the chip's Tx processes. */
+ tulip_restart_rxtx(tp);
+ /* Trigger an immediate transmit demand. */
+ iowrite32(0, ioaddr + CSR1);
+
+ tp->dev->stats.tx_errors++;
+ }
+
+ #endif /* __NET_TULIP_H__ */
--- /dev/null
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
+ /* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux.
+
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please submit bugs to http://bugzilla.kernel.org/ .
+ */
+
+ #define pr_fmt(fmt) "tulip: " fmt
+
+ #define DRV_NAME "tulip"
+ #ifdef CONFIG_TULIP_NAPI
+ #define DRV_VERSION "1.1.15-NAPI" /* Keep at least for test */
+ #else
+ #define DRV_VERSION "1.1.15"
+ #endif
+ #define DRV_RELDATE "Feb 27, 2007"
+
+
+ #include <linux/module.h>
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include "tulip.h"
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/etherdevice.h>
+ #include <linux/delay.h>
+ #include <linux/mii.h>
+ #include <linux/crc32.h>
+ #include <asm/unaligned.h>
+ #include <asm/uaccess.h>
+
+ #ifdef CONFIG_SPARC
+ #include <asm/prom.h>
+ #endif
+
+ static char version[] __devinitdata =
+ "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n";
+
+ /* A few user-configurable values. */
+
+ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+ static unsigned int max_interrupt_work = 25;
+
+ #define MAX_UNITS 8
+ /* Used to pass the full-duplex flag, etc. */
+ static int full_duplex[MAX_UNITS];
+ static int options[MAX_UNITS];
+ static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */
+
+ /* The possible media types that can be set in options[] are: */
+ const char * const medianame[32] = {
+ "10baseT", "10base2", "AUI", "100baseTx",
+ "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
+ "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
+ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
+ "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
+ "","","","", "","","","", "","","","Transceiver reset",
+ };
+
+ /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
+ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) || \
+ defined(CONFIG_SPARC) || defined(__ia64__) || \
+ defined(__sh__) || defined(__mips__)
+ static int rx_copybreak = 1518;
+ #else
+ static int rx_copybreak = 100;
+ #endif
+
+ /*
+ Set the bus performance register.
+ Typical: Set 16 longword cache alignment, no burst limit.
+ Cache alignment bits 15:14 Burst length 13:8
+ 0000 No alignment 0x00000000 unlimited 0800 8 longwords
+ 4000 8 longwords 0100 1 longword 1000 16 longwords
+ 8000 16 longwords 0200 2 longwords 2000 32 longwords
+ C000 32 longwords 0400 4 longwords
+ Warning: many older 486 systems are broken and require setting 0x00A04800
+ 8 longword cache alignment, 8 longword burst.
+ ToDo: Non-Intel setting could be better.
+ */
+
+ #if defined(__alpha__) || defined(__ia64__)
+ static int csr0 = 0x01A00000 | 0xE000;
+ #elif defined(__i386__) || defined(__powerpc__) || defined(__x86_64__)
+ static int csr0 = 0x01A00000 | 0x8000;
+ #elif defined(CONFIG_SPARC) || defined(__hppa__)
+ /* The UltraSparc PCI controllers will disconnect at every 64-byte
+ * crossing anyways so it makes no sense to tell Tulip to burst
+ * any more than that.
+ */
+ static int csr0 = 0x01A00000 | 0x9000;
+ #elif defined(__arm__) || defined(__sh__)
+ static int csr0 = 0x01A00000 | 0x4800;
+ #elif defined(__mips__)
+ static int csr0 = 0x00200000 | 0x4000;
+ #else
+ #warning Processor architecture undefined!
+ static int csr0 = 0x00A00000 | 0x4800;
+ #endif
+
+ /* Operational parameters that usually are not changed. */
+ /* Time in jiffies before concluding the transmitter is hung. */
+ #define TX_TIMEOUT (4*HZ)
+
+
+ MODULE_AUTHOR("The Linux Kernel Team");
+ MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
+ module_param(tulip_debug, int, 0);
+ module_param(max_interrupt_work, int, 0);
+ module_param(rx_copybreak, int, 0);
+ module_param(csr0, int, 0);
+ module_param_array(options, int, NULL, 0);
+ module_param_array(full_duplex, int, NULL, 0);
+
+ #ifdef TULIP_DEBUG
+ int tulip_debug = TULIP_DEBUG;
+ #else
+ int tulip_debug = 1;
+ #endif
+
+ static void tulip_timer(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+
+ if (netif_running(dev))
+ schedule_work(&tp->media_work);
+ }
+
+ /*
+ * This table use during operation for capabilities and media timer.
+ *
+ * It is indexed via the values in 'enum chips'
+ */
+
+ struct tulip_chip_table tulip_tbl[] = {
+ { }, /* placeholder for array, slot unused currently */
+ { }, /* placeholder for array, slot unused currently */
+
+ /* DC21140 */
+ { "Digital DS21140 Tulip", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer,
+ tulip_media_task },
+
+ /* DC21142, DC21143 */
+ { "Digital DS21142/43 Tulip", 128, 0x0801fbff,
+ HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY
+ | HAS_INTR_MITIGATION | HAS_PCI_MWI, tulip_timer, t21142_media_task },
+
+ /* LC82C168 */
+ { "Lite-On 82c168 PNIC", 256, 0x0001fbef,
+ HAS_MII | HAS_PNICNWAY, pnic_timer, },
+
+ /* MX98713 */
+ { "Macronix 98713 PMAC", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, },
+
+ /* MX98715 */
+ { "Macronix 98715 PMAC", 256, 0x0001ebef,
+ HAS_MEDIA_TABLE, mxic_timer, },
+
+ /* MX98725 */
+ { "Macronix 98725 PMAC", 256, 0x0001ebef,
+ HAS_MEDIA_TABLE, mxic_timer, },
+
+ /* AX88140 */
+ { "ASIX AX88140", 128, 0x0001fbff,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
+ | IS_ASIX, tulip_timer, tulip_media_task },
+
+ /* PNIC2 */
+ { "Lite-On PNIC-II", 256, 0x0801fbff,
+ HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer, },
+
+ /* COMET */
+ { "ADMtek Comet", 256, 0x0001abef,
+ HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer, },
+
+ /* COMPEX9881 */
+ { "Compex 9881 PMAC", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, },
+
+ /* I21145 */
+ { "Intel DS21145 Tulip", 128, 0x0801fbff,
+ HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI
+ | HAS_NWAY | HAS_PCI_MWI, tulip_timer, tulip_media_task },
+
+ /* DM910X */
+ #ifdef CONFIG_TULIP_DM910X
+ { "Davicom DM9102/DM9102A", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
+ tulip_timer, tulip_media_task },
+ #else
+ { NULL },
+ #endif
+
+ /* RS7112 */
+ { "Conexant LANfinity", 256, 0x0001ebef,
+ HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task },
+
+ };
+
+
+ static DEFINE_PCI_DEVICE_TABLE(tulip_pci_tbl) = {
+ { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
+ { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 },
+ { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 },
+ { 0x10d9, 0x0512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98713 },
+ { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
+ /* { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98725 },*/
+ { 0x125B, 0x1400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AX88140 },
+ { 0x11AD, 0xc115, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PNIC2 },
+ { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1317, 0x1985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1317, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x13D1, 0xAB02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x13D1, 0xAB03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x13D1, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x104A, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x104A, 0x2774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
+ { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
+ #ifdef CONFIG_TULIP_DM910X
+ { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
+ { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
+ #endif
+ { 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
+ { 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1186, 0x1541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1186, 0x1591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
+ { 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
+ { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
+ { 0x1414, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Microsoft MN-120 */
+ { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { } /* terminate list */
+ };
+ MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
+
+
+ /* A full-duplex map for media types. */
+ const char tulip_media_cap[32] =
+ {0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 28,31,0,0, };
+
+ static void tulip_tx_timeout(struct net_device *dev);
+ static void tulip_init_ring(struct net_device *dev);
+ static void tulip_free_ring(struct net_device *dev);
+ static netdev_tx_t tulip_start_xmit(struct sk_buff *skb,
+ struct net_device *dev);
+ static int tulip_open(struct net_device *dev);
+ static int tulip_close(struct net_device *dev);
+ static void tulip_up(struct net_device *dev);
+ static void tulip_down(struct net_device *dev);
+ static struct net_device_stats *tulip_get_stats(struct net_device *dev);
+ static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+ static void set_rx_mode(struct net_device *dev);
+ static void tulip_set_wolopts(struct pci_dev *pdev, u32 wolopts);
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void poll_tulip(struct net_device *dev);
+ #endif
+
+ static void tulip_set_power_state (struct tulip_private *tp,
+ int sleep, int snooze)
+ {
+ if (tp->flags & HAS_ACPI) {
+ u32 tmp, newtmp;
+ pci_read_config_dword (tp->pdev, CFDD, &tmp);
+ newtmp = tmp & ~(CFDD_Sleep | CFDD_Snooze);
+ if (sleep)
+ newtmp |= CFDD_Sleep;
+ else if (snooze)
+ newtmp |= CFDD_Snooze;
+ if (tmp != newtmp)
+ pci_write_config_dword (tp->pdev, CFDD, newtmp);
+ }
+
+ }
+
+
+ static void tulip_up(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int next_tick = 3*HZ;
+ u32 reg;
+ int i;
+
+ #ifdef CONFIG_TULIP_NAPI
+ napi_enable(&tp->napi);
+ #endif
+
+ /* Wake the chip from sleep/snooze mode. */
+ tulip_set_power_state (tp, 0, 0);
+
+ /* Disable all WOL events */
+ pci_enable_wake(tp->pdev, PCI_D3hot, 0);
+ pci_enable_wake(tp->pdev, PCI_D3cold, 0);
+ tulip_set_wolopts(tp->pdev, 0);
+
+ /* On some chip revs we must set the MII/SYM port before the reset!? */
+ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii))
+ iowrite32(0x00040000, ioaddr + CSR6);
+
+ /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+ iowrite32(0x00000001, ioaddr + CSR0);
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, ®); /* flush write */
+ udelay(100);
+
+ /* Deassert reset.
+ Wait the specified 50 PCI cycles after a reset by initializing
+ Tx and Rx queues and the address filter list. */
+ iowrite32(tp->csr0, ioaddr + CSR0);
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, ®); /* flush write */
+ udelay(100);
+
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "tulip_up(), irq==%d\n", dev->irq);
+
+ iowrite32(tp->rx_ring_dma, ioaddr + CSR3);
+ iowrite32(tp->tx_ring_dma, ioaddr + CSR4);
+ tp->cur_rx = tp->cur_tx = 0;
+ tp->dirty_rx = tp->dirty_tx = 0;
+
+ if (tp->flags & MC_HASH_ONLY) {
+ u32 addr_low = get_unaligned_le32(dev->dev_addr);
+ u32 addr_high = get_unaligned_le16(dev->dev_addr + 4);
+ if (tp->chip_id == AX88140) {
+ iowrite32(0, ioaddr + CSR13);
+ iowrite32(addr_low, ioaddr + CSR14);
+ iowrite32(1, ioaddr + CSR13);
+ iowrite32(addr_high, ioaddr + CSR14);
+ } else if (tp->flags & COMET_MAC_ADDR) {
+ iowrite32(addr_low, ioaddr + 0xA4);
+ iowrite32(addr_high, ioaddr + 0xA8);
+ iowrite32(0, ioaddr + CSR27);
+ iowrite32(0, ioaddr + CSR28);
+ }
+ } else {
+ /* This is set_rx_mode(), but without starting the transmitter. */
+ u16 *eaddrs = (u16 *)dev->dev_addr;
+ u16 *setup_frm = &tp->setup_frame[15*6];
+ dma_addr_t mapping;
+
+ /* 21140 bug: you must add the broadcast address. */
+ memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame));
+ /* Fill the final entry of the table with our physical address. */
+ *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+ *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+ *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+
+ mapping = pci_map_single(tp->pdev, tp->setup_frame,
+ sizeof(tp->setup_frame),
+ PCI_DMA_TODEVICE);
+ tp->tx_buffers[tp->cur_tx].skb = NULL;
+ tp->tx_buffers[tp->cur_tx].mapping = mapping;
+
+ /* Put the setup frame on the Tx list. */
+ tp->tx_ring[tp->cur_tx].length = cpu_to_le32(0x08000000 | 192);
+ tp->tx_ring[tp->cur_tx].buffer1 = cpu_to_le32(mapping);
+ tp->tx_ring[tp->cur_tx].status = cpu_to_le32(DescOwned);
+
+ tp->cur_tx++;
+ }
+
+ tp->saved_if_port = dev->if_port;
+ if (dev->if_port == 0)
+ dev->if_port = tp->default_port;
+
+ /* Allow selecting a default media. */
+ i = 0;
+ if (tp->mtable == NULL)
+ goto media_picked;
+ if (dev->if_port) {
+ int looking_for = tulip_media_cap[dev->if_port] & MediaIsMII ? 11 :
+ (dev->if_port == 12 ? 0 : dev->if_port);
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ dev_info(&dev->dev,
+ "Using user-specified media %s\n",
+ medianame[dev->if_port]);
+ goto media_picked;
+ }
+ }
+ if ((tp->mtable->defaultmedia & 0x0800) == 0) {
+ int looking_for = tp->mtable->defaultmedia & MEDIA_MASK;
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ dev_info(&dev->dev,
+ "Using EEPROM-set media %s\n",
+ medianame[looking_for]);
+ goto media_picked;
+ }
+ }
+ /* Start sensing first non-full-duplex media. */
+ for (i = tp->mtable->leafcount - 1;
+ (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
+ ;
+ media_picked:
+
+ tp->csr6 = 0;
+ tp->cur_index = i;
+ tp->nwayset = 0;
+
+ if (dev->if_port) {
+ if (tp->chip_id == DC21143 &&
+ (tulip_media_cap[dev->if_port] & MediaIsMII)) {
+ /* We must reset the media CSRs when we force-select MII mode. */
+ iowrite32(0x0000, ioaddr + CSR13);
+ iowrite32(0x0000, ioaddr + CSR14);
+ iowrite32(0x0008, ioaddr + CSR15);
+ }
+ tulip_select_media(dev, 1);
+ } else if (tp->chip_id == DC21142) {
+ if (tp->mii_cnt) {
+ tulip_select_media(dev, 1);
+ if (tulip_debug > 1)
+ dev_info(&dev->dev,
+ "Using MII transceiver %d, status %04x\n",
+ tp->phys[0],
+ tulip_mdio_read(dev, tp->phys[0], 1));
+ iowrite32(csr6_mask_defstate, ioaddr + CSR6);
+ tp->csr6 = csr6_mask_hdcap;
+ dev->if_port = 11;
+ iowrite32(0x0000, ioaddr + CSR13);
+ iowrite32(0x0000, ioaddr + CSR14);
+ } else
+ t21142_start_nway(dev);
+ } else if (tp->chip_id == PNIC2) {
+ /* for initial startup advertise 10/100 Full and Half */
+ tp->sym_advertise = 0x01E0;
+ /* enable autonegotiate end interrupt */
+ iowrite32(ioread32(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5);
+ iowrite32(ioread32(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7);
+ pnic2_start_nway(dev);
+ } else if (tp->chip_id == LC82C168 && ! tp->medialock) {
+ if (tp->mii_cnt) {
+ dev->if_port = 11;
+ tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
+ iowrite32(0x0001, ioaddr + CSR15);
+ } else if (ioread32(ioaddr + CSR5) & TPLnkPass)
+ pnic_do_nway(dev);
+ else {
+ /* Start with 10mbps to do autonegotiation. */
+ iowrite32(0x32, ioaddr + CSR12);
+ tp->csr6 = 0x00420000;
+ iowrite32(0x0001B078, ioaddr + 0xB8);
+ iowrite32(0x0201B078, ioaddr + 0xB8);
+ next_tick = 1*HZ;
+ }
+ } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) &&
+ ! tp->medialock) {
+ dev->if_port = 0;
+ tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
+ iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80);
+ } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) {
+ /* Provided by BOLO, Macronix - 12/10/1998. */
+ dev->if_port = 0;
+ tp->csr6 = 0x01a80200;
+ iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80);
+ iowrite32(0x11000 | ioread16(ioaddr + 0xa0), ioaddr + 0xa0);
+ } else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) {
+ /* Enable automatic Tx underrun recovery. */
+ iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88);
+ dev->if_port = tp->mii_cnt ? 11 : 0;
+ tp->csr6 = 0x00040000;
+ } else if (tp->chip_id == AX88140) {
+ tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
+ } else
+ tulip_select_media(dev, 1);
+
+ /* Start the chip's Tx to process setup frame. */
+ tulip_stop_rxtx(tp);
+ barrier();
+ udelay(5);
+ iowrite32(tp->csr6 | TxOn, ioaddr + CSR6);
+
+ /* Enable interrupts by setting the interrupt mask. */
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
+ iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+ tulip_start_rxtx(tp);
+ iowrite32(0, ioaddr + CSR2); /* Rx poll demand */
+
+ if (tulip_debug > 2) {
+ netdev_dbg(dev, "Done tulip_up(), CSR0 %08x, CSR5 %08x CSR6 %08x\n",
+ ioread32(ioaddr + CSR0),
+ ioread32(ioaddr + CSR5),
+ ioread32(ioaddr + CSR6));
+ }
+
+ /* Set the timer to switch to check for link beat and perhaps switch
+ to an alternate media type. */
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+ #ifdef CONFIG_TULIP_NAPI
+ init_timer(&tp->oom_timer);
+ tp->oom_timer.data = (unsigned long)dev;
+ tp->oom_timer.function = oom_timer;
+ #endif
+ }
+
+ static int
+ tulip_open(struct net_device *dev)
+ {
+ int retval;
+
+ tulip_init_ring (dev);
+
+ retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev);
+ if (retval)
+ goto free_ring;
+
+ tulip_up (dev);
+
+ netif_start_queue (dev);
+
+ return 0;
+
+ free_ring:
+ tulip_free_ring (dev);
+ return retval;
+ }
+
+
+ static void tulip_tx_timeout(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ unsigned long flags;
+
+ spin_lock_irqsave (&tp->lock, flags);
+
+ if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+ /* Do nothing -- the media monitor should handle this. */
+ if (tulip_debug > 1)
+ dev_warn(&dev->dev,
+ "Transmit timeout using MII device\n");
+ } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142 ||
+ tp->chip_id == MX98713 || tp->chip_id == COMPEX9881 ||
+ tp->chip_id == DM910X) {
+ dev_warn(&dev->dev,
+ "21140 transmit timed out, status %08x, SIA %08x %08x %08x %08x, resetting...\n",
+ ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
+ ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14),
+ ioread32(ioaddr + CSR15));
+ tp->timeout_recovery = 1;
+ schedule_work(&tp->media_work);
+ goto out_unlock;
+ } else if (tp->chip_id == PNIC2) {
+ dev_warn(&dev->dev,
+ "PNIC2 transmit timed out, status %08x, CSR6/7 %08x / %08x CSR12 %08x, resetting...\n",
+ (int)ioread32(ioaddr + CSR5),
+ (int)ioread32(ioaddr + CSR6),
+ (int)ioread32(ioaddr + CSR7),
+ (int)ioread32(ioaddr + CSR12));
+ } else {
+ dev_warn(&dev->dev,
+ "Transmit timed out, status %08x, CSR12 %08x, resetting...\n",
+ ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12));
+ dev->if_port = 0;
+ }
+
+ #if defined(way_too_many_messages)
+ if (tulip_debug > 3) {
+ int i;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
+ int j;
+ printk(KERN_DEBUG
+ "%2d: %08x %08x %08x %08x %02x %02x %02x\n",
+ i,
+ (unsigned int)tp->rx_ring[i].status,
+ (unsigned int)tp->rx_ring[i].length,
+ (unsigned int)tp->rx_ring[i].buffer1,
+ (unsigned int)tp->rx_ring[i].buffer2,
+ buf[0], buf[1], buf[2]);
+ for (j = 0; buf[j] != 0xee && j < 1600; j++)
+ if (j < 100)
+ pr_cont(" %02x", buf[j]);
+ pr_cont(" j=%d\n", j);
+ }
+ printk(KERN_DEBUG " Rx ring %p: ", tp->rx_ring);
+ for (i = 0; i < RX_RING_SIZE; i++)
+ pr_cont(" %08x", (unsigned int)tp->rx_ring[i].status);
+ printk(KERN_DEBUG " Tx ring %p: ", tp->tx_ring);
+ for (i = 0; i < TX_RING_SIZE; i++)
+ pr_cont(" %08x", (unsigned int)tp->tx_ring[i].status);
+ pr_cont("\n");
+ }
+ #endif
+
+ tulip_tx_timeout_complete(tp, ioaddr);
+
+ out_unlock:
+ spin_unlock_irqrestore (&tp->lock, flags);
+ dev->trans_start = jiffies; /* prevent tx timeout */
+ netif_wake_queue (dev);
+ }
+
+
+ /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+ static void tulip_init_ring(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int i;
+
+ tp->susp_rx = 0;
+ tp->ttimer = 0;
+ tp->nir = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ tp->rx_ring[i].status = 0x00000000;
+ tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
+ tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1));
+ tp->rx_buffers[i].skb = NULL;
+ tp->rx_buffers[i].mapping = 0;
+ }
+ /* Mark the last entry as wrapping the ring. */
+ tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP);
+ tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma);
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ dma_addr_t mapping;
+
+ /* Note the receive buffer must be longword aligned.
+ dev_alloc_skb() provides 16 byte alignment. But do *not*
+ use skb_reserve() to align the IP header! */
+ struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+ tp->rx_buffers[i].skb = skb;
+ if (skb == NULL)
+ break;
+ mapping = pci_map_single(tp->pdev, skb->data,
+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ tp->rx_buffers[i].mapping = mapping;
+ skb->dev = dev; /* Mark as being used by this device. */
+ tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */
+ tp->rx_ring[i].buffer1 = cpu_to_le32(mapping);
+ }
+ tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+
+ /* The Tx buffer descriptor is filled in as needed, but we
+ do need to clear the ownership bit. */
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ tp->tx_buffers[i].skb = NULL;
+ tp->tx_buffers[i].mapping = 0;
+ tp->tx_ring[i].status = 0x00000000;
+ tp->tx_ring[i].buffer2 = cpu_to_le32(tp->tx_ring_dma + sizeof(struct tulip_tx_desc) * (i + 1));
+ }
+ tp->tx_ring[i-1].buffer2 = cpu_to_le32(tp->tx_ring_dma);
+ }
+
+ static netdev_tx_t
+ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int entry;
+ u32 flag;
+ dma_addr_t mapping;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->lock, flags);
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = tp->cur_tx % TX_RING_SIZE;
+
+ tp->tx_buffers[entry].skb = skb;
+ mapping = pci_map_single(tp->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+ tp->tx_buffers[entry].mapping = mapping;
+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping);
+
+ if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+ flag = 0x60000000; /* No interrupt */
+ } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+ flag = 0xe0000000; /* Tx-done intr. */
+ } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+ flag = 0x60000000; /* No Tx-done intr. */
+ } else { /* Leave room for set_rx_mode() to fill entries. */
+ flag = 0xe0000000; /* Tx-done intr. */
+ netif_stop_queue(dev);
+ }
+ if (entry == TX_RING_SIZE-1)
+ flag = 0xe0000000 | DESC_RING_WRAP;
+
+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag);
+ /* if we were using Transmit Automatic Polling, we would need a
+ * wmb() here. */
+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned);
+ wmb();
+
+ tp->cur_tx++;
+
+ /* Trigger an immediate transmit demand. */
+ iowrite32(0, tp->base_addr + CSR1);
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+
+ return NETDEV_TX_OK;
+ }
+
+ static void tulip_clean_tx_ring(struct tulip_private *tp)
+ {
+ unsigned int dirty_tx;
+
+ for (dirty_tx = tp->dirty_tx ; tp->cur_tx - dirty_tx > 0;
+ dirty_tx++) {
+ int entry = dirty_tx % TX_RING_SIZE;
+ int status = le32_to_cpu(tp->tx_ring[entry].status);
+
+ if (status < 0) {
+ tp->dev->stats.tx_errors++; /* It wasn't Txed */
+ tp->tx_ring[entry].status = 0;
+ }
+
+ /* Check for Tx filter setup frames. */
+ if (tp->tx_buffers[entry].skb == NULL) {
+ /* test because dummy frames not mapped */
+ if (tp->tx_buffers[entry].mapping)
+ pci_unmap_single(tp->pdev,
+ tp->tx_buffers[entry].mapping,
+ sizeof(tp->setup_frame),
+ PCI_DMA_TODEVICE);
+ continue;
+ }
+
+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
+ tp->tx_buffers[entry].skb->len,
+ PCI_DMA_TODEVICE);
+
+ /* Free the original skb. */
+ dev_kfree_skb_irq(tp->tx_buffers[entry].skb);
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ }
+ }
+
+ static void tulip_down (struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ unsigned long flags;
+
+ cancel_work_sync(&tp->media_work);
+
+ #ifdef CONFIG_TULIP_NAPI
+ napi_disable(&tp->napi);
+ #endif
+
+ del_timer_sync (&tp->timer);
+ #ifdef CONFIG_TULIP_NAPI
+ del_timer_sync (&tp->oom_timer);
+ #endif
+ spin_lock_irqsave (&tp->lock, flags);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ iowrite32 (0x00000000, ioaddr + CSR7);
+
+ /* Stop the Tx and Rx processes. */
+ tulip_stop_rxtx(tp);
+
+ /* prepare receive buffers */
+ tulip_refill_rx(dev);
+
+ /* release any unconsumed transmit buffers */
+ tulip_clean_tx_ring(tp);
+
+ if (ioread32(ioaddr + CSR6) != 0xffffffff)
+ dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+
+ spin_unlock_irqrestore (&tp->lock, flags);
+
+ init_timer(&tp->timer);
+ tp->timer.data = (unsigned long)dev;
+ tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
+
+ dev->if_port = tp->saved_if_port;
+
+ /* Leave the driver in snooze, not sleep, mode. */
+ tulip_set_power_state (tp, 0, 1);
+ }
+
+ static void tulip_free_ring (struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ int i;
+
+ /* Free all the skbuffs in the Rx queue. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ struct sk_buff *skb = tp->rx_buffers[i].skb;
+ dma_addr_t mapping = tp->rx_buffers[i].mapping;
+
+ tp->rx_buffers[i].skb = NULL;
+ tp->rx_buffers[i].mapping = 0;
+
+ tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */
+ tp->rx_ring[i].length = 0;
+ /* An invalid address. */
+ tp->rx_ring[i].buffer1 = cpu_to_le32(0xBADF00D0);
+ if (skb) {
+ pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb (skb);
+ }
+ }
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ struct sk_buff *skb = tp->tx_buffers[i].skb;
+
+ if (skb != NULL) {
+ pci_unmap_single(tp->pdev, tp->tx_buffers[i].mapping,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb (skb);
+ }
+ tp->tx_buffers[i].skb = NULL;
+ tp->tx_buffers[i].mapping = 0;
+ }
+ }
+
+ static int tulip_close (struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+
+ netif_stop_queue (dev);
+
+ tulip_down (dev);
+
+ if (tulip_debug > 1)
+ netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
+ ioread32 (ioaddr + CSR5));
+
+ free_irq (dev->irq, dev);
+
+ tulip_free_ring (dev);
+
+ return 0;
+ }
+
+ static struct net_device_stats *tulip_get_stats(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+
+ if (netif_running(dev)) {
+ unsigned long flags;
+
+ spin_lock_irqsave (&tp->lock, flags);
+
+ dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+ }
+
+ return &dev->stats;
+ }
+
+
+ static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+ {
+ struct tulip_private *np = netdev_priv(dev);
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(np->pdev));
+ }
+
+
+ static int tulip_ethtool_set_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wolinfo)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+
+ if (wolinfo->wolopts & (~tp->wolinfo.supported))
+ return -EOPNOTSUPP;
+
+ tp->wolinfo.wolopts = wolinfo->wolopts;
+ device_set_wakeup_enable(&tp->pdev->dev, tp->wolinfo.wolopts);
+ return 0;
+ }
+
+ static void tulip_ethtool_get_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wolinfo)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+
+ wolinfo->supported = tp->wolinfo.supported;
+ wolinfo->wolopts = tp->wolinfo.wolopts;
+ return;
+ }
+
+
+ static const struct ethtool_ops ops = {
+ .get_drvinfo = tulip_get_drvinfo,
+ .set_wol = tulip_ethtool_set_wol,
+ .get_wol = tulip_ethtool_get_wol,
+ };
+
+ /* Provide ioctl() calls to examine the MII xcvr state. */
+ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ struct mii_ioctl_data *data = if_mii(rq);
+ const unsigned int phy_idx = 0;
+ int phy = tp->phys[phy_idx] & 0x1f;
+ unsigned int regnum = data->reg_num;
+
+ switch (cmd) {
+ case SIOCGMIIPHY: /* Get address of MII PHY in use. */
+ if (tp->mii_cnt)
+ data->phy_id = phy;
+ else if (tp->flags & HAS_NWAY)
+ data->phy_id = 32;
+ else if (tp->chip_id == COMET)
+ data->phy_id = 1;
+ else
+ return -ENODEV;
+
+ case SIOCGMIIREG: /* Read MII PHY register. */
+ if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) {
+ int csr12 = ioread32 (ioaddr + CSR12);
+ int csr14 = ioread32 (ioaddr + CSR14);
+ switch (regnum) {
+ case 0:
+ if (((csr14<<5) & 0x1000) ||
+ (dev->if_port == 5 && tp->nwayset))
+ data->val_out = 0x1000;
+ else
+ data->val_out = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0)
+ | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0);
+ break;
+ case 1:
+ data->val_out =
+ 0x1848 +
+ ((csr12&0x7000) == 0x5000 ? 0x20 : 0) +
+ ((csr12&0x06) == 6 ? 0 : 4);
+ data->val_out |= 0x6048;
+ break;
+ case 4:
+ /* Advertised value, bogus 10baseTx-FD value from CSR6. */
+ data->val_out =
+ ((ioread32(ioaddr + CSR6) >> 3) & 0x0040) +
+ ((csr14 >> 1) & 0x20) + 1;
+ data->val_out |= ((csr14 >> 9) & 0x03C0);
+ break;
+ case 5: data->val_out = tp->lpar; break;
+ default: data->val_out = 0; break;
+ }
+ } else {
+ data->val_out = tulip_mdio_read (dev, data->phy_id & 0x1f, regnum);
+ }
+ return 0;
+
+ case SIOCSMIIREG: /* Write MII PHY register. */
+ if (regnum & ~0x1f)
+ return -EINVAL;
+ if (data->phy_id == phy) {
+ u16 value = data->val_in;
+ switch (regnum) {
+ case 0: /* Check for autonegotiation on or reset. */
+ tp->full_duplex_lock = (value & 0x9000) ? 0 : 1;
+ if (tp->full_duplex_lock)
+ tp->full_duplex = (value & 0x0100) ? 1 : 0;
+ break;
+ case 4:
+ tp->advertising[phy_idx] =
+ tp->mii_advertise = data->val_in;
+ break;
+ }
+ }
+ if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) {
+ u16 value = data->val_in;
+ if (regnum == 0) {
+ if ((value & 0x1200) == 0x1200) {
+ if (tp->chip_id == PNIC2) {
+ pnic2_start_nway (dev);
+ } else {
+ t21142_start_nway (dev);
+ }
+ }
+ } else if (regnum == 4)
+ tp->sym_advertise = value;
+ } else {
+ tulip_mdio_write (dev, data->phy_id & 0x1f, regnum, data->val_in);
+ }
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return -EOPNOTSUPP;
+ }
+
+
+ /* Set or clear the multicast filter for this adaptor.
+ Note that we only use exclusion around actually queueing the
+ new frame, not around filling tp->setup_frame. This is non-deterministic
+ when re-entered but still correct. */
+
+ #undef set_bit_le
+ #define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
+
+ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ u16 hash_table[32];
+ struct netdev_hw_addr *ha;
+ int i;
+ u16 *eaddrs;
+
+ memset(hash_table, 0, sizeof(hash_table));
+ set_bit_le(255, hash_table); /* Broadcast entry */
+ /* This should work on big-endian machines as well. */
+ netdev_for_each_mc_addr(ha, dev) {
+ int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;
+
+ set_bit_le(index, hash_table);
+ }
+ for (i = 0; i < 32; i++) {
+ *setup_frm++ = hash_table[i];
+ *setup_frm++ = hash_table[i];
+ }
+ setup_frm = &tp->setup_frame[13*6];
+
+ /* Fill the final entry with our physical address. */
+ eaddrs = (u16 *)dev->dev_addr;
+ *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+ *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+ *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+ }
+
+ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ struct netdev_hw_addr *ha;
+ u16 *eaddrs;
+
+ /* We have <= 14 addresses so we can use the wonderful
+ 16 address perfect filtering of the Tulip. */
+ netdev_for_each_mc_addr(ha, dev) {
+ eaddrs = (u16 *) ha->addr;
+ *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;
+ *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;
+ *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;
+ }
+ /* Fill the unused entries with the broadcast address. */
+ memset(setup_frm, 0xff, (15 - netdev_mc_count(dev)) * 12);
+ setup_frm = &tp->setup_frame[15*6];
+
+ /* Fill the final entry with our physical address. */
+ eaddrs = (u16 *)dev->dev_addr;
+ *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+ *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+ *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+ }
+
+
+ static void set_rx_mode(struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int csr6;
+
+ csr6 = ioread32(ioaddr + CSR6) & ~0x00D5;
+
+ tp->csr6 &= ~0x00D5;
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
+ tp->csr6 |= AcceptAllMulticast | AcceptAllPhys;
+ csr6 |= AcceptAllMulticast | AcceptAllPhys;
+ } else if ((netdev_mc_count(dev) > 1000) ||
+ (dev->flags & IFF_ALLMULTI)) {
+ /* Too many to filter well -- accept all multicasts. */
+ tp->csr6 |= AcceptAllMulticast;
+ csr6 |= AcceptAllMulticast;
+ } else if (tp->flags & MC_HASH_ONLY) {
+ /* Some work-alikes have only a 64-entry hash filter table. */
+ /* Should verify correctness on big-endian/__powerpc__ */
+ struct netdev_hw_addr *ha;
+ if (netdev_mc_count(dev) > 64) {
+ /* Arbitrary non-effective limit. */
+ tp->csr6 |= AcceptAllMulticast;
+ csr6 |= AcceptAllMulticast;
+ } else {
+ u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */
+ int filterbit;
+ netdev_for_each_mc_addr(ha, dev) {
+ if (tp->flags & COMET_MAC_ADDR)
+ filterbit = ether_crc_le(ETH_ALEN,
+ ha->addr);
+ else
+ filterbit = ether_crc(ETH_ALEN,
+ ha->addr) >> 26;
+ filterbit &= 0x3f;
+ mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
+ if (tulip_debug > 2)
+ dev_info(&dev->dev,
+ "Added filter for %pM %08x bit %d\n",
+ ha->addr,
+ ether_crc(ETH_ALEN, ha->addr),
+ filterbit);
+ }
+ if (mc_filter[0] == tp->mc_filter[0] &&
+ mc_filter[1] == tp->mc_filter[1])
+ ; /* No change. */
+ else if (tp->flags & IS_ASIX) {
+ iowrite32(2, ioaddr + CSR13);
+ iowrite32(mc_filter[0], ioaddr + CSR14);
+ iowrite32(3, ioaddr + CSR13);
+ iowrite32(mc_filter[1], ioaddr + CSR14);
+ } else if (tp->flags & COMET_MAC_ADDR) {
+ iowrite32(mc_filter[0], ioaddr + CSR27);
+ iowrite32(mc_filter[1], ioaddr + CSR28);
+ }
+ tp->mc_filter[0] = mc_filter[0];
+ tp->mc_filter[1] = mc_filter[1];
+ }
+ } else {
+ unsigned long flags;
+ u32 tx_flags = 0x08000000 | 192;
+
+ /* Note that only the low-address shortword of setup_frame is valid!
+ The values are doubled for big-endian architectures. */
+ if (netdev_mc_count(dev) > 14) {
+ /* Must use a multicast hash table. */
+ build_setup_frame_hash(tp->setup_frame, dev);
+ tx_flags = 0x08400000 | 192;
+ } else {
+ build_setup_frame_perfect(tp->setup_frame, dev);
+ }
+
+ spin_lock_irqsave(&tp->lock, flags);
+
+ if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
+ /* Same setup recently queued, we need not add it. */
+ } else {
+ unsigned int entry;
+ int dummy = -1;
+
+ /* Now add this frame to the Tx list. */
+
+ entry = tp->cur_tx++ % TX_RING_SIZE;
+
+ if (entry != 0) {
+ /* Avoid a chip errata by prefixing a dummy entry. */
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ tp->tx_ring[entry].length =
+ (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
+ tp->tx_ring[entry].buffer1 = 0;
+ /* Must set DescOwned later to avoid race with chip */
+ dummy = entry;
+ entry = tp->cur_tx++ % TX_RING_SIZE;
+
+ }
+
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping =
+ pci_map_single(tp->pdev, tp->setup_frame,
+ sizeof(tp->setup_frame),
+ PCI_DMA_TODEVICE);
+ /* Put the setup frame on the Tx list. */
+ if (entry == TX_RING_SIZE-1)
+ tx_flags |= DESC_RING_WRAP; /* Wrap ring. */
+ tp->tx_ring[entry].length = cpu_to_le32(tx_flags);
+ tp->tx_ring[entry].buffer1 =
+ cpu_to_le32(tp->tx_buffers[entry].mapping);
+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned);
+ if (dummy >= 0)
+ tp->tx_ring[dummy].status = cpu_to_le32(DescOwned);
+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2)
+ netif_stop_queue(dev);
+
+ /* Trigger an immediate transmit demand. */
+ iowrite32(0, ioaddr + CSR1);
+ }
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+ }
+
+ iowrite32(csr6, ioaddr + CSR6);
+ }
+
+ #ifdef CONFIG_TULIP_MWI
+ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
+ struct net_device *dev)
+ {
+ struct tulip_private *tp = netdev_priv(dev);
+ u8 cache;
+ u16 pci_command;
+ u32 csr0;
+
+ if (tulip_debug > 3)
+ netdev_dbg(dev, "tulip_mwi_config()\n");
+
+ tp->csr0 = csr0 = 0;
+
+ /* if we have any cache line size at all, we can do MRM and MWI */
+ csr0 |= MRM | MWI;
+
+ /* Enable MWI in the standard PCI command bit.
+ * Check for the case where MWI is desired but not available
+ */
+ pci_try_set_mwi(pdev);
+
+ /* read result from hardware (in case bit refused to enable) */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+ if ((csr0 & MWI) && (!(pci_command & PCI_COMMAND_INVALIDATE)))
+ csr0 &= ~MWI;
+
+ /* if cache line size hardwired to zero, no MWI */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache);
+ if ((csr0 & MWI) && (cache == 0)) {
+ csr0 &= ~MWI;
+ pci_clear_mwi(pdev);
+ }
+
+ /* assign per-cacheline-size cache alignment and
+ * burst length values
+ */
+ switch (cache) {
+ case 8:
+ csr0 |= MRL | (1 << CALShift) | (16 << BurstLenShift);
+ break;
+ case 16:
+ csr0 |= MRL | (2 << CALShift) | (16 << BurstLenShift);
+ break;
+ case 32:
+ csr0 |= MRL | (3 << CALShift) | (32 << BurstLenShift);
+ break;
+ default:
+ cache = 0;
+ break;
+ }
+
+ /* if we have a good cache line size, we by now have a good
+ * csr0, so save it and exit
+ */
+ if (cache)
+ goto out;
+
+ /* we don't have a good csr0 or cache line size, disable MWI */
+ if (csr0 & MWI) {
+ pci_clear_mwi(pdev);
+ csr0 &= ~MWI;
+ }
+
+ /* sane defaults for burst length and cache alignment
+ * originally from de4x5 driver
+ */
+ csr0 |= (8 << BurstLenShift) | (1 << CALShift);
+
+ out:
+ tp->csr0 = csr0;
+ if (tulip_debug > 2)
+ netdev_dbg(dev, "MWI config cacheline=%d, csr0=%08x\n",
+ cache, csr0);
+ }
+ #endif
+
+ /*
+ * Chips that have the MRM/reserved bit quirk and the burst quirk. That
+ * is the DM910X and the on chip ULi devices
+ */
+
+ static int tulip_uli_dm_quirk(struct pci_dev *pdev)
+ {
+ if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
+ return 1;
+ return 0;
+ }
+
+ static const struct net_device_ops tulip_netdev_ops = {
+ .ndo_open = tulip_open,
+ .ndo_start_xmit = tulip_start_xmit,
+ .ndo_tx_timeout = tulip_tx_timeout,
+ .ndo_stop = tulip_close,
+ .ndo_get_stats = tulip_get_stats,
+ .ndo_do_ioctl = private_ioctl,
+ .ndo_set_rx_mode = set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = poll_tulip,
+ #endif
+ };
+
+ DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
+ { },
+ };
+
+ static int __devinit tulip_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+ struct tulip_private *tp;
+ /* See note below on the multiport cards. */
+ static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+ static int last_irq;
+ static int multiport_cnt; /* For four-port boards w/one EEPROM */
+ int i, irq;
+ unsigned short sum;
+ unsigned char *ee_data;
+ struct net_device *dev;
+ void __iomem *ioaddr;
+ static int board_idx = -1;
+ int chip_idx = ent->driver_data;
+ const char *chip_name = tulip_tbl[chip_idx].chip_name;
+ unsigned int eeprom_missing = 0;
+ unsigned int force_csr0 = 0;
+
+ #ifndef MODULE
+ if (tulip_debug > 0)
+ printk_once(KERN_INFO "%s", version);
+ #endif
+
+ board_idx++;
+
+ /*
+ * Lan media wire a tulip chip to a wan interface. Needs a very
+ * different driver (lmc driver)
+ */
+
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_LMC) {
+ pr_err("skipping LMC card\n");
+ return -ENODEV;
+ } else if (pdev->subsystem_vendor == PCI_VENDOR_ID_SBE &&
+ (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_T3E3 ||
+ pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P0 ||
+ pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)) {
+ pr_err("skipping SBE T3E3 port\n");
+ return -ENODEV;
+ }
+
+ /*
+ * DM910x chips should be handled by the dmfe driver, except
+ * on-board chips on SPARC systems. Also, early DM9100s need
+ * software CRC which only the dmfe driver supports.
+ */
+
+ #ifdef CONFIG_TULIP_DM910X
+ if (chip_idx == DM910X) {
+ struct device_node *dp;
+
+ if (pdev->vendor == 0x1282 && pdev->device == 0x9100 &&
+ pdev->revision < 0x30) {
+ pr_info("skipping early DM9100 with Crc bug (use dmfe)\n");
+ return -ENODEV;
+ }
+
+ dp = pci_device_to_OF_node(pdev);
+ if (!(dp && of_get_property(dp, "local-mac-address", NULL))) {
+ pr_info("skipping DM910x expansion card (use dmfe)\n");
+ return -ENODEV;
+ }
+ }
+ #endif
+
+ /*
+ * Looks for early PCI chipsets where people report hangs
+ * without the workarounds being on.
+ */
+
+ /* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache
+ aligned. Aries might need this too. The Saturn errata are not
+ pretty reading but thankfully it's an old 486 chipset.
+
+ 2. The dreaded SiS496 486 chipset. Same workaround as Intel
+ Saturn.
+ */
+
+ if (pci_dev_present(early_486_chipsets)) {
+ csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
+ force_csr0 = 1;
+ }
+
+ /* bugfix: the ASIX must have a burst limit or horrible things happen. */
+ if (chip_idx == AX88140) {
+ if ((csr0 & 0x3f00) == 0)
+ csr0 |= 0x2000;
+ }
+
+ /* PNIC doesn't have MWI/MRL/MRM... */
+ if (chip_idx == LC82C168)
+ csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
+
+ /* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */
+ if (tulip_uli_dm_quirk(pdev)) {
+ csr0 &= ~0x01f100ff;
+ #if defined(CONFIG_SPARC)
+ csr0 = (csr0 & ~0xff00) | 0xe000;
+ #endif
+ }
+ /*
+ * And back to business
+ */
+
+ i = pci_enable_device(pdev);
+ if (i) {
+ pr_err("Cannot enable tulip board #%d, aborting\n", board_idx);
+ return i;
+ }
+
+ /* The chip will fail to enter a low-power state later unless
+ * first explicitly commanded into D0 */
+ if (pci_set_power_state(pdev, PCI_D0)) {
+ pr_notice("Failed to set power state to D0\n");
+ }
+
+ irq = pdev->irq;
+
+ /* alloc_etherdev ensures aligned and zeroed private structures */
+ dev = alloc_etherdev (sizeof (*tp));
+ if (!dev) {
+ pr_err("ether device alloc failed, aborting\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
+ pr_err("%s: I/O region (0x%llx@0x%llx) too small, aborting\n",
+ pci_name(pdev),
+ (unsigned long long)pci_resource_len (pdev, 0),
+ (unsigned long long)pci_resource_start (pdev, 0));
+ goto err_out_free_netdev;
+ }
+
+ /* grab all resources from both PIO and MMIO regions, as we
+ * don't want anyone else messing around with our hardware */
+ if (pci_request_regions (pdev, DRV_NAME))
+ goto err_out_free_netdev;
+
+ ioaddr = pci_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size);
+
+ if (!ioaddr)
+ goto err_out_free_res;
+
+ /*
+ * initialize private data structure 'tp'
+ * it is zeroed and aligned in alloc_etherdev
+ */
+ tp = netdev_priv(dev);
+ tp->dev = dev;
+
+ tp->rx_ring = pci_alloc_consistent(pdev,
+ sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
+ sizeof(struct tulip_tx_desc) * TX_RING_SIZE,
+ &tp->rx_ring_dma);
+ if (!tp->rx_ring)
+ goto err_out_mtable;
+ tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE);
+ tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE;
+
+ tp->chip_id = chip_idx;
+ tp->flags = tulip_tbl[chip_idx].flags;
+
+ tp->wolinfo.supported = 0;
+ tp->wolinfo.wolopts = 0;
+ /* COMET: Enable power management only for AN983B */
+ if (chip_idx == COMET ) {
+ u32 sig;
+ pci_read_config_dword (pdev, 0x80, &sig);
+ if (sig == 0x09811317) {
+ tp->flags |= COMET_PM;
+ tp->wolinfo.supported = WAKE_PHY | WAKE_MAGIC;
+ pr_info("%s: Enabled WOL support for AN983B\n",
+ __func__);
+ }
+ }
+ tp->pdev = pdev;
+ tp->base_addr = ioaddr;
+ tp->revision = pdev->revision;
+ tp->csr0 = csr0;
+ spin_lock_init(&tp->lock);
+ spin_lock_init(&tp->mii_lock);
+ init_timer(&tp->timer);
+ tp->timer.data = (unsigned long)dev;
+ tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
+
+ INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task);
+
+ dev->base_addr = (unsigned long)ioaddr;
+
+ #ifdef CONFIG_TULIP_MWI
+ if (!force_csr0 && (tp->flags & HAS_PCI_MWI))
+ tulip_mwi_config (pdev, dev);
+ #endif
+
+ /* Stop the chip's Tx and Rx processes. */
+ tulip_stop_rxtx(tp);
+
+ pci_set_master(pdev);
+
+ #ifdef CONFIG_GSC
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP) {
+ switch (pdev->subsystem_device) {
+ default:
+ break;
+ case 0x1061:
+ case 0x1062:
+ case 0x1063:
+ case 0x1098:
+ case 0x1099:
+ case 0x10EE:
+ tp->flags |= HAS_SWAPPED_SEEPROM | NEEDS_FAKE_MEDIA_TABLE;
+ chip_name = "GSC DS21140 Tulip";
+ }
+ }
+ #endif
+
+ /* Clear the missed-packet counter. */
+ ioread32(ioaddr + CSR8);
+
+ /* The station address ROM is read byte serially. The register must
+ be polled, waiting for the value to be read bit serially from the
+ EEPROM.
+ */
+ ee_data = tp->eeprom;
+ memset(ee_data, 0, sizeof(tp->eeprom));
+ sum = 0;
+ if (chip_idx == LC82C168) {
+ for (i = 0; i < 3; i++) {
+ int value, boguscnt = 100000;
+ iowrite32(0x600 | i, ioaddr + 0x98);
+ do {
+ value = ioread32(ioaddr + CSR9);
+ } while (value < 0 && --boguscnt > 0);
+ put_unaligned_le16(value, ((__le16 *)dev->dev_addr) + i);
+ sum += value & 0xffff;
+ }
+ } else if (chip_idx == COMET) {
+ /* No need to read the EEPROM. */
+ put_unaligned_le32(ioread32(ioaddr + 0xA4), dev->dev_addr);
+ put_unaligned_le16(ioread32(ioaddr + 0xA8), dev->dev_addr + 4);
+ for (i = 0; i < 6; i ++)
+ sum += dev->dev_addr[i];
+ } else {
+ /* A serial EEPROM interface, we read now and sort it out later. */
+ int sa_offset = 0;
+ int ee_addr_size = tulip_read_eeprom(dev, 0xff, 8) & 0x40000 ? 8 : 6;
+ int ee_max_addr = ((1 << ee_addr_size) - 1) * sizeof(u16);
+
+ if (ee_max_addr > sizeof(tp->eeprom))
+ ee_max_addr = sizeof(tp->eeprom);
+
+ for (i = 0; i < ee_max_addr ; i += sizeof(u16)) {
+ u16 data = tulip_read_eeprom(dev, i/2, ee_addr_size);
+ ee_data[i] = data & 0xff;
+ ee_data[i + 1] = data >> 8;
+ }
+
+ /* DEC now has a specification (see Notes) but early board makers
+ just put the address in the first EEPROM locations. */
+ /* This does memcmp(ee_data, ee_data+16, 8) */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ sa_offset = 20;
+ if (chip_idx == CONEXANT) {
+ /* Check that the tuple type and length is correct. */
+ if (ee_data[0x198] == 0x04 && ee_data[0x199] == 6)
+ sa_offset = 0x19A;
+ } else if (ee_data[0] == 0xff && ee_data[1] == 0xff &&
+ ee_data[2] == 0) {
+ sa_offset = 2; /* Grrr, damn Matrox boards. */
+ multiport_cnt = 4;
+ }
+ #ifdef CONFIG_MIPS_COBALT
+ if ((pdev->bus->number == 0) &&
+ ((PCI_SLOT(pdev->devfn) == 7) ||
+ (PCI_SLOT(pdev->devfn) == 12))) {
+ /* Cobalt MAC address in first EEPROM locations. */
+ sa_offset = 0;
+ /* Ensure our media table fixup get's applied */
+ memcpy(ee_data + 16, ee_data, 8);
+ }
+ #endif
+ #ifdef CONFIG_GSC
+ /* Check to see if we have a broken srom */
+ if (ee_data[0] == 0x61 && ee_data[1] == 0x10) {
+ /* pci_vendor_id and subsystem_id are swapped */
+ ee_data[0] = ee_data[2];
+ ee_data[1] = ee_data[3];
+ ee_data[2] = 0x61;
+ ee_data[3] = 0x10;
+
+ /* HSC-PCI boards need to be byte-swaped and shifted
+ * up 1 word. This shift needs to happen at the end
+ * of the MAC first because of the 2 byte overlap.
+ */
+ for (i = 4; i >= 0; i -= 2) {
+ ee_data[17 + i + 3] = ee_data[17 + i];
+ ee_data[16 + i + 5] = ee_data[16 + i];
+ }
+ }
+ #endif
+
+ for (i = 0; i < 6; i ++) {
+ dev->dev_addr[i] = ee_data[i + sa_offset];
+ sum += ee_data[i + sa_offset];
+ }
+ }
+ /* Lite-On boards have the address byte-swapped. */
+ if ((dev->dev_addr[0] == 0xA0 ||
+ dev->dev_addr[0] == 0xC0 ||
+ dev->dev_addr[0] == 0x02) &&
+ dev->dev_addr[1] == 0x00)
+ for (i = 0; i < 6; i+=2) {
+ char tmp = dev->dev_addr[i];
+ dev->dev_addr[i] = dev->dev_addr[i+1];
+ dev->dev_addr[i+1] = tmp;
+ }
+ /* On the Zynx 315 Etherarray and other multiport boards only the
+ first Tulip has an EEPROM.
+ On Sparc systems the mac address is held in the OBP property
+ "local-mac-address".
+ The addresses of the subsequent ports are derived from the first.
+ Many PCI BIOSes also incorrectly report the IRQ line, so we correct
+ that here as well. */
+ if (sum == 0 || sum == 6*0xff) {
+ #if defined(CONFIG_SPARC)
+ struct device_node *dp = pci_device_to_OF_node(pdev);
+ const unsigned char *addr;
+ int len;
+ #endif
+ eeprom_missing = 1;
+ for (i = 0; i < 5; i++)
+ dev->dev_addr[i] = last_phys_addr[i];
+ dev->dev_addr[i] = last_phys_addr[i] + 1;
+ #if defined(CONFIG_SPARC)
+ addr = of_get_property(dp, "local-mac-address", &len);
+ if (addr && len == 6)
+ memcpy(dev->dev_addr, addr, 6);
+ #endif
+ #if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */
+ if (last_irq)
+ irq = last_irq;
+ #endif
+ }
+
+ for (i = 0; i < 6; i++)
+ last_phys_addr[i] = dev->dev_addr[i];
+ last_irq = irq;
+ dev->irq = irq;
+
+ /* The lower four bits are the media type. */
+ if (board_idx >= 0 && board_idx < MAX_UNITS) {
+ if (options[board_idx] & MEDIA_MASK)
+ tp->default_port = options[board_idx] & MEDIA_MASK;
+ if ((options[board_idx] & FullDuplex) || full_duplex[board_idx] > 0)
+ tp->full_duplex = 1;
+ if (mtu[board_idx] > 0)
+ dev->mtu = mtu[board_idx];
+ }
+ if (dev->mem_start & MEDIA_MASK)
+ tp->default_port = dev->mem_start & MEDIA_MASK;
+ if (tp->default_port) {
+ pr_info(DRV_NAME "%d: Transceiver selection forced to %s\n",
+ board_idx, medianame[tp->default_port & MEDIA_MASK]);
+ tp->medialock = 1;
+ if (tulip_media_cap[tp->default_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+ }
+ if (tp->full_duplex)
+ tp->full_duplex_lock = 1;
+
+ if (tulip_media_cap[tp->default_port] & MediaIsMII) {
+ static const u16 media2advert[] = {
+ 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200
+ };
+ tp->mii_advertise = media2advert[tp->default_port - 9];
+ tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
+ }
+
+ if (tp->flags & HAS_MEDIA_TABLE) {
+ sprintf(dev->name, DRV_NAME "%d", board_idx); /* hack */
+ tulip_parse_eeprom(dev);
+ strcpy(dev->name, "eth%d"); /* un-hack */
+ }
+
+ if ((tp->flags & ALWAYS_CHECK_MII) ||
+ (tp->mtable && tp->mtable->has_mii) ||
+ ( ! tp->mtable && (tp->flags & HAS_MII))) {
+ if (tp->mtable && tp->mtable->has_mii) {
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == 11) {
+ tp->cur_index = i;
+ tp->saved_if_port = dev->if_port;
+ tulip_select_media(dev, 2);
+ dev->if_port = tp->saved_if_port;
+ break;
+ }
+ }
+
+ /* Find the connected MII xcvrs.
+ Doing this in open() would allow detecting external xcvrs
+ later, but takes much time. */
+ tulip_find_mii (dev, board_idx);
+ }
+
+ /* The Tulip-specific entries in the device structure. */
+ dev->netdev_ops = &tulip_netdev_ops;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ #ifdef CONFIG_TULIP_NAPI
+ netif_napi_add(dev, &tp->napi, tulip_poll, 16);
+ #endif
+ SET_ETHTOOL_OPS(dev, &ops);
+
+ if (register_netdev(dev))
+ goto err_out_free_ring;
+
+ pci_set_drvdata(pdev, dev);
+
+ dev_info(&dev->dev,
+ #ifdef CONFIG_TULIP_MMIO
+ "%s rev %d at MMIO %#llx,%s %pM, IRQ %d\n",
+ #else
+ "%s rev %d at Port %#llx,%s %pM, IRQ %d\n",
+ #endif
+ chip_name, pdev->revision,
+ (unsigned long long)pci_resource_start(pdev, TULIP_BAR),
+ eeprom_missing ? " EEPROM not present," : "",
+ dev->dev_addr, irq);
+
+ if (tp->chip_id == PNIC2)
+ tp->link_change = pnic2_lnk_change;
+ else if (tp->flags & HAS_NWAY)
+ tp->link_change = t21142_lnk_change;
+ else if (tp->flags & HAS_PNICNWAY)
+ tp->link_change = pnic_lnk_change;
+
+ /* Reset the xcvr interface and turn on heartbeat. */
+ switch (chip_idx) {
+ case DC21140:
+ case DM910X:
+ default:
+ if (tp->mtable)
+ iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
+ break;
+ case DC21142:
+ if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) {
+ iowrite32(csr6_mask_defstate, ioaddr + CSR6);
+ iowrite32(0x0000, ioaddr + CSR13);
+ iowrite32(0x0000, ioaddr + CSR14);
+ iowrite32(csr6_mask_hdcap, ioaddr + CSR6);
+ } else
+ t21142_start_nway(dev);
+ break;
+ case PNIC2:
+ /* just do a reset for sanity sake */
+ iowrite32(0x0000, ioaddr + CSR13);
+ iowrite32(0x0000, ioaddr + CSR14);
+ break;
+ case LC82C168:
+ if ( ! tp->mii_cnt) {
+ tp->nway = 1;
+ tp->nwayset = 0;
+ iowrite32(csr6_ttm | csr6_ca, ioaddr + CSR6);
+ iowrite32(0x30, ioaddr + CSR12);
+ iowrite32(0x0001F078, ioaddr + CSR6);
+ iowrite32(0x0201F078, ioaddr + CSR6); /* Turn on autonegotiation. */
+ }
+ break;
+ case MX98713:
+ case COMPEX9881:
+ iowrite32(0x00000000, ioaddr + CSR6);
+ iowrite32(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
+ iowrite32(0x00000001, ioaddr + CSR13);
+ break;
+ case MX98715:
+ case MX98725:
+ iowrite32(0x01a80000, ioaddr + CSR6);
+ iowrite32(0xFFFFFFFF, ioaddr + CSR14);
+ iowrite32(0x00001000, ioaddr + CSR12);
+ break;
+ case COMET:
+ /* No initialization necessary. */
+ break;
+ }
+
+ /* put the chip in snooze mode until opened */
+ tulip_set_power_state (tp, 0, 1);
+
+ return 0;
+
+ err_out_free_ring:
+ pci_free_consistent (pdev,
+ sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
+ sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
+ tp->rx_ring, tp->rx_ring_dma);
+
+ err_out_mtable:
+ kfree (tp->mtable);
+ pci_iounmap(pdev, ioaddr);
+
+ err_out_free_res:
+ pci_release_regions (pdev);
+
+ err_out_free_netdev:
+ free_netdev (dev);
+ return -ENODEV;
+ }
+
+
+ /* set the registers according to the given wolopts */
+ static void tulip_set_wolopts (struct pci_dev *pdev, u32 wolopts)
+ {
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+
+ if (tp->flags & COMET_PM) {
+
+ unsigned int tmp;
+
+ tmp = ioread32(ioaddr + CSR18);
+ tmp &= ~(comet_csr18_pmes_sticky | comet_csr18_apm_mode | comet_csr18_d3a);
+ tmp |= comet_csr18_pm_mode;
+ iowrite32(tmp, ioaddr + CSR18);
+
+ /* Set the Wake-up Control/Status Register to the given WOL options*/
+ tmp = ioread32(ioaddr + CSR13);
+ tmp &= ~(comet_csr13_linkoffe | comet_csr13_linkone | comet_csr13_wfre | comet_csr13_lsce | comet_csr13_mpre);
+ if (wolopts & WAKE_MAGIC)
+ tmp |= comet_csr13_mpre;
+ if (wolopts & WAKE_PHY)
+ tmp |= comet_csr13_linkoffe | comet_csr13_linkone | comet_csr13_lsce;
+ /* Clear the event flags */
+ tmp |= comet_csr13_wfr | comet_csr13_mpr | comet_csr13_lsc;
+ iowrite32(tmp, ioaddr + CSR13);
+ }
+ }
+
+ #ifdef CONFIG_PM
+
+
+ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
+ {
+ pci_power_t pstate;
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct tulip_private *tp = netdev_priv(dev);
+
+ if (!dev)
+ return -EINVAL;
+
+ if (!netif_running(dev))
+ goto save_state;
+
+ tulip_down(dev);
+
+ netif_device_detach(dev);
+ free_irq(dev->irq, dev);
+
+ save_state:
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pstate = pci_choose_state(pdev, state);
+ if (state.event == PM_EVENT_SUSPEND && pstate != PCI_D0) {
+ int rc;
+
+ tulip_set_wolopts(pdev, tp->wolinfo.wolopts);
+ rc = pci_enable_wake(pdev, pstate, tp->wolinfo.wolopts);
+ if (rc)
+ pr_err("pci_enable_wake failed (%d)\n", rc);
+ }
+ pci_set_power_state(pdev, pstate);
+
+ return 0;
+ }
+
+
+ static int tulip_resume(struct pci_dev *pdev)
+ {
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct tulip_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->base_addr;
+ int retval;
+ unsigned int tmp;
+
+ if (!dev)
+ return -EINVAL;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if (!netif_running(dev))
+ return 0;
+
+ if ((retval = pci_enable_device(pdev))) {
+ pr_err("pci_enable_device failed in resume\n");
+ return retval;
+ }
+
+ if ((retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev))) {
+ pr_err("request_irq failed in resume\n");
+ return retval;
+ }
+
+ if (tp->flags & COMET_PM) {
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ /* Clear the PMES flag */
+ tmp = ioread32(ioaddr + CSR20);
+ tmp |= comet_csr20_pmes;
+ iowrite32(tmp, ioaddr + CSR20);
+
+ /* Disable all wake-up events */
+ tulip_set_wolopts(pdev, 0);
+ }
+ netif_device_attach(dev);
+
+ if (netif_running(dev))
+ tulip_up(dev);
+
+ return 0;
+ }
+
+ #endif /* CONFIG_PM */
+
+
+ static void __devexit tulip_remove_one (struct pci_dev *pdev)
+ {
+ struct net_device *dev = pci_get_drvdata (pdev);
+ struct tulip_private *tp;
+
+ if (!dev)
+ return;
+
+ tp = netdev_priv(dev);
+ unregister_netdev(dev);
+ pci_free_consistent (pdev,
+ sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
+ sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
+ tp->rx_ring, tp->rx_ring_dma);
+ kfree (tp->mtable);
+ pci_iounmap(pdev, tp->base_addr);
+ free_netdev (dev);
+ pci_release_regions (pdev);
+ pci_set_drvdata (pdev, NULL);
+
+ /* pci_power_off (pdev, -1); */
+ }
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ /*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+ static void poll_tulip (struct net_device *dev)
+ {
+ /* disable_irq here is not very nice, but with the lockless
+ interrupt handler we have no other choice. */
+ disable_irq(dev->irq);
+ tulip_interrupt (dev->irq, dev);
+ enable_irq(dev->irq);
+ }
+ #endif
+
+ static struct pci_driver tulip_driver = {
+ .name = DRV_NAME,
+ .id_table = tulip_pci_tbl,
+ .probe = tulip_init_one,
+ .remove = __devexit_p(tulip_remove_one),
+ #ifdef CONFIG_PM
+ .suspend = tulip_suspend,
+ .resume = tulip_resume,
+ #endif /* CONFIG_PM */
+ };
+
+
+ static int __init tulip_init (void)
+ {
+ #ifdef MODULE
+ pr_info("%s", version);
+ #endif
+
+ /* copy module parms into globals */
+ tulip_rx_copybreak = rx_copybreak;
+ tulip_max_interrupt_work = max_interrupt_work;
+
+ /* probe for and init boards */
+ return pci_register_driver(&tulip_driver);
+ }
+
+
+ static void __exit tulip_cleanup (void)
+ {
+ pci_unregister_driver (&tulip_driver);
+ }
+
+
+ module_init(tulip_init);
+ module_exit(tulip_cleanup);
--- /dev/null
- * returns SUCCESS if it successfuly read message from buffer
+ /*******************************************************************************
+
+ Intel(R) Gigabit Ethernet Linux driver
+ Copyright(c) 2007-2011 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+ *******************************************************************************/
+
+ #include "e1000_mbx.h"
+
+ /**
+ * igb_read_mbx - Reads a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
++ * returns SUCCESS if it successfully read message from buffer
+ **/
+ s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ /* limit read to size of mailbox */
+ if (size > mbx->size)
+ size = mbx->size;
+
+ if (mbx->ops.read)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * igb_write_mbx - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+ s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = 0;
+
+ if (size > mbx->size)
+ ret_val = -E1000_ERR_MBX;
+
+ else if (mbx->ops.write)
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * igb_check_for_msg - checks to see if someone sent us mail
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+ s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (mbx->ops.check_for_msg)
+ ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * igb_check_for_ack - checks to see if someone sent us ACK
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+ s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (mbx->ops.check_for_ack)
+ ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * igb_check_for_rst - checks to see if other side has reset
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+ s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (mbx->ops.check_for_rst)
+ ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * igb_poll_for_msg - Wait for message notification
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification
+ **/
+ static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ if (!countdown || !mbx->ops.check_for_msg)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ udelay(mbx->usec_delay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+ out:
+ return countdown ? 0 : -E1000_ERR_MBX;
+ }
+
+ /**
+ * igb_poll_for_ack - Wait for message acknowledgement
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message acknowledgement
+ **/
+ static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ if (!countdown || !mbx->ops.check_for_ack)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ udelay(mbx->usec_delay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+ out:
+ return countdown ? 0 : -E1000_ERR_MBX;
+ }
+
+ /**
+ * igb_read_posted_mbx - Wait for message notification and receive message
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification and
+ * copied it into the receive buffer.
+ **/
+ static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!mbx->ops.read)
+ goto out;
+
+ ret_val = igb_poll_for_msg(hw, mbx_id);
+
+ if (!ret_val)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+ out:
+ return ret_val;
+ }
+
+ /**
+ * igb_write_posted_mbx - Write a message to the mailbox, wait for ack
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer and
+ * received an ack to that message within delay * timeout period
+ **/
+ static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ /* exit if either we can't write or there isn't a defined timeout */
+ if (!mbx->ops.write || !mbx->timeout)
+ goto out;
+
+ /* send msg */
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ /* if msg sent wait until we receive an ack */
+ if (!ret_val)
+ ret_val = igb_poll_for_ack(hw, mbx_id);
+ out:
+ return ret_val;
+ }
+
+ static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
+ {
+ u32 mbvficr = rd32(E1000_MBVFICR);
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (mbvficr & mask) {
+ ret_val = 0;
+ wr32(E1000_MBVFICR, mask);
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * igb_check_for_msg_pf - checks to see if the VF has sent mail
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+ static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
+ ret_val = 0;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * igb_check_for_ack_pf - checks to see if the VF has ACKed
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+ static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
+ ret_val = 0;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * igb_check_for_rst_pf - checks to see if the VF has reset
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+ static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
+ {
+ u32 vflre = rd32(E1000_VFLRE);
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (vflre & (1 << vf_number)) {
+ ret_val = 0;
+ wr32(E1000_VFLRE, (1 << vf_number));
+ hw->mbx.stats.rsts++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * igb_obtain_mbx_lock_pf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * return SUCCESS if we obtained the mailbox lock
+ **/
+ static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+ u32 p2v_mailbox;
+
+
+ /* Take ownership of the buffer */
+ wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
+
+ /* reserve mailbox for vf use */
+ p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
+ if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
+ ret_val = 0;
+
+ return ret_val;
+ }
+
+ /**
+ * igb_write_mbx_pf - Places a message in the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+ static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
+ u16 vf_number)
+ {
+ s32 ret_val;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
+ if (ret_val)
+ goto out_no_write;
+
+ /* flush msg and acks as we are overwriting the message buffer */
+ igb_check_for_msg_pf(hw, vf_number);
+ igb_check_for_ack_pf(hw, vf_number);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ array_wr32(E1000_VMBMEM(vf_number), i, msg[i]);
+
+ /* Interrupt VF to tell it a message has been sent and release buffer*/
+ wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+ out_no_write:
+ return ret_val;
+
+ }
+
+ /**
+ * igb_read_mbx_pf - Read a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_number: the VF index
+ *
+ * This function copies a message from the mailbox buffer to the caller's
+ * memory buffer. The presumption is that the caller knows that there was
+ * a message due to a VF request so no polling for message is needed.
+ **/
+ static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
+ u16 vf_number)
+ {
+ s32 ret_val;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
+ if (ret_val)
+ goto out_no_read;
+
+ /* copy the message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
+
+ /* Acknowledge the message and release buffer */
+ wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+ out_no_read:
+ return ret_val;
+ }
+
+ /**
+ * e1000_init_mbx_params_pf - set initial values for pf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for pf mailbox
+ */
+ s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+
+ mbx->timeout = 0;
+ mbx->usec_delay = 0;
+
+ mbx->size = E1000_VFMAILBOX_SIZE;
+
+ mbx->ops.read = igb_read_mbx_pf;
+ mbx->ops.write = igb_write_mbx_pf;
+ mbx->ops.read_posted = igb_read_posted_mbx;
+ mbx->ops.write_posted = igb_write_posted_mbx;
+ mbx->ops.check_for_msg = igb_check_for_msg_pf;
+ mbx->ops.check_for_ack = igb_check_for_ack_pf;
+ mbx->ops.check_for_rst = igb_check_for_rst_pf;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+
+ return 0;
+ }
+
--- /dev/null
- * returns SUCCESS if it successfuly read message from buffer
+ /*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 2009 - 2010 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+ *******************************************************************************/
+
+ #include "mbx.h"
+
+ /**
+ * e1000_poll_for_msg - Wait for message notification
+ * @hw: pointer to the HW structure
+ *
+ * returns SUCCESS if it successfully received a message notification
+ **/
+ static s32 e1000_poll_for_msg(struct e1000_hw *hw)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ if (!mbx->ops.check_for_msg)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_msg(hw)) {
+ countdown--;
+ udelay(mbx->usec_delay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+ out:
+ return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
+ }
+
+ /**
+ * e1000_poll_for_ack - Wait for message acknowledgement
+ * @hw: pointer to the HW structure
+ *
+ * returns SUCCESS if it successfully received a message acknowledgement
+ **/
+ static s32 e1000_poll_for_ack(struct e1000_hw *hw)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ if (!mbx->ops.check_for_ack)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_ack(hw)) {
+ countdown--;
+ udelay(mbx->usec_delay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+ out:
+ return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
+ }
+
+ /**
+ * e1000_read_posted_mbx - Wait for message notification and receive message
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
+ * returns SUCCESS if it successfully received a message notification and
+ * copied it into the receive buffer.
+ **/
+ static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!mbx->ops.read)
+ goto out;
+
+ ret_val = e1000_poll_for_msg(hw);
+
+ /* if ack received read message, otherwise we timed out */
+ if (!ret_val)
+ ret_val = mbx->ops.read(hw, msg, size);
+ out:
+ return ret_val;
+ }
+
+ /**
+ * e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
+ * returns SUCCESS if it successfully copied message into the buffer and
+ * received an ack to that message within delay * timeout period
+ **/
+ static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ /* exit if we either can't write or there isn't a defined timeout */
+ if (!mbx->ops.write || !mbx->timeout)
+ goto out;
+
+ /* send msg*/
+ ret_val = mbx->ops.write(hw, msg, size);
+
+ /* if msg sent wait until we receive an ack */
+ if (!ret_val)
+ ret_val = e1000_poll_for_ack(hw);
+ out:
+ return ret_val;
+ }
+
+ /**
+ * e1000_read_v2p_mailbox - read v2p mailbox
+ * @hw: pointer to the HW structure
+ *
+ * This function is used to read the v2p mailbox without losing the read to
+ * clear status bits.
+ **/
+ static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
+ {
+ u32 v2p_mailbox = er32(V2PMAILBOX(0));
+
+ v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
+ hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
+
+ return v2p_mailbox;
+ }
+
+ /**
+ * e1000_check_for_bit_vf - Determine if a status bit was set
+ * @hw: pointer to the HW structure
+ * @mask: bitmask for bits to be tested and cleared
+ *
+ * This function is used to check for the read to clear bits within
+ * the V2P mailbox.
+ **/
+ static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
+ {
+ u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (v2p_mailbox & mask)
+ ret_val = E1000_SUCCESS;
+
+ hw->dev_spec.vf.v2p_mailbox &= ~mask;
+
+ return ret_val;
+ }
+
+ /**
+ * e1000_check_for_msg_vf - checks to see if the PF has sent mail
+ * @hw: pointer to the HW structure
+ *
+ * returns SUCCESS if the PF has set the Status bit or else ERR_MBX
+ **/
+ static s32 e1000_check_for_msg_vf(struct e1000_hw *hw)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
+ ret_val = E1000_SUCCESS;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * e1000_check_for_ack_vf - checks to see if the PF has ACK'd
+ * @hw: pointer to the HW structure
+ *
+ * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
+ **/
+ static s32 e1000_check_for_ack_vf(struct e1000_hw *hw)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
+ ret_val = E1000_SUCCESS;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * e1000_check_for_rst_vf - checks to see if the PF has reset
+ * @hw: pointer to the HW structure
+ *
+ * returns true if the PF has set the reset done bit or else false
+ **/
+ static s32 e1000_check_for_rst_vf(struct e1000_hw *hw)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
+ E1000_V2PMAILBOX_RSTI))) {
+ ret_val = E1000_SUCCESS;
+ hw->mbx.stats.rsts++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * e1000_obtain_mbx_lock_vf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ *
+ * return SUCCESS if we obtained the mailbox lock
+ **/
+ static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
+ {
+ s32 ret_val = -E1000_ERR_MBX;
+
+ /* Take ownership of the buffer */
+ ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
+
+ /* reserve mailbox for vf use */
+ if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
+ ret_val = E1000_SUCCESS;
+
+ return ret_val;
+ }
+
+ /**
+ * e1000_write_mbx_vf - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+ static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
+ {
+ s32 err;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ err = e1000_obtain_mbx_lock_vf(hw);
+ if (err)
+ goto out_no_write;
+
+ /* flush any ack or msg as we are going to overwrite mailbox */
+ e1000_check_for_ack_vf(hw);
+ e1000_check_for_msg_vf(hw);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ array_ew32(VMBMEM(0), i, msg[i]);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+ /* Drop VFU and interrupt the PF to tell it a message has been sent */
+ ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
+
+ out_no_write:
+ return err;
+ }
+
+ /**
+ * e1000_read_mbx_vf - Reads a message from the inbox intended for vf
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
++ * returns SUCCESS if it successfully read message from buffer
+ **/
+ static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
+ {
+ s32 err;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ err = e1000_obtain_mbx_lock_vf(hw);
+ if (err)
+ goto out_no_read;
+
+ /* copy the message from the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = array_er32(VMBMEM(0), i);
+
+ /* Acknowledge receipt and release mailbox, then we're done */
+ ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+ out_no_read:
+ return err;
+ }
+
+ /**
+ * e1000_init_mbx_params_vf - set initial values for vf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+ s32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
+ {
+ struct e1000_mbx_info *mbx = &hw->mbx;
+
+ /* start mailbox as timed out and let the reset_hw call set the timeout
+ * value to being communications */
+ mbx->timeout = 0;
+ mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
+
+ mbx->size = E1000_VFMAILBOX_SIZE;
+
+ mbx->ops.read = e1000_read_mbx_vf;
+ mbx->ops.write = e1000_write_mbx_vf;
+ mbx->ops.read_posted = e1000_read_posted_mbx;
+ mbx->ops.write_posted = e1000_write_posted_mbx;
+ mbx->ops.check_for_msg = e1000_check_for_msg_vf;
+ mbx->ops.check_for_ack = e1000_check_for_ack_vf;
+ mbx->ops.check_for_rst = e1000_check_for_rst_vf;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+
+ return E1000_SUCCESS;
+ }
+
--- /dev/null
- * returns SUCCESS if it successfuly read message from buffer
+ /*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2011 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+ *******************************************************************************/
+
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include "ixgbe_type.h"
+ #include "ixgbe_common.h"
+ #include "ixgbe_mbx.h"
+
+ /**
+ * ixgbe_read_mbx - Reads a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
++ * returns SUCCESS if it successfully read message from buffer
+ **/
+ s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ /* limit read to size of mailbox */
+ if (size > mbx->size)
+ size = mbx->size;
+
+ if (mbx->ops.read)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_write_mbx - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+ s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = 0;
+
+ if (size > mbx->size)
+ ret_val = IXGBE_ERR_MBX;
+
+ else if (mbx->ops.write)
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_check_for_msg - checks to see if someone sent us mail
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+ s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (mbx->ops.check_for_msg)
+ ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_check_for_ack - checks to see if someone sent us ACK
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+ s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (mbx->ops.check_for_ack)
+ ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_check_for_rst - checks to see if other side has reset
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+ s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (mbx->ops.check_for_rst)
+ ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_poll_for_msg - Wait for message notification
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification
+ **/
+ static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ if (!countdown || !mbx->ops.check_for_msg)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ udelay(mbx->usec_delay);
+ }
+
+ out:
+ return countdown ? 0 : IXGBE_ERR_MBX;
+ }
+
+ /**
+ * ixgbe_poll_for_ack - Wait for message acknowledgement
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message acknowledgement
+ **/
+ static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ if (!countdown || !mbx->ops.check_for_ack)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ udelay(mbx->usec_delay);
+ }
+
+ out:
+ return countdown ? 0 : IXGBE_ERR_MBX;
+ }
+
+ /**
+ * ixgbe_read_posted_mbx - Wait for message notification and receive message
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification and
+ * copied it into the receive buffer.
+ **/
+ static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (!mbx->ops.read)
+ goto out;
+
+ ret_val = ixgbe_poll_for_msg(hw, mbx_id);
+
+ /* if ack received read message, otherwise we timed out */
+ if (!ret_val)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+ out:
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer and
+ * received an ack to that message within delay * timeout period
+ **/
+ static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ /* exit if either we can't write or there isn't a defined timeout */
+ if (!mbx->ops.write || !mbx->timeout)
+ goto out;
+
+ /* send msg */
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ /* if msg sent wait until we receive an ack */
+ if (!ret_val)
+ ret_val = ixgbe_poll_for_ack(hw, mbx_id);
+ out:
+ return ret_val;
+ }
+
+ static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
+ {
+ u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (mbvficr & mask) {
+ ret_val = 0;
+ IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+ static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+ s32 index = IXGBE_MBVFICR_INDEX(vf_number);
+ u32 vf_bit = vf_number % 16;
+
+ if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
+ index)) {
+ ret_val = 0;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+ static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+ s32 index = IXGBE_MBVFICR_INDEX(vf_number);
+ u32 vf_bit = vf_number % 16;
+
+ if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
+ index)) {
+ ret_val = 0;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_check_for_rst_pf - checks to see if the VF has reset
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
+ {
+ u32 reg_offset = (vf_number < 32) ? 0 : 1;
+ u32 vf_shift = vf_number % 32;
+ u32 vflre = 0;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
+ break;
+ case ixgbe_mac_X540:
+ vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
+ break;
+ default:
+ break;
+ }
+
+ if (vflre & (1 << vf_shift)) {
+ ret_val = 0;
+ IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
+ hw->mbx.stats.rsts++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * return SUCCESS if we obtained the mailbox lock
+ **/
+ static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+ u32 p2v_mailbox;
+
+ /* Take ownership of the buffer */
+ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
+
+ /* reserve mailbox for vf use */
+ p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
+ if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
+ ret_val = 0;
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbe_write_mbx_pf - Places a message in the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+ static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
+ u16 vf_number)
+ {
+ s32 ret_val;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
+ if (ret_val)
+ goto out_no_write;
+
+ /* flush msg and acks as we are overwriting the message buffer */
+ ixgbe_check_for_msg_pf(hw, vf_number);
+ ixgbe_check_for_ack_pf(hw, vf_number);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
+
+ /* Interrupt VF to tell it a message has been sent and release buffer*/
+ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+ out_no_write:
+ return ret_val;
+
+ }
+
+ /**
+ * ixgbe_read_mbx_pf - Read a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_number: the VF index
+ *
+ * This function copies a message from the mailbox buffer to the caller's
+ * memory buffer. The presumption is that the caller knows that there was
+ * a message due to a VF request so no polling for message is needed.
+ **/
+ static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
+ u16 vf_number)
+ {
+ s32 ret_val;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
+ if (ret_val)
+ goto out_no_read;
+
+ /* copy the message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
+
+ /* Acknowledge the message and release buffer */
+ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+ out_no_read:
+ return ret_val;
+ }
+
+ #ifdef CONFIG_PCI_IOV
+ /**
+ * ixgbe_init_mbx_params_pf - set initial values for pf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for pf mailbox
+ */
+ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+ if (hw->mac.type != ixgbe_mac_82599EB &&
+ hw->mac.type != ixgbe_mac_X540)
+ return;
+
+ mbx->timeout = 0;
+ mbx->usec_delay = 0;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+
+ mbx->size = IXGBE_VFMAILBOX_SIZE;
+ }
+ #endif /* CONFIG_PCI_IOV */
+
+ struct ixgbe_mbx_operations mbx_ops_generic = {
+ .read = ixgbe_read_mbx_pf,
+ .write = ixgbe_write_mbx_pf,
+ .read_posted = ixgbe_read_posted_mbx,
+ .write_posted = ixgbe_write_posted_mbx,
+ .check_for_msg = ixgbe_check_for_msg_pf,
+ .check_for_ack = ixgbe_check_for_ack_pf,
+ .check_for_rst = ixgbe_check_for_rst_pf,
+ };
+
--- /dev/null
- * returns 0 if it successfuly read message from buffer
+ /*******************************************************************************
+
+ Intel 82599 Virtual Function driver
+ Copyright(c) 1999 - 2010 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+ *******************************************************************************/
+
+ #include "mbx.h"
+
+ /**
+ * ixgbevf_poll_for_msg - Wait for message notification
+ * @hw: pointer to the HW structure
+ *
+ * returns 0 if it successfully received a message notification
+ **/
+ static s32 ixgbevf_poll_for_msg(struct ixgbe_hw *hw)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ while (countdown && mbx->ops.check_for_msg(hw)) {
+ countdown--;
+ udelay(mbx->udelay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+
+ return countdown ? 0 : IXGBE_ERR_MBX;
+ }
+
+ /**
+ * ixgbevf_poll_for_ack - Wait for message acknowledgement
+ * @hw: pointer to the HW structure
+ *
+ * returns 0 if it successfully received a message acknowledgement
+ **/
+ static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ while (countdown && mbx->ops.check_for_ack(hw)) {
+ countdown--;
+ udelay(mbx->udelay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+
+ return countdown ? 0 : IXGBE_ERR_MBX;
+ }
+
+ /**
+ * ixgbevf_read_posted_mbx - Wait for message notification and receive message
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
+ * returns 0 if it successfully received a message notification and
+ * copied it into the receive buffer.
+ **/
+ static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ ret_val = ixgbevf_poll_for_msg(hw);
+
+ /* if ack received read message, otherwise we timed out */
+ if (!ret_val)
+ ret_val = mbx->ops.read(hw, msg, size);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_write_posted_mbx - Write a message to the mailbox, wait for ack
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
+ * returns 0 if it successfully copied message into the buffer and
+ * received an ack to that message within delay * timeout period
+ **/
+ static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ s32 ret_val;
+
+ /* send msg */
+ ret_val = mbx->ops.write(hw, msg, size);
+
+ /* if msg sent wait until we receive an ack */
+ if (!ret_val)
+ ret_val = ixgbevf_poll_for_ack(hw);
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_read_v2p_mailbox - read v2p mailbox
+ * @hw: pointer to the HW structure
+ *
+ * This function is used to read the v2p mailbox without losing the read to
+ * clear status bits.
+ **/
+ static u32 ixgbevf_read_v2p_mailbox(struct ixgbe_hw *hw)
+ {
+ u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
+
+ v2p_mailbox |= hw->mbx.v2p_mailbox;
+ hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
+
+ return v2p_mailbox;
+ }
+
+ /**
+ * ixgbevf_check_for_bit_vf - Determine if a status bit was set
+ * @hw: pointer to the HW structure
+ * @mask: bitmask for bits to be tested and cleared
+ *
+ * This function is used to check for the read to clear bits within
+ * the V2P mailbox.
+ **/
+ static s32 ixgbevf_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask)
+ {
+ u32 v2p_mailbox = ixgbevf_read_v2p_mailbox(hw);
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (v2p_mailbox & mask)
+ ret_val = 0;
+
+ hw->mbx.v2p_mailbox &= ~mask;
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail
+ * @hw: pointer to the HW structure
+ *
+ * returns 0 if the PF has set the Status bit or else ERR_MBX
+ **/
+ static s32 ixgbevf_check_for_msg_vf(struct ixgbe_hw *hw)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) {
+ ret_val = 0;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd
+ * @hw: pointer to the HW structure
+ *
+ * returns 0 if the PF has set the ACK bit or else ERR_MBX
+ **/
+ static s32 ixgbevf_check_for_ack_vf(struct ixgbe_hw *hw)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) {
+ ret_val = 0;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_check_for_rst_vf - checks to see if the PF has reset
+ * @hw: pointer to the HW structure
+ *
+ * returns true if the PF has set the reset done bit or else false
+ **/
+ static s32 ixgbevf_check_for_rst_vf(struct ixgbe_hw *hw)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ if (!ixgbevf_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD |
+ IXGBE_VFMAILBOX_RSTI))) {
+ ret_val = 0;
+ hw->mbx.stats.rsts++;
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ *
+ * return 0 if we obtained the mailbox lock
+ **/
+ static s32 ixgbevf_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
+ {
+ s32 ret_val = IXGBE_ERR_MBX;
+
+ /* Take ownership of the buffer */
+ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU);
+
+ /* reserve mailbox for vf use */
+ if (ixgbevf_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU)
+ ret_val = 0;
+
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_write_mbx_vf - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
+ * returns 0 if it successfully copied message into the buffer
+ **/
+ static s32 ixgbevf_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size)
+ {
+ s32 ret_val;
+ u16 i;
+
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbevf_obtain_mbx_lock_vf(hw);
+ if (ret_val)
+ goto out_no_write;
+
+ /* flush msg and acks as we are overwriting the message buffer */
+ ixgbevf_check_for_msg_vf(hw);
+ ixgbevf_check_for_ack_vf(hw);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+ /* Drop VFU and interrupt the PF to tell it a message has been sent */
+ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
+
+ out_no_write:
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_read_mbx_vf - Reads a message from the inbox intended for vf
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ *
++ * returns 0 if it successfully read message from buffer
+ **/
+ static s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size)
+ {
+ s32 ret_val = 0;
+ u16 i;
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbevf_obtain_mbx_lock_vf(hw);
+ if (ret_val)
+ goto out_no_read;
+
+ /* copy the message from the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i);
+
+ /* Acknowledge receipt and release mailbox, then we're done */
+ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+ out_no_read:
+ return ret_val;
+ }
+
+ /**
+ * ixgbevf_init_mbx_params_vf - set initial values for vf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+ static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
+ {
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+ /* start mailbox as timed out and let the reset_hw call set the timeout
+ * value to begin communications */
+ mbx->timeout = 0;
+ mbx->udelay = IXGBE_VF_MBX_INIT_DELAY;
+
+ mbx->size = IXGBE_VFMAILBOX_SIZE;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+
+ return 0;
+ }
+
+ struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
+ .init_params = ixgbevf_init_mbx_params_vf,
+ .read = ixgbevf_read_mbx_vf,
+ .write = ixgbevf_write_mbx_vf,
+ .read_posted = ixgbevf_read_posted_mbx,
+ .write_posted = ixgbevf_write_posted_mbx,
+ .check_for_msg = ixgbevf_check_for_msg_vf,
+ .check_for_ack = ixgbevf_check_for_ack_vf,
+ .check_for_rst = ixgbevf_check_for_rst_vf,
+ };
+
--- /dev/null
- /* Force any delayed status interrrupt and NAPI */
+ /*
+ * New driver for Marvell Yukon 2 chipset.
+ * Based on earlier sk98lin, and skge driver.
+ *
+ * This driver intentionally does not support all the features
+ * of the original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+ #include <linux/crc32.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/etherdevice.h>
+ #include <linux/ethtool.h>
+ #include <linux/pci.h>
+ #include <linux/interrupt.h>
+ #include <linux/ip.h>
+ #include <linux/slab.h>
+ #include <net/ip.h>
+ #include <linux/tcp.h>
+ #include <linux/in.h>
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/if_vlan.h>
+ #include <linux/prefetch.h>
+ #include <linux/debugfs.h>
+ #include <linux/mii.h>
+
+ #include <asm/irq.h>
+
+ #include "sky2.h"
+
+ #define DRV_NAME "sky2"
+ #define DRV_VERSION "1.29"
+
+ /*
+ * The Yukon II chipset takes 64 bit command blocks (called list elements)
+ * that are organized into three (receive, transmit, status) different rings
+ * similar to Tigon3.
+ */
+
+ #define RX_LE_SIZE 1024
+ #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
+ #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2)
+ #define RX_DEF_PENDING RX_MAX_PENDING
+
+ /* This is the worst case number of transmit list elements for a single skb:
+ VLAN:GSO + CKSUM + Data + skb_frags * DMA */
+ #define MAX_SKB_TX_LE (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1))
+ #define TX_MIN_PENDING (MAX_SKB_TX_LE+1)
+ #define TX_MAX_PENDING 1024
+ #define TX_DEF_PENDING 127
+
+ #define TX_WATCHDOG (5 * HZ)
+ #define NAPI_WEIGHT 64
+ #define PHY_RETRIES 1000
+
+ #define SKY2_EEPROM_MAGIC 0x9955aabb
+
+ #define RING_NEXT(x, s) (((x)+1) & ((s)-1))
+
+ static const u32 default_msg =
+ NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+ | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
+ | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+
+ static int debug = -1; /* defaults above */
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+ static int copybreak __read_mostly = 128;
+ module_param(copybreak, int, 0);
+ MODULE_PARM_DESC(copybreak, "Receive copy threshold");
+
+ static int disable_msi = 0;
+ module_param(disable_msi, int, 0);
+ MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+
+ static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E01) }, /* SK-9E21M */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B03) }, /* DGE-550T */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) }, /* 88E8062 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) }, /* 88E8021 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) }, /* 88E8022 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) }, /* 88E8061 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) }, /* 88E8062 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, /* 88E8035 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4355) }, /* 88E8040T */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */
+ { 0 }
+ };
+
+ MODULE_DEVICE_TABLE(pci, sky2_id_table);
+
+ /* Avoid conditionals by using array */
+ static const unsigned txqaddr[] = { Q_XA1, Q_XA2 };
+ static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
+ static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 };
+
+ static void sky2_set_multicast(struct net_device *dev);
+ static irqreturn_t sky2_intr(int irq, void *dev_id);
+
+ /* Access to PHY via serial interconnect */
+ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
+ {
+ int i;
+
+ gma_write16(hw, port, GM_SMI_DATA, val);
+ gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg));
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (!(ctrl & GM_SMI_CT_BUSY))
+ return 0;
+
+ udelay(10);
+ }
+
+ dev_warn(&hw->pdev->dev, "%s: phy write timeout\n", hw->dev[port]->name);
+ return -ETIMEDOUT;
+
+ io_error:
+ dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
+ }
+
+ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
+ {
+ int i;
+
+ gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(PHY_ADDR_MARV)
+ | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (ctrl & GM_SMI_CT_RD_VAL) {
+ *val = gma_read16(hw, port, GM_SMI_DATA);
+ return 0;
+ }
+
+ udelay(10);
+ }
+
+ dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name);
+ return -ETIMEDOUT;
+ io_error:
+ dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
+ }
+
+ static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
+ {
+ u16 v;
+ __gm_phy_read(hw, port, reg, &v);
+ return v;
+ }
+
+
+ static void sky2_power_on(struct sky2_hw *hw)
+ {
+ /* switch power to VCC (WA for VAUX problem) */
+ sky2_write8(hw, B0_POWER_CTRL,
+ PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+
+ /* disable Core Clock Division, */
+ sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > CHIP_REV_YU_XL_A1)
+ /* enable bits are inverted */
+ sky2_write8(hw, B2_Y2_CLK_GATE,
+ Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+ else
+ sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+
+ if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
+ u32 reg;
+
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+ /* set all bits to 0 except bits 15..12 and 8 */
+ reg &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+ /* set all bits to 0 except bits 28 & 27 */
+ reg &= P_CTL_TIM_VMAIN_AV_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+ sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+ sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
+
+ /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+ reg = sky2_read32(hw, B2_GP_IO);
+ reg |= GLB_GPIO_STAT_RACE_DIS;
+ sky2_write32(hw, B2_GP_IO, reg);
+
+ sky2_read32(hw, B2_GP_IO);
+ }
+
+ /* Turn on "driver loaded" LED */
+ sky2_write16(hw, B0_CTST, Y2_LED_STAT_ON);
+ }
+
+ static void sky2_power_aux(struct sky2_hw *hw)
+ {
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > CHIP_REV_YU_XL_A1)
+ sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+ else
+ /* enable bits are inverted */
+ sky2_write8(hw, B2_Y2_CLK_GATE,
+ Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+
+ /* switch power to VAUX if supported and PME from D3cold */
+ if ( (sky2_read32(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+ pci_pme_capable(hw->pdev, PCI_D3cold))
+ sky2_write8(hw, B0_POWER_CTRL,
+ (PC_VAUX_ENA | PC_VCC_ENA |
+ PC_VAUX_ON | PC_VCC_OFF));
+
+ /* turn off "driver loaded LED" */
+ sky2_write16(hw, B0_CTST, Y2_LED_STAT_OFF);
+ }
+
+ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
+ {
+ u16 reg;
+
+ /* disable all GMAC IRQ's */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
+ gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
+ gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+ reg = gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA;
+ gma_write16(hw, port, GM_RX_CTRL, reg);
+ }
+
+ /* flow control to advertise bits */
+ static const u16 copper_fc_adv[] = {
+ [FC_NONE] = 0,
+ [FC_TX] = PHY_M_AN_ASP,
+ [FC_RX] = PHY_M_AN_PC,
+ [FC_BOTH] = PHY_M_AN_PC | PHY_M_AN_ASP,
+ };
+
+ /* flow control to advertise bits when using 1000BaseX */
+ static const u16 fiber_fc_adv[] = {
+ [FC_NONE] = PHY_M_P_NO_PAUSE_X,
+ [FC_TX] = PHY_M_P_ASYM_MD_X,
+ [FC_RX] = PHY_M_P_SYM_MD_X,
+ [FC_BOTH] = PHY_M_P_BOTH_MD_X,
+ };
+
+ /* flow control to GMA disable bits */
+ static const u16 gm_fc_disable[] = {
+ [FC_NONE] = GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS,
+ [FC_TX] = GM_GPCR_FC_RX_DIS,
+ [FC_RX] = GM_GPCR_FC_TX_DIS,
+ [FC_BOTH] = 0,
+ };
+
+
+ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
+ {
+ struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+ u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
+
+ if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED) &&
+ !(hw->flags & SKY2_HW_NEWER_PHY)) {
+ u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+ ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+ PHY_M_EC_MAC_S_MSK);
+ ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+ /* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */
+ if (hw->chip_id == CHIP_ID_YUKON_EC)
+ /* set downshift counter to 3x and enable downshift */
+ ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
+ else
+ /* set master & slave downshift counter to 1x */
+ ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+ }
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ if (sky2_is_copper(hw)) {
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
+ /* enable automatic crossover */
+ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ u16 spec;
+
+ /* Enable Class A driver for FE+ A0 */
+ spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2);
+ spec |= PHY_M_FESC_SEL_CL_A;
+ gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec);
+ }
+ } else {
+ if (hw->chip_id >= CHIP_ID_YUKON_OPT) {
+ u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2);
+
+ /* enable PHY Reverse Auto-Negotiation */
+ ctrl2 |= 1u << 13;
+
+ /* Write PHY changes (SW-reset must follow) */
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2);
+ }
+
+
+ /* disable energy detect */
+ ctrl &= ~PHY_M_PC_EN_DET_MSK;
+
+ /* enable automatic crossover */
+ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
+
+ /* downshift on PHY 88E1112 and 88E1149 is changed */
+ if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED) &&
+ (hw->flags & SKY2_HW_NEWER_PHY)) {
+ /* set downshift counter to 3x and enable downshift */
+ ctrl &= ~PHY_M_PC_DSC_MSK;
+ ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
+ }
+ }
+ } else {
+ /* workaround for deviation #4.88 (CRC errors) */
+ /* disable Automatic Crossover */
+
+ ctrl &= ~PHY_M_PC_MDIX_MSK;
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* special setup for PHY 88E1112 Fiber */
+ if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl &= ~PHY_M_MAC_MD_MSK;
+ ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ if (hw->pmd_type == 'P') {
+ /* select page 1 to access Fiber registers */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1);
+
+ /* for SFP-module set SIGDET polarity to low */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl |= PHY_M_FIB_SIGD_POL;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ }
+
+ ctrl = PHY_CT_RESET;
+ ct1000 = 0;
+ adv = PHY_AN_CSMA;
+ reg = 0;
+
+ if (sky2->flags & SKY2_FLAG_AUTO_SPEED) {
+ if (sky2_is_copper(hw)) {
+ if (sky2->advertising & ADVERTISED_1000baseT_Full)
+ ct1000 |= PHY_M_1000C_AFD;
+ if (sky2->advertising & ADVERTISED_1000baseT_Half)
+ ct1000 |= PHY_M_1000C_AHD;
+ if (sky2->advertising & ADVERTISED_100baseT_Full)
+ adv |= PHY_M_AN_100_FD;
+ if (sky2->advertising & ADVERTISED_100baseT_Half)
+ adv |= PHY_M_AN_100_HD;
+ if (sky2->advertising & ADVERTISED_10baseT_Full)
+ adv |= PHY_M_AN_10_FD;
+ if (sky2->advertising & ADVERTISED_10baseT_Half)
+ adv |= PHY_M_AN_10_HD;
+
+ } else { /* special defines for FIBER (88E1040S only) */
+ if (sky2->advertising & ADVERTISED_1000baseT_Full)
+ adv |= PHY_M_AN_1000X_AFD;
+ if (sky2->advertising & ADVERTISED_1000baseT_Half)
+ adv |= PHY_M_AN_1000X_AHD;
+ }
+
+ /* Restart Auto-negotiation */
+ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ /* forced speed/duplex settings */
+ ct1000 = PHY_M_1000C_MSE;
+
+ /* Disable auto update for duplex flow control and duplex */
+ reg |= GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_SPD_DIS;
+
+ switch (sky2->speed) {
+ case SPEED_1000:
+ ctrl |= PHY_CT_SP1000;
+ reg |= GM_GPCR_SPEED_1000;
+ break;
+ case SPEED_100:
+ ctrl |= PHY_CT_SP100;
+ reg |= GM_GPCR_SPEED_100;
+ break;
+ }
+
+ if (sky2->duplex == DUPLEX_FULL) {
+ reg |= GM_GPCR_DUP_FULL;
+ ctrl |= PHY_CT_DUP_MD;
+ } else if (sky2->speed < SPEED_1000)
+ sky2->flow_mode = FC_NONE;
+ }
+
+ if (sky2->flags & SKY2_FLAG_AUTO_PAUSE) {
+ if (sky2_is_copper(hw))
+ adv |= copper_fc_adv[sky2->flow_mode];
+ else
+ adv |= fiber_fc_adv[sky2->flow_mode];
+ } else {
+ reg |= GM_GPCR_AU_FCT_DIS;
+ reg |= gm_fc_disable[sky2->flow_mode];
+
+ /* Forward pause packets to GMAC? */
+ if (sky2->flow_mode & FC_RX)
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ else
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ }
+
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ if (hw->flags & SKY2_HW_GIGABIT)
+ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ /* Setup Phy LED's */
+ ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+ ledover = 0;
+
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_FE:
+ /* on 88E3082 these bits are at 11..9 (shifted left) */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR);
+
+ /* delete ACT LED control bits */
+ ctrl &= ~PHY_M_FELP_LED1_MSK;
+ /* change ACT LED control to blink mode */
+ ctrl |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL);
+ gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+ break;
+
+ case CHIP_ID_YUKON_FE_P:
+ /* Enable Link Partner Next Page */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl |= PHY_M_PC_ENA_LIP_NP;
+
+ /* disable Energy Detect and enable scrambler */
+ ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
+ ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
+ PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) |
+ PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED);
+
+ gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+ break;
+
+ case CHIP_ID_YUKON_XL:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* select page 3 to access LED control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ /* set LED Function Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
+
+ /* set Polarity Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
+ (PHY_M_POLC_LS1_P_MIX(4) |
+ PHY_M_POLC_IS0_P_MIX(4) |
+ PHY_M_POLC_LOS_CTRL(2) |
+ PHY_M_POLC_INIT_CTRL(2) |
+ PHY_M_POLC_STA1_CTRL(2) |
+ PHY_M_POLC_STA0_CTRL(2)));
+
+ /* restore page register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ case CHIP_ID_YUKON_EX:
+ case CHIP_ID_YUKON_SUPR:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* select page 3 to access LED control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ /* set LED Function Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */
+
+ /* set Blink Rate in LED Timer Control Register */
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK,
+ ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS));
+ /* restore page register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
+
+ default:
+ /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+
+ /* turn off the Rx LED (LED_RX) */
+ ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+ }
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_UL_2) {
+ /* apply fixes in PHY AFE */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
+
+ /* increase differential signal amplitude in 10BASE-T */
+ gm_phy_write(hw, port, 0x18, 0xaa99);
+ gm_phy_write(hw, port, 0x17, 0x2011);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ /* fix for IEEE A/B Symmetry failure in 1000BASE-T */
+ gm_phy_write(hw, port, 0x18, 0xa204);
+ gm_phy_write(hw, port, 0x17, 0x2002);
+ }
+
+ /* set page register to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ } else if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ /* apply workaround for integrated resistors calibration */
+ gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17);
+ gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60);
+ } else if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
+ /* apply fixes in PHY AFE */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff);
+
+ /* apply RDAC termination workaround */
+ gm_phy_write(hw, port, 24, 0x2800);
+ gm_phy_write(hw, port, 23, 0x2001);
+
+ /* set page register back to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ } else if (hw->chip_id != CHIP_ID_YUKON_EX &&
+ hw->chip_id < CHIP_ID_YUKON_SUPR) {
+ /* no effect on Yukon-XL */
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+ if (!(sky2->flags & SKY2_FLAG_AUTO_SPEED) ||
+ sky2->speed == SPEED_100) {
+ /* turn on 100 Mbps LED (LED_LINK100) */
+ ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+
+ if (ledover)
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+
+ } else if (hw->chip_id == CHIP_ID_YUKON_PRM &&
+ (sky2_read8(hw, B2_MAC_CFG) & 0xf) == 0x7) {
+ int i;
+ /* This a phy register setup workaround copied from vendor driver. */
+ static const struct {
+ u16 reg, val;
+ } eee_afe[] = {
+ { 0x156, 0x58ce },
+ { 0x153, 0x99eb },
+ { 0x141, 0x8064 },
+ /* { 0x155, 0x130b },*/
+ { 0x000, 0x0000 },
+ { 0x151, 0x8433 },
+ { 0x14b, 0x8c44 },
+ { 0x14c, 0x0f90 },
+ { 0x14f, 0x39aa },
+ /* { 0x154, 0x2f39 },*/
+ { 0x14d, 0xba33 },
+ { 0x144, 0x0048 },
+ { 0x152, 0x2010 },
+ /* { 0x158, 0x1223 },*/
+ { 0x140, 0x4444 },
+ { 0x154, 0x2f3b },
+ { 0x158, 0xb203 },
+ { 0x157, 0x2029 },
+ };
+
+ /* Start Workaround for OptimaEEE Rev.Z0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fb);
+
+ gm_phy_write(hw, port, 1, 0x4099);
+ gm_phy_write(hw, port, 3, 0x1120);
+ gm_phy_write(hw, port, 11, 0x113c);
+ gm_phy_write(hw, port, 14, 0x8100);
+ gm_phy_write(hw, port, 15, 0x112a);
+ gm_phy_write(hw, port, 17, 0x1008);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fc);
+ gm_phy_write(hw, port, 1, 0x20b0);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff);
+
+ for (i = 0; i < ARRAY_SIZE(eee_afe); i++) {
+ /* apply AFE settings */
+ gm_phy_write(hw, port, 17, eee_afe[i].val);
+ gm_phy_write(hw, port, 16, eee_afe[i].reg | 1u<<13);
+ }
+
+ /* End Workaround for OptimaEEE */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+
+ /* Enable 10Base-Te (EEE) */
+ if (hw->chip_id >= CHIP_ID_YUKON_PRM) {
+ reg = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL,
+ reg | PHY_M_10B_TE_ENABLE);
+ }
+ }
+
+ /* Enable phy interrupt on auto-negotiation complete (or link up) */
+ if (sky2->flags & SKY2_FLAG_AUTO_SPEED)
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ else
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ }
+
+ static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
+ static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
+
+ static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port)
+ {
+ u32 reg1;
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ reg1 &= ~phy_power[port];
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > CHIP_REV_YU_XL_A1)
+ reg1 |= coma_mode[port];
+
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ sky2_pci_read32(hw, PCI_DEV_REG1);
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_ANE);
+ else if (hw->flags & SKY2_HW_ADV_POWER_CTL)
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+ }
+
+ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
+ {
+ u32 reg1;
+ u16 ctrl;
+
+ /* release GPHY Control reset */
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+
+ /* release GMAC reset */
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ if (hw->flags & SKY2_HW_NEWER_PHY) {
+ /* select page 2 to access MAC control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ /* allow GMII Power Down */
+ ctrl &= ~PHY_M_MAC_GMIF_PUP;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set page register back to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ }
+
+ /* setup General Purpose Control Register */
+ gma_write16(hw, port, GM_GP_CTRL,
+ GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 |
+ GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |
+ GM_GPCR_AU_SPD_DIS);
+
+ if (hw->chip_id != CHIP_ID_YUKON_EC) {
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ /* select page 2 to access MAC control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ /* enable Power Down */
+ ctrl |= PHY_M_PC_POW_D_ENA;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set page register back to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ }
+
+ /* set IEEE compatible Power Down Mode (dev. #4.99) */
+ gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN);
+ }
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ reg1 |= phy_power[port]; /* set PHY to PowerDown/COMA Mode */
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ }
+
+ /* configure IPG according to used link speed */
+ static void sky2_set_ipg(struct sky2_port *sky2)
+ {
+ u16 reg;
+
+ reg = gma_read16(sky2->hw, sky2->port, GM_SERIAL_MODE);
+ reg &= ~GM_SMOD_IPG_MSK;
+ if (sky2->speed > SPEED_100)
+ reg |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
+ else
+ reg |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);
+ gma_write16(sky2->hw, sky2->port, GM_SERIAL_MODE, reg);
+ }
+
+ /* Enable Rx/Tx */
+ static void sky2_enable_rx_tx(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ }
+
+ /* Force a renegotiation */
+ static void sky2_phy_reinit(struct sky2_port *sky2)
+ {
+ spin_lock_bh(&sky2->phy_lock);
+ sky2_phy_init(sky2->hw, sky2->port);
+ sky2_enable_rx_tx(sky2);
+ spin_unlock_bh(&sky2->phy_lock);
+ }
+
+ /* Put device in state to listen for Wake On Lan */
+ static void sky2_wol_init(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ enum flow_control save_mode;
+ u16 ctrl;
+
+ /* Bring hardware out of reset */
+ sky2_write16(hw, B0_CTST, CS_RST_CLR);
+ sky2_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ /* Force to 10/100
+ * sky2_reset will re-enable on resume
+ */
+ save_mode = sky2->flow_mode;
+ ctrl = sky2->advertising;
+
+ sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full);
+ sky2->flow_mode = FC_NONE;
+
+ spin_lock_bh(&sky2->phy_lock);
+ sky2_phy_power_up(hw, port);
+ sky2_phy_init(hw, port);
+ spin_unlock_bh(&sky2->phy_lock);
+
+ sky2->flow_mode = save_mode;
+ sky2->advertising = ctrl;
+
+ /* Set GMAC to no flow control and auto update for speed/duplex */
+ gma_write16(hw, port, GM_GP_CTRL,
+ GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA|
+ GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS);
+
+ /* Set WOL address */
+ memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR),
+ sky2->netdev->dev_addr, ETH_ALEN);
+
+ /* Turn on appropriate WOL control bits */
+ sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT);
+ ctrl = 0;
+ if (sky2->wol & WAKE_PHY)
+ ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT;
+ else
+ ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT;
+
+ if (sky2->wol & WAKE_MAGIC)
+ ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT;
+ else
+ ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;
+
+ ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT;
+ sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl);
+
+ /* Disable PiG firmware */
+ sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF);
+
+ /* block receiver */
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+ }
+
+ static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+ {
+ struct net_device *dev = hw->dev[port];
+
+ if ( (hw->chip_id == CHIP_ID_YUKON_EX &&
+ hw->chip_rev != CHIP_REV_YU_EX_A0) ||
+ hw->chip_id >= CHIP_ID_YUKON_FE_P) {
+ /* Yukon-Extreme B0 and further Extreme devices */
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA);
+ } else if (dev->mtu > ETH_DATA_LEN) {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+ (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
+ } else
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA);
+ }
+
+ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
+ {
+ struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+ u16 reg;
+ u32 rx_reg;
+ int i;
+ const u8 *addr = hw->dev[port]->dev_addr;
+
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL &&
+ hw->chip_rev == CHIP_REV_YU_XL_A0 &&
+ port == 1) {
+ /* WA DEV_472 -- looks like crossed wires on port 2 */
+ /* clear GMAC 1 Control reset */
+ sky2_write8(hw, SK_REG(0, GMAC_CTRL), GMC_RST_CLR);
+ do {
+ sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_SET);
+ sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_CLR);
+ } while (gm_phy_read(hw, 1, PHY_MARV_ID0) != PHY_MARV_ID0_VAL ||
+ gm_phy_read(hw, 1, PHY_MARV_ID1) != PHY_MARV_ID1_Y2 ||
+ gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0);
+ }
+
+ sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ /* Enable Transmit FIFO Underrun */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
+
+ spin_lock_bh(&sky2->phy_lock);
+ sky2_phy_power_up(hw, port);
+ sky2_phy_init(hw, port);
+ spin_unlock_bh(&sky2->phy_lock);
+
+ /* MIB clear */
+ reg = gma_read16(hw, port, GM_PHY_ADDR);
+ gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+ for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
+ gma_read16(hw, port, i);
+ gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+ /* transmit control */
+ gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+ /* receive control reg: unicast + multicast + no FCS */
+ gma_write16(hw, port, GM_RX_CTRL,
+ GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+ /* transmit flow control */
+ gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+ /* transmit parameter */
+ gma_write16(hw, port, GM_TX_PARAM,
+ TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+ TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+ TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) |
+ TX_BACK_OFF_LIM(TX_BOF_LIM_DEF));
+
+ /* serial mode register */
+ reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
+ GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF_1000);
+
+ if (hw->dev[port]->mtu > ETH_DATA_LEN)
+ reg |= GM_SMOD_JUMBO_ENA;
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+ hw->chip_rev == CHIP_REV_YU_EC_U_B1)
+ reg |= GM_NEW_FLOW_CTRL;
+
+ gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+
+ /* ignore counter overflows */
+ gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+ /* Configure Rx MAC FIFO */
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+ rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
+ rx_reg |= GMF_RX_OVER_ON;
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ /* Hardware errata - clear flush mask */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), 0);
+ } else {
+ /* Flush Rx MAC FIFO on any flow control or error */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
+ }
+
+ /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */
+ reg = RX_GMF_FL_THR_DEF + 1;
+ /* Another magic mystery workaround from sk98lin */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ reg = 0x178;
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg);
+
+ /* Configure Tx MAC FIFO */
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+ sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+
+ /* On chips without ram buffer, pause is controlled by MAC level */
+ if (!(hw->flags & SKY2_HW_RAM_BUFFER)) {
+ /* Pause threshold is scaled by 8 in bytes */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ reg = 1568 / 8;
+ else
+ reg = 1024 / 8;
+ sky2_write16(hw, SK_REG(port, RX_GMF_UP_THR), reg);
+ sky2_write16(hw, SK_REG(port, RX_GMF_LP_THR), 768 / 8);
+
+ sky2_set_tx_stfwd(hw, port);
+ }
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ /* disable dynamic watermark */
+ reg = sky2_read16(hw, SK_REG(port, TX_GMF_EA));
+ reg &= ~TX_DYN_WM_ENA;
+ sky2_write16(hw, SK_REG(port, TX_GMF_EA), reg);
+ }
+ }
+
+ /* Assign Ram Buffer allocation to queue */
+ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
+ {
+ u32 end;
+
+ /* convert from K bytes to qwords used for hw register */
+ start *= 1024/8;
+ space *= 1024/8;
+ end = start + space - 1;
+
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+ sky2_write32(hw, RB_ADDR(q, RB_START), start);
+ sky2_write32(hw, RB_ADDR(q, RB_END), end);
+ sky2_write32(hw, RB_ADDR(q, RB_WP), start);
+ sky2_write32(hw, RB_ADDR(q, RB_RP), start);
+
+ if (q == Q_R1 || q == Q_R2) {
+ u32 tp = space - space/4;
+
+ /* On receive queue's set the thresholds
+ * give receiver priority when > 3/4 full
+ * send pause when down to 2K
+ */
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
+
+ tp = space - 2048/8;
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
+ } else {
+ /* Enable store & forward on Tx queue's because
+ * Tx FIFO is only 1K on Yukon
+ */
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+ }
+
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+ sky2_read8(hw, RB_ADDR(q, RB_CTRL));
+ }
+
+ /* Setup Bus Memory Interface */
+ static void sky2_qset(struct sky2_hw *hw, u16 q)
+ {
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_RESET);
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_OPER_INIT);
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_FIFO_OP_ON);
+ sky2_write32(hw, Q_ADDR(q, Q_WM), BMU_WM_DEFAULT);
+ }
+
+ /* Setup prefetch unit registers. This is the interface between
+ * hardware and driver list elements
+ */
+ static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr,
+ dma_addr_t addr, u32 last)
+ {
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_CLR);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_HI), upper_32_bits(addr));
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_LO), lower_32_bits(addr));
+ sky2_write16(hw, Y2_QADDR(qaddr, PREF_UNIT_LAST_IDX), last);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_OP_ON);
+
+ sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL));
+ }
+
+ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot)
+ {
+ struct sky2_tx_le *le = sky2->tx_le + *slot;
+
+ *slot = RING_NEXT(*slot, sky2->tx_ring_size);
+ le->ctrl = 0;
+ return le;
+ }
+
+ static void tx_init(struct sky2_port *sky2)
+ {
+ struct sky2_tx_le *le;
+
+ sky2->tx_prod = sky2->tx_cons = 0;
+ sky2->tx_tcpsum = 0;
+ sky2->tx_last_mss = 0;
+
+ le = get_tx_le(sky2, &sky2->tx_prod);
+ le->addr = 0;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ sky2->tx_last_upper = 0;
+ }
+
+ /* Update chip's next pointer */
+ static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
+ {
+ /* Make sure write' to descriptors are complete before we tell hardware */
+ wmb();
+ sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
+
+ /* Synchronize I/O on since next processor may write to tail */
+ mmiowb();
+ }
+
+
+ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
+ {
+ struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
+ sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE);
+ le->ctrl = 0;
+ return le;
+ }
+
+ static unsigned sky2_get_rx_threshold(struct sky2_port *sky2)
+ {
+ unsigned size;
+
+ /* Space needed for frame data + headers rounded up */
+ size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
+
+ /* Stopping point for hardware truncation */
+ return (size - 8) / sizeof(u32);
+ }
+
+ static unsigned sky2_get_rx_data_size(struct sky2_port *sky2)
+ {
+ struct rx_ring_info *re;
+ unsigned size;
+
+ /* Space needed for frame data + headers rounded up */
+ size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
+
+ sky2->rx_nfrags = size >> PAGE_SHIFT;
+ BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr));
+
+ /* Compute residue after pages */
+ size -= sky2->rx_nfrags << PAGE_SHIFT;
+
+ /* Optimize to handle small packets and headers */
+ if (size < copybreak)
+ size = copybreak;
+ if (size < ETH_HLEN)
+ size = ETH_HLEN;
+
+ return size;
+ }
+
+ /* Build description to hardware for one receive segment */
+ static void sky2_rx_add(struct sky2_port *sky2, u8 op,
+ dma_addr_t map, unsigned len)
+ {
+ struct sky2_rx_le *le;
+
+ if (sizeof(dma_addr_t) > sizeof(u32)) {
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32(upper_32_bits(map));
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ }
+
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32(lower_32_bits(map));
+ le->length = cpu_to_le16(len);
+ le->opcode = op | HW_OWNER;
+ }
+
+ /* Build description to hardware for one possibly fragmented skb */
+ static void sky2_rx_submit(struct sky2_port *sky2,
+ const struct rx_ring_info *re)
+ {
+ int i;
+
+ sky2_rx_add(sky2, OP_PACKET, re->data_addr, sky2->rx_data_size);
+
+ for (i = 0; i < skb_shinfo(re->skb)->nr_frags; i++)
+ sky2_rx_add(sky2, OP_BUFFER, re->frag_addr[i], PAGE_SIZE);
+ }
+
+
+ static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
+ unsigned size)
+ {
+ struct sk_buff *skb = re->skb;
+ int i;
+
+ re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, re->data_addr))
+ goto mapping_error;
+
+ dma_unmap_len_set(re, data_size, size);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ re->frag_addr[i] = skb_frag_dma_map(&pdev->dev, frag, 0,
+ skb_frag_size(frag),
+ DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(&pdev->dev, re->frag_addr[i]))
+ goto map_page_error;
+ }
+ return 0;
+
+ map_page_error:
+ while (--i >= 0) {
+ pci_unmap_page(pdev, re->frag_addr[i],
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
+ PCI_DMA_FROMDEVICE);
+ }
+
+ pci_unmap_single(pdev, re->data_addr, dma_unmap_len(re, data_size),
+ PCI_DMA_FROMDEVICE);
+
+ mapping_error:
+ if (net_ratelimit())
+ dev_warn(&pdev->dev, "%s: rx mapping error\n",
+ skb->dev->name);
+ return -EIO;
+ }
+
+ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re)
+ {
+ struct sk_buff *skb = re->skb;
+ int i;
+
+ pci_unmap_single(pdev, re->data_addr, dma_unmap_len(re, data_size),
+ PCI_DMA_FROMDEVICE);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+ pci_unmap_page(pdev, re->frag_addr[i],
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
+ PCI_DMA_FROMDEVICE);
+ }
+
+ /* Tell chip where to start receive checksum.
+ * Actually has two checksums, but set both same to avoid possible byte
+ * order problems.
+ */
+ static void rx_set_checksum(struct sky2_port *sky2)
+ {
+ struct sky2_rx_le *le = sky2_next_rx(sky2);
+
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
+
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ (sky2->netdev->features & NETIF_F_RXCSUM)
+ ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ }
+
+ /* Enable/disable receive hash calculation (RSS) */
+ static void rx_set_rss(struct net_device *dev, u32 features)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ int i, nkeys = 4;
+
+ /* Supports IPv6 and other modes */
+ if (hw->flags & SKY2_HW_NEW_LE) {
+ nkeys = 10;
+ sky2_write32(hw, SK_REG(sky2->port, RSS_CFG), HASH_ALL);
+ }
+
+ /* Program RSS initial values */
+ if (features & NETIF_F_RXHASH) {
+ u32 key[nkeys];
+
+ get_random_bytes(key, nkeys * sizeof(u32));
+ for (i = 0; i < nkeys; i++)
+ sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4),
+ key[i]);
+
+ /* Need to turn on (undocumented) flag to make hashing work */
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T),
+ RX_STFW_ENA);
+
+ sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ BMU_ENA_RX_RSS_HASH);
+ } else
+ sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ BMU_DIS_RX_RSS_HASH);
+ }
+
+ /*
+ * The RX Stop command will not work for Yukon-2 if the BMU does not
+ * reach the end of packet and since we can't make sure that we have
+ * incoming data, we must reset the BMU while it is not doing a DMA
+ * transfer. Since it is possible that the RX path is still active,
+ * the RX RAM buffer will be stopped first, so any possible incoming
+ * data will not trigger a DMA. After the RAM buffer is stopped, the
+ * BMU is polled until any DMA in progress is ended and only then it
+ * will be reset.
+ */
+ static void sky2_rx_stop(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned rxq = rxqaddr[sky2->port];
+ int i;
+
+ /* disable the RAM Buffer receive queue */
+ sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_DIS_OP_MD);
+
+ for (i = 0; i < 0xffff; i++)
+ if (sky2_read8(hw, RB_ADDR(rxq, Q_RSL))
+ == sky2_read8(hw, RB_ADDR(rxq, Q_RL)))
+ goto stopped;
+
+ netdev_warn(sky2->netdev, "receiver stop failed\n");
+ stopped:
+ sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST);
+
+ /* reset the Rx prefetch unit */
+ sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+ mmiowb();
+ }
+
+ /* Clean out receive buffer area, assumes receiver hardware stopped */
+ static void sky2_rx_clean(struct sky2_port *sky2)
+ {
+ unsigned i;
+
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+ for (i = 0; i < sky2->rx_pending; i++) {
+ struct rx_ring_info *re = sky2->rx_ring + i;
+
+ if (re->skb) {
+ sky2_rx_unmap_skb(sky2->hw->pdev, re);
+ kfree_skb(re->skb);
+ re->skb = NULL;
+ }
+ }
+ }
+
+ /* Basic MII support */
+ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ struct mii_ioctl_data *data = if_mii(ifr);
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ int err = -EOPNOTSUPP;
+
+ if (!netif_running(dev))
+ return -ENODEV; /* Phy still in reset */
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = PHY_ADDR_MARV;
+
+ /* fallthru */
+ case SIOCGMIIREG: {
+ u16 val = 0;
+
+ spin_lock_bh(&sky2->phy_lock);
+ err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val);
+ spin_unlock_bh(&sky2->phy_lock);
+
+ data->val_out = val;
+ break;
+ }
+
+ case SIOCSMIIREG:
+ spin_lock_bh(&sky2->phy_lock);
+ err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f,
+ data->val_in);
+ spin_unlock_bh(&sky2->phy_lock);
+ break;
+ }
+ return err;
+ }
+
+ #define SKY2_VLAN_OFFLOADS (NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO)
+
+ static void sky2_vlan_mode(struct net_device *dev, u32 features)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ u16 port = sky2->port;
+
+ if (features & NETIF_F_HW_VLAN_RX)
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+ RX_VLAN_STRIP_ON);
+ else
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+ RX_VLAN_STRIP_OFF);
+
+ if (features & NETIF_F_HW_VLAN_TX) {
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_VLAN_TAG_ON);
+
+ dev->vlan_features |= SKY2_VLAN_OFFLOADS;
+ } else {
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_VLAN_TAG_OFF);
+
+ /* Can't do transmit offload of vlan without hw vlan */
+ dev->vlan_features &= ~SKY2_VLAN_OFFLOADS;
+ }
+ }
+
+ /* Amount of required worst case padding in rx buffer */
+ static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
+ {
+ return (hw->flags & SKY2_HW_RAM_BUFFER) ? 8 : 2;
+ }
+
+ /*
+ * Allocate an skb for receiving. If the MTU is large enough
+ * make the skb non-linear with a fragment list of pages.
+ */
+ static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2, gfp_t gfp)
+ {
+ struct sk_buff *skb;
+ int i;
+
+ skb = __netdev_alloc_skb(sky2->netdev,
+ sky2->rx_data_size + sky2_rx_pad(sky2->hw),
+ gfp);
+ if (!skb)
+ goto nomem;
+
+ if (sky2->hw->flags & SKY2_HW_RAM_BUFFER) {
+ unsigned char *start;
+ /*
+ * Workaround for a bug in FIFO that cause hang
+ * if the FIFO if the receive buffer is not 64 byte aligned.
+ * The buffer returned from netdev_alloc_skb is
+ * aligned except if slab debugging is enabled.
+ */
+ start = PTR_ALIGN(skb->data, 8);
+ skb_reserve(skb, start - skb->data);
+ } else
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ for (i = 0; i < sky2->rx_nfrags; i++) {
+ struct page *page = alloc_page(gfp);
+
+ if (!page)
+ goto free_partial;
+ skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
+ }
+
+ return skb;
+ free_partial:
+ kfree_skb(skb);
+ nomem:
+ return NULL;
+ }
+
+ static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
+ {
+ sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
+ }
+
+ static int sky2_alloc_rx_skbs(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned i;
+
+ sky2->rx_data_size = sky2_get_rx_data_size(sky2);
+
+ /* Fill Rx ring */
+ for (i = 0; i < sky2->rx_pending; i++) {
+ struct rx_ring_info *re = sky2->rx_ring + i;
+
+ re->skb = sky2_rx_alloc(sky2, GFP_KERNEL);
+ if (!re->skb)
+ return -ENOMEM;
+
+ if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) {
+ dev_kfree_skb(re->skb);
+ re->skb = NULL;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * Setup receiver buffer pool.
+ * Normal case this ends up creating one list element for skb
+ * in the receive ring. Worst case if using large MTU and each
+ * allocation falls on a different 64 bit region, that results
+ * in 6 list elements per ring entry.
+ * One element is used for checksum enable/disable, and one
+ * extra to avoid wrap.
+ */
+ static void sky2_rx_start(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ struct rx_ring_info *re;
+ unsigned rxq = rxqaddr[sky2->port];
+ unsigned i, thresh;
+
+ sky2->rx_put = sky2->rx_next = 0;
+ sky2_qset(hw, rxq);
+
+ /* On PCI express lowering the watermark gives better performance */
+ if (pci_is_pcie(hw->pdev))
+ sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX);
+
+ /* These chips have no ram buffer?
+ * MAC Rx RAM Read is controlled by hardware */
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+ hw->chip_rev > CHIP_REV_YU_EC_U_A0)
+ sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
+
+ sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
+
+ if (!(hw->flags & SKY2_HW_NEW_LE))
+ rx_set_checksum(sky2);
+
+ if (!(hw->flags & SKY2_HW_RSS_BROKEN))
+ rx_set_rss(sky2->netdev, sky2->netdev->features);
+
+ /* submit Rx ring */
+ for (i = 0; i < sky2->rx_pending; i++) {
+ re = sky2->rx_ring + i;
+ sky2_rx_submit(sky2, re);
+ }
+
+ /*
+ * The receiver hangs if it receives frames larger than the
+ * packet buffer. As a workaround, truncate oversize frames, but
+ * the register is limited to 9 bits, so if you do frames > 2052
+ * you better get the MTU right!
+ */
+ thresh = sky2_get_rx_threshold(sky2);
+ if (thresh > 0x1ff)
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
+ else {
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh);
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+ }
+
+ /* Tell chip about available buffers */
+ sky2_rx_update(sky2, rxq);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_SUPR) {
+ /*
+ * Disable flushing of non ASF packets;
+ * must be done after initializing the BMUs;
+ * drivers without ASF support should do this too, otherwise
+ * it may happen that they cannot run on ASF devices;
+ * remember that the MAC FIFO isn't reset during initialization.
+ */
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_MACSEC_FLUSH_OFF);
+ }
+
+ if (hw->chip_id >= CHIP_ID_YUKON_SUPR) {
+ /* Enable RX Home Address & Routing Header checksum fix */
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_FL_CTRL),
+ RX_IPV6_SA_MOB_ENA | RX_IPV6_DA_MOB_ENA);
+
+ /* Enable TX Home Address & Routing Header checksum fix */
+ sky2_write32(hw, Q_ADDR(txqaddr[sky2->port], Q_TEST),
+ TBMU_TEST_HOME_ADD_FIX_EN | TBMU_TEST_ROUTING_ADD_FIX_EN);
+ }
+ }
+
+ static int sky2_alloc_buffers(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+
+ /* must be power of 2 */
+ sky2->tx_le = pci_alloc_consistent(hw->pdev,
+ sky2->tx_ring_size *
+ sizeof(struct sky2_tx_le),
+ &sky2->tx_le_map);
+ if (!sky2->tx_le)
+ goto nomem;
+
+ sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info),
+ GFP_KERNEL);
+ if (!sky2->tx_ring)
+ goto nomem;
+
+ sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
+ &sky2->rx_le_map);
+ if (!sky2->rx_le)
+ goto nomem;
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+
+ sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
+ GFP_KERNEL);
+ if (!sky2->rx_ring)
+ goto nomem;
+
+ return sky2_alloc_rx_skbs(sky2);
+ nomem:
+ return -ENOMEM;
+ }
+
+ static void sky2_free_buffers(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+
+ sky2_rx_clean(sky2);
+
+ if (sky2->rx_le) {
+ pci_free_consistent(hw->pdev, RX_LE_BYTES,
+ sky2->rx_le, sky2->rx_le_map);
+ sky2->rx_le = NULL;
+ }
+ if (sky2->tx_le) {
+ pci_free_consistent(hw->pdev,
+ sky2->tx_ring_size * sizeof(struct sky2_tx_le),
+ sky2->tx_le, sky2->tx_le_map);
+ sky2->tx_le = NULL;
+ }
+ kfree(sky2->tx_ring);
+ kfree(sky2->rx_ring);
+
+ sky2->tx_ring = NULL;
+ sky2->rx_ring = NULL;
+ }
+
+ static void sky2_hw_up(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u32 ramsize;
+ int cap;
+ struct net_device *otherdev = hw->dev[sky2->port^1];
+
+ tx_init(sky2);
+
+ /*
+ * On dual port PCI-X card, there is an problem where status
+ * can be received out of order due to split transactions
+ */
+ if (otherdev && netif_running(otherdev) &&
+ (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) {
+ u16 cmd;
+
+ cmd = sky2_pci_read16(hw, cap + PCI_X_CMD);
+ cmd &= ~PCI_X_CMD_MAX_SPLIT;
+ sky2_pci_write16(hw, cap + PCI_X_CMD, cmd);
+ }
+
+ sky2_mac_init(hw, port);
+
+ /* Register is number of 4K blocks on internal RAM buffer. */
+ ramsize = sky2_read8(hw, B2_E_0) * 4;
+ if (ramsize > 0) {
+ u32 rxspace;
+
+ netdev_dbg(sky2->netdev, "ram buffer %dK\n", ramsize);
+ if (ramsize < 16)
+ rxspace = ramsize / 2;
+ else
+ rxspace = 8 + (2*(ramsize - 16))/3;
+
+ sky2_ramset(hw, rxqaddr[port], 0, rxspace);
+ sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
+
+ /* Make sure SyncQ is disabled */
+ sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
+ RB_RST_SET);
+ }
+
+ sky2_qset(hw, txqaddr[port]);
+
+ /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
+ /* Set almost empty threshold */
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+ hw->chip_rev == CHIP_REV_YU_EC_U_A0)
+ sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV);
+
+ sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
+ sky2->tx_ring_size - 1);
+
+ sky2_vlan_mode(sky2->netdev, sky2->netdev->features);
+ netdev_update_features(sky2->netdev);
+
+ sky2_rx_start(sky2);
+ }
+
+ /* Setup device IRQ and enable napi to process */
+ static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
+ {
+ struct pci_dev *pdev = hw->pdev;
+ int err;
+
+ err = request_irq(pdev->irq, sky2_intr,
+ (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
+ name, hw);
+ if (err)
+ dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
+ else {
+ napi_enable(&hw->napi);
+ sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ sky2_read32(hw, B0_IMSK);
+ }
+
+ return err;
+ }
+
+
+ /* Bring up network interface. */
+ static int sky2_up(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u32 imask;
+ int err;
+
+ netif_carrier_off(dev);
+
+ err = sky2_alloc_buffers(sky2);
+ if (err)
+ goto err_out;
+
+ /* With single port, IRQ is setup when device is brought up */
+ if (hw->ports == 1 && (err = sky2_setup_irq(hw, dev->name)))
+ goto err_out;
+
+ sky2_hw_up(sky2);
+
+ /* Enable interrupts from phy/mac for port */
+ imask = sky2_read32(hw, B0_IMSK);
+ imask |= portirq_msk[port];
+ sky2_write32(hw, B0_IMSK, imask);
+ sky2_read32(hw, B0_IMSK);
+
+ netif_info(sky2, ifup, dev, "enabling interface\n");
+
+ return 0;
+
+ err_out:
+ sky2_free_buffers(sky2);
+ return err;
+ }
+
+ /* Modular subtraction in ring */
+ static inline int tx_inuse(const struct sky2_port *sky2)
+ {
+ return (sky2->tx_prod - sky2->tx_cons) & (sky2->tx_ring_size - 1);
+ }
+
+ /* Number of list elements available for next tx */
+ static inline int tx_avail(const struct sky2_port *sky2)
+ {
+ return sky2->tx_pending - tx_inuse(sky2);
+ }
+
+ /* Estimate of number of transmit list elements required */
+ static unsigned tx_le_req(const struct sk_buff *skb)
+ {
+ unsigned count;
+
+ count = (skb_shinfo(skb)->nr_frags + 1)
+ * (sizeof(dma_addr_t) / sizeof(u32));
+
+ if (skb_is_gso(skb))
+ ++count;
+ else if (sizeof(dma_addr_t) == sizeof(u32))
+ ++count; /* possible vlan */
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ ++count;
+
+ return count;
+ }
+
+ static void sky2_tx_unmap(struct pci_dev *pdev, struct tx_ring_info *re)
+ {
+ if (re->flags & TX_MAP_SINGLE)
+ pci_unmap_single(pdev, dma_unmap_addr(re, mapaddr),
+ dma_unmap_len(re, maplen),
+ PCI_DMA_TODEVICE);
+ else if (re->flags & TX_MAP_PAGE)
+ pci_unmap_page(pdev, dma_unmap_addr(re, mapaddr),
+ dma_unmap_len(re, maplen),
+ PCI_DMA_TODEVICE);
+ re->flags = 0;
+ }
+
+ /*
+ * Put one packet in ring for transmit.
+ * A single packet can generate multiple list elements, and
+ * the number of ring elements will probably be less than the number
+ * of list elements used.
+ */
+ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ struct sky2_tx_le *le = NULL;
+ struct tx_ring_info *re;
+ unsigned i, len;
+ dma_addr_t mapping;
+ u32 upper;
+ u16 slot;
+ u16 mss;
+ u8 ctrl;
+
+ if (unlikely(tx_avail(sky2) < tx_le_req(skb)))
+ return NETDEV_TX_BUSY;
+
+ len = skb_headlen(skb);
+ mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+
+ if (pci_dma_mapping_error(hw->pdev, mapping))
+ goto mapping_error;
+
+ slot = sky2->tx_prod;
+ netif_printk(sky2, tx_queued, KERN_DEBUG, dev,
+ "tx queued, slot %u, len %d\n", slot, skb->len);
+
+ /* Send high bits if needed */
+ upper = upper_32_bits(mapping);
+ if (upper != sky2->tx_last_upper) {
+ le = get_tx_le(sky2, &slot);
+ le->addr = cpu_to_le32(upper);
+ sky2->tx_last_upper = upper;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ }
+
+ /* Check for TCP Segmentation Offload */
+ mss = skb_shinfo(skb)->gso_size;
+ if (mss != 0) {
+
+ if (!(hw->flags & SKY2_HW_NEW_LE))
+ mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
+
+ if (mss != sky2->tx_last_mss) {
+ le = get_tx_le(sky2, &slot);
+ le->addr = cpu_to_le32(mss);
+
+ if (hw->flags & SKY2_HW_NEW_LE)
+ le->opcode = OP_MSS | HW_OWNER;
+ else
+ le->opcode = OP_LRGLEN | HW_OWNER;
+ sky2->tx_last_mss = mss;
+ }
+ }
+
+ ctrl = 0;
+
+ /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
+ if (vlan_tx_tag_present(skb)) {
+ if (!le) {
+ le = get_tx_le(sky2, &slot);
+ le->addr = 0;
+ le->opcode = OP_VLAN|HW_OWNER;
+ } else
+ le->opcode |= OP_VLAN;
+ le->length = cpu_to_be16(vlan_tx_tag_get(skb));
+ ctrl |= INS_VLAN;
+ }
+
+ /* Handle TCP checksum offload */
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ /* On Yukon EX (some versions) encoding change. */
+ if (hw->flags & SKY2_HW_AUTO_TX_SUM)
+ ctrl |= CALSUM; /* auto checksum */
+ else {
+ const unsigned offset = skb_transport_offset(skb);
+ u32 tcpsum;
+
+ tcpsum = offset << 16; /* sum start */
+ tcpsum |= offset + skb->csum_offset; /* sum write */
+
+ ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ ctrl |= UDPTCP;
+
+ if (tcpsum != sky2->tx_tcpsum) {
+ sky2->tx_tcpsum = tcpsum;
+
+ le = get_tx_le(sky2, &slot);
+ le->addr = cpu_to_le32(tcpsum);
+ le->length = 0; /* initial checksum value */
+ le->ctrl = 1; /* one packet */
+ le->opcode = OP_TCPLISW | HW_OWNER;
+ }
+ }
+ }
+
+ re = sky2->tx_ring + slot;
+ re->flags = TX_MAP_SINGLE;
+ dma_unmap_addr_set(re, mapaddr, mapping);
+ dma_unmap_len_set(re, maplen, len);
+
+ le = get_tx_le(sky2, &slot);
+ le->addr = cpu_to_le32(lower_32_bits(mapping));
+ le->length = cpu_to_le16(len);
+ le->ctrl = ctrl;
+ le->opcode = mss ? (OP_LARGESEND | HW_OWNER) : (OP_PACKET | HW_OWNER);
+
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ mapping = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
+
+ if (dma_mapping_error(&hw->pdev->dev, mapping))
+ goto mapping_unwind;
+
+ upper = upper_32_bits(mapping);
+ if (upper != sky2->tx_last_upper) {
+ le = get_tx_le(sky2, &slot);
+ le->addr = cpu_to_le32(upper);
+ sky2->tx_last_upper = upper;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ }
+
+ re = sky2->tx_ring + slot;
+ re->flags = TX_MAP_PAGE;
+ dma_unmap_addr_set(re, mapaddr, mapping);
+ dma_unmap_len_set(re, maplen, skb_frag_size(frag));
+
+ le = get_tx_le(sky2, &slot);
+ le->addr = cpu_to_le32(lower_32_bits(mapping));
+ le->length = cpu_to_le16(skb_frag_size(frag));
+ le->ctrl = ctrl;
+ le->opcode = OP_BUFFER | HW_OWNER;
+ }
+
+ re->skb = skb;
+ le->ctrl |= EOP;
+
+ sky2->tx_prod = slot;
+
+ if (tx_avail(sky2) <= MAX_SKB_TX_LE)
+ netif_stop_queue(dev);
+
+ sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod);
+
+ return NETDEV_TX_OK;
+
+ mapping_unwind:
+ for (i = sky2->tx_prod; i != slot; i = RING_NEXT(i, sky2->tx_ring_size)) {
+ re = sky2->tx_ring + i;
+
+ sky2_tx_unmap(hw->pdev, re);
+ }
+
+ mapping_error:
+ if (net_ratelimit())
+ dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ /*
+ * Free ring elements from starting at tx_cons until "done"
+ *
+ * NB:
+ * 1. The hardware will tell us about partial completion of multi-part
+ * buffers so make sure not to free skb to early.
+ * 2. This may run in parallel start_xmit because the it only
+ * looks at the tail of the queue of FIFO (tx_cons), not
+ * the head (tx_prod)
+ */
+ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
+ {
+ struct net_device *dev = sky2->netdev;
+ unsigned idx;
+
+ BUG_ON(done >= sky2->tx_ring_size);
+
+ for (idx = sky2->tx_cons; idx != done;
+ idx = RING_NEXT(idx, sky2->tx_ring_size)) {
+ struct tx_ring_info *re = sky2->tx_ring + idx;
+ struct sk_buff *skb = re->skb;
+
+ sky2_tx_unmap(sky2->hw->pdev, re);
+
+ if (skb) {
+ netif_printk(sky2, tx_done, KERN_DEBUG, dev,
+ "tx done %u\n", idx);
+
+ u64_stats_update_begin(&sky2->tx_stats.syncp);
+ ++sky2->tx_stats.packets;
+ sky2->tx_stats.bytes += skb->len;
+ u64_stats_update_end(&sky2->tx_stats.syncp);
+
+ re->skb = NULL;
+ dev_kfree_skb_any(skb);
+
+ sky2->tx_next = RING_NEXT(idx, sky2->tx_ring_size);
+ }
+ }
+
+ sky2->tx_cons = idx;
+ smp_mb();
+ }
+
+ static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
+ {
+ /* Disable Force Sync bit and Enable Alloc bit */
+ sky2_write8(hw, SK_REG(port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+ sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
+
+ /* Reset the PCI FIFO of the async Tx queue */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR),
+ BMU_RST_SET | BMU_FIFO_RST);
+
+ /* Reset the Tx prefetch units */
+ sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL),
+ PREF_UNIT_RST_SET);
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+ }
+
+ static void sky2_hw_down(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 ctrl;
+
+ /* Force flow control off */
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+
+ /* Stop transmitter */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP);
+ sky2_read32(hw, Q_ADDR(txqaddr[port], Q_CSR));
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+ RB_RST_SET | RB_DIS_OP_MD);
+
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
+
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+
+ /* Workaround shared GMAC reset */
+ if (!(hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 &&
+ port == 0 && hw->dev[1] && netif_running(hw->dev[1])))
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+
++ /* Force any delayed status interrupt and NAPI */
+ sky2_write32(hw, STAT_LEV_TIMER_CNT, 0);
+ sky2_write32(hw, STAT_TX_TIMER_CNT, 0);
+ sky2_write32(hw, STAT_ISR_TIMER_CNT, 0);
+ sky2_read8(hw, STAT_ISR_TIMER_CTRL);
+
+ sky2_rx_stop(sky2);
+
+ spin_lock_bh(&sky2->phy_lock);
+ sky2_phy_power_down(hw, port);
+ spin_unlock_bh(&sky2->phy_lock);
+
+ sky2_tx_reset(hw, port);
+
+ /* Free any pending frames stuck in HW queue */
+ sky2_tx_complete(sky2, sky2->tx_prod);
+ }
+
+ /* Network shutdown */
+ static int sky2_down(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ /* Never really got started! */
+ if (!sky2->tx_le)
+ return 0;
+
+ netif_info(sky2, ifdown, dev, "disabling interface\n");
+
+ /* Disable port IRQ */
+ sky2_write32(hw, B0_IMSK,
+ sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]);
+ sky2_read32(hw, B0_IMSK);
+
+ if (hw->ports == 1) {
+ napi_disable(&hw->napi);
+ free_irq(hw->pdev->irq, hw);
+ } else {
+ synchronize_irq(hw->pdev->irq);
+ napi_synchronize(&hw->napi);
+ }
+
+ sky2_hw_down(sky2);
+
+ sky2_free_buffers(sky2);
+
+ return 0;
+ }
+
+ static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
+ {
+ if (hw->flags & SKY2_HW_FIBRE_PHY)
+ return SPEED_1000;
+
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
+ if (aux & PHY_M_PS_SPEED_100)
+ return SPEED_100;
+ else
+ return SPEED_10;
+ }
+
+ switch (aux & PHY_M_PS_SPEED_MSK) {
+ case PHY_M_PS_SPEED_1000:
+ return SPEED_1000;
+ case PHY_M_PS_SPEED_100:
+ return SPEED_100;
+ default:
+ return SPEED_10;
+ }
+ }
+
+ static void sky2_link_up(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ static const char *fc_name[] = {
+ [FC_NONE] = "none",
+ [FC_TX] = "tx",
+ [FC_RX] = "rx",
+ [FC_BOTH] = "both",
+ };
+
+ sky2_set_ipg(sky2);
+
+ sky2_enable_rx_tx(sky2);
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+
+ netif_carrier_on(sky2->netdev);
+
+ mod_timer(&hw->watchdog_timer, jiffies + 1);
+
+ /* Turn on link LED */
+ sky2_write8(hw, SK_REG(port, LNK_LED_REG),
+ LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
+
+ netif_info(sky2, link, sky2->netdev,
+ "Link is up at %d Mbps, %s duplex, flow control %s\n",
+ sky2->speed,
+ sky2->duplex == DUPLEX_FULL ? "full" : "half",
+ fc_name[sky2->flow_status]);
+ }
+
+ static void sky2_link_down(struct sky2_port *sky2)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ netif_carrier_off(sky2->netdev);
+
+ /* Turn off link LED */
+ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+
+ netif_info(sky2, link, sky2->netdev, "Link is down\n");
+
+ sky2_phy_init(hw, port);
+ }
+
+ static enum flow_control sky2_flow(int rx, int tx)
+ {
+ if (rx)
+ return tx ? FC_BOTH : FC_RX;
+ else
+ return tx ? FC_TX : FC_NONE;
+ }
+
+ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 advert, lpa;
+
+ advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
+ lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
+ if (lpa & PHY_M_AN_RF) {
+ netdev_err(sky2->netdev, "remote fault\n");
+ return -1;
+ }
+
+ if (!(aux & PHY_M_PS_SPDUP_RES)) {
+ netdev_err(sky2->netdev, "speed/duplex mismatch\n");
+ return -1;
+ }
+
+ sky2->speed = sky2_phy_speed(hw, aux);
+ sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+ /* Since the pause result bits seem to in different positions on
+ * different chips. look at registers.
+ */
+ if (hw->flags & SKY2_HW_FIBRE_PHY) {
+ /* Shift for bits in fiber PHY */
+ advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
+ lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
+
+ if (advert & ADVERTISE_1000XPAUSE)
+ advert |= ADVERTISE_PAUSE_CAP;
+ if (advert & ADVERTISE_1000XPSE_ASYM)
+ advert |= ADVERTISE_PAUSE_ASYM;
+ if (lpa & LPA_1000XPAUSE)
+ lpa |= LPA_PAUSE_CAP;
+ if (lpa & LPA_1000XPAUSE_ASYM)
+ lpa |= LPA_PAUSE_ASYM;
+ }
+
+ sky2->flow_status = FC_NONE;
+ if (advert & ADVERTISE_PAUSE_CAP) {
+ if (lpa & LPA_PAUSE_CAP)
+ sky2->flow_status = FC_BOTH;
+ else if (advert & ADVERTISE_PAUSE_ASYM)
+ sky2->flow_status = FC_RX;
+ } else if (advert & ADVERTISE_PAUSE_ASYM) {
+ if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM))
+ sky2->flow_status = FC_TX;
+ }
+
+ if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 &&
+ !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX))
+ sky2->flow_status = FC_NONE;
+
+ if (sky2->flow_status & FC_TX)
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ else
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+
+ return 0;
+ }
+
+ /* Interrupt from PHY */
+ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
+ {
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u16 istatus, phystat;
+
+ if (!netif_running(dev))
+ return;
+
+ spin_lock(&sky2->phy_lock);
+ istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
+ phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
+
+ netif_info(sky2, intr, sky2->netdev, "phy interrupt status 0x%x 0x%x\n",
+ istatus, phystat);
+
+ if (istatus & PHY_M_IS_AN_COMPL) {
+ if (sky2_autoneg_done(sky2, phystat) == 0 &&
+ !netif_carrier_ok(dev))
+ sky2_link_up(sky2);
+ goto out;
+ }
+
+ if (istatus & PHY_M_IS_LSP_CHANGE)
+ sky2->speed = sky2_phy_speed(hw, phystat);
+
+ if (istatus & PHY_M_IS_DUP_CHANGE)
+ sky2->duplex =
+ (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+ if (istatus & PHY_M_IS_LST_CHANGE) {
+ if (phystat & PHY_M_PS_LINK_UP)
+ sky2_link_up(sky2);
+ else
+ sky2_link_down(sky2);
+ }
+ out:
+ spin_unlock(&sky2->phy_lock);
+ }
+
+ /* Special quick link interrupt (Yukon-2 Optima only) */
+ static void sky2_qlink_intr(struct sky2_hw *hw)
+ {
+ struct sky2_port *sky2 = netdev_priv(hw->dev[0]);
+ u32 imask;
+ u16 phy;
+
+ /* disable irq */
+ imask = sky2_read32(hw, B0_IMSK);
+ imask &= ~Y2_IS_PHY_QLNK;
+ sky2_write32(hw, B0_IMSK, imask);
+
+ /* reset PHY Link Detect */
+ phy = sky2_pci_read16(hw, PSM_CONFIG_REG4);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ sky2_link_up(sky2);
+ }
+
+ /* Transmit timeout is only called if we are running, carrier is up
+ * and tx queue is full (stopped).
+ */
+ static void sky2_tx_timeout(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ netif_err(sky2, timer, dev, "tx timeout\n");
+
+ netdev_printk(KERN_DEBUG, dev, "transmit ring %u .. %u report=%u done=%u\n",
+ sky2->tx_cons, sky2->tx_prod,
+ sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
+ sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
+
+ /* can't restart safely under softirq */
+ schedule_work(&hw->restart_work);
+ }
+
+ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ int err;
+ u16 ctl, mode;
+ u32 imask;
+
+ /* MTU size outside the spec */
+ if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
+ return -EINVAL;
+
+ /* MTU > 1500 on yukon FE and FE+ not allowed */
+ if (new_mtu > ETH_DATA_LEN &&
+ (hw->chip_id == CHIP_ID_YUKON_FE ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P))
+ return -EINVAL;
+
+ if (!netif_running(dev)) {
+ dev->mtu = new_mtu;
+ netdev_update_features(dev);
+ return 0;
+ }
+
+ imask = sky2_read32(hw, B0_IMSK);
+ sky2_write32(hw, B0_IMSK, 0);
+
+ dev->trans_start = jiffies; /* prevent tx timeout */
+ napi_disable(&hw->napi);
+ netif_tx_disable(dev);
+
+ synchronize_irq(hw->pdev->irq);
+
+ if (!(hw->flags & SKY2_HW_RAM_BUFFER))
+ sky2_set_tx_stfwd(hw, port);
+
+ ctl = gma_read16(hw, port, GM_GP_CTRL);
+ gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
+ sky2_rx_stop(sky2);
+ sky2_rx_clean(sky2);
+
+ dev->mtu = new_mtu;
+ netdev_update_features(dev);
+
+ mode = DATA_BLIND_VAL(DATA_BLIND_DEF) | GM_SMOD_VLAN_ENA;
+ if (sky2->speed > SPEED_100)
+ mode |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
+ else
+ mode |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);
+
+ if (dev->mtu > ETH_DATA_LEN)
+ mode |= GM_SMOD_JUMBO_ENA;
+
+ gma_write16(hw, port, GM_SERIAL_MODE, mode);
+
+ sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);
+
+ err = sky2_alloc_rx_skbs(sky2);
+ if (!err)
+ sky2_rx_start(sky2);
+ else
+ sky2_rx_clean(sky2);
+ sky2_write32(hw, B0_IMSK, imask);
+
+ sky2_read32(hw, B0_Y2_SP_LISR);
+ napi_enable(&hw->napi);
+
+ if (err)
+ dev_close(dev);
+ else {
+ gma_write16(hw, port, GM_GP_CTRL, ctl);
+
+ netif_wake_queue(dev);
+ }
+
+ return err;
+ }
+
+ /* For small just reuse existing skb for next receive */
+ static struct sk_buff *receive_copy(struct sky2_port *sky2,
+ const struct rx_ring_info *re,
+ unsigned length)
+ {
+ struct sk_buff *skb;
+
+ skb = netdev_alloc_skb_ip_align(sky2->netdev, length);
+ if (likely(skb)) {
+ pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
+ length, PCI_DMA_FROMDEVICE);
+ skb_copy_from_linear_data(re->skb, skb->data, length);
+ skb->ip_summed = re->skb->ip_summed;
+ skb->csum = re->skb->csum;
+ pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
+ length, PCI_DMA_FROMDEVICE);
+ re->skb->ip_summed = CHECKSUM_NONE;
+ skb_put(skb, length);
+ }
+ return skb;
+ }
+
+ /* Adjust length of skb with fragments to match received data */
+ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
+ unsigned int length)
+ {
+ int i, num_frags;
+ unsigned int size;
+
+ /* put header into skb */
+ size = min(length, hdr_space);
+ skb->tail += size;
+ skb->len += size;
+ length -= size;
+
+ num_frags = skb_shinfo(skb)->nr_frags;
+ for (i = 0; i < num_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ if (length == 0) {
+ /* don't need this page */
+ __skb_frag_unref(frag);
+ --skb_shinfo(skb)->nr_frags;
+ } else {
+ size = min(length, (unsigned) PAGE_SIZE);
+
+ skb_frag_size_set(frag, size);
+ skb->data_len += size;
+ skb->truesize += PAGE_SIZE;
+ skb->len += size;
+ length -= size;
+ }
+ }
+ }
+
+ /* Normal packet - take skb from ring element and put in a new one */
+ static struct sk_buff *receive_new(struct sky2_port *sky2,
+ struct rx_ring_info *re,
+ unsigned int length)
+ {
+ struct sk_buff *skb;
+ struct rx_ring_info nre;
+ unsigned hdr_space = sky2->rx_data_size;
+
+ nre.skb = sky2_rx_alloc(sky2, GFP_ATOMIC);
+ if (unlikely(!nre.skb))
+ goto nobuf;
+
+ if (sky2_rx_map_skb(sky2->hw->pdev, &nre, hdr_space))
+ goto nomap;
+
+ skb = re->skb;
+ sky2_rx_unmap_skb(sky2->hw->pdev, re);
+ prefetch(skb->data);
+ *re = nre;
+
+ if (skb_shinfo(skb)->nr_frags)
+ skb_put_frags(skb, hdr_space, length);
+ else
+ skb_put(skb, length);
+ return skb;
+
+ nomap:
+ dev_kfree_skb(nre.skb);
+ nobuf:
+ return NULL;
+ }
+
+ /*
+ * Receive one packet.
+ * For larger packets, get new buffer.
+ */
+ static struct sk_buff *sky2_receive(struct net_device *dev,
+ u16 length, u32 status)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
+ struct sk_buff *skb = NULL;
+ u16 count = (status & GMR_FS_LEN) >> 16;
+
+ if (status & GMR_FS_VLAN)
+ count -= VLAN_HLEN; /* Account for vlan tag */
+
+ netif_printk(sky2, rx_status, KERN_DEBUG, dev,
+ "rx slot %u status 0x%x len %d\n",
+ sky2->rx_next, status, length);
+
+ sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
+ prefetch(sky2->rx_ring + sky2->rx_next);
+
+ /* This chip has hardware problems that generates bogus status.
+ * So do only marginal checking and expect higher level protocols
+ * to handle crap frames.
+ */
+ if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 &&
+ length != count)
+ goto okay;
+
+ if (status & GMR_FS_ANY_ERR)
+ goto error;
+
+ if (!(status & GMR_FS_RX_OK))
+ goto resubmit;
+
+ /* if length reported by DMA does not match PHY, packet was truncated */
+ if (length != count)
+ goto error;
+
+ okay:
+ if (length < copybreak)
+ skb = receive_copy(sky2, re, length);
+ else
+ skb = receive_new(sky2, re, length);
+
+ dev->stats.rx_dropped += (skb == NULL);
+
+ resubmit:
+ sky2_rx_submit(sky2, re);
+
+ return skb;
+
+ error:
+ ++dev->stats.rx_errors;
+
+ if (net_ratelimit())
+ netif_info(sky2, rx_err, dev,
+ "rx error, status 0x%x length %d\n", status, length);
+
+ goto resubmit;
+ }
+
+ /* Transmit complete */
+ static inline void sky2_tx_done(struct net_device *dev, u16 last)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (netif_running(dev)) {
+ sky2_tx_complete(sky2, last);
+
+ /* Wake unless it's detached, and called e.g. from sky2_down() */
+ if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
+ netif_wake_queue(dev);
+ }
+ }
+
+ static inline void sky2_skb_rx(const struct sky2_port *sky2,
+ u32 status, struct sk_buff *skb)
+ {
+ if (status & GMR_FS_VLAN)
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
+
+ if (skb->ip_summed == CHECKSUM_NONE)
+ netif_receive_skb(skb);
+ else
+ napi_gro_receive(&sky2->hw->napi, skb);
+ }
+
+ static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port,
+ unsigned packets, unsigned bytes)
+ {
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (packets == 0)
+ return;
+
+ u64_stats_update_begin(&sky2->rx_stats.syncp);
+ sky2->rx_stats.packets += packets;
+ sky2->rx_stats.bytes += bytes;
+ u64_stats_update_end(&sky2->rx_stats.syncp);
+
+ dev->last_rx = jiffies;
+ sky2_rx_update(netdev_priv(dev), rxqaddr[port]);
+ }
+
+ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
+ {
+ /* If this happens then driver assuming wrong format for chip type */
+ BUG_ON(sky2->hw->flags & SKY2_HW_NEW_LE);
+
+ /* Both checksum counters are programmed to start at
+ * the same offset, so unless there is a problem they
+ * should match. This failure is an early indication that
+ * hardware receive checksumming won't work.
+ */
+ if (likely((u16)(status >> 16) == (u16)status)) {
+ struct sk_buff *skb = sky2->rx_ring[sky2->rx_next].skb;
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = le16_to_cpu(status);
+ } else {
+ dev_notice(&sky2->hw->pdev->dev,
+ "%s: receive checksum problem (status = %#x)\n",
+ sky2->netdev->name, status);
+
+ /* Disable checksum offload
+ * It will be reenabled on next ndo_set_features, but if it's
+ * really broken, will get disabled again
+ */
+ sky2->netdev->features &= ~NETIF_F_RXCSUM;
+ sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ BMU_DIS_RX_CHKSUM);
+ }
+ }
+
+ static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
+ {
+ struct sk_buff *skb;
+
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ skb->rxhash = le32_to_cpu(status);
+ }
+
+ /* Process status response ring */
+ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
+ {
+ int work_done = 0;
+ unsigned int total_bytes[2] = { 0 };
+ unsigned int total_packets[2] = { 0 };
+
+ rmb();
+ do {
+ struct sky2_port *sky2;
+ struct sky2_status_le *le = hw->st_le + hw->st_idx;
+ unsigned port;
+ struct net_device *dev;
+ struct sk_buff *skb;
+ u32 status;
+ u16 length;
+ u8 opcode = le->opcode;
+
+ if (!(opcode & HW_OWNER))
+ break;
+
+ hw->st_idx = RING_NEXT(hw->st_idx, hw->st_size);
+
+ port = le->css & CSS_LINK_BIT;
+ dev = hw->dev[port];
+ sky2 = netdev_priv(dev);
+ length = le16_to_cpu(le->length);
+ status = le32_to_cpu(le->status);
+
+ le->opcode = 0;
+ switch (opcode & ~HW_OWNER) {
+ case OP_RXSTAT:
+ total_packets[port]++;
+ total_bytes[port] += length;
+
+ skb = sky2_receive(dev, length, status);
+ if (!skb)
+ break;
+
+ /* This chip reports checksum status differently */
+ if (hw->flags & SKY2_HW_NEW_LE) {
+ if ((dev->features & NETIF_F_RXCSUM) &&
+ (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
+ (le->css & CSS_TCPUDPCSOK))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
+ skb->protocol = eth_type_trans(skb, dev);
+
+ sky2_skb_rx(sky2, status, skb);
+
+ /* Stop after net poll weight */
+ if (++work_done >= to_do)
+ goto exit_loop;
+ break;
+
+ case OP_RXVLAN:
+ sky2->rx_tag = length;
+ break;
+
+ case OP_RXCHKSVLAN:
+ sky2->rx_tag = length;
+ /* fall through */
+ case OP_RXCHKS:
+ if (likely(dev->features & NETIF_F_RXCSUM))
+ sky2_rx_checksum(sky2, status);
+ break;
+
+ case OP_RSS_HASH:
+ sky2_rx_hash(sky2, status);
+ break;
+
+ case OP_TXINDEXLE:
+ /* TX index reports status for both ports */
+ sky2_tx_done(hw->dev[0], status & 0xfff);
+ if (hw->dev[1])
+ sky2_tx_done(hw->dev[1],
+ ((status >> 24) & 0xff)
+ | (u16)(length & 0xf) << 8);
+ break;
+
+ default:
+ if (net_ratelimit())
+ pr_warning("unknown status opcode 0x%x\n", opcode);
+ }
+ } while (hw->st_idx != idx);
+
+ /* Fully processed status ring so clear irq */
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+ exit_loop:
+ sky2_rx_done(hw, 0, total_packets[0], total_bytes[0]);
+ sky2_rx_done(hw, 1, total_packets[1], total_bytes[1]);
+
+ return work_done;
+ }
+
+ static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
+ {
+ struct net_device *dev = hw->dev[port];
+
+ if (net_ratelimit())
+ netdev_info(dev, "hw error interrupt status 0x%x\n", status);
+
+ if (status & Y2_IS_PAR_RD1) {
+ if (net_ratelimit())
+ netdev_err(dev, "ram data read parity error\n");
+ /* Clear IRQ */
+ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
+ }
+
+ if (status & Y2_IS_PAR_WR1) {
+ if (net_ratelimit())
+ netdev_err(dev, "ram data write parity error\n");
+
+ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
+ }
+
+ if (status & Y2_IS_PAR_MAC1) {
+ if (net_ratelimit())
+ netdev_err(dev, "MAC parity error\n");
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
+ }
+
+ if (status & Y2_IS_PAR_RX1) {
+ if (net_ratelimit())
+ netdev_err(dev, "RX parity error\n");
+ sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
+ }
+
+ if (status & Y2_IS_TCP_TXA1) {
+ if (net_ratelimit())
+ netdev_err(dev, "TCP segmentation error\n");
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
+ }
+ }
+
+ static void sky2_hw_intr(struct sky2_hw *hw)
+ {
+ struct pci_dev *pdev = hw->pdev;
+ u32 status = sky2_read32(hw, B0_HWE_ISRC);
+ u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
+
+ status &= hwmsk;
+
+ if (status & Y2_IS_TIST_OV)
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
+ u16 pci_err;
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ pci_err = sky2_pci_read16(hw, PCI_STATUS);
+ if (net_ratelimit())
+ dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
+ pci_err);
+
+ sky2_pci_write16(hw, PCI_STATUS,
+ pci_err | PCI_STATUS_ERROR_BITS);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ }
+
+ if (status & Y2_IS_PCI_EXP) {
+ /* PCI-Express uncorrectable Error occurred */
+ u32 err;
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
+ if (net_ratelimit())
+ dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
+
+ sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ }
+
+ if (status & Y2_HWE_L1_MASK)
+ sky2_hw_error(hw, 0, status);
+ status >>= 8;
+ if (status & Y2_HWE_L1_MASK)
+ sky2_hw_error(hw, 1, status);
+ }
+
+ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port)
+ {
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ netif_info(sky2, intr, dev, "mac interrupt status 0x%x\n", status);
+
+ if (status & GM_IS_RX_CO_OV)
+ gma_read16(hw, port, GM_RX_IRQ_SRC);
+
+ if (status & GM_IS_TX_CO_OV)
+ gma_read16(hw, port, GM_TX_IRQ_SRC);
+
+ if (status & GM_IS_RX_FF_OR) {
+ ++dev->stats.rx_fifo_errors;
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
+ }
+
+ if (status & GM_IS_TX_FF_UR) {
+ ++dev->stats.tx_fifo_errors;
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
+ }
+ }
+
+ /* This should never happen it is a bug. */
+ static void sky2_le_error(struct sky2_hw *hw, unsigned port, u16 q)
+ {
+ struct net_device *dev = hw->dev[port];
+ u16 idx = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
+
+ dev_err(&hw->pdev->dev, "%s: descriptor error q=%#x get=%u put=%u\n",
+ dev->name, (unsigned) q, (unsigned) idx,
+ (unsigned) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX)));
+
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
+ }
+
+ static int sky2_rx_hung(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned rxq = rxqaddr[port];
+ u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP));
+ u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV));
+ u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP));
+ u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL));
+
+ /* If idle and MAC or PCI is stuck */
+ if (sky2->check.last == dev->last_rx &&
+ ((mac_rp == sky2->check.mac_rp &&
+ mac_lev != 0 && mac_lev >= sky2->check.mac_lev) ||
+ /* Check if the PCI RX hang */
+ (fifo_rp == sky2->check.fifo_rp &&
+ fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) {
+ netdev_printk(KERN_DEBUG, dev,
+ "hung mac %d:%d fifo %d (%d:%d)\n",
+ mac_lev, mac_rp, fifo_lev,
+ fifo_rp, sky2_read8(hw, Q_ADDR(rxq, Q_WP)));
+ return 1;
+ } else {
+ sky2->check.last = dev->last_rx;
+ sky2->check.mac_rp = mac_rp;
+ sky2->check.mac_lev = mac_lev;
+ sky2->check.fifo_rp = fifo_rp;
+ sky2->check.fifo_lev = fifo_lev;
+ return 0;
+ }
+ }
+
+ static void sky2_watchdog(unsigned long arg)
+ {
+ struct sky2_hw *hw = (struct sky2_hw *) arg;
+
+ /* Check for lost IRQ once a second */
+ if (sky2_read32(hw, B0_ISRC)) {
+ napi_schedule(&hw->napi);
+ } else {
+ int i, active = 0;
+
+ for (i = 0; i < hw->ports; i++) {
+ struct net_device *dev = hw->dev[i];
+ if (!netif_running(dev))
+ continue;
+ ++active;
+
+ /* For chips with Rx FIFO, check if stuck */
+ if ((hw->flags & SKY2_HW_RAM_BUFFER) &&
+ sky2_rx_hung(dev)) {
+ netdev_info(dev, "receiver hang detected\n");
+ schedule_work(&hw->restart_work);
+ return;
+ }
+ }
+
+ if (active == 0)
+ return;
+ }
+
+ mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
+ }
+
+ /* Hardware/software error handling */
+ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
+ {
+ if (net_ratelimit())
+ dev_warn(&hw->pdev->dev, "error interrupt status=%#x\n", status);
+
+ if (status & Y2_IS_HW_ERR)
+ sky2_hw_intr(hw);
+
+ if (status & Y2_IS_IRQ_MAC1)
+ sky2_mac_intr(hw, 0);
+
+ if (status & Y2_IS_IRQ_MAC2)
+ sky2_mac_intr(hw, 1);
+
+ if (status & Y2_IS_CHK_RX1)
+ sky2_le_error(hw, 0, Q_R1);
+
+ if (status & Y2_IS_CHK_RX2)
+ sky2_le_error(hw, 1, Q_R2);
+
+ if (status & Y2_IS_CHK_TXA1)
+ sky2_le_error(hw, 0, Q_XA1);
+
+ if (status & Y2_IS_CHK_TXA2)
+ sky2_le_error(hw, 1, Q_XA2);
+ }
+
+ static int sky2_poll(struct napi_struct *napi, int work_limit)
+ {
+ struct sky2_hw *hw = container_of(napi, struct sky2_hw, napi);
+ u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
+ int work_done = 0;
+ u16 idx;
+
+ if (unlikely(status & Y2_IS_ERROR))
+ sky2_err_intr(hw, status);
+
+ if (status & Y2_IS_IRQ_PHY1)
+ sky2_phy_intr(hw, 0);
+
+ if (status & Y2_IS_IRQ_PHY2)
+ sky2_phy_intr(hw, 1);
+
+ if (status & Y2_IS_PHY_QLNK)
+ sky2_qlink_intr(hw);
+
+ while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) {
+ work_done += sky2_status_intr(hw, work_limit - work_done, idx);
+
+ if (work_done >= work_limit)
+ goto done;
+ }
+
+ napi_complete(napi);
+ sky2_read32(hw, B0_Y2_SP_LISR);
+ done:
+
+ return work_done;
+ }
+
+ static irqreturn_t sky2_intr(int irq, void *dev_id)
+ {
+ struct sky2_hw *hw = dev_id;
+ u32 status;
+
+ /* Reading this mask interrupts as side effect */
+ status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+ if (status == 0 || status == ~0)
+ return IRQ_NONE;
+
+ prefetch(&hw->st_le[hw->st_idx]);
+
+ napi_schedule(&hw->napi);
+
+ return IRQ_HANDLED;
+ }
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void sky2_netpoll(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ napi_schedule(&sky2->hw->napi);
+ }
+ #endif
+
+ /* Chip internal frequency for clock calculations */
+ static u32 sky2_mhz(const struct sky2_hw *hw)
+ {
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_EC:
+ case CHIP_ID_YUKON_EC_U:
+ case CHIP_ID_YUKON_EX:
+ case CHIP_ID_YUKON_SUPR:
+ case CHIP_ID_YUKON_UL_2:
+ case CHIP_ID_YUKON_OPT:
+ case CHIP_ID_YUKON_PRM:
+ case CHIP_ID_YUKON_OP_2:
+ return 125;
+
+ case CHIP_ID_YUKON_FE:
+ return 100;
+
+ case CHIP_ID_YUKON_FE_P:
+ return 50;
+
+ case CHIP_ID_YUKON_XL:
+ return 156;
+
+ default:
+ BUG();
+ }
+ }
+
+ static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us)
+ {
+ return sky2_mhz(hw) * us;
+ }
+
+ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
+ {
+ return clk / sky2_mhz(hw);
+ }
+
+
+ static int __devinit sky2_init(struct sky2_hw *hw)
+ {
+ u8 t8;
+
+ /* Enable all clocks and check for bad PCI access */
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
+ sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
+ hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
+ hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_XL:
+ hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY;
+ if (hw->chip_rev < CHIP_REV_YU_XL_A2)
+ hw->flags |= SKY2_HW_RSS_BROKEN;
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_EX:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_ADV_POWER_CTL
+ | SKY2_HW_RSS_CHKSUM;
+
+ /* New transmit checksum */
+ if (hw->chip_rev != CHIP_REV_YU_EX_B0)
+ hw->flags |= SKY2_HW_AUTO_TX_SUM;
+ break;
+
+ case CHIP_ID_YUKON_EC:
+ /* This rev is really old, and requires untested workarounds */
+ if (hw->chip_rev == CHIP_REV_YU_EC_A1) {
+ dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
+ return -EOPNOTSUPP;
+ }
+ hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RSS_BROKEN;
+ break;
+
+ case CHIP_ID_YUKON_FE:
+ hw->flags = SKY2_HW_RSS_BROKEN;
+ break;
+
+ case CHIP_ID_YUKON_FE_P:
+ hw->flags = SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_AUTO_TX_SUM
+ | SKY2_HW_ADV_POWER_CTL;
+
+ /* The workaround for status conflicts VLAN tag detection. */
+ if (hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ hw->flags |= SKY2_HW_VLAN_BROKEN | SKY2_HW_RSS_CHKSUM;
+ break;
+
+ case CHIP_ID_YUKON_SUPR:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_AUTO_TX_SUM
+ | SKY2_HW_ADV_POWER_CTL;
+
+ if (hw->chip_rev == CHIP_REV_YU_SU_A0)
+ hw->flags |= SKY2_HW_RSS_CHKSUM;
+ break;
+
+ case CHIP_ID_YUKON_UL_2:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_OPT:
+ case CHIP_ID_YUKON_PRM:
+ case CHIP_ID_YUKON_OP_2:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ default:
+ dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
+ hw->chip_id);
+ return -EOPNOTSUPP;
+ }
+
+ hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
+ if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
+ hw->flags |= SKY2_HW_FIBRE_PHY;
+
+ hw->ports = 1;
+ t8 = sky2_read8(hw, B2_Y2_HW_RES);
+ if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
+ if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC))
+ ++hw->ports;
+ }
+
+ if (sky2_read8(hw, B2_E_0))
+ hw->flags |= SKY2_HW_RAM_BUFFER;
+
+ return 0;
+ }
+
+ static void sky2_reset(struct sky2_hw *hw)
+ {
+ struct pci_dev *pdev = hw->pdev;
+ u16 status;
+ int i;
+ u32 hwe_mask = Y2_HWE_ALL_MASK;
+
+ /* disable ASF */
+ if (hw->chip_id == CHIP_ID_YUKON_EX
+ || hw->chip_id == CHIP_ID_YUKON_SUPR) {
+ sky2_write32(hw, CPU_WDOG, 0);
+ status = sky2_read16(hw, HCU_CCSR);
+ status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE |
+ HCU_CCSR_UC_STATE_MSK);
+ /*
+ * CPU clock divider shouldn't be used because
+ * - ASF firmware may malfunction
+ * - Yukon-Supreme: Parallel FLASH doesn't support divided clocks
+ */
+ status &= ~HCU_CCSR_CPU_CLK_DIVIDE_MSK;
+ sky2_write16(hw, HCU_CCSR, status);
+ sky2_write32(hw, CPU_WDOG, 0);
+ } else
+ sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
+ sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE);
+
+ /* do a SW reset */
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
+ /* allow writes to PCI config */
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
+ /* clear PCI errors, if any */
+ status = sky2_pci_read16(hw, PCI_STATUS);
+ status |= PCI_STATUS_ERROR_BITS;
+ sky2_pci_write16(hw, PCI_STATUS, status);
+
+ sky2_write8(hw, B0_CTST, CS_MRST_CLR);
+
+ if (pci_is_pcie(pdev)) {
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
+
+ /* If error bit is stuck on ignore it */
+ if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP)
+ dev_info(&pdev->dev, "ignoring stuck error report bit\n");
+ else
+ hwe_mask |= Y2_IS_PCI_EXP;
+ }
+
+ sky2_power_on(hw);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ for (i = 0; i < hw->ports; i++) {
+ sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+ sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_SUPR)
+ sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+ GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+ | GMC_BYP_RETR_ON);
+
+ }
+
+ if (hw->chip_id == CHIP_ID_YUKON_SUPR && hw->chip_rev > CHIP_REV_YU_SU_B0) {
+ /* enable MACSec clock gating */
+ sky2_pci_write32(hw, PCI_DEV_REG3, P_CLK_MACSEC_DIS);
+ }
+
+ if (hw->chip_id == CHIP_ID_YUKON_OPT ||
+ hw->chip_id == CHIP_ID_YUKON_PRM ||
+ hw->chip_id == CHIP_ID_YUKON_OP_2) {
+ u16 reg;
+ u32 msk;
+
+ if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
+ /* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */
+ sky2_write32(hw, Y2_PEX_PHY_DATA, (0x80UL << 16) | (1 << 7));
+
+ /* set PHY Link Detect Timer to 1.1 second (11x 100ms) */
+ reg = 10;
+
+ /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
+ sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
+ } else {
+ /* set PHY Link Detect Timer to 0.4 second (4x 100ms) */
+ reg = 3;
+ }
+
+ reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
+ reg |= PSM_CONFIG_REG4_RST_PHY_LINK_DETECT;
+
+ /* reset PHY Link Detect */
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
+
+ /* enable PHY Quick Link */
+ msk = sky2_read32(hw, B0_IMSK);
+ msk |= Y2_IS_PHY_QLNK;
+ sky2_write32(hw, B0_IMSK, msk);
+
+ /* check if PSMv2 was running before */
+ reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
+ if (reg & PCI_EXP_LNKCTL_ASPMC)
+ /* restore the PCIe Link Control register */
+ sky2_pci_write16(hw, pdev->pcie_cap + PCI_EXP_LNKCTL,
+ reg);
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
+ sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
+ }
+
+ /* Clear I2C IRQ noise */
+ sky2_write32(hw, B2_I2C_IRQ, 1);
+
+ /* turn off hardware timer (unused) */
+ sky2_write8(hw, B2_TI_CTRL, TIM_STOP);
+ sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+
+ /* Turn off descriptor polling */
+ sky2_write32(hw, B28_DPT_CTRL, DPT_STOP);
+
+ /* Turn off receive timestamp */
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_STOP);
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ /* enable the Tx Arbiters */
+ for (i = 0; i < hw->ports; i++)
+ sky2_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+ /* Initialize ram interface */
+ for (i = 0; i < hw->ports; i++) {
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR);
+
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
+ }
+
+ sky2_write32(hw, B0_HWE_IMSK, hwe_mask);
+
+ for (i = 0; i < hw->ports; i++)
+ sky2_gmac_reset(hw, i);
+
+ memset(hw->st_le, 0, hw->st_size * sizeof(struct sky2_status_le));
+ hw->st_idx = 0;
+
+ sky2_write32(hw, STAT_CTRL, SC_STAT_RST_SET);
+ sky2_write32(hw, STAT_CTRL, SC_STAT_RST_CLR);
+
+ sky2_write32(hw, STAT_LIST_ADDR_LO, hw->st_dma);
+ sky2_write32(hw, STAT_LIST_ADDR_HI, (u64) hw->st_dma >> 32);
+
+ /* Set the list last index */
+ sky2_write16(hw, STAT_LAST_IDX, hw->st_size - 1);
+
+ sky2_write16(hw, STAT_TX_IDX_TH, 10);
+ sky2_write8(hw, STAT_FIFO_WM, 16);
+
+ /* set Status-FIFO ISR watermark */
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0)
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 4);
+ else
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
+
+ sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
+ sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
+ sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100));
+
+ /* enable status unit */
+ sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON);
+
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+ }
+
+ /* Take device down (offline).
+ * Equivalent to doing dev_stop() but this does not
+ * inform upper layers of the transition.
+ */
+ static void sky2_detach(struct net_device *dev)
+ {
+ if (netif_running(dev)) {
+ netif_tx_lock(dev);
+ netif_device_detach(dev); /* stop txq */
+ netif_tx_unlock(dev);
+ sky2_down(dev);
+ }
+ }
+
+ /* Bring device back after doing sky2_detach */
+ static int sky2_reattach(struct net_device *dev)
+ {
+ int err = 0;
+
+ if (netif_running(dev)) {
+ err = sky2_up(dev);
+ if (err) {
+ netdev_info(dev, "could not restart %d\n", err);
+ dev_close(dev);
+ } else {
+ netif_device_attach(dev);
+ sky2_set_multicast(dev);
+ }
+ }
+
+ return err;
+ }
+
+ static void sky2_all_down(struct sky2_hw *hw)
+ {
+ int i;
+
+ sky2_read32(hw, B0_IMSK);
+ sky2_write32(hw, B0_IMSK, 0);
+ synchronize_irq(hw->pdev->irq);
+ napi_disable(&hw->napi);
+
+ for (i = 0; i < hw->ports; i++) {
+ struct net_device *dev = hw->dev[i];
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ continue;
+
+ netif_carrier_off(dev);
+ netif_tx_disable(dev);
+ sky2_hw_down(sky2);
+ }
+ }
+
+ static void sky2_all_up(struct sky2_hw *hw)
+ {
+ u32 imask = Y2_IS_BASE;
+ int i;
+
+ for (i = 0; i < hw->ports; i++) {
+ struct net_device *dev = hw->dev[i];
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ continue;
+
+ sky2_hw_up(sky2);
+ sky2_set_multicast(dev);
+ imask |= portirq_msk[i];
+ netif_wake_queue(dev);
+ }
+
+ sky2_write32(hw, B0_IMSK, imask);
+ sky2_read32(hw, B0_IMSK);
+
+ sky2_read32(hw, B0_Y2_SP_LISR);
+ napi_enable(&hw->napi);
+ }
+
+ static void sky2_restart(struct work_struct *work)
+ {
+ struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
+
+ rtnl_lock();
+
+ sky2_all_down(hw);
+ sky2_reset(hw);
+ sky2_all_up(hw);
+
+ rtnl_unlock();
+ }
+
+ static inline u8 sky2_wol_supported(const struct sky2_hw *hw)
+ {
+ return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0;
+ }
+
+ static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+ {
+ const struct sky2_port *sky2 = netdev_priv(dev);
+
+ wol->supported = sky2_wol_supported(sky2->hw);
+ wol->wolopts = sky2->wol;
+ }
+
+ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ bool enable_wakeup = false;
+ int i;
+
+ if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) ||
+ !device_can_wakeup(&hw->pdev->dev))
+ return -EOPNOTSUPP;
+
+ sky2->wol = wol->wolopts;
+
+ for (i = 0; i < hw->ports; i++) {
+ struct net_device *dev = hw->dev[i];
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (sky2->wol)
+ enable_wakeup = true;
+ }
+ device_set_wakeup_enable(&hw->pdev->dev, enable_wakeup);
+
+ return 0;
+ }
+
+ static u32 sky2_supported_modes(const struct sky2_hw *hw)
+ {
+ if (sky2_is_copper(hw)) {
+ u32 modes = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full;
+
+ if (hw->flags & SKY2_HW_GIGABIT)
+ modes |= SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full;
+ return modes;
+ } else
+ return SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full;
+ }
+
+ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ ecmd->transceiver = XCVR_INTERNAL;
+ ecmd->supported = sky2_supported_modes(hw);
+ ecmd->phy_address = PHY_ADDR_MARV;
+ if (sky2_is_copper(hw)) {
+ ecmd->port = PORT_TP;
+ ethtool_cmd_speed_set(ecmd, sky2->speed);
+ ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_TP;
+ } else {
+ ethtool_cmd_speed_set(ecmd, SPEED_1000);
+ ecmd->port = PORT_FIBRE;
+ ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_FIBRE;
+ }
+
+ ecmd->advertising = sky2->advertising;
+ ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_SPEED)
+ ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ ecmd->duplex = sky2->duplex;
+ return 0;
+ }
+
+ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ const struct sky2_hw *hw = sky2->hw;
+ u32 supported = sky2_supported_modes(hw);
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ if (ecmd->advertising & ~supported)
+ return -EINVAL;
+
+ if (sky2_is_copper(hw))
+ sky2->advertising = ecmd->advertising |
+ ADVERTISED_TP |
+ ADVERTISED_Autoneg;
+ else
+ sky2->advertising = ecmd->advertising |
+ ADVERTISED_FIBRE |
+ ADVERTISED_Autoneg;
+
+ sky2->flags |= SKY2_FLAG_AUTO_SPEED;
+ sky2->duplex = -1;
+ sky2->speed = -1;
+ } else {
+ u32 setting;
+ u32 speed = ethtool_cmd_speed(ecmd);
+
+ switch (speed) {
+ case SPEED_1000:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_1000baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_1000baseT_Half;
+ else
+ return -EINVAL;
+ break;
+ case SPEED_100:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_100baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_100baseT_Half;
+ else
+ return -EINVAL;
+ break;
+
+ case SPEED_10:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_10baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_10baseT_Half;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((setting & supported) == 0)
+ return -EINVAL;
+
+ sky2->speed = speed;
+ sky2->duplex = ecmd->duplex;
+ sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
+ }
+
+ if (netif_running(dev)) {
+ sky2_phy_reinit(sky2);
+ sky2_set_multicast(dev);
+ }
+
+ return 0;
+ }
+
+ static void sky2_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "N/A");
+ strcpy(info->bus_info, pci_name(sky2->hw->pdev));
+ }
+
+ static const struct sky2_stat {
+ char name[ETH_GSTRING_LEN];
+ u16 offset;
+ } sky2_stats[] = {
+ { "tx_bytes", GM_TXO_OK_HI },
+ { "rx_bytes", GM_RXO_OK_HI },
+ { "tx_broadcast", GM_TXF_BC_OK },
+ { "rx_broadcast", GM_RXF_BC_OK },
+ { "tx_multicast", GM_TXF_MC_OK },
+ { "rx_multicast", GM_RXF_MC_OK },
+ { "tx_unicast", GM_TXF_UC_OK },
+ { "rx_unicast", GM_RXF_UC_OK },
+ { "tx_mac_pause", GM_TXF_MPAUSE },
+ { "rx_mac_pause", GM_RXF_MPAUSE },
+ { "collisions", GM_TXF_COL },
+ { "late_collision",GM_TXF_LAT_COL },
+ { "aborted", GM_TXF_ABO_COL },
+ { "single_collisions", GM_TXF_SNG_COL },
+ { "multi_collisions", GM_TXF_MUL_COL },
+
+ { "rx_short", GM_RXF_SHT },
+ { "rx_runt", GM_RXE_FRAG },
+ { "rx_64_byte_packets", GM_RXF_64B },
+ { "rx_65_to_127_byte_packets", GM_RXF_127B },
+ { "rx_128_to_255_byte_packets", GM_RXF_255B },
+ { "rx_256_to_511_byte_packets", GM_RXF_511B },
+ { "rx_512_to_1023_byte_packets", GM_RXF_1023B },
+ { "rx_1024_to_1518_byte_packets", GM_RXF_1518B },
+ { "rx_1518_to_max_byte_packets", GM_RXF_MAX_SZ },
+ { "rx_too_long", GM_RXF_LNG_ERR },
+ { "rx_fifo_overflow", GM_RXE_FIFO_OV },
+ { "rx_jabber", GM_RXF_JAB_PKT },
+ { "rx_fcs_error", GM_RXF_FCS_ERR },
+
+ { "tx_64_byte_packets", GM_TXF_64B },
+ { "tx_65_to_127_byte_packets", GM_TXF_127B },
+ { "tx_128_to_255_byte_packets", GM_TXF_255B },
+ { "tx_256_to_511_byte_packets", GM_TXF_511B },
+ { "tx_512_to_1023_byte_packets", GM_TXF_1023B },
+ { "tx_1024_to_1518_byte_packets", GM_TXF_1518B },
+ { "tx_1519_to_max_byte_packets", GM_TXF_MAX_SZ },
+ { "tx_fifo_underrun", GM_TXE_FIFO_UR },
+ };
+
+ static u32 sky2_get_msglevel(struct net_device *netdev)
+ {
+ struct sky2_port *sky2 = netdev_priv(netdev);
+ return sky2->msg_enable;
+ }
+
+ static int sky2_nway_reset(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (!netif_running(dev) || !(sky2->flags & SKY2_FLAG_AUTO_SPEED))
+ return -EINVAL;
+
+ sky2_phy_reinit(sky2);
+ sky2_set_multicast(dev);
+
+ return 0;
+ }
+
+ static void sky2_phy_stats(struct sky2_port *sky2, u64 * data, unsigned count)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ int i;
+
+ data[0] = get_stats64(hw, port, GM_TXO_OK_LO);
+ data[1] = get_stats64(hw, port, GM_RXO_OK_LO);
+
+ for (i = 2; i < count; i++)
+ data[i] = get_stats32(hw, port, sky2_stats[i].offset);
+ }
+
+ static void sky2_set_msglevel(struct net_device *netdev, u32 value)
+ {
+ struct sky2_port *sky2 = netdev_priv(netdev);
+ sky2->msg_enable = value;
+ }
+
+ static int sky2_get_sset_count(struct net_device *dev, int sset)
+ {
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(sky2_stats);
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ static void sky2_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 * data)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ sky2_phy_stats(sky2, data, ARRAY_SIZE(sky2_stats));
+ }
+
+ static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+ {
+ int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < ARRAY_SIZE(sky2_stats); i++)
+ memcpy(data + i * ETH_GSTRING_LEN,
+ sky2_stats[i].name, ETH_GSTRING_LEN);
+ break;
+ }
+ }
+
+ static int sky2_set_mac_address(struct net_device *dev, void *p)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ const struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_1 + port * 8,
+ dev->dev_addr, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_2 + port * 8,
+ dev->dev_addr, ETH_ALEN);
+
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
+
+ return 0;
+ }
+
+ static inline void sky2_add_filter(u8 filter[8], const u8 *addr)
+ {
+ u32 bit;
+
+ bit = ether_crc(ETH_ALEN, addr) & 63;
+ filter[bit >> 3] |= 1 << (bit & 7);
+ }
+
+ static void sky2_set_multicast(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ struct netdev_hw_addr *ha;
+ u16 reg;
+ u8 filter[8];
+ int rx_pause;
+ static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
+
+ rx_pause = (sky2->flow_status == FC_RX || sky2->flow_status == FC_BOTH);
+ memset(filter, 0, sizeof(filter));
+
+ reg = gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA;
+
+ if (dev->flags & IFF_PROMISC) /* promiscuous */
+ reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+ else if (dev->flags & IFF_ALLMULTI)
+ memset(filter, 0xff, sizeof(filter));
+ else if (netdev_mc_empty(dev) && !rx_pause)
+ reg &= ~GM_RXCR_MCF_ENA;
+ else {
+ reg |= GM_RXCR_MCF_ENA;
+
+ if (rx_pause)
+ sky2_add_filter(filter, pause_mc_addr);
+
+ netdev_for_each_mc_addr(ha, dev)
+ sky2_add_filter(filter, ha->addr);
+ }
+
+ gma_write16(hw, port, GM_MC_ADDR_H1,
+ (u16) filter[0] | ((u16) filter[1] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H2,
+ (u16) filter[2] | ((u16) filter[3] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H3,
+ (u16) filter[4] | ((u16) filter[5] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H4,
+ (u16) filter[6] | ((u16) filter[7] << 8));
+
+ gma_write16(hw, port, GM_RX_CTRL, reg);
+ }
+
+ static struct rtnl_link_stats64 *sky2_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned int start;
+ u64 _bytes, _packets;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&sky2->rx_stats.syncp);
+ _bytes = sky2->rx_stats.bytes;
+ _packets = sky2->rx_stats.packets;
+ } while (u64_stats_fetch_retry_bh(&sky2->rx_stats.syncp, start));
+
+ stats->rx_packets = _packets;
+ stats->rx_bytes = _bytes;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&sky2->tx_stats.syncp);
+ _bytes = sky2->tx_stats.bytes;
+ _packets = sky2->tx_stats.packets;
+ } while (u64_stats_fetch_retry_bh(&sky2->tx_stats.syncp, start));
+
+ stats->tx_packets = _packets;
+ stats->tx_bytes = _bytes;
+
+ stats->multicast = get_stats32(hw, port, GM_RXF_MC_OK)
+ + get_stats32(hw, port, GM_RXF_BC_OK);
+
+ stats->collisions = get_stats32(hw, port, GM_TXF_COL);
+
+ stats->rx_length_errors = get_stats32(hw, port, GM_RXF_LNG_ERR);
+ stats->rx_crc_errors = get_stats32(hw, port, GM_RXF_FCS_ERR);
+ stats->rx_frame_errors = get_stats32(hw, port, GM_RXF_SHT)
+ + get_stats32(hw, port, GM_RXE_FRAG);
+ stats->rx_over_errors = get_stats32(hw, port, GM_RXE_FIFO_OV);
+
+ stats->rx_dropped = dev->stats.rx_dropped;
+ stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
+ stats->tx_fifo_errors = dev->stats.tx_fifo_errors;
+
+ return stats;
+ }
+
+ /* Can have one global because blinking is controlled by
+ * ethtool and that is always under RTNL mutex
+ */
+ static void sky2_led(struct sky2_port *sky2, enum led_mode mode)
+ {
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+
+ spin_lock_bh(&sky2->phy_lock);
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+ hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_SUPR) {
+ u16 pg;
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ switch (mode) {
+ case MO_LED_OFF:
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ PHY_M_LEDC_LOS_CTRL(8) |
+ PHY_M_LEDC_INIT_CTRL(8) |
+ PHY_M_LEDC_STA1_CTRL(8) |
+ PHY_M_LEDC_STA0_CTRL(8));
+ break;
+ case MO_LED_ON:
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ PHY_M_LEDC_LOS_CTRL(9) |
+ PHY_M_LEDC_INIT_CTRL(9) |
+ PHY_M_LEDC_STA1_CTRL(9) |
+ PHY_M_LEDC_STA0_CTRL(9));
+ break;
+ case MO_LED_BLINK:
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ PHY_M_LEDC_LOS_CTRL(0xa) |
+ PHY_M_LEDC_INIT_CTRL(0xa) |
+ PHY_M_LEDC_STA1_CTRL(0xa) |
+ PHY_M_LEDC_STA0_CTRL(0xa));
+ break;
+ case MO_LED_NORM:
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ PHY_M_LEDC_LOS_CTRL(1) |
+ PHY_M_LEDC_INIT_CTRL(8) |
+ PHY_M_LEDC_STA1_CTRL(7) |
+ PHY_M_LEDC_STA0_CTRL(7));
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ } else
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(mode) |
+ PHY_M_LED_MO_10(mode) |
+ PHY_M_LED_MO_100(mode) |
+ PHY_M_LED_MO_1000(mode) |
+ PHY_M_LED_MO_RX(mode) |
+ PHY_M_LED_MO_TX(mode));
+
+ spin_unlock_bh(&sky2->phy_lock);
+ }
+
+ /* blink LED's for finding board */
+ static int sky2_set_phys_id(struct net_device *dev,
+ enum ethtool_phys_id_state state)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ return 1; /* cycle on/off once per second */
+ case ETHTOOL_ID_INACTIVE:
+ sky2_led(sky2, MO_LED_NORM);
+ break;
+ case ETHTOOL_ID_ON:
+ sky2_led(sky2, MO_LED_ON);
+ break;
+ case ETHTOOL_ID_OFF:
+ sky2_led(sky2, MO_LED_OFF);
+ break;
+ }
+
+ return 0;
+ }
+
+ static void sky2_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *ecmd)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ switch (sky2->flow_mode) {
+ case FC_NONE:
+ ecmd->tx_pause = ecmd->rx_pause = 0;
+ break;
+ case FC_TX:
+ ecmd->tx_pause = 1, ecmd->rx_pause = 0;
+ break;
+ case FC_RX:
+ ecmd->tx_pause = 0, ecmd->rx_pause = 1;
+ break;
+ case FC_BOTH:
+ ecmd->tx_pause = ecmd->rx_pause = 1;
+ }
+
+ ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_PAUSE)
+ ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ }
+
+ static int sky2_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *ecmd)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (ecmd->autoneg == AUTONEG_ENABLE)
+ sky2->flags |= SKY2_FLAG_AUTO_PAUSE;
+ else
+ sky2->flags &= ~SKY2_FLAG_AUTO_PAUSE;
+
+ sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause);
+
+ if (netif_running(dev))
+ sky2_phy_reinit(sky2);
+
+ return 0;
+ }
+
+ static int sky2_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ecmd)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_STOP)
+ ecmd->tx_coalesce_usecs = 0;
+ else {
+ u32 clks = sky2_read32(hw, STAT_TX_TIMER_INI);
+ ecmd->tx_coalesce_usecs = sky2_clk2us(hw, clks);
+ }
+ ecmd->tx_max_coalesced_frames = sky2_read16(hw, STAT_TX_IDX_TH);
+
+ if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_STOP)
+ ecmd->rx_coalesce_usecs = 0;
+ else {
+ u32 clks = sky2_read32(hw, STAT_LEV_TIMER_INI);
+ ecmd->rx_coalesce_usecs = sky2_clk2us(hw, clks);
+ }
+ ecmd->rx_max_coalesced_frames = sky2_read8(hw, STAT_FIFO_WM);
+
+ if (sky2_read8(hw, STAT_ISR_TIMER_CTRL) == TIM_STOP)
+ ecmd->rx_coalesce_usecs_irq = 0;
+ else {
+ u32 clks = sky2_read32(hw, STAT_ISR_TIMER_INI);
+ ecmd->rx_coalesce_usecs_irq = sky2_clk2us(hw, clks);
+ }
+
+ ecmd->rx_max_coalesced_frames_irq = sky2_read8(hw, STAT_FIFO_ISR_WM);
+
+ return 0;
+ }
+
+ /* Note: this affect both ports */
+ static int sky2_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ecmd)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ const u32 tmax = sky2_clk2us(hw, 0x0ffffff);
+
+ if (ecmd->tx_coalesce_usecs > tmax ||
+ ecmd->rx_coalesce_usecs > tmax ||
+ ecmd->rx_coalesce_usecs_irq > tmax)
+ return -EINVAL;
+
+ if (ecmd->tx_max_coalesced_frames >= sky2->tx_ring_size-1)
+ return -EINVAL;
+ if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING)
+ return -EINVAL;
+ if (ecmd->rx_max_coalesced_frames_irq > RX_MAX_PENDING)
+ return -EINVAL;
+
+ if (ecmd->tx_coalesce_usecs == 0)
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ else {
+ sky2_write32(hw, STAT_TX_TIMER_INI,
+ sky2_us2clk(hw, ecmd->tx_coalesce_usecs));
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ }
+ sky2_write16(hw, STAT_TX_IDX_TH, ecmd->tx_max_coalesced_frames);
+
+ if (ecmd->rx_coalesce_usecs == 0)
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP);
+ else {
+ sky2_write32(hw, STAT_LEV_TIMER_INI,
+ sky2_us2clk(hw, ecmd->rx_coalesce_usecs));
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ }
+ sky2_write8(hw, STAT_FIFO_WM, ecmd->rx_max_coalesced_frames);
+
+ if (ecmd->rx_coalesce_usecs_irq == 0)
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
+ else {
+ sky2_write32(hw, STAT_ISR_TIMER_INI,
+ sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+ }
+ sky2_write8(hw, STAT_FIFO_ISR_WM, ecmd->rx_max_coalesced_frames_irq);
+ return 0;
+ }
+
+ static void sky2_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ering)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ ering->rx_max_pending = RX_MAX_PENDING;
+ ering->tx_max_pending = TX_MAX_PENDING;
+
+ ering->rx_pending = sky2->rx_pending;
+ ering->tx_pending = sky2->tx_pending;
+ }
+
+ static int sky2_set_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ering)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (ering->rx_pending > RX_MAX_PENDING ||
+ ering->rx_pending < 8 ||
+ ering->tx_pending < TX_MIN_PENDING ||
+ ering->tx_pending > TX_MAX_PENDING)
+ return -EINVAL;
+
+ sky2_detach(dev);
+
+ sky2->rx_pending = ering->rx_pending;
+ sky2->tx_pending = ering->tx_pending;
+ sky2->tx_ring_size = roundup_pow_of_two(sky2->tx_pending+1);
+
+ return sky2_reattach(dev);
+ }
+
+ static int sky2_get_regs_len(struct net_device *dev)
+ {
+ return 0x4000;
+ }
+
+ static int sky2_reg_access_ok(struct sky2_hw *hw, unsigned int b)
+ {
+ /* This complicated switch statement is to make sure and
+ * only access regions that are unreserved.
+ * Some blocks are only valid on dual port cards.
+ */
+ switch (b) {
+ /* second port */
+ case 5: /* Tx Arbiter 2 */
+ case 9: /* RX2 */
+ case 14 ... 15: /* TX2 */
+ case 17: case 19: /* Ram Buffer 2 */
+ case 22 ... 23: /* Tx Ram Buffer 2 */
+ case 25: /* Rx MAC Fifo 1 */
+ case 27: /* Tx MAC Fifo 2 */
+ case 31: /* GPHY 2 */
+ case 40 ... 47: /* Pattern Ram 2 */
+ case 52: case 54: /* TCP Segmentation 2 */
+ case 112 ... 116: /* GMAC 2 */
+ return hw->ports > 1;
+
+ case 0: /* Control */
+ case 2: /* Mac address */
+ case 4: /* Tx Arbiter 1 */
+ case 7: /* PCI express reg */
+ case 8: /* RX1 */
+ case 12 ... 13: /* TX1 */
+ case 16: case 18:/* Rx Ram Buffer 1 */
+ case 20 ... 21: /* Tx Ram Buffer 1 */
+ case 24: /* Rx MAC Fifo 1 */
+ case 26: /* Tx MAC Fifo 1 */
+ case 28 ... 29: /* Descriptor and status unit */
+ case 30: /* GPHY 1*/
+ case 32 ... 39: /* Pattern Ram 1 */
+ case 48: case 50: /* TCP Segmentation 1 */
+ case 56 ... 60: /* PCI space */
+ case 80 ... 84: /* GMAC 1 */
+ return 1;
+
+ default:
+ return 0;
+ }
+ }
+
+ /*
+ * Returns copy of control register region
+ * Note: ethtool_get_regs always provides full size (16k) buffer
+ */
+ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+ {
+ const struct sky2_port *sky2 = netdev_priv(dev);
+ const void __iomem *io = sky2->hw->regs;
+ unsigned int b;
+
+ regs->version = 1;
+
+ for (b = 0; b < 128; b++) {
+ /* skip poisonous diagnostic ram region in block 3 */
+ if (b == 3)
+ memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10);
+ else if (sky2_reg_access_ok(sky2->hw, b))
+ memcpy_fromio(p, io, 128);
+ else
+ memset(p, 0, 128);
+
+ p += 128;
+ io += 128;
+ }
+ }
+
+ static int sky2_get_eeprom_len(struct net_device *dev)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ u16 reg2;
+
+ reg2 = sky2_pci_read16(hw, PCI_DEV_REG2);
+ return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+ }
+
+ static int sky2_vpd_wait(const struct sky2_hw *hw, int cap, u16 busy)
+ {
+ unsigned long start = jiffies;
+
+ while ( (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F) == busy) {
+ /* Can take up to 10.6 ms for write */
+ if (time_after(jiffies, start + HZ/4)) {
+ dev_err(&hw->pdev->dev, "VPD cycle timed out\n");
+ return -ETIMEDOUT;
+ }
+ mdelay(1);
+ }
+
+ return 0;
+ }
+
+ static int sky2_vpd_read(struct sky2_hw *hw, int cap, void *data,
+ u16 offset, size_t length)
+ {
+ int rc = 0;
+
+ while (length > 0) {
+ u32 val;
+
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+ rc = sky2_vpd_wait(hw, cap, 0);
+ if (rc)
+ break;
+
+ val = sky2_pci_read32(hw, cap + PCI_VPD_DATA);
+
+ memcpy(data, &val, min(sizeof(val), length));
+ offset += sizeof(u32);
+ data += sizeof(u32);
+ length -= sizeof(u32);
+ }
+
+ return rc;
+ }
+
+ static int sky2_vpd_write(struct sky2_hw *hw, int cap, const void *data,
+ u16 offset, unsigned int length)
+ {
+ unsigned int i;
+ int rc = 0;
+
+ for (i = 0; i < length; i += sizeof(u32)) {
+ u32 val = *(u32 *)(data + i);
+
+ sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
+ sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+
+ rc = sky2_vpd_wait(hw, cap, PCI_VPD_ADDR_F);
+ if (rc)
+ break;
+ }
+ return rc;
+ }
+
+ static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+
+ if (!cap)
+ return -EINVAL;
+
+ eeprom->magic = SKY2_EEPROM_MAGIC;
+
+ return sky2_vpd_read(sky2->hw, cap, data, eeprom->offset, eeprom->len);
+ }
+
+ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+
+ if (!cap)
+ return -EINVAL;
+
+ if (eeprom->magic != SKY2_EEPROM_MAGIC)
+ return -EINVAL;
+
+ /* Partial writes not supported */
+ if ((eeprom->offset & 3) || (eeprom->len & 3))
+ return -EINVAL;
+
+ return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len);
+ }
+
+ static u32 sky2_fix_features(struct net_device *dev, u32 features)
+ {
+ const struct sky2_port *sky2 = netdev_priv(dev);
+ const struct sky2_hw *hw = sky2->hw;
+
+ /* In order to do Jumbo packets on these chips, need to turn off the
+ * transmit store/forward. Therefore checksum offload won't work.
+ */
+ if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ netdev_info(dev, "checksum offload not possible with jumbo frames\n");
+ features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM);
+ }
+
+ /* Some hardware requires receive checksum for RSS to work. */
+ if ( (features & NETIF_F_RXHASH) &&
+ !(features & NETIF_F_RXCSUM) &&
+ (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
+ netdev_info(dev, "receive hashing forces receive checksum\n");
+ features |= NETIF_F_RXCSUM;
+ }
+
+ return features;
+ }
+
+ static int sky2_set_features(struct net_device *dev, u32 features)
+ {
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u32 changed = dev->features ^ features;
+
+ if (changed & NETIF_F_RXCSUM) {
+ u32 on = features & NETIF_F_RXCSUM;
+ sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ }
+
+ if (changed & NETIF_F_RXHASH)
+ rx_set_rss(dev, features);
+
+ if (changed & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX))
+ sky2_vlan_mode(dev, features);
+
+ return 0;
+ }
+
+ static const struct ethtool_ops sky2_ethtool_ops = {
+ .get_settings = sky2_get_settings,
+ .set_settings = sky2_set_settings,
+ .get_drvinfo = sky2_get_drvinfo,
+ .get_wol = sky2_get_wol,
+ .set_wol = sky2_set_wol,
+ .get_msglevel = sky2_get_msglevel,
+ .set_msglevel = sky2_set_msglevel,
+ .nway_reset = sky2_nway_reset,
+ .get_regs_len = sky2_get_regs_len,
+ .get_regs = sky2_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = sky2_get_eeprom_len,
+ .get_eeprom = sky2_get_eeprom,
+ .set_eeprom = sky2_set_eeprom,
+ .get_strings = sky2_get_strings,
+ .get_coalesce = sky2_get_coalesce,
+ .set_coalesce = sky2_set_coalesce,
+ .get_ringparam = sky2_get_ringparam,
+ .set_ringparam = sky2_set_ringparam,
+ .get_pauseparam = sky2_get_pauseparam,
+ .set_pauseparam = sky2_set_pauseparam,
+ .set_phys_id = sky2_set_phys_id,
+ .get_sset_count = sky2_get_sset_count,
+ .get_ethtool_stats = sky2_get_ethtool_stats,
+ };
+
+ #ifdef CONFIG_SKY2_DEBUG
+
+ static struct dentry *sky2_debug;
+
+
+ /*
+ * Read and parse the first part of Vital Product Data
+ */
+ #define VPD_SIZE 128
+ #define VPD_MAGIC 0x82
+
+ static const struct vpd_tag {
+ char tag[2];
+ char *label;
+ } vpd_tags[] = {
+ { "PN", "Part Number" },
+ { "EC", "Engineering Level" },
+ { "MN", "Manufacturer" },
+ { "SN", "Serial Number" },
+ { "YA", "Asset Tag" },
+ { "VL", "First Error Log Message" },
+ { "VF", "Second Error Log Message" },
+ { "VB", "Boot Agent ROM Configuration" },
+ { "VE", "EFI UNDI Configuration" },
+ };
+
+ static void sky2_show_vpd(struct seq_file *seq, struct sky2_hw *hw)
+ {
+ size_t vpd_size;
+ loff_t offs;
+ u8 len;
+ unsigned char *buf;
+ u16 reg2;
+
+ reg2 = sky2_pci_read16(hw, PCI_DEV_REG2);
+ vpd_size = 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+
+ seq_printf(seq, "%s Product Data\n", pci_name(hw->pdev));
+ buf = kmalloc(vpd_size, GFP_KERNEL);
+ if (!buf) {
+ seq_puts(seq, "no memory!\n");
+ return;
+ }
+
+ if (pci_read_vpd(hw->pdev, 0, vpd_size, buf) < 0) {
+ seq_puts(seq, "VPD read failed\n");
+ goto out;
+ }
+
+ if (buf[0] != VPD_MAGIC) {
+ seq_printf(seq, "VPD tag mismatch: %#x\n", buf[0]);
+ goto out;
+ }
+ len = buf[1];
+ if (len == 0 || len > vpd_size - 4) {
+ seq_printf(seq, "Invalid id length: %d\n", len);
+ goto out;
+ }
+
+ seq_printf(seq, "%.*s\n", len, buf + 3);
+ offs = len + 3;
+
+ while (offs < vpd_size - 4) {
+ int i;
+
+ if (!memcmp("RW", buf + offs, 2)) /* end marker */
+ break;
+ len = buf[offs + 2];
+ if (offs + len + 3 >= vpd_size)
+ break;
+
+ for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) {
+ if (!memcmp(vpd_tags[i].tag, buf + offs, 2)) {
+ seq_printf(seq, " %s: %.*s\n",
+ vpd_tags[i].label, len, buf + offs + 3);
+ break;
+ }
+ }
+ offs += len + 3;
+ }
+ out:
+ kfree(buf);
+ }
+
+ static int sky2_debug_show(struct seq_file *seq, void *v)
+ {
+ struct net_device *dev = seq->private;
+ const struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned idx, last;
+ int sop;
+
+ sky2_show_vpd(seq, hw);
+
+ seq_printf(seq, "\nIRQ src=%x mask=%x control=%x\n",
+ sky2_read32(hw, B0_ISRC),
+ sky2_read32(hw, B0_IMSK),
+ sky2_read32(hw, B0_Y2_SP_ICR));
+
+ if (!netif_running(dev)) {
+ seq_printf(seq, "network not running\n");
+ return 0;
+ }
+
+ napi_disable(&hw->napi);
+ last = sky2_read16(hw, STAT_PUT_IDX);
+
+ seq_printf(seq, "Status ring %u\n", hw->st_size);
+ if (hw->st_idx == last)
+ seq_puts(seq, "Status ring (empty)\n");
+ else {
+ seq_puts(seq, "Status ring\n");
+ for (idx = hw->st_idx; idx != last && idx < hw->st_size;
+ idx = RING_NEXT(idx, hw->st_size)) {
+ const struct sky2_status_le *le = hw->st_le + idx;
+ seq_printf(seq, "[%d] %#x %d %#x\n",
+ idx, le->opcode, le->length, le->status);
+ }
+ seq_puts(seq, "\n");
+ }
+
+ seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n",
+ sky2->tx_cons, sky2->tx_prod,
+ sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
+ sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE)));
+
+ /* Dump contents of tx ring */
+ sop = 1;
+ for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < sky2->tx_ring_size;
+ idx = RING_NEXT(idx, sky2->tx_ring_size)) {
+ const struct sky2_tx_le *le = sky2->tx_le + idx;
+ u32 a = le32_to_cpu(le->addr);
+
+ if (sop)
+ seq_printf(seq, "%u:", idx);
+ sop = 0;
+
+ switch (le->opcode & ~HW_OWNER) {
+ case OP_ADDR64:
+ seq_printf(seq, " %#x:", a);
+ break;
+ case OP_LRGLEN:
+ seq_printf(seq, " mtu=%d", a);
+ break;
+ case OP_VLAN:
+ seq_printf(seq, " vlan=%d", be16_to_cpu(le->length));
+ break;
+ case OP_TCPLISW:
+ seq_printf(seq, " csum=%#x", a);
+ break;
+ case OP_LARGESEND:
+ seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ case OP_PACKET:
+ seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ case OP_BUFFER:
+ seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ default:
+ seq_printf(seq, " op=%#x,%#x(%d)", le->opcode,
+ a, le16_to_cpu(le->length));
+ }
+
+ if (le->ctrl & EOP) {
+ seq_putc(seq, '\n');
+ sop = 1;
+ }
+ }
+
+ seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
+
+ sky2_read32(hw, B0_Y2_SP_LISR);
+ napi_enable(&hw->napi);
+ return 0;
+ }
+
+ static int sky2_debug_open(struct inode *inode, struct file *file)
+ {
+ return single_open(file, sky2_debug_show, inode->i_private);
+ }
+
+ static const struct file_operations sky2_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = sky2_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ };
+
+ /*
+ * Use network device events to create/remove/rename
+ * debugfs file entries
+ */
+ static int sky2_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+ {
+ struct net_device *dev = ptr;
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+ if (sky2->debugfs) {
+ sky2->debugfs = debugfs_rename(sky2_debug, sky2->debugfs,
+ sky2_debug, dev->name);
+ }
+ break;
+
+ case NETDEV_GOING_DOWN:
+ if (sky2->debugfs) {
+ netdev_printk(KERN_DEBUG, dev, "remove debugfs\n");
+ debugfs_remove(sky2->debugfs);
+ sky2->debugfs = NULL;
+ }
+ break;
+
+ case NETDEV_UP:
+ sky2->debugfs = debugfs_create_file(dev->name, S_IRUGO,
+ sky2_debug, dev,
+ &sky2_debug_fops);
+ if (IS_ERR(sky2->debugfs))
+ sky2->debugfs = NULL;
+ }
+
+ return NOTIFY_DONE;
+ }
+
+ static struct notifier_block sky2_notifier = {
+ .notifier_call = sky2_device_event,
+ };
+
+
+ static __init void sky2_debug_init(void)
+ {
+ struct dentry *ent;
+
+ ent = debugfs_create_dir("sky2", NULL);
+ if (!ent || IS_ERR(ent))
+ return;
+
+ sky2_debug = ent;
+ register_netdevice_notifier(&sky2_notifier);
+ }
+
+ static __exit void sky2_debug_cleanup(void)
+ {
+ if (sky2_debug) {
+ unregister_netdevice_notifier(&sky2_notifier);
+ debugfs_remove(sky2_debug);
+ sky2_debug = NULL;
+ }
+ }
+
+ #else
+ #define sky2_debug_init()
+ #define sky2_debug_cleanup()
+ #endif
+
+ /* Two copies of network device operations to handle special case of
+ not allowing netpoll on second port */
+ static const struct net_device_ops sky2_netdev_ops[2] = {
+ {
+ .ndo_open = sky2_up,
+ .ndo_stop = sky2_down,
+ .ndo_start_xmit = sky2_xmit_frame,
+ .ndo_do_ioctl = sky2_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = sky2_set_mac_address,
+ .ndo_set_rx_mode = sky2_set_multicast,
+ .ndo_change_mtu = sky2_change_mtu,
+ .ndo_fix_features = sky2_fix_features,
+ .ndo_set_features = sky2_set_features,
+ .ndo_tx_timeout = sky2_tx_timeout,
+ .ndo_get_stats64 = sky2_get_stats,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = sky2_netpoll,
+ #endif
+ },
+ {
+ .ndo_open = sky2_up,
+ .ndo_stop = sky2_down,
+ .ndo_start_xmit = sky2_xmit_frame,
+ .ndo_do_ioctl = sky2_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = sky2_set_mac_address,
+ .ndo_set_rx_mode = sky2_set_multicast,
+ .ndo_change_mtu = sky2_change_mtu,
+ .ndo_fix_features = sky2_fix_features,
+ .ndo_set_features = sky2_set_features,
+ .ndo_tx_timeout = sky2_tx_timeout,
+ .ndo_get_stats64 = sky2_get_stats,
+ },
+ };
+
+ /* Initialize network device */
+ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
+ unsigned port,
+ int highmem, int wol)
+ {
+ struct sky2_port *sky2;
+ struct net_device *dev = alloc_etherdev(sizeof(*sky2));
+
+ if (!dev) {
+ dev_err(&hw->pdev->dev, "etherdev alloc failed\n");
+ return NULL;
+ }
+
+ SET_NETDEV_DEV(dev, &hw->pdev->dev);
+ dev->irq = hw->pdev->irq;
+ SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
+ dev->watchdog_timeo = TX_WATCHDOG;
+ dev->netdev_ops = &sky2_netdev_ops[port];
+
+ sky2 = netdev_priv(dev);
+ sky2->netdev = dev;
+ sky2->hw = hw;
+ sky2->msg_enable = netif_msg_init(debug, default_msg);
+
+ /* Auto speed and flow control */
+ sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE;
+ if (hw->chip_id != CHIP_ID_YUKON_XL)
+ dev->hw_features |= NETIF_F_RXCSUM;
+
+ sky2->flow_mode = FC_BOTH;
+
+ sky2->duplex = -1;
+ sky2->speed = -1;
+ sky2->advertising = sky2_supported_modes(hw);
+ sky2->wol = wol;
+
+ spin_lock_init(&sky2->phy_lock);
+
+ sky2->tx_pending = TX_DEF_PENDING;
+ sky2->tx_ring_size = roundup_pow_of_two(TX_DEF_PENDING+1);
+ sky2->rx_pending = RX_DEF_PENDING;
+
+ hw->dev[port] = dev;
+
+ sky2->port = port;
+
+ dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO;
+
+ if (highmem)
+ dev->features |= NETIF_F_HIGHDMA;
+
+ /* Enable receive hashing unless hardware is known broken */
+ if (!(hw->flags & SKY2_HW_RSS_BROKEN))
+ dev->hw_features |= NETIF_F_RXHASH;
+
+ if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) {
+ dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_features |= SKY2_VLAN_OFFLOADS;
+ }
+
+ dev->features |= dev->hw_features;
+
+ /* read the mac address */
+ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ return dev;
+ }
+
+ static void __devinit sky2_show_addr(struct net_device *dev)
+ {
+ const struct sky2_port *sky2 = netdev_priv(dev);
+
+ netif_info(sky2, probe, dev, "addr %pM\n", dev->dev_addr);
+ }
+
+ /* Handle software interrupt used during MSI test */
+ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
+ {
+ struct sky2_hw *hw = dev_id;
+ u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+
+ if (status == 0)
+ return IRQ_NONE;
+
+ if (status & Y2_IS_IRQ_SW) {
+ hw->flags |= SKY2_HW_USE_MSI;
+ wake_up(&hw->msi_wait);
+ sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
+ }
+ sky2_write32(hw, B0_Y2_SP_ICR, 2);
+
+ return IRQ_HANDLED;
+ }
+
+ /* Test interrupt path by forcing a a software IRQ */
+ static int __devinit sky2_test_msi(struct sky2_hw *hw)
+ {
+ struct pci_dev *pdev = hw->pdev;
+ int err;
+
+ init_waitqueue_head(&hw->msi_wait);
+
+ sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
+
+ err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw);
+ if (err) {
+ dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
+ return err;
+ }
+
+ sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
+ sky2_read8(hw, B0_CTST);
+
+ wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10);
+
+ if (!(hw->flags & SKY2_HW_USE_MSI)) {
+ /* MSI test failed, go back to INTx mode */
+ dev_info(&pdev->dev, "No interrupt generated using MSI, "
+ "switching to INTx mode.\n");
+
+ err = -EOPNOTSUPP;
+ sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
+ }
+
+ sky2_write32(hw, B0_IMSK, 0);
+ sky2_read32(hw, B0_IMSK);
+
+ free_irq(pdev->irq, hw);
+
+ return err;
+ }
+
+ /* This driver supports yukon2 chipset only */
+ static const char *sky2_name(u8 chipid, char *buf, int sz)
+ {
+ const char *name[] = {
+ "XL", /* 0xb3 */
+ "EC Ultra", /* 0xb4 */
+ "Extreme", /* 0xb5 */
+ "EC", /* 0xb6 */
+ "FE", /* 0xb7 */
+ "FE+", /* 0xb8 */
+ "Supreme", /* 0xb9 */
+ "UL 2", /* 0xba */
+ "Unknown", /* 0xbb */
+ "Optima", /* 0xbc */
+ "Optima Prime", /* 0xbd */
+ "Optima 2", /* 0xbe */
+ };
+
+ if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2)
+ strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
+ else
+ snprintf(buf, sz, "(chip %#x)", chipid);
+ return buf;
+ }
+
+ static int __devinit sky2_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+ struct net_device *dev, *dev1;
+ struct sky2_hw *hw;
+ int err, using_dac = 0, wol_default;
+ u32 reg;
+ char buf1[16];
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "cannot enable PCI device\n");
+ goto err_out;
+ }
+
+ /* Get configuration information
+ * Note: only regular PCI config access once to test for HW issues
+ * other PCI access through shared memory for speed and to
+ * avoid MMCONFIG problems.
+ */
+ err = pci_read_config_dword(pdev, PCI_DEV_REG2, ®);
+ if (err) {
+ dev_err(&pdev->dev, "PCI read config failed\n");
+ goto err_out;
+ }
+
+ if (~reg == 0) {
+ dev_err(&pdev->dev, "PCI configuration read error\n");
+ goto err_out;
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+ goto err_out_disable;
+ }
+
+ pci_set_master(pdev);
+
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))) {
+ using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (err < 0) {
+ dev_err(&pdev->dev, "unable to obtain 64 bit DMA "
+ "for consistent allocations\n");
+ goto err_out_free_regions;
+ }
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev, "no usable DMA configuration\n");
+ goto err_out_free_regions;
+ }
+ }
+
+
+ #ifdef __BIG_ENDIAN
+ /* The sk98lin vendor driver uses hardware byte swapping but
+ * this driver uses software swapping.
+ */
+ reg &= ~PCI_REV_DESC;
+ err = pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
+ if (err) {
+ dev_err(&pdev->dev, "PCI write config failed\n");
+ goto err_out_free_regions;
+ }
+ #endif
+
+ wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0;
+
+ err = -ENOMEM;
+
+ hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:")
+ + strlen(pci_name(pdev)) + 1, GFP_KERNEL);
+ if (!hw) {
+ dev_err(&pdev->dev, "cannot allocate hardware struct\n");
+ goto err_out_free_regions;
+ }
+
+ hw->pdev = pdev;
+ sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev));
+
+ hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
+ if (!hw->regs) {
+ dev_err(&pdev->dev, "cannot map device registers\n");
+ goto err_out_free_hw;
+ }
+
+ err = sky2_init(hw);
+ if (err)
+ goto err_out_iounmap;
+
+ /* ring for status responses */
+ hw->st_size = hw->ports * roundup_pow_of_two(3*RX_MAX_PENDING + TX_MAX_PENDING);
+ hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
+ &hw->st_dma);
+ if (!hw->st_le)
+ goto err_out_reset;
+
+ dev_info(&pdev->dev, "Yukon-2 %s chip revision %d\n",
+ sky2_name(hw->chip_id, buf1, sizeof(buf1)), hw->chip_rev);
+
+ sky2_reset(hw);
+
+ dev = sky2_init_netdev(hw, 0, using_dac, wol_default);
+ if (!dev) {
+ err = -ENOMEM;
+ goto err_out_free_pci;
+ }
+
+ if (!disable_msi && pci_enable_msi(pdev) == 0) {
+ err = sky2_test_msi(hw);
+ if (err == -EOPNOTSUPP)
+ pci_disable_msi(pdev);
+ else if (err)
+ goto err_out_free_netdev;
+ }
+
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register net device\n");
+ goto err_out_free_netdev;
+ }
+
+ netif_carrier_off(dev);
+
+ netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
+
+ sky2_show_addr(dev);
+
+ if (hw->ports > 1) {
+ dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default);
+ if (!dev1) {
+ err = -ENOMEM;
+ goto err_out_unregister;
+ }
+
+ err = register_netdev(dev1);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register second net device\n");
+ goto err_out_free_dev1;
+ }
+
+ err = sky2_setup_irq(hw, hw->irq_name);
+ if (err)
+ goto err_out_unregister_dev1;
+
+ sky2_show_addr(dev1);
+ }
+
+ setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw);
+ INIT_WORK(&hw->restart_work, sky2_restart);
+
+ pci_set_drvdata(pdev, hw);
+ pdev->d3_delay = 150;
+
+ return 0;
+
+ err_out_unregister_dev1:
+ unregister_netdev(dev1);
+ err_out_free_dev1:
+ free_netdev(dev1);
+ err_out_unregister:
+ if (hw->flags & SKY2_HW_USE_MSI)
+ pci_disable_msi(pdev);
+ unregister_netdev(dev);
+ err_out_free_netdev:
+ free_netdev(dev);
+ err_out_free_pci:
+ pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
+ hw->st_le, hw->st_dma);
+ err_out_reset:
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ err_out_iounmap:
+ iounmap(hw->regs);
+ err_out_free_hw:
+ kfree(hw);
+ err_out_free_regions:
+ pci_release_regions(pdev);
+ err_out_disable:
+ pci_disable_device(pdev);
+ err_out:
+ pci_set_drvdata(pdev, NULL);
+ return err;
+ }
+
+ static void __devexit sky2_remove(struct pci_dev *pdev)
+ {
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int i;
+
+ if (!hw)
+ return;
+
+ del_timer_sync(&hw->watchdog_timer);
+ cancel_work_sync(&hw->restart_work);
+
+ for (i = hw->ports-1; i >= 0; --i)
+ unregister_netdev(hw->dev[i]);
+
+ sky2_write32(hw, B0_IMSK, 0);
+ sky2_read32(hw, B0_IMSK);
+
+ sky2_power_aux(hw);
+
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ sky2_read8(hw, B0_CTST);
+
+ if (hw->ports > 1) {
+ napi_disable(&hw->napi);
+ free_irq(pdev->irq, hw);
+ }
+
+ if (hw->flags & SKY2_HW_USE_MSI)
+ pci_disable_msi(pdev);
+ pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
+ hw->st_le, hw->st_dma);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ for (i = hw->ports-1; i >= 0; --i)
+ free_netdev(hw->dev[i]);
+
+ iounmap(hw->regs);
+ kfree(hw);
+
+ pci_set_drvdata(pdev, NULL);
+ }
+
+ static int sky2_suspend(struct device *dev)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int i;
+
+ if (!hw)
+ return 0;
+
+ del_timer_sync(&hw->watchdog_timer);
+ cancel_work_sync(&hw->restart_work);
+
+ rtnl_lock();
+
+ sky2_all_down(hw);
+ for (i = 0; i < hw->ports; i++) {
+ struct net_device *dev = hw->dev[i];
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (sky2->wol)
+ sky2_wol_init(sky2);
+ }
+
+ sky2_power_aux(hw);
+ rtnl_unlock();
+
+ return 0;
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+ static int sky2_resume(struct device *dev)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int err;
+
+ if (!hw)
+ return 0;
+
+ /* Re-enable all clocks */
+ err = pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
+ if (err) {
+ dev_err(&pdev->dev, "PCI write config failed\n");
+ goto out;
+ }
+
+ rtnl_lock();
+ sky2_reset(hw);
+ sky2_all_up(hw);
+ rtnl_unlock();
+
+ return 0;
+ out:
+
+ dev_err(&pdev->dev, "resume failed (%d)\n", err);
+ pci_disable_device(pdev);
+ return err;
+ }
+
+ static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume);
+ #define SKY2_PM_OPS (&sky2_pm_ops)
+
+ #else
+
+ #define SKY2_PM_OPS NULL
+ #endif
+
+ static void sky2_shutdown(struct pci_dev *pdev)
+ {
+ sky2_suspend(&pdev->dev);
+ pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
+ pci_set_power_state(pdev, PCI_D3hot);
+ }
+
+ static struct pci_driver sky2_driver = {
+ .name = DRV_NAME,
+ .id_table = sky2_id_table,
+ .probe = sky2_probe,
+ .remove = __devexit_p(sky2_remove),
+ .shutdown = sky2_shutdown,
+ .driver.pm = SKY2_PM_OPS,
+ };
+
+ static int __init sky2_init_module(void)
+ {
+ pr_info("driver version " DRV_VERSION "\n");
+
+ sky2_debug_init();
+ return pci_register_driver(&sky2_driver);
+ }
+
+ static void __exit sky2_cleanup_module(void)
+ {
+ pci_unregister_driver(&sky2_driver);
+ sky2_debug_cleanup();
+ }
+
+ module_init(sky2_init_module);
+ module_exit(sky2_cleanup_module);
+
+ MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver");
+ MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
--- /dev/null
- * So, this Rx interrrupt enable/status bit number is equal
+ /*
+ * Micrel KS8695 (Centaur) Ethernet.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Copyright 2008 Simtec Electronics
+ * Daniel Silverstone <dsilvers@simtec.co.uk>
+ * Vincent Sanders <vince@simtec.co.uk>
+ */
+
+ #include <linux/dma-mapping.h>
+ #include <linux/module.h>
+ #include <linux/ioport.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/skbuff.h>
+ #include <linux/spinlock.h>
+ #include <linux/crc32.h>
+ #include <linux/mii.h>
+ #include <linux/ethtool.h>
+ #include <linux/delay.h>
+ #include <linux/platform_device.h>
+ #include <linux/irq.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
+
+ #include <asm/irq.h>
+
+ #include <mach/regs-switch.h>
+ #include <mach/regs-misc.h>
+ #include <asm/mach/irq.h>
+ #include <mach/regs-irq.h>
+
+ #include "ks8695net.h"
+
+ #define MODULENAME "ks8695_ether"
+ #define MODULEVERSION "1.02"
+
+ /*
+ * Transmit and device reset timeout, default 5 seconds.
+ */
+ static int watchdog = 5000;
+
+ /* Hardware structures */
+
+ /**
+ * struct rx_ring_desc - Receive descriptor ring element
+ * @status: The status of the descriptor element (E.g. who owns it)
+ * @length: The number of bytes in the block pointed to by data_ptr
+ * @data_ptr: The physical address of the data block to receive into
+ * @next_desc: The physical address of the next descriptor element.
+ */
+ struct rx_ring_desc {
+ __le32 status;
+ __le32 length;
+ __le32 data_ptr;
+ __le32 next_desc;
+ };
+
+ /**
+ * struct tx_ring_desc - Transmit descriptor ring element
+ * @owner: Who owns the descriptor
+ * @status: The number of bytes in the block pointed to by data_ptr
+ * @data_ptr: The physical address of the data block to receive into
+ * @next_desc: The physical address of the next descriptor element.
+ */
+ struct tx_ring_desc {
+ __le32 owner;
+ __le32 status;
+ __le32 data_ptr;
+ __le32 next_desc;
+ };
+
+ /**
+ * struct ks8695_skbuff - sk_buff wrapper for rx/tx rings.
+ * @skb: The buffer in the ring
+ * @dma_ptr: The mapped DMA pointer of the buffer
+ * @length: The number of bytes mapped to dma_ptr
+ */
+ struct ks8695_skbuff {
+ struct sk_buff *skb;
+ dma_addr_t dma_ptr;
+ u32 length;
+ };
+
+ /* Private device structure */
+
+ #define MAX_TX_DESC 8
+ #define MAX_TX_DESC_MASK 0x7
+ #define MAX_RX_DESC 16
+ #define MAX_RX_DESC_MASK 0xf
+
+ /*napi_weight have better more than rx DMA buffers*/
+ #define NAPI_WEIGHT 64
+
+ #define MAX_RXBUF_SIZE 0x700
+
+ #define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC)
+ #define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC)
+ #define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE)
+
+ /**
+ * enum ks8695_dtype - Device type
+ * @KS8695_DTYPE_WAN: This device is a WAN interface
+ * @KS8695_DTYPE_LAN: This device is a LAN interface
+ * @KS8695_DTYPE_HPNA: This device is an HPNA interface
+ */
+ enum ks8695_dtype {
+ KS8695_DTYPE_WAN,
+ KS8695_DTYPE_LAN,
+ KS8695_DTYPE_HPNA,
+ };
+
+ /**
+ * struct ks8695_priv - Private data for the KS8695 Ethernet
+ * @in_suspend: Flag to indicate if we're suspending/resuming
+ * @ndev: The net_device for this interface
+ * @dev: The platform device object for this interface
+ * @dtype: The type of this device
+ * @io_regs: The ioremapped registers for this interface
+ * @napi : Add support NAPI for Rx
+ * @rx_irq_name: The textual name of the RX IRQ from the platform data
+ * @tx_irq_name: The textual name of the TX IRQ from the platform data
+ * @link_irq_name: The textual name of the link IRQ from the
+ * platform data if available
+ * @rx_irq: The IRQ number for the RX IRQ
+ * @tx_irq: The IRQ number for the TX IRQ
+ * @link_irq: The IRQ number for the link IRQ if available
+ * @regs_req: The resource request for the registers region
+ * @phyiface_req: The resource request for the phy/switch region
+ * if available
+ * @phyiface_regs: The ioremapped registers for the phy/switch if available
+ * @ring_base: The base pointer of the dma coherent memory for the rings
+ * @ring_base_dma: The DMA mapped equivalent of ring_base
+ * @tx_ring: The pointer in ring_base of the TX ring
+ * @tx_ring_used: The number of slots in the TX ring which are occupied
+ * @tx_ring_next_slot: The next slot to fill in the TX ring
+ * @tx_ring_dma: The DMA mapped equivalent of tx_ring
+ * @tx_buffers: The sk_buff mappings for the TX ring
+ * @txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables
+ * @rx_ring: The pointer in ring_base of the RX ring
+ * @rx_ring_dma: The DMA mapped equivalent of rx_ring
+ * @rx_buffers: The sk_buff mappings for the RX ring
+ * @next_rx_desc_read: The next RX descriptor to read from on IRQ
+ * @rx_lock: A lock to protect Rx irq function
+ * @msg_enable: The flags for which messages to emit
+ */
+ struct ks8695_priv {
+ int in_suspend;
+ struct net_device *ndev;
+ struct device *dev;
+ enum ks8695_dtype dtype;
+ void __iomem *io_regs;
+
+ struct napi_struct napi;
+
+ const char *rx_irq_name, *tx_irq_name, *link_irq_name;
+ int rx_irq, tx_irq, link_irq;
+
+ struct resource *regs_req, *phyiface_req;
+ void __iomem *phyiface_regs;
+
+ void *ring_base;
+ dma_addr_t ring_base_dma;
+
+ struct tx_ring_desc *tx_ring;
+ int tx_ring_used;
+ int tx_ring_next_slot;
+ dma_addr_t tx_ring_dma;
+ struct ks8695_skbuff tx_buffers[MAX_TX_DESC];
+ spinlock_t txq_lock;
+
+ struct rx_ring_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+ struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
+ int next_rx_desc_read;
+ spinlock_t rx_lock;
+
+ int msg_enable;
+ };
+
+ /* Register access */
+
+ /**
+ * ks8695_readreg - Read from a KS8695 ethernet register
+ * @ksp: The device to read from
+ * @reg: The register to read
+ */
+ static inline u32
+ ks8695_readreg(struct ks8695_priv *ksp, int reg)
+ {
+ return readl(ksp->io_regs + reg);
+ }
+
+ /**
+ * ks8695_writereg - Write to a KS8695 ethernet register
+ * @ksp: The device to write to
+ * @reg: The register to write
+ * @value: The value to write to the register
+ */
+ static inline void
+ ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value)
+ {
+ writel(value, ksp->io_regs + reg);
+ }
+
+ /* Utility functions */
+
+ /**
+ * ks8695_port_type - Retrieve port-type as user-friendly string
+ * @ksp: The device to return the type for
+ *
+ * Returns a string indicating which of the WAN, LAN or HPNA
+ * ports this device is likely to represent.
+ */
+ static const char *
+ ks8695_port_type(struct ks8695_priv *ksp)
+ {
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_LAN:
+ return "LAN";
+ case KS8695_DTYPE_WAN:
+ return "WAN";
+ case KS8695_DTYPE_HPNA:
+ return "HPNA";
+ }
+
+ return "UNKNOWN";
+ }
+
+ /**
+ * ks8695_update_mac - Update the MAC registers in the device
+ * @ksp: The device to update
+ *
+ * Updates the MAC registers in the KS8695 device from the address in the
+ * net_device structure associated with this interface.
+ */
+ static void
+ ks8695_update_mac(struct ks8695_priv *ksp)
+ {
+ /* Update the HW with the MAC from the net_device */
+ struct net_device *ndev = ksp->ndev;
+ u32 machigh, maclow;
+
+ maclow = ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) |
+ (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5] << 0));
+ machigh = ((ndev->dev_addr[0] << 8) | (ndev->dev_addr[1] << 0));
+
+ ks8695_writereg(ksp, KS8695_MAL, maclow);
+ ks8695_writereg(ksp, KS8695_MAH, machigh);
+
+ }
+
+ /**
+ * ks8695_refill_rxbuffers - Re-fill the RX buffer ring
+ * @ksp: The device to refill
+ *
+ * Iterates the RX ring of the device looking for empty slots.
+ * For each empty slot, we allocate and map a new SKB and give it
+ * to the hardware.
+ * This can be called from interrupt context safely.
+ */
+ static void
+ ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
+ {
+ /* Run around the RX ring, filling in any missing sk_buff's */
+ int buff_n;
+
+ for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
+ if (!ksp->rx_buffers[buff_n].skb) {
+ struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE);
+ dma_addr_t mapping;
+
+ ksp->rx_buffers[buff_n].skb = skb;
+ if (skb == NULL) {
+ /* Failed to allocate one, perhaps
+ * we'll try again later.
+ */
+ break;
+ }
+
+ mapping = dma_map_single(ksp->dev, skb->data,
+ MAX_RXBUF_SIZE,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(ksp->dev, mapping))) {
+ /* Failed to DMA map this SKB, try later */
+ dev_kfree_skb_irq(skb);
+ ksp->rx_buffers[buff_n].skb = NULL;
+ break;
+ }
+ ksp->rx_buffers[buff_n].dma_ptr = mapping;
+ skb->dev = ksp->ndev;
+ ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
+
+ /* Record this into the DMA ring */
+ ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping);
+ ksp->rx_ring[buff_n].length =
+ cpu_to_le32(MAX_RXBUF_SIZE);
+
+ wmb();
+
+ /* And give ownership over to the hardware */
+ ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
+ }
+ }
+ }
+
+ /* Maximum number of multicast addresses which the KS8695 HW supports */
+ #define KS8695_NR_ADDRESSES 16
+
+ /**
+ * ks8695_init_partial_multicast - Init the mcast addr registers
+ * @ksp: The device to initialise
+ * @addr: The multicast address list to use
+ * @nr_addr: The number of addresses in the list
+ *
+ * This routine is a helper for ks8695_set_multicast - it writes
+ * the additional-address registers in the KS8695 ethernet device
+ * and cleans up any others left behind.
+ */
+ static void
+ ks8695_init_partial_multicast(struct ks8695_priv *ksp,
+ struct net_device *ndev)
+ {
+ u32 low, high;
+ int i;
+ struct netdev_hw_addr *ha;
+
+ i = 0;
+ netdev_for_each_mc_addr(ha, ndev) {
+ /* Ran out of space in chip? */
+ BUG_ON(i == KS8695_NR_ADDRESSES);
+
+ low = (ha->addr[2] << 24) | (ha->addr[3] << 16) |
+ (ha->addr[4] << 8) | (ha->addr[5]);
+ high = (ha->addr[0] << 8) | (ha->addr[1]);
+
+ ks8695_writereg(ksp, KS8695_AAL_(i), low);
+ ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high);
+ i++;
+ }
+
+ /* Clear the remaining Additional Station Addresses */
+ for (; i < KS8695_NR_ADDRESSES; i++) {
+ ks8695_writereg(ksp, KS8695_AAL_(i), 0);
+ ks8695_writereg(ksp, KS8695_AAH_(i), 0);
+ }
+ }
+
+ /* Interrupt handling */
+
+ /**
+ * ks8695_tx_irq - Transmit IRQ handler
+ * @irq: The IRQ which went off (ignored)
+ * @dev_id: The net_device for the interrupt
+ *
+ * Process the TX ring, clearing out any transmitted slots.
+ * Allows the net_device to pass us new packets once slots are
+ * freed.
+ */
+ static irqreturn_t
+ ks8695_tx_irq(int irq, void *dev_id)
+ {
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ int buff_n;
+
+ for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
+ if (ksp->tx_buffers[buff_n].skb &&
+ !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) {
+ rmb();
+ /* An SKB which is not owned by HW is present */
+ /* Update the stats for the net_device */
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length;
+
+ /* Free the packet from the ring */
+ ksp->tx_ring[buff_n].data_ptr = 0;
+
+ /* Free the sk_buff */
+ dma_unmap_single(ksp->dev,
+ ksp->tx_buffers[buff_n].dma_ptr,
+ ksp->tx_buffers[buff_n].length,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
+ ksp->tx_buffers[buff_n].skb = NULL;
+ ksp->tx_ring_used--;
+ }
+ }
+
+ netif_wake_queue(ndev);
+
+ return IRQ_HANDLED;
+ }
+
+ /**
+ * ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit
+ * @ksp: Private data for the KS8695 Ethernet
+ *
+ * For KS8695 document:
+ * Interrupt Enable Register (offset 0xE204)
+ * Bit29 : WAN MAC Receive Interrupt Enable
+ * Bit16 : LAN MAC Receive Interrupt Enable
+ * Interrupt Status Register (Offset 0xF208)
+ * Bit29: WAN MAC Receive Status
+ * Bit16: LAN MAC Receive Status
++ * So, this Rx interrupt enable/status bit number is equal
+ * as Rx IRQ number.
+ */
+ static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp)
+ {
+ return ksp->rx_irq;
+ }
+
+ /**
+ * ks8695_rx_irq - Receive IRQ handler
+ * @irq: The IRQ which went off (ignored)
+ * @dev_id: The net_device for the interrupt
+ *
+ * Inform NAPI that packet reception needs to be scheduled
+ */
+
+ static irqreturn_t
+ ks8695_rx_irq(int irq, void *dev_id)
+ {
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ spin_lock(&ksp->rx_lock);
+
+ if (napi_schedule_prep(&ksp->napi)) {
+ unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
+ unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
+ /*disable rx interrupt*/
+ status &= ~mask_bit;
+ writel(status , KS8695_IRQ_VA + KS8695_INTEN);
+ __napi_schedule(&ksp->napi);
+ }
+
+ spin_unlock(&ksp->rx_lock);
+ return IRQ_HANDLED;
+ }
+
+ /**
+ * ks8695_rx - Receive packets called by NAPI poll method
+ * @ksp: Private data for the KS8695 Ethernet
+ * @budget: Number of packets allowed to process
+ */
+ static int ks8695_rx(struct ks8695_priv *ksp, int budget)
+ {
+ struct net_device *ndev = ksp->ndev;
+ struct sk_buff *skb;
+ int buff_n;
+ u32 flags;
+ int pktlen;
+ int received = 0;
+
+ buff_n = ksp->next_rx_desc_read;
+ while (received < budget
+ && ksp->rx_buffers[buff_n].skb
+ && (!(ksp->rx_ring[buff_n].status &
+ cpu_to_le32(RDES_OWN)))) {
+ rmb();
+ flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
+
+ /* Found an SKB which we own, this means we
+ * received a packet
+ */
+ if ((flags & (RDES_FS | RDES_LS)) !=
+ (RDES_FS | RDES_LS)) {
+ /* This packet is not the first and
+ * the last segment. Therefore it is
+ * a "spanning" packet and we can't
+ * handle it
+ */
+ goto rx_failure;
+ }
+
+ if (flags & (RDES_ES | RDES_RE)) {
+ /* It's an error packet */
+ ndev->stats.rx_errors++;
+ if (flags & RDES_TL)
+ ndev->stats.rx_length_errors++;
+ if (flags & RDES_RF)
+ ndev->stats.rx_length_errors++;
+ if (flags & RDES_CE)
+ ndev->stats.rx_crc_errors++;
+ if (flags & RDES_RE)
+ ndev->stats.rx_missed_errors++;
+
+ goto rx_failure;
+ }
+
+ pktlen = flags & RDES_FLEN;
+ pktlen -= 4; /* Drop the CRC */
+
+ /* Retrieve the sk_buff */
+ skb = ksp->rx_buffers[buff_n].skb;
+
+ /* Clear it from the ring */
+ ksp->rx_buffers[buff_n].skb = NULL;
+ ksp->rx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap the SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->rx_buffers[buff_n].dma_ptr,
+ ksp->rx_buffers[buff_n].length,
+ DMA_FROM_DEVICE);
+
+ /* Relinquish the SKB to the network layer */
+ skb_put(skb, pktlen);
+ skb->protocol = eth_type_trans(skb, ndev);
+ netif_receive_skb(skb);
+
+ /* Record stats */
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += pktlen;
+ goto rx_finished;
+
+ rx_failure:
+ /* This ring entry is an error, but we can
+ * re-use the skb
+ */
+ /* Give the ring entry back to the hardware */
+ ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
+ rx_finished:
+ received++;
+ buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
+ }
+
+ /* And note which RX descriptor we last did */
+ ksp->next_rx_desc_read = buff_n;
+
+ /* And refill the buffers */
+ ks8695_refill_rxbuffers(ksp);
+
+ /* Kick the RX DMA engine, in case it became suspended */
+ ks8695_writereg(ksp, KS8695_DRSC, 0);
+
+ return received;
+ }
+
+
+ /**
+ * ks8695_poll - Receive packet by NAPI poll method
+ * @ksp: Private data for the KS8695 Ethernet
+ * @budget: The remaining number packets for network subsystem
+ *
+ * Invoked by the network core when it requests for new
+ * packets from the driver
+ */
+ static int ks8695_poll(struct napi_struct *napi, int budget)
+ {
+ struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
+ unsigned long work_done;
+
+ unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN);
+ unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
+
+ work_done = ks8695_rx(ksp, budget);
+
+ if (work_done < budget) {
+ unsigned long flags;
+ spin_lock_irqsave(&ksp->rx_lock, flags);
+ __napi_complete(napi);
+ /*enable rx interrupt*/
+ writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
+ spin_unlock_irqrestore(&ksp->rx_lock, flags);
+ }
+ return work_done;
+ }
+
+ /**
+ * ks8695_link_irq - Link change IRQ handler
+ * @irq: The IRQ which went off (ignored)
+ * @dev_id: The net_device for the interrupt
+ *
+ * The WAN interface can generate an IRQ when the link changes,
+ * report this to the net layer and the user.
+ */
+ static irqreturn_t
+ ks8695_link_irq(int irq, void *dev_id)
+ {
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+ if (ctrl & WMC_WLS) {
+ netif_carrier_on(ndev);
+ if (netif_msg_link(ksp))
+ dev_info(ksp->dev,
+ "%s: Link is now up (10%sMbps/%s-duplex)\n",
+ ndev->name,
+ (ctrl & WMC_WSS) ? "0" : "",
+ (ctrl & WMC_WDS) ? "Full" : "Half");
+ } else {
+ netif_carrier_off(ndev);
+ if (netif_msg_link(ksp))
+ dev_info(ksp->dev, "%s: Link is now down.\n",
+ ndev->name);
+ }
+
+ return IRQ_HANDLED;
+ }
+
+
+ /* KS8695 Device functions */
+
+ /**
+ * ks8695_reset - Reset a KS8695 ethernet interface
+ * @ksp: The interface to reset
+ *
+ * Perform an engine reset of the interface and re-program it
+ * with sensible defaults.
+ */
+ static void
+ ks8695_reset(struct ks8695_priv *ksp)
+ {
+ int reset_timeout = watchdog;
+ /* Issue the reset via the TX DMA control register */
+ ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST);
+ while (reset_timeout--) {
+ if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST))
+ break;
+ msleep(1);
+ }
+
+ if (reset_timeout < 0) {
+ dev_crit(ksp->dev,
+ "Timeout waiting for DMA engines to reset\n");
+ /* And blithely carry on */
+ }
+
+ /* Definitely wait long enough before attempting to program
+ * the engines
+ */
+ msleep(10);
+
+ /* RX: unicast and broadcast */
+ ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB);
+ /* TX: pad and add CRC */
+ ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC);
+ }
+
+ /**
+ * ks8695_shutdown - Shut down a KS8695 ethernet interface
+ * @ksp: The interface to shut down
+ *
+ * This disables packet RX/TX, cleans up IRQs, drains the rings,
+ * and basically places the interface into a clean shutdown
+ * state.
+ */
+ static void
+ ks8695_shutdown(struct ks8695_priv *ksp)
+ {
+ u32 ctrl;
+ int buff_n;
+
+ /* Disable packet transmission */
+ ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+ ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE);
+
+ /* Disable packet reception */
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+ ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE);
+
+ /* Release the IRQs */
+ free_irq(ksp->rx_irq, ksp->ndev);
+ free_irq(ksp->tx_irq, ksp->ndev);
+ if (ksp->link_irq != -1)
+ free_irq(ksp->link_irq, ksp->ndev);
+
+ /* Throw away any pending TX packets */
+ for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
+ if (ksp->tx_buffers[buff_n].skb) {
+ /* Remove this SKB from the TX ring */
+ ksp->tx_ring[buff_n].owner = 0;
+ ksp->tx_ring[buff_n].status = 0;
+ ksp->tx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap and bin this SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->tx_buffers[buff_n].dma_ptr,
+ ksp->tx_buffers[buff_n].length,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
+ ksp->tx_buffers[buff_n].skb = NULL;
+ }
+ }
+
+ /* Purge the RX buffers */
+ for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
+ if (ksp->rx_buffers[buff_n].skb) {
+ /* Remove the SKB from the RX ring */
+ ksp->rx_ring[buff_n].status = 0;
+ ksp->rx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap and bin the SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->rx_buffers[buff_n].dma_ptr,
+ ksp->rx_buffers[buff_n].length,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb);
+ ksp->rx_buffers[buff_n].skb = NULL;
+ }
+ }
+ }
+
+
+ /**
+ * ks8695_setup_irq - IRQ setup helper function
+ * @irq: The IRQ number to claim
+ * @irq_name: The name to give the IRQ claimant
+ * @handler: The function to call to handle the IRQ
+ * @ndev: The net_device to pass in as the dev_id argument to the handler
+ *
+ * Return 0 on success.
+ */
+ static int
+ ks8695_setup_irq(int irq, const char *irq_name,
+ irq_handler_t handler, struct net_device *ndev)
+ {
+ int ret;
+
+ ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev);
+
+ if (ret) {
+ dev_err(&ndev->dev, "failure to request IRQ %d\n", irq);
+ return ret;
+ }
+
+ return 0;
+ }
+
+ /**
+ * ks8695_init_net - Initialise a KS8695 ethernet interface
+ * @ksp: The interface to initialise
+ *
+ * This routine fills the RX ring, initialises the DMA engines,
+ * allocates the IRQs and then starts the packet TX and RX
+ * engines.
+ */
+ static int
+ ks8695_init_net(struct ks8695_priv *ksp)
+ {
+ int ret;
+ u32 ctrl;
+
+ ks8695_refill_rxbuffers(ksp);
+
+ /* Initialise the DMA engines */
+ ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma);
+ ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma);
+
+ /* Request the IRQs */
+ ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name,
+ ks8695_rx_irq, ksp->ndev);
+ if (ret)
+ return ret;
+ ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name,
+ ks8695_tx_irq, ksp->ndev);
+ if (ret)
+ return ret;
+ if (ksp->link_irq != -1) {
+ ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name,
+ ks8695_link_irq, ksp->ndev);
+ if (ret)
+ return ret;
+ }
+
+ /* Set up the ring indices */
+ ksp->next_rx_desc_read = 0;
+ ksp->tx_ring_next_slot = 0;
+ ksp->tx_ring_used = 0;
+
+ /* Bring up transmission */
+ ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+ /* Enable packet transmission */
+ ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE);
+
+ /* Bring up the reception */
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+ /* Enable packet reception */
+ ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE);
+ /* And start the DMA engine */
+ ks8695_writereg(ksp, KS8695_DRSC, 0);
+
+ /* All done */
+ return 0;
+ }
+
+ /**
+ * ks8695_release_device - HW resource release for KS8695 e-net
+ * @ksp: The device to be freed
+ *
+ * This unallocates io memory regions, dma-coherent regions etc
+ * which were allocated in ks8695_probe.
+ */
+ static void
+ ks8695_release_device(struct ks8695_priv *ksp)
+ {
+ /* Unmap the registers */
+ iounmap(ksp->io_regs);
+ if (ksp->phyiface_regs)
+ iounmap(ksp->phyiface_regs);
+
+ /* And release the request */
+ release_resource(ksp->regs_req);
+ kfree(ksp->regs_req);
+ if (ksp->phyiface_req) {
+ release_resource(ksp->phyiface_req);
+ kfree(ksp->phyiface_req);
+ }
+
+ /* Free the ring buffers */
+ dma_free_coherent(ksp->dev, RING_DMA_SIZE,
+ ksp->ring_base, ksp->ring_base_dma);
+ }
+
+ /* Ethtool support */
+
+ /**
+ * ks8695_get_msglevel - Get the messages enabled for emission
+ * @ndev: The network device to read from
+ */
+ static u32
+ ks8695_get_msglevel(struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ return ksp->msg_enable;
+ }
+
+ /**
+ * ks8695_set_msglevel - Set the messages enabled for emission
+ * @ndev: The network device to configure
+ * @value: The messages to set for emission
+ */
+ static void
+ ks8695_set_msglevel(struct net_device *ndev, u32 value)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ ksp->msg_enable = value;
+ }
+
+ /**
+ * ks8695_wan_get_settings - Get device-specific settings.
+ * @ndev: The network device to read settings from
+ * @cmd: The ethtool structure to read into
+ */
+ static int
+ ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ /* All ports on the KS8695 support these... */
+ cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_TP | SUPPORTED_MII);
+ cmd->transceiver = XCVR_INTERNAL;
+
+ cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+ cmd->port = PORT_MII;
+ cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
+ cmd->phy_address = 0;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+ if ((ctrl & WMC_WAND) == 0) {
+ /* auto-negotiation is enabled */
+ cmd->advertising |= ADVERTISED_Autoneg;
+ if (ctrl & WMC_WANA100F)
+ cmd->advertising |= ADVERTISED_100baseT_Full;
+ if (ctrl & WMC_WANA100H)
+ cmd->advertising |= ADVERTISED_100baseT_Half;
+ if (ctrl & WMC_WANA10F)
+ cmd->advertising |= ADVERTISED_10baseT_Full;
+ if (ctrl & WMC_WANA10H)
+ cmd->advertising |= ADVERTISED_10baseT_Half;
+ if (ctrl & WMC_WANAP)
+ cmd->advertising |= ADVERTISED_Pause;
+ cmd->autoneg = AUTONEG_ENABLE;
+
+ ethtool_cmd_speed_set(cmd,
+ (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10);
+ cmd->duplex = (ctrl & WMC_WDS) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ } else {
+ /* auto-negotiation is disabled */
+ cmd->autoneg = AUTONEG_DISABLE;
+
+ ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ?
+ SPEED_100 : SPEED_10));
+ cmd->duplex = (ctrl & WMC_WANFF) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ }
+
+ return 0;
+ }
+
+ /**
+ * ks8695_wan_set_settings - Set device-specific settings.
+ * @ndev: The network device to configure
+ * @cmd: The settings to configure
+ */
+ static int
+ ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ if ((cmd->speed != SPEED_10) && (cmd->speed != SPEED_100))
+ return -EINVAL;
+ if ((cmd->duplex != DUPLEX_HALF) && (cmd->duplex != DUPLEX_FULL))
+ return -EINVAL;
+ if (cmd->port != PORT_MII)
+ return -EINVAL;
+ if (cmd->transceiver != XCVR_INTERNAL)
+ return -EINVAL;
+ if ((cmd->autoneg != AUTONEG_DISABLE) &&
+ (cmd->autoneg != AUTONEG_ENABLE))
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ if ((cmd->advertising & (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full)) == 0)
+ return -EINVAL;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
+ WMC_WANA10F | WMC_WANA10H);
+ if (cmd->advertising & ADVERTISED_100baseT_Full)
+ ctrl |= WMC_WANA100F;
+ if (cmd->advertising & ADVERTISED_100baseT_Half)
+ ctrl |= WMC_WANA100H;
+ if (cmd->advertising & ADVERTISED_10baseT_Full)
+ ctrl |= WMC_WANA10F;
+ if (cmd->advertising & ADVERTISED_10baseT_Half)
+ ctrl |= WMC_WANA10H;
+
+ /* force a re-negotiation */
+ ctrl |= WMC_WANR;
+ writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
+ } else {
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ /* disable auto-negotiation */
+ ctrl |= WMC_WAND;
+ ctrl &= ~(WMC_WANF100 | WMC_WANFF);
+
+ if (cmd->speed == SPEED_100)
+ ctrl |= WMC_WANF100;
+ if (cmd->duplex == DUPLEX_FULL)
+ ctrl |= WMC_WANFF;
+
+ writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
+ }
+
+ return 0;
+ }
+
+ /**
+ * ks8695_wan_nwayreset - Restart the autonegotiation on the port.
+ * @ndev: The network device to restart autoneotiation on
+ */
+ static int
+ ks8695_wan_nwayreset(struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ if ((ctrl & WMC_WAND) == 0)
+ writel(ctrl | WMC_WANR,
+ ksp->phyiface_regs + KS8695_WMC);
+ else
+ /* auto-negotiation not enabled */
+ return -EINVAL;
+
+ return 0;
+ }
+
+ /**
+ * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising
+ * @ndev: The device to retrieve settings from
+ * @param: The structure to fill out with the information
+ */
+ static void
+ ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ /* advertise Pause */
+ param->autoneg = (ctrl & WMC_WANAP);
+
+ /* current Rx Flow-control */
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+ param->rx_pause = (ctrl & DRXC_RFCE);
+
+ /* current Tx Flow-control */
+ ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+ param->tx_pause = (ctrl & DTXC_TFCE);
+ }
+
+ /**
+ * ks8695_get_drvinfo - Retrieve driver information
+ * @ndev: The network device to retrieve info about
+ * @info: The info structure to fill out.
+ */
+ static void
+ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
+ {
+ strlcpy(info->driver, MODULENAME, sizeof(info->driver));
+ strlcpy(info->version, MODULEVERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+ sizeof(info->bus_info));
+ }
+
+ static const struct ethtool_ops ks8695_ethtool_ops = {
+ .get_msglevel = ks8695_get_msglevel,
+ .set_msglevel = ks8695_set_msglevel,
+ .get_drvinfo = ks8695_get_drvinfo,
+ };
+
+ static const struct ethtool_ops ks8695_wan_ethtool_ops = {
+ .get_msglevel = ks8695_get_msglevel,
+ .set_msglevel = ks8695_set_msglevel,
+ .get_settings = ks8695_wan_get_settings,
+ .set_settings = ks8695_wan_set_settings,
+ .nway_reset = ks8695_wan_nwayreset,
+ .get_link = ethtool_op_get_link,
+ .get_pauseparam = ks8695_wan_get_pause,
+ .get_drvinfo = ks8695_get_drvinfo,
+ };
+
+ /* Network device interface functions */
+
+ /**
+ * ks8695_set_mac - Update MAC in net dev and HW
+ * @ndev: The network device to update
+ * @addr: The new MAC address to set
+ */
+ static int
+ ks8695_set_mac(struct net_device *ndev, void *addr)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ struct sockaddr *address = addr;
+
+ if (!is_valid_ether_addr(address->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len);
+
+ ks8695_update_mac(ksp);
+
+ dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n",
+ ndev->name, ndev->dev_addr);
+
+ return 0;
+ }
+
+ /**
+ * ks8695_set_multicast - Set up the multicast behaviour of the interface
+ * @ndev: The net_device to configure
+ *
+ * This routine, called by the net layer, configures promiscuity
+ * and multicast reception behaviour for the interface.
+ */
+ static void
+ ks8695_set_multicast(struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+
+ if (ndev->flags & IFF_PROMISC) {
+ /* enable promiscuous mode */
+ ctrl |= DRXC_RA;
+ } else if (ndev->flags & ~IFF_PROMISC) {
+ /* disable promiscuous mode */
+ ctrl &= ~DRXC_RA;
+ }
+
+ if (ndev->flags & IFF_ALLMULTI) {
+ /* enable all multicast mode */
+ ctrl |= DRXC_RM;
+ } else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) {
+ /* more specific multicast addresses than can be
+ * handled in hardware
+ */
+ ctrl |= DRXC_RM;
+ } else {
+ /* enable specific multicasts */
+ ctrl &= ~DRXC_RM;
+ ks8695_init_partial_multicast(ksp, ndev);
+ }
+
+ ks8695_writereg(ksp, KS8695_DRXC, ctrl);
+ }
+
+ /**
+ * ks8695_timeout - Handle a network tx/rx timeout.
+ * @ndev: The net_device which timed out.
+ *
+ * A network transaction timed out, reset the device.
+ */
+ static void
+ ks8695_timeout(struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ ks8695_shutdown(ksp);
+
+ ks8695_reset(ksp);
+
+ ks8695_update_mac(ksp);
+
+ /* We ignore the return from this since it managed to init
+ * before it probably will be okay to init again.
+ */
+ ks8695_init_net(ksp);
+
+ /* Reconfigure promiscuity etc */
+ ks8695_set_multicast(ndev);
+
+ /* And start the TX queue once more */
+ netif_start_queue(ndev);
+ }
+
+ /**
+ * ks8695_start_xmit - Start a packet transmission
+ * @skb: The packet to transmit
+ * @ndev: The network device to send the packet on
+ *
+ * This routine, called by the net layer, takes ownership of the
+ * sk_buff and adds it to the TX ring. It then kicks the TX DMA
+ * engine to ensure transmission begins.
+ */
+ static int
+ ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ int buff_n;
+ dma_addr_t dmap;
+
+ spin_lock_irq(&ksp->txq_lock);
+
+ if (ksp->tx_ring_used == MAX_TX_DESC) {
+ /* Somehow we got entered when we have no room */
+ spin_unlock_irq(&ksp->txq_lock);
+ return NETDEV_TX_BUSY;
+ }
+
+ buff_n = ksp->tx_ring_next_slot;
+
+ BUG_ON(ksp->tx_buffers[buff_n].skb);
+
+ dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(ksp->dev, dmap))) {
+ /* Failed to DMA map this SKB, give it back for now */
+ spin_unlock_irq(&ksp->txq_lock);
+ dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\
+ "transmission, trying later\n", ndev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ ksp->tx_buffers[buff_n].dma_ptr = dmap;
+ /* Mapped okay, store the buffer pointer and length for later */
+ ksp->tx_buffers[buff_n].skb = skb;
+ ksp->tx_buffers[buff_n].length = skb->len;
+
+ /* Fill out the TX descriptor */
+ ksp->tx_ring[buff_n].data_ptr =
+ cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr);
+ ksp->tx_ring[buff_n].status =
+ cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
+ (skb->len & TDES_TBS));
+
+ wmb();
+
+ /* Hand it over to the hardware */
+ ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN);
+
+ if (++ksp->tx_ring_used == MAX_TX_DESC)
+ netif_stop_queue(ndev);
+
+ /* Kick the TX DMA in case it decided to go IDLE */
+ ks8695_writereg(ksp, KS8695_DTSC, 0);
+
+ /* And update the next ring slot */
+ ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK;
+
+ spin_unlock_irq(&ksp->txq_lock);
+ return NETDEV_TX_OK;
+ }
+
+ /**
+ * ks8695_stop - Stop (shutdown) a KS8695 ethernet interface
+ * @ndev: The net_device to stop
+ *
+ * This disables the TX queue and cleans up a KS8695 ethernet
+ * device.
+ */
+ static int
+ ks8695_stop(struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ napi_disable(&ksp->napi);
+
+ ks8695_shutdown(ksp);
+
+ return 0;
+ }
+
+ /**
+ * ks8695_open - Open (bring up) a KS8695 ethernet interface
+ * @ndev: The net_device to open
+ *
+ * This resets, configures the MAC, initialises the RX ring and
+ * DMA engines and starts the TX queue for a KS8695 ethernet
+ * device.
+ */
+ static int
+ ks8695_open(struct net_device *ndev)
+ {
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ int ret;
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ return -EADDRNOTAVAIL;
+
+ ks8695_reset(ksp);
+
+ ks8695_update_mac(ksp);
+
+ ret = ks8695_init_net(ksp);
+ if (ret) {
+ ks8695_shutdown(ksp);
+ return ret;
+ }
+
+ napi_enable(&ksp->napi);
+ netif_start_queue(ndev);
+
+ return 0;
+ }
+
+ /* Platform device driver */
+
+ /**
+ * ks8695_init_switch - Init LAN switch to known good defaults.
+ * @ksp: The device to initialise
+ *
+ * This initialises the LAN switch in the KS8695 to a known-good
+ * set of defaults.
+ */
+ static void __devinit
+ ks8695_init_switch(struct ks8695_priv *ksp)
+ {
+ u32 ctrl;
+
+ /* Default value for SEC0 according to datasheet */
+ ctrl = 0x40819e00;
+
+ /* LED0 = Speed LED1 = Link/Activity */
+ ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S);
+ ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY);
+
+ /* Enable Switch */
+ ctrl |= SEC0_ENABLE;
+
+ writel(ctrl, ksp->phyiface_regs + KS8695_SEC0);
+
+ /* Defaults for SEC1 */
+ writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1);
+ }
+
+ /**
+ * ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults
+ * @ksp: The device to initialise
+ *
+ * This initialises a KS8695's WAN phy to sensible values for
+ * autonegotiation etc.
+ */
+ static void __devinit
+ ks8695_init_wan_phy(struct ks8695_priv *ksp)
+ {
+ u32 ctrl;
+
+ /* Support auto-negotiation */
+ ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H |
+ WMC_WANA10F | WMC_WANA10H);
+
+ /* LED0 = Activity , LED1 = Link */
+ ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK);
+
+ /* Restart Auto-negotiation */
+ ctrl |= WMC_WANR;
+
+ writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
+
+ writel(0, ksp->phyiface_regs + KS8695_WPPM);
+ writel(0, ksp->phyiface_regs + KS8695_PPS);
+ }
+
+ static const struct net_device_ops ks8695_netdev_ops = {
+ .ndo_open = ks8695_open,
+ .ndo_stop = ks8695_stop,
+ .ndo_start_xmit = ks8695_start_xmit,
+ .ndo_tx_timeout = ks8695_timeout,
+ .ndo_set_mac_address = ks8695_set_mac,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_rx_mode = ks8695_set_multicast,
+ };
+
+ /**
+ * ks8695_probe - Probe and initialise a KS8695 ethernet interface
+ * @pdev: The platform device to probe
+ *
+ * Initialise a KS8695 ethernet device from platform data.
+ *
+ * This driver requires at least one IORESOURCE_MEM for the
+ * registers and two IORESOURCE_IRQ for the RX and TX IRQs
+ * respectively. It can optionally take an additional
+ * IORESOURCE_MEM for the switch or phy in the case of the lan or
+ * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
+ * port.
+ */
+ static int __devinit
+ ks8695_probe(struct platform_device *pdev)
+ {
+ struct ks8695_priv *ksp;
+ struct net_device *ndev;
+ struct resource *regs_res, *phyiface_res;
+ struct resource *rxirq_res, *txirq_res, *linkirq_res;
+ int ret = 0;
+ int buff_n;
+ u32 machigh, maclow;
+
+ /* Initialise a net_device */
+ ndev = alloc_etherdev(sizeof(struct ks8695_priv));
+ if (!ndev) {
+ dev_err(&pdev->dev, "could not allocate device.\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ dev_dbg(&pdev->dev, "ks8695_probe() called\n");
+
+ /* Configure our private structure a little */
+ ksp = netdev_priv(ndev);
+
+ ksp->dev = &pdev->dev;
+ ksp->ndev = ndev;
+ ksp->msg_enable = NETIF_MSG_LINK;
+
+ /* Retrieve resources */
+ regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+ rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
+
+ if (!(regs_res && rxirq_res && txirq_res)) {
+ dev_err(ksp->dev, "insufficient resources\n");
+ ret = -ENOENT;
+ goto failure;
+ }
+
+ ksp->regs_req = request_mem_region(regs_res->start,
+ resource_size(regs_res),
+ pdev->name);
+
+ if (!ksp->regs_req) {
+ dev_err(ksp->dev, "cannot claim register space\n");
+ ret = -EIO;
+ goto failure;
+ }
+
+ ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res));
+
+ if (!ksp->io_regs) {
+ dev_err(ksp->dev, "failed to ioremap registers\n");
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ if (phyiface_res) {
+ ksp->phyiface_req =
+ request_mem_region(phyiface_res->start,
+ resource_size(phyiface_res),
+ phyiface_res->name);
+
+ if (!ksp->phyiface_req) {
+ dev_err(ksp->dev,
+ "cannot claim switch register space\n");
+ ret = -EIO;
+ goto failure;
+ }
+
+ ksp->phyiface_regs = ioremap(phyiface_res->start,
+ resource_size(phyiface_res));
+
+ if (!ksp->phyiface_regs) {
+ dev_err(ksp->dev,
+ "failed to ioremap switch registers\n");
+ ret = -EINVAL;
+ goto failure;
+ }
+ }
+
+ ksp->rx_irq = rxirq_res->start;
+ ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX";
+ ksp->tx_irq = txirq_res->start;
+ ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX";
+ ksp->link_irq = (linkirq_res ? linkirq_res->start : -1);
+ ksp->link_irq_name = (linkirq_res && linkirq_res->name) ?
+ linkirq_res->name : "Ethernet Link";
+
+ /* driver system setup */
+ ndev->netdev_ops = &ks8695_netdev_ops;
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+
+ netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT);
+
+ /* Retrieve the default MAC addr from the chip. */
+ /* The bootloader should have left it in there for us. */
+
+ machigh = ks8695_readreg(ksp, KS8695_MAH);
+ maclow = ks8695_readreg(ksp, KS8695_MAL);
+
+ ndev->dev_addr[0] = (machigh >> 8) & 0xFF;
+ ndev->dev_addr[1] = machigh & 0xFF;
+ ndev->dev_addr[2] = (maclow >> 24) & 0xFF;
+ ndev->dev_addr[3] = (maclow >> 16) & 0xFF;
+ ndev->dev_addr[4] = (maclow >> 8) & 0xFF;
+ ndev->dev_addr[5] = maclow & 0xFF;
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please "
+ "set using ifconfig\n", ndev->name);
+
+ /* In order to be efficient memory-wise, we allocate both
+ * rings in one go.
+ */
+ ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE,
+ &ksp->ring_base_dma, GFP_KERNEL);
+ if (!ksp->ring_base) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ /* Specify the TX DMA ring buffer */
+ ksp->tx_ring = ksp->ring_base;
+ ksp->tx_ring_dma = ksp->ring_base_dma;
+
+ /* And initialise the queue's lock */
+ spin_lock_init(&ksp->txq_lock);
+ spin_lock_init(&ksp->rx_lock);
+
+ /* Specify the RX DMA ring buffer */
+ ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
+ ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE;
+
+ /* Zero the descriptor rings */
+ memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE);
+ memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE);
+
+ /* Build the rings */
+ for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
+ ksp->tx_ring[buff_n].next_desc =
+ cpu_to_le32(ksp->tx_ring_dma +
+ (sizeof(struct tx_ring_desc) *
+ ((buff_n + 1) & MAX_TX_DESC_MASK)));
+ }
+
+ for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
+ ksp->rx_ring[buff_n].next_desc =
+ cpu_to_le32(ksp->rx_ring_dma +
+ (sizeof(struct rx_ring_desc) *
+ ((buff_n + 1) & MAX_RX_DESC_MASK)));
+ }
+
+ /* Initialise the port (physically) */
+ if (ksp->phyiface_regs && ksp->link_irq == -1) {
+ ks8695_init_switch(ksp);
+ ksp->dtype = KS8695_DTYPE_LAN;
+ SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
+ } else if (ksp->phyiface_regs && ksp->link_irq != -1) {
+ ks8695_init_wan_phy(ksp);
+ ksp->dtype = KS8695_DTYPE_WAN;
+ SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops);
+ } else {
+ /* No initialisation since HPNA does not have a PHY */
+ ksp->dtype = KS8695_DTYPE_HPNA;
+ SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
+ }
+
+ /* And bring up the net_device with the net core */
+ platform_set_drvdata(pdev, ndev);
+ ret = register_netdev(ndev);
+
+ if (ret == 0) {
+ dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n",
+ ks8695_port_type(ksp), ndev->dev_addr);
+ } else {
+ /* Report the failure to register the net_device */
+ dev_err(ksp->dev, "ks8695net: failed to register netdev.\n");
+ goto failure;
+ }
+
+ /* All is well */
+ return 0;
+
+ /* Error exit path */
+ failure:
+ ks8695_release_device(ksp);
+ free_netdev(ndev);
+
+ return ret;
+ }
+
+ /**
+ * ks8695_drv_suspend - Suspend a KS8695 ethernet platform device.
+ * @pdev: The device to suspend
+ * @state: The suspend state
+ *
+ * This routine detaches and shuts down a KS8695 ethernet device.
+ */
+ static int
+ ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ ksp->in_suspend = 1;
+
+ if (netif_running(ndev)) {
+ netif_device_detach(ndev);
+ ks8695_shutdown(ksp);
+ }
+
+ return 0;
+ }
+
+ /**
+ * ks8695_drv_resume - Resume a KS8695 ethernet platform device.
+ * @pdev: The device to resume
+ *
+ * This routine re-initialises and re-attaches a KS8695 ethernet
+ * device.
+ */
+ static int
+ ks8695_drv_resume(struct platform_device *pdev)
+ {
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ ks8695_reset(ksp);
+ ks8695_init_net(ksp);
+ ks8695_set_multicast(ndev);
+ netif_device_attach(ndev);
+ }
+
+ ksp->in_suspend = 0;
+
+ return 0;
+ }
+
+ /**
+ * ks8695_drv_remove - Remove a KS8695 net device on driver unload.
+ * @pdev: The platform device to remove
+ *
+ * This unregisters and releases a KS8695 ethernet device.
+ */
+ static int __devexit
+ ks8695_drv_remove(struct platform_device *pdev)
+ {
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ platform_set_drvdata(pdev, NULL);
+ netif_napi_del(&ksp->napi);
+
+ unregister_netdev(ndev);
+ ks8695_release_device(ksp);
+ free_netdev(ndev);
+
+ dev_dbg(&pdev->dev, "released and freed device\n");
+ return 0;
+ }
+
+ static struct platform_driver ks8695_driver = {
+ .driver = {
+ .name = MODULENAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = ks8695_probe,
+ .remove = __devexit_p(ks8695_drv_remove),
+ .suspend = ks8695_drv_suspend,
+ .resume = ks8695_drv_resume,
+ };
+
+ /* Module interface */
+
+ static int __init
+ ks8695_init(void)
+ {
+ printk(KERN_INFO "%s Ethernet driver, V%s\n",
+ MODULENAME, MODULEVERSION);
+
+ return platform_driver_register(&ks8695_driver);
+ }
+
+ static void __exit
+ ks8695_cleanup(void)
+ {
+ platform_driver_unregister(&ks8695_driver);
+ }
+
+ module_init(ks8695_init);
+ module_exit(ks8695_cleanup);
+
+ MODULE_AUTHOR("Simtec Electronics");
+ MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("platform:" MODULENAME);
+
+ module_param(watchdog, int, 0400);
+ MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
--- /dev/null
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ #
+ # Western Digital/SMC network device configuration
+ #
+
+ config NET_VENDOR_SMSC
+ bool "SMC (SMSC)/Western Digital devices"
+ default y
+ depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \
+ BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about SMC/Western Digital cards. If you say Y, you will
+ be asked for your specific card in the following questions.
+
+ if NET_VENDOR_SMSC
+
+ config SMC9194
+ tristate "SMC 9194 support"
+ depends on (ISA || MAC && BROKEN)
+ select CRC32
+ ---help---
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+ option if you have a DELL laptop with the docking station, or
+ another SMC9192/9194 based chipset. Say Y if you want it compiled
+ into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called smc9194.
+
+ config SMC91X
+ tristate "SMC 91C9x/91C1xxx support"
+ select CRC32
+ select NET_CORE
+ select MII
+ depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \
+ MN10300 || COLDFIRE)
+ ---help---
+ This is a driver for SMC's 91x series of Ethernet chipsets,
+ including the SMC91C94 and the SMC91C111. Say Y if you want it
+ compiled into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc91x. If you want to compile it as a
+ module, say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ config PCMCIA_SMC91C92
+ tristate "SMC 91Cxx PCMCIA support"
+ depends on PCMCIA
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
+ (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called smc91c92_cs. If unsure, say N.
+
+ config EPIC100
+ tristate "SMC EtherPower II"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
+ which is based on the SMC83c17x (EPIC/100).
+ More specific information and updates are available from
+ <http://www.scyld.com/network/epic100.html>.
+
+ config SMC911X
+ tristate "SMSC LAN911[5678] support"
+ select CRC32
+ select NET_CORE
+ select MII
+ depends on (ARM || SUPERH || MN10300)
+ ---help---
+ This is a driver for SMSC's LAN911x series of Ethernet chipsets
+ including the new LAN9115, LAN9116, LAN9117, and LAN9118.
+ Say Y if you want it compiled into the kernel,
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module. The module will be
+ called smc911x. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>
+
+ config SMSC911X
+ tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
+ depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300)
+ select CRC32
+ select NET_CORE
+ select MII
+ select PHYLIB
+ ---help---
+ Say Y here if you want support for SMSC LAN911x and LAN921x families
+ of ethernet controllers.
+
++ To compile this driver as a module, choose M here. The module
+ will be called smsc911x.
+
+ config SMSC911X_ARCH_HOOKS
+ def_bool n
+ depends on SMSC911X
+ ---help---
+ If the arch enables this, it allows the arch to implement various
+ hooks for more comprehensive interrupt control and also to override
+ the source of the MAC address.
+
+ config SMSC9420
+ tristate "SMSC LAN9420 PCI ethernet adapter support"
+ depends on PCI
+ select CRC32
+ select PHYLIB
+ select SMSC_PHY
+ ---help---
+ This is a driver for SMSC's LAN9420 PCI ethernet adapter.
+ Say Y if you want it compiled into the kernel,
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module. The module will be
+ called smsc9420. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>
+
+ endif # NET_VENDOR_SMSC
--- /dev/null
- /* True if this tile has succcessfully registered with the IPP. */
+ /*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for
+ * more details.
+ */
+
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/moduleparam.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h> /* printk() */
+ #include <linux/slab.h> /* kmalloc() */
+ #include <linux/errno.h> /* error codes */
+ #include <linux/types.h> /* size_t */
+ #include <linux/interrupt.h>
+ #include <linux/in.h>
+ #include <linux/netdevice.h> /* struct device, and other headers */
+ #include <linux/etherdevice.h> /* eth_type_trans */
+ #include <linux/skbuff.h>
+ #include <linux/ioctl.h>
+ #include <linux/cdev.h>
+ #include <linux/hugetlb.h>
+ #include <linux/in6.h>
+ #include <linux/timer.h>
+ #include <linux/io.h>
+ #include <asm/checksum.h>
+ #include <asm/homecache.h>
+
+ #include <hv/drv_xgbe_intf.h>
+ #include <hv/drv_xgbe_impl.h>
+ #include <hv/hypervisor.h>
+ #include <hv/netio_intf.h>
+
+ /* For TSO */
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+
+
+ /*
+ * First, "tile_net_init_module()" initializes all four "devices" which
+ * can be used by linux.
+ *
+ * Then, "ifconfig DEVICE up" calls "tile_net_open()", which analyzes
+ * the network cpus, then uses "tile_net_open_aux()" to initialize
+ * LIPP/LEPP, and then uses "tile_net_open_inner()" to register all
+ * the tiles, provide buffers to LIPP, allow ingress to start, and
+ * turn on hypervisor interrupt handling (and NAPI) on all tiles.
+ *
+ * If registration fails due to the link being down, then "retry_work"
+ * is used to keep calling "tile_net_open_inner()" until it succeeds.
+ *
+ * If "ifconfig DEVICE down" is called, it uses "tile_net_stop()" to
+ * stop egress, drain the LIPP buffers, unregister all the tiles, stop
+ * LIPP/LEPP, and wipe the LEPP queue.
+ *
+ * We start out with the ingress interrupt enabled on each CPU. When
+ * this interrupt fires, we disable it, and call "napi_schedule()".
+ * This will cause "tile_net_poll()" to be called, which will pull
+ * packets from the netio queue, filtering them out, or passing them
+ * to "netif_receive_skb()". If our budget is exhausted, we will
+ * return, knowing we will be called again later. Otherwise, we
+ * reenable the ingress interrupt, and call "napi_complete()".
+ *
+ * HACK: Since disabling the ingress interrupt is not reliable, we
+ * ignore the interrupt if the global "active" flag is false.
+ *
+ *
+ * NOTE: The use of "native_driver" ensures that EPP exists, and that
+ * we are using "LIPP" and "LEPP".
+ *
+ * NOTE: Failing to free completions for an arbitrarily long time
+ * (which is defined to be illegal) does in fact cause bizarre
+ * problems. The "egress_timer" helps prevent this from happening.
+ */
+
+
+ /* HACK: Allow use of "jumbo" packets. */
+ /* This should be 1500 if "jumbo" is not set in LIPP. */
+ /* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */
+ /* ISSUE: This has not been thoroughly tested (except at 1500). */
+ #define TILE_NET_MTU 1500
+
+ /* HACK: Define to support GSO. */
+ /* ISSUE: This may actually hurt performance of the TCP blaster. */
+ /* #define TILE_NET_GSO */
+
+ /* Define this to collapse "duplicate" acks. */
+ /* #define IGNORE_DUP_ACKS */
+
+ /* HACK: Define this to verify incoming packets. */
+ /* #define TILE_NET_VERIFY_INGRESS */
+
+ /* Use 3000 to enable the Linux Traffic Control (QoS) layer, else 0. */
+ #define TILE_NET_TX_QUEUE_LEN 0
+
+ /* Define to dump packets (prints out the whole packet on tx and rx). */
+ /* #define TILE_NET_DUMP_PACKETS */
+
+ /* Define to enable debug spew (all PDEBUG's are enabled). */
+ /* #define TILE_NET_DEBUG */
+
+
+ /* Define to activate paranoia checks. */
+ /* #define TILE_NET_PARANOIA */
+
+ /* Default transmit lockup timeout period, in jiffies. */
+ #define TILE_NET_TIMEOUT (5 * HZ)
+
+ /* Default retry interval for bringing up the NetIO interface, in jiffies. */
+ #define TILE_NET_RETRY_INTERVAL (5 * HZ)
+
+ /* Number of ports (xgbe0, xgbe1, gbe0, gbe1). */
+ #define TILE_NET_DEVS 4
+
+
+
+ /* Paranoia. */
+ #if NET_IP_ALIGN != LIPP_PACKET_PADDING
+ #error "NET_IP_ALIGN must match LIPP_PACKET_PADDING."
+ #endif
+
+
+ /* Debug print. */
+ #ifdef TILE_NET_DEBUG
+ #define PDEBUG(fmt, args...) net_printk(fmt, ## args)
+ #else
+ #define PDEBUG(fmt, args...)
+ #endif
+
+
+ MODULE_AUTHOR("Tilera");
+ MODULE_LICENSE("GPL");
+
+
+ /*
+ * Queue of incoming packets for a specific cpu and device.
+ *
+ * Includes a pointer to the "system" data, and the actual "user" data.
+ */
+ struct tile_netio_queue {
+ netio_queue_impl_t *__system_part;
+ netio_queue_user_impl_t __user_part;
+
+ };
+
+
+ /*
+ * Statistics counters for a specific cpu and device.
+ */
+ struct tile_net_stats_t {
+ u32 rx_packets;
+ u32 rx_bytes;
+ u32 tx_packets;
+ u32 tx_bytes;
+ };
+
+
+ /*
+ * Info for a specific cpu and device.
+ *
+ * ISSUE: There is a "dev" pointer in "napi" as well.
+ */
+ struct tile_net_cpu {
+ /* The NAPI struct. */
+ struct napi_struct napi;
+ /* Packet queue. */
+ struct tile_netio_queue queue;
+ /* Statistics. */
+ struct tile_net_stats_t stats;
+ /* True iff NAPI is enabled. */
+ bool napi_enabled;
++ /* True if this tile has successfully registered with the IPP. */
+ bool registered;
+ /* True if the link was down last time we tried to register. */
+ bool link_down;
+ /* True if "egress_timer" is scheduled. */
+ bool egress_timer_scheduled;
+ /* Number of small sk_buffs which must still be provided. */
+ unsigned int num_needed_small_buffers;
+ /* Number of large sk_buffs which must still be provided. */
+ unsigned int num_needed_large_buffers;
+ /* A timer for handling egress completions. */
+ struct timer_list egress_timer;
+ };
+
+
+ /*
+ * Info for a specific device.
+ */
+ struct tile_net_priv {
+ /* Our network device. */
+ struct net_device *dev;
+ /* Pages making up the egress queue. */
+ struct page *eq_pages;
+ /* Address of the actual egress queue. */
+ lepp_queue_t *eq;
+ /* Protects "eq". */
+ spinlock_t eq_lock;
+ /* The hypervisor handle for this interface. */
+ int hv_devhdl;
+ /* The intr bit mask that IDs this device. */
+ u32 intr_id;
+ /* True iff "tile_net_open_aux()" has succeeded. */
+ bool partly_opened;
+ /* True iff the device is "active". */
+ bool active;
+ /* Effective network cpus. */
+ struct cpumask network_cpus_map;
+ /* Number of network cpus. */
+ int network_cpus_count;
+ /* Credits per network cpu. */
+ int network_cpus_credits;
+ /* Network stats. */
+ struct net_device_stats stats;
+ /* For NetIO bringup retries. */
+ struct delayed_work retry_work;
+ /* Quick access to per cpu data. */
+ struct tile_net_cpu *cpu[NR_CPUS];
+ };
+
+ /* Log2 of the number of small pages needed for the egress queue. */
+ #define EQ_ORDER get_order(sizeof(lepp_queue_t))
+ /* Size of the egress queue's pages. */
+ #define EQ_SIZE (1 << (PAGE_SHIFT + EQ_ORDER))
+
+ /*
+ * The actual devices (xgbe0, xgbe1, gbe0, gbe1).
+ */
+ static struct net_device *tile_net_devs[TILE_NET_DEVS];
+
+ /*
+ * The "tile_net_cpu" structures for each device.
+ */
+ static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe0);
+ static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe1);
+ static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe0);
+ static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe1);
+
+
+ /*
+ * True if "network_cpus" was specified.
+ */
+ static bool network_cpus_used;
+
+ /*
+ * The actual cpus in "network_cpus".
+ */
+ static struct cpumask network_cpus_map;
+
+
+
+ #ifdef TILE_NET_DEBUG
+ /*
+ * printk with extra stuff.
+ *
+ * We print the CPU we're running in brackets.
+ */
+ static void net_printk(char *fmt, ...)
+ {
+ int i;
+ int len;
+ va_list args;
+ static char buf[256];
+
+ len = sprintf(buf, "tile_net[%2.2d]: ", smp_processor_id());
+ va_start(args, fmt);
+ i = vscnprintf(buf + len, sizeof(buf) - len - 1, fmt, args);
+ va_end(args);
+ buf[255] = '\0';
+ pr_notice(buf);
+ }
+ #endif
+
+
+ #ifdef TILE_NET_DUMP_PACKETS
+ /*
+ * Dump a packet.
+ */
+ static void dump_packet(unsigned char *data, unsigned long length, char *s)
+ {
+ int my_cpu = smp_processor_id();
+
+ unsigned long i;
+ char buf[128];
+
+ static unsigned int count;
+
+ pr_info("dump_packet(data %p, length 0x%lx s %s count 0x%x)\n",
+ data, length, s, count++);
+
+ pr_info("\n");
+
+ for (i = 0; i < length; i++) {
+ if ((i & 0xf) == 0)
+ sprintf(buf, "[%02d] %8.8lx:", my_cpu, i);
+ sprintf(buf + strlen(buf), " %2.2x", data[i]);
+ if ((i & 0xf) == 0xf || i == length - 1) {
+ strcat(buf, "\n");
+ pr_info("%s", buf);
+ }
+ }
+ }
+ #endif
+
+
+ /*
+ * Provide support for the __netio_fastio1() swint
+ * (see <hv/drv_xgbe_intf.h> for how it is used).
+ *
+ * The fastio swint2 call may clobber all the caller-saved registers.
+ * It rarely clobbers memory, but we allow for the possibility in
+ * the signature just to be on the safe side.
+ *
+ * Also, gcc doesn't seem to allow an input operand to be
+ * clobbered, so we fake it with dummy outputs.
+ *
+ * This function can't be static because of the way it is declared
+ * in the netio header.
+ */
+ inline int __netio_fastio1(u32 fastio_index, u32 arg0)
+ {
+ long result, clobber_r1, clobber_r10;
+ asm volatile("swint2"
+ : "=R00" (result),
+ "=R01" (clobber_r1), "=R10" (clobber_r10)
+ : "R10" (fastio_index), "R01" (arg0)
+ : "memory", "r2", "r3", "r4",
+ "r5", "r6", "r7", "r8", "r9",
+ "r11", "r12", "r13", "r14",
+ "r15", "r16", "r17", "r18", "r19",
+ "r20", "r21", "r22", "r23", "r24",
+ "r25", "r26", "r27", "r28", "r29");
+ return result;
+ }
+
+
+ /*
+ * Provide a linux buffer to LIPP.
+ */
+ static void tile_net_provide_linux_buffer(struct tile_net_cpu *info,
+ void *va, bool small)
+ {
+ struct tile_netio_queue *queue = &info->queue;
+
+ /* Convert "va" and "small" to "linux_buffer_t". */
+ unsigned int buffer = ((unsigned int)(__pa(va) >> 7) << 1) + small;
+
+ __netio_fastio_free_buffer(queue->__user_part.__fastio_index, buffer);
+ }
+
+
+ /*
+ * Provide a linux buffer for LIPP.
+ *
+ * Note that the ACTUAL allocation for each buffer is a "struct sk_buff",
+ * plus a chunk of memory that includes not only the requested bytes, but
+ * also NET_SKB_PAD bytes of initial padding, and a "struct skb_shared_info".
+ *
+ * Note that "struct skb_shared_info" is 88 bytes with 64K pages and
+ * 268 bytes with 4K pages (since the frags[] array needs 18 entries).
+ *
+ * Without jumbo packets, the maximum packet size will be 1536 bytes,
+ * and we use 2 bytes (NET_IP_ALIGN) of padding. ISSUE: If we told
+ * the hardware to clip at 1518 bytes instead of 1536 bytes, then we
+ * could save an entire cache line, but in practice, we don't need it.
+ *
+ * Since CPAs are 38 bits, and we can only encode the high 31 bits in
+ * a "linux_buffer_t", the low 7 bits must be zero, and thus, we must
+ * align the actual "va" mod 128.
+ *
+ * We assume that the underlying "head" will be aligned mod 64. Note
+ * that in practice, we have seen "head" NOT aligned mod 128 even when
+ * using 2048 byte allocations, which is surprising.
+ *
+ * If "head" WAS always aligned mod 128, we could change LIPP to
+ * assume that the low SIX bits are zero, and the 7th bit is one, that
+ * is, align the actual "va" mod 128 plus 64, which would be "free".
+ *
+ * For now, the actual "head" pointer points at NET_SKB_PAD bytes of
+ * padding, plus 28 or 92 bytes of extra padding, plus the sk_buff
+ * pointer, plus the NET_IP_ALIGN padding, plus 126 or 1536 bytes for
+ * the actual packet, plus 62 bytes of empty padding, plus some
+ * padding and the "struct skb_shared_info".
+ *
+ * With 64K pages, a large buffer thus needs 32+92+4+2+1536+62+88
+ * bytes, or 1816 bytes, which fits comfortably into 2048 bytes.
+ *
+ * With 64K pages, a small buffer thus needs 32+92+4+2+126+88
+ * bytes, or 344 bytes, which means we are wasting 64+ bytes, and
+ * could presumably increase the size of small buffers.
+ *
+ * With 4K pages, a large buffer thus needs 32+92+4+2+1536+62+268
+ * bytes, or 1996 bytes, which fits comfortably into 2048 bytes.
+ *
+ * With 4K pages, a small buffer thus needs 32+92+4+2+126+268
+ * bytes, or 524 bytes, which is annoyingly wasteful.
+ *
+ * Maybe we should increase LIPP_SMALL_PACKET_SIZE to 192?
+ *
+ * ISSUE: Maybe we should increase "NET_SKB_PAD" to 64?
+ */
+ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
+ bool small)
+ {
+ #if TILE_NET_MTU <= 1536
+ /* Without "jumbo", 2 + 1536 should be sufficient. */
+ unsigned int large_size = NET_IP_ALIGN + 1536;
+ #else
+ /* ISSUE: This has not been tested. */
+ unsigned int large_size = NET_IP_ALIGN + TILE_NET_MTU + 100;
+ #endif
+
+ /* Avoid "false sharing" with last cache line. */
+ /* ISSUE: This is already done by "dev_alloc_skb()". */
+ unsigned int len =
+ (((small ? LIPP_SMALL_PACKET_SIZE : large_size) +
+ CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE());
+
+ unsigned int padding = 128 - NET_SKB_PAD;
+ unsigned int align;
+
+ struct sk_buff *skb;
+ void *va;
+
+ struct sk_buff **skb_ptr;
+
+ /* Request 96 extra bytes for alignment purposes. */
+ skb = dev_alloc_skb(len + padding);
+ if (skb == NULL)
+ return false;
+
+ /* Skip 32 or 96 bytes to align "data" mod 128. */
+ align = -(long)skb->data & (128 - 1);
+ BUG_ON(align > padding);
+ skb_reserve(skb, align);
+
+ /* This address is given to IPP. */
+ va = skb->data;
+
+ /* Buffers must not span a huge page. */
+ BUG_ON(((((long)va & ~HPAGE_MASK) + len) & HPAGE_MASK) != 0);
+
+ #ifdef TILE_NET_PARANOIA
+ #if CHIP_HAS_CBOX_HOME_MAP()
+ if (hash_default) {
+ HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va);
+ if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
+ panic("Non-HFH ingress buffer! VA=%p Mode=%d PTE=%llx",
+ va, hv_pte_get_mode(pte), hv_pte_val(pte));
+ }
+ #endif
+ #endif
+
+ /* Invalidate the packet buffer. */
+ if (!hash_default)
+ __inv_buffer(va, len);
+
+ /* Skip two bytes to satisfy LIPP assumptions. */
+ /* Note that this aligns IP on a 16 byte boundary. */
+ /* ISSUE: Do this when the packet arrives? */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ /* Save a back-pointer to 'skb'. */
+ skb_ptr = va - sizeof(*skb_ptr);
+ *skb_ptr = skb;
+
+ /* Make sure "skb_ptr" has been flushed. */
+ __insn_mf();
+
+ /* Provide the new buffer. */
+ tile_net_provide_linux_buffer(info, va, small);
+
+ return true;
+ }
+
+
+ /*
+ * Provide linux buffers for LIPP.
+ */
+ static void tile_net_provide_needed_buffers(struct tile_net_cpu *info)
+ {
+ while (info->num_needed_small_buffers != 0) {
+ if (!tile_net_provide_needed_buffer(info, true))
+ goto oops;
+ info->num_needed_small_buffers--;
+ }
+
+ while (info->num_needed_large_buffers != 0) {
+ if (!tile_net_provide_needed_buffer(info, false))
+ goto oops;
+ info->num_needed_large_buffers--;
+ }
+
+ return;
+
+ oops:
+
+ /* Add a description to the page allocation failure dump. */
+ pr_notice("Could not provide a linux buffer to LIPP.\n");
+ }
+
+
+ /*
+ * Grab some LEPP completions, and store them in "comps", of size
+ * "comps_size", and return the number of completions which were
+ * stored, so the caller can free them.
+ */
+ static unsigned int tile_net_lepp_grab_comps(lepp_queue_t *eq,
+ struct sk_buff *comps[],
+ unsigned int comps_size,
+ unsigned int min_size)
+ {
+ unsigned int n = 0;
+
+ unsigned int comp_head = eq->comp_head;
+ unsigned int comp_busy = eq->comp_busy;
+
+ while (comp_head != comp_busy && n < comps_size) {
+ comps[n++] = eq->comps[comp_head];
+ LEPP_QINC(comp_head);
+ }
+
+ if (n < min_size)
+ return 0;
+
+ eq->comp_head = comp_head;
+
+ return n;
+ }
+
+
+ /*
+ * Free some comps, and return true iff there are still some pending.
+ */
+ static bool tile_net_lepp_free_comps(struct net_device *dev, bool all)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+
+ lepp_queue_t *eq = priv->eq;
+
+ struct sk_buff *olds[64];
+ unsigned int wanted = 64;
+ unsigned int i, n;
+ bool pending;
+
+ spin_lock(&priv->eq_lock);
+
+ if (all)
+ eq->comp_busy = eq->comp_tail;
+
+ n = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+
+ pending = (eq->comp_head != eq->comp_tail);
+
+ spin_unlock(&priv->eq_lock);
+
+ for (i = 0; i < n; i++)
+ kfree_skb(olds[i]);
+
+ return pending;
+ }
+
+
+ /*
+ * Make sure the egress timer is scheduled.
+ *
+ * Note that we use "schedule if not scheduled" logic instead of the more
+ * obvious "reschedule" logic, because "reschedule" is fairly expensive.
+ */
+ static void tile_net_schedule_egress_timer(struct tile_net_cpu *info)
+ {
+ if (!info->egress_timer_scheduled) {
+ mod_timer_pinned(&info->egress_timer, jiffies + 1);
+ info->egress_timer_scheduled = true;
+ }
+ }
+
+
+ /*
+ * The "function" for "info->egress_timer".
+ *
+ * This timer will reschedule itself as long as there are any pending
+ * completions expected (on behalf of any tile).
+ *
+ * ISSUE: Realistically, will the timer ever stop scheduling itself?
+ *
+ * ISSUE: This timer is almost never actually needed, so just use a global
+ * timer that can run on any tile.
+ *
+ * ISSUE: Maybe instead track number of expected completions, and free
+ * only that many, resetting to zero if "pending" is ever false.
+ */
+ static void tile_net_handle_egress_timer(unsigned long arg)
+ {
+ struct tile_net_cpu *info = (struct tile_net_cpu *)arg;
+ struct net_device *dev = info->napi.dev;
+
+ /* The timer is no longer scheduled. */
+ info->egress_timer_scheduled = false;
+
+ /* Free comps, and reschedule timer if more are pending. */
+ if (tile_net_lepp_free_comps(dev, false))
+ tile_net_schedule_egress_timer(info);
+ }
+
+
+ #ifdef IGNORE_DUP_ACKS
+
+ /*
+ * Help detect "duplicate" ACKs. These are sequential packets (for a
+ * given flow) which are exactly 66 bytes long, sharing everything but
+ * ID=2@0x12, Hsum=2@0x18, Ack=4@0x2a, WinSize=2@0x30, Csum=2@0x32,
+ * Tstamps=10@0x38. The ID's are +1, the Hsum's are -1, the Ack's are
+ * +N, and the Tstamps are usually identical.
+ *
+ * NOTE: Apparently truly duplicate acks (with identical "ack" values),
+ * should not be collapsed, as they are used for some kind of flow control.
+ */
+ static bool is_dup_ack(char *s1, char *s2, unsigned int len)
+ {
+ int i;
+
+ unsigned long long ignorable = 0;
+
+ /* Identification. */
+ ignorable |= (1ULL << 0x12);
+ ignorable |= (1ULL << 0x13);
+
+ /* Header checksum. */
+ ignorable |= (1ULL << 0x18);
+ ignorable |= (1ULL << 0x19);
+
+ /* ACK. */
+ ignorable |= (1ULL << 0x2a);
+ ignorable |= (1ULL << 0x2b);
+ ignorable |= (1ULL << 0x2c);
+ ignorable |= (1ULL << 0x2d);
+
+ /* WinSize. */
+ ignorable |= (1ULL << 0x30);
+ ignorable |= (1ULL << 0x31);
+
+ /* Checksum. */
+ ignorable |= (1ULL << 0x32);
+ ignorable |= (1ULL << 0x33);
+
+ for (i = 0; i < len; i++, ignorable >>= 1) {
+
+ if ((ignorable & 1) || (s1[i] == s2[i]))
+ continue;
+
+ #ifdef TILE_NET_DEBUG
+ /* HACK: Mention non-timestamp diffs. */
+ if (i < 0x38 && i != 0x2f &&
+ net_ratelimit())
+ pr_info("Diff at 0x%x\n", i);
+ #endif
+
+ return false;
+ }
+
+ #ifdef TILE_NET_NO_SUPPRESS_DUP_ACKS
+ /* HACK: Do not suppress truly duplicate ACKs. */
+ /* ISSUE: Is this actually necessary or helpful? */
+ if (s1[0x2a] == s2[0x2a] &&
+ s1[0x2b] == s2[0x2b] &&
+ s1[0x2c] == s2[0x2c] &&
+ s1[0x2d] == s2[0x2d]) {
+ return false;
+ }
+ #endif
+
+ return true;
+ }
+
+ #endif
+
+
+
+ static void tile_net_discard_aux(struct tile_net_cpu *info, int index)
+ {
+ struct tile_netio_queue *queue = &info->queue;
+ netio_queue_impl_t *qsp = queue->__system_part;
+ netio_queue_user_impl_t *qup = &queue->__user_part;
+
+ int index2_aux = index + sizeof(netio_pkt_t);
+ int index2 =
+ ((index2_aux ==
+ qsp->__packet_receive_queue.__last_packet_plus_one) ?
+ 0 : index2_aux);
+
+ netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index);
+
+ /* Extract the "linux_buffer_t". */
+ unsigned int buffer = pkt->__packet.word;
+
+ /* Convert "linux_buffer_t" to "va". */
+ void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+ /* Acquire the associated "skb". */
+ struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+ struct sk_buff *skb = *skb_ptr;
+
+ kfree_skb(skb);
+
+ /* Consume this packet. */
+ qup->__packet_receive_read = index2;
+ }
+
+
+ /*
+ * Like "tile_net_poll()", but just discard packets.
+ */
+ static void tile_net_discard_packets(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+ struct tile_netio_queue *queue = &info->queue;
+ netio_queue_impl_t *qsp = queue->__system_part;
+ netio_queue_user_impl_t *qup = &queue->__user_part;
+
+ while (qup->__packet_receive_read !=
+ qsp->__packet_receive_queue.__packet_write) {
+ int index = qup->__packet_receive_read;
+ tile_net_discard_aux(info, index);
+ }
+ }
+
+
+ /*
+ * Handle the next packet. Return true if "processed", false if "filtered".
+ */
+ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
+ {
+ struct net_device *dev = info->napi.dev;
+
+ struct tile_netio_queue *queue = &info->queue;
+ netio_queue_impl_t *qsp = queue->__system_part;
+ netio_queue_user_impl_t *qup = &queue->__user_part;
+ struct tile_net_stats_t *stats = &info->stats;
+
+ int filter;
+
+ int index2_aux = index + sizeof(netio_pkt_t);
+ int index2 =
+ ((index2_aux ==
+ qsp->__packet_receive_queue.__last_packet_plus_one) ?
+ 0 : index2_aux);
+
+ netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index);
+
+ netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt);
+
+ /* Extract the packet size. FIXME: Shouldn't the second line */
+ /* get subtracted? Mostly moot, since it should be "zero". */
+ unsigned long len =
+ (NETIO_PKT_CUSTOM_LENGTH(pkt) +
+ NET_IP_ALIGN - NETIO_PACKET_PADDING);
+
+ /* Extract the "linux_buffer_t". */
+ unsigned int buffer = pkt->__packet.word;
+
+ /* Extract "small" (vs "large"). */
+ bool small = ((buffer & 1) != 0);
+
+ /* Convert "linux_buffer_t" to "va". */
+ void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+ /* Extract the packet data pointer. */
+ /* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
+ unsigned char *buf = va + NET_IP_ALIGN;
+
+ /* Invalidate the packet buffer. */
+ if (!hash_default)
+ __inv_buffer(buf, len);
+
+ /* ISSUE: Is this needed? */
+ dev->last_rx = jiffies;
+
+ #ifdef TILE_NET_DUMP_PACKETS
+ dump_packet(buf, len, "rx");
+ #endif /* TILE_NET_DUMP_PACKETS */
+
+ #ifdef TILE_NET_VERIFY_INGRESS
+ if (!NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt) &&
+ NETIO_PKT_L4_CSUM_CALCULATED_M(metadata, pkt)) {
+ /* Bug 6624: Includes UDP packets with a "zero" checksum. */
+ pr_warning("Bad L4 checksum on %d byte packet.\n", len);
+ }
+ if (!NETIO_PKT_L3_CSUM_CORRECT_M(metadata, pkt) &&
+ NETIO_PKT_L3_CSUM_CALCULATED_M(metadata, pkt)) {
+ dump_packet(buf, len, "rx");
+ panic("Bad L3 checksum.");
+ }
+ switch (NETIO_PKT_STATUS_M(metadata, pkt)) {
+ case NETIO_PKT_STATUS_OVERSIZE:
+ if (len >= 64) {
+ dump_packet(buf, len, "rx");
+ panic("Unexpected OVERSIZE.");
+ }
+ break;
+ case NETIO_PKT_STATUS_BAD:
+ pr_warning("Unexpected BAD %ld byte packet.\n", len);
+ }
+ #endif
+
+ filter = 0;
+
+ /* ISSUE: Filter TCP packets with "bad" checksums? */
+
+ if (!(dev->flags & IFF_UP)) {
+ /* Filter packets received before we're up. */
+ filter = 1;
+ } else if (NETIO_PKT_STATUS_M(metadata, pkt) == NETIO_PKT_STATUS_BAD) {
+ /* Filter "truncated" packets. */
+ filter = 1;
+ } else if (!(dev->flags & IFF_PROMISC)) {
+ /* FIXME: Implement HW multicast filter. */
+ if (!is_multicast_ether_addr(buf)) {
+ /* Filter packets not for our address. */
+ const u8 *mine = dev->dev_addr;
+ filter = compare_ether_addr(mine, buf);
+ }
+ }
+
+ if (filter) {
+
+ /* ISSUE: Update "drop" statistics? */
+
+ tile_net_provide_linux_buffer(info, va, small);
+
+ } else {
+
+ /* Acquire the associated "skb". */
+ struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+ struct sk_buff *skb = *skb_ptr;
+
+ /* Paranoia. */
+ if (skb->data != buf)
+ panic("Corrupt linux buffer from LIPP! "
+ "VA=%p, skb=%p, skb->data=%p\n",
+ va, skb, skb->data);
+
+ /* Encode the actual packet length. */
+ skb_put(skb, len);
+
+ /* NOTE: This call also sets "skb->dev = dev". */
+ skb->protocol = eth_type_trans(skb, dev);
+
+ /* Avoid recomputing "good" TCP/UDP checksums. */
+ if (NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ netif_receive_skb(skb);
+
+ stats->rx_packets++;
+ stats->rx_bytes += len;
+
+ if (small)
+ info->num_needed_small_buffers++;
+ else
+ info->num_needed_large_buffers++;
+ }
+
+ /* Return four credits after every fourth packet. */
+ if (--qup->__receive_credit_remaining == 0) {
+ u32 interval = qup->__receive_credit_interval;
+ qup->__receive_credit_remaining = interval;
+ __netio_fastio_return_credits(qup->__fastio_index, interval);
+ }
+
+ /* Consume this packet. */
+ qup->__packet_receive_read = index2;
+
+ return !filter;
+ }
+
+
+ /*
+ * Handle some packets for the given device on the current CPU.
+ *
+ * If "tile_net_stop()" is called on some other tile while this
+ * function is running, we will return, hopefully before that
+ * other tile asks us to call "napi_disable()".
+ *
+ * The "rotting packet" race condition occurs if a packet arrives
+ * during the extremely narrow window between the queue appearing to
+ * be empty, and the ingress interrupt being re-enabled. This happens
+ * a LOT under heavy network load.
+ */
+ static int tile_net_poll(struct napi_struct *napi, int budget)
+ {
+ struct net_device *dev = napi->dev;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+ struct tile_netio_queue *queue = &info->queue;
+ netio_queue_impl_t *qsp = queue->__system_part;
+ netio_queue_user_impl_t *qup = &queue->__user_part;
+
+ unsigned int work = 0;
+
+ while (priv->active) {
+ int index = qup->__packet_receive_read;
+ if (index == qsp->__packet_receive_queue.__packet_write)
+ break;
+
+ if (tile_net_poll_aux(info, index)) {
+ if (++work >= budget)
+ goto done;
+ }
+ }
+
+ napi_complete(&info->napi);
+
+ if (!priv->active)
+ goto done;
+
+ /* Re-enable the ingress interrupt. */
+ enable_percpu_irq(priv->intr_id);
+
+ /* HACK: Avoid the "rotting packet" problem (see above). */
+ if (qup->__packet_receive_read !=
+ qsp->__packet_receive_queue.__packet_write) {
+ /* ISSUE: Sometimes this returns zero, presumably */
+ /* because an interrupt was handled for this tile. */
+ (void)napi_reschedule(&info->napi);
+ }
+
+ done:
+
+ if (priv->active)
+ tile_net_provide_needed_buffers(info);
+
+ return work;
+ }
+
+
+ /*
+ * Handle an ingress interrupt for the given device on the current cpu.
+ *
+ * ISSUE: Sometimes this gets called after "disable_percpu_irq()" has
+ * been called! This is probably due to "pending hypervisor downcalls".
+ *
+ * ISSUE: Is there any race condition between the "napi_schedule()" here
+ * and the "napi_complete()" call above?
+ */
+ static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr)
+ {
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+ /* Disable the ingress interrupt. */
+ disable_percpu_irq(priv->intr_id);
+
+ /* Ignore unwanted interrupts. */
+ if (!priv->active)
+ return IRQ_HANDLED;
+
+ /* ISSUE: Sometimes "info->napi_enabled" is false here. */
+
+ napi_schedule(&info->napi);
+
+ return IRQ_HANDLED;
+ }
+
+
+ /*
+ * One time initialization per interface.
+ */
+ static int tile_net_open_aux(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+
+ int ret;
+ int dummy;
+ unsigned int epp_lotar;
+
+ /*
+ * Find out where EPP memory should be homed.
+ */
+ ret = hv_dev_pread(priv->hv_devhdl, 0,
+ (HV_VirtAddr)&epp_lotar, sizeof(epp_lotar),
+ NETIO_EPP_SHM_OFF);
+ if (ret < 0) {
+ pr_err("could not read epp_shm_queue lotar.\n");
+ return -EIO;
+ }
+
+ /*
+ * Home the page on the EPP.
+ */
+ {
+ int epp_home = hv_lotar_to_cpu(epp_lotar);
+ homecache_change_page_home(priv->eq_pages, EQ_ORDER, epp_home);
+ }
+
+ /*
+ * Register the EPP shared memory queue.
+ */
+ {
+ netio_ipp_address_t ea = {
+ .va = 0,
+ .pa = __pa(priv->eq),
+ .pte = hv_pte(0),
+ .size = EQ_SIZE,
+ };
+ ea.pte = hv_pte_set_lotar(ea.pte, epp_lotar);
+ ea.pte = hv_pte_set_mode(ea.pte, HV_PTE_MODE_CACHE_TILE_L3);
+ ret = hv_dev_pwrite(priv->hv_devhdl, 0,
+ (HV_VirtAddr)&ea,
+ sizeof(ea),
+ NETIO_EPP_SHM_OFF);
+ if (ret < 0)
+ return -EIO;
+ }
+
+ /*
+ * Start LIPP/LEPP.
+ */
+ if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+ sizeof(dummy), NETIO_IPP_START_SHIM_OFF) < 0) {
+ pr_warning("Failed to start LIPP/LEPP.\n");
+ return -EIO;
+ }
+
+ return 0;
+ }
+
+
+ /*
+ * Register with hypervisor on the current CPU.
+ *
+ * Strangely, this function does important things even if it "fails",
+ * which is especially common if the link is not up yet. Hopefully
+ * these things are all "harmless" if done twice!
+ */
+ static void tile_net_register(void *dev_ptr)
+ {
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info;
+
+ struct tile_netio_queue *queue;
+
+ /* Only network cpus can receive packets. */
+ int queue_id =
+ cpumask_test_cpu(my_cpu, &priv->network_cpus_map) ? 0 : 255;
+
+ netio_input_config_t config = {
+ .flags = 0,
+ .num_receive_packets = priv->network_cpus_credits,
+ .queue_id = queue_id
+ };
+
+ int ret = 0;
+ netio_queue_impl_t *queuep;
+
+ PDEBUG("tile_net_register(queue_id %d)\n", queue_id);
+
+ if (!strcmp(dev->name, "xgbe0"))
+ info = &__get_cpu_var(hv_xgbe0);
+ else if (!strcmp(dev->name, "xgbe1"))
+ info = &__get_cpu_var(hv_xgbe1);
+ else if (!strcmp(dev->name, "gbe0"))
+ info = &__get_cpu_var(hv_gbe0);
+ else if (!strcmp(dev->name, "gbe1"))
+ info = &__get_cpu_var(hv_gbe1);
+ else
+ BUG();
+
+ /* Initialize the egress timer. */
+ init_timer(&info->egress_timer);
+ info->egress_timer.data = (long)info;
+ info->egress_timer.function = tile_net_handle_egress_timer;
+
+ priv->cpu[my_cpu] = info;
+
+ /*
+ * Register ourselves with LIPP. This does a lot of stuff,
+ * including invoking the LIPP registration code.
+ */
+ ret = hv_dev_pwrite(priv->hv_devhdl, 0,
+ (HV_VirtAddr)&config,
+ sizeof(netio_input_config_t),
+ NETIO_IPP_INPUT_REGISTER_OFF);
+ PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n",
+ ret);
+ if (ret < 0) {
+ if (ret != NETIO_LINK_DOWN) {
+ printk(KERN_DEBUG "hv_dev_pwrite "
+ "NETIO_IPP_INPUT_REGISTER_OFF failure %d\n",
+ ret);
+ }
+ info->link_down = (ret == NETIO_LINK_DOWN);
+ return;
+ }
+
+ /*
+ * Get the pointer to our queue's system part.
+ */
+
+ ret = hv_dev_pread(priv->hv_devhdl, 0,
+ (HV_VirtAddr)&queuep,
+ sizeof(netio_queue_impl_t *),
+ NETIO_IPP_INPUT_REGISTER_OFF);
+ PDEBUG("hv_dev_pread(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n",
+ ret);
+ PDEBUG("queuep %p\n", queuep);
+ if (ret <= 0) {
+ /* ISSUE: Shouldn't this be a fatal error? */
+ pr_err("hv_dev_pread NETIO_IPP_INPUT_REGISTER_OFF failure\n");
+ return;
+ }
+
+ queue = &info->queue;
+
+ queue->__system_part = queuep;
+
+ memset(&queue->__user_part, 0, sizeof(netio_queue_user_impl_t));
+
+ /* This is traditionally "config.num_receive_packets / 2". */
+ queue->__user_part.__receive_credit_interval = 4;
+ queue->__user_part.__receive_credit_remaining =
+ queue->__user_part.__receive_credit_interval;
+
+ /*
+ * Get a fastio index from the hypervisor.
+ * ISSUE: Shouldn't this check the result?
+ */
+ ret = hv_dev_pread(priv->hv_devhdl, 0,
+ (HV_VirtAddr)&queue->__user_part.__fastio_index,
+ sizeof(queue->__user_part.__fastio_index),
+ NETIO_IPP_GET_FASTIO_OFF);
+ PDEBUG("hv_dev_pread(NETIO_IPP_GET_FASTIO_OFF) returned %d\n", ret);
+
+ /* Now we are registered. */
+ info->registered = true;
+ }
+
+
+ /*
+ * Deregister with hypervisor on the current CPU.
+ *
+ * This simply discards all our credits, so no more packets will be
+ * delivered to this tile. There may still be packets in our queue.
+ *
+ * Also, disable the ingress interrupt.
+ */
+ static void tile_net_deregister(void *dev_ptr)
+ {
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+ /* Disable the ingress interrupt. */
+ disable_percpu_irq(priv->intr_id);
+
+ /* Do nothing else if not registered. */
+ if (info == NULL || !info->registered)
+ return;
+
+ {
+ struct tile_netio_queue *queue = &info->queue;
+ netio_queue_user_impl_t *qup = &queue->__user_part;
+
+ /* Discard all our credits. */
+ __netio_fastio_return_credits(qup->__fastio_index, -1);
+ }
+ }
+
+
+ /*
+ * Unregister with hypervisor on the current CPU.
+ *
+ * Also, disable the ingress interrupt.
+ */
+ static void tile_net_unregister(void *dev_ptr)
+ {
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+ int ret;
+ int dummy = 0;
+
+ /* Disable the ingress interrupt. */
+ disable_percpu_irq(priv->intr_id);
+
+ /* Do nothing else if not registered. */
+ if (info == NULL || !info->registered)
+ return;
+
+ /* Unregister ourselves with LIPP/LEPP. */
+ ret = hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+ sizeof(dummy), NETIO_IPP_INPUT_UNREGISTER_OFF);
+ if (ret < 0)
+ panic("Failed to unregister with LIPP/LEPP!\n");
+
+ /* Discard all packets still in our NetIO queue. */
+ tile_net_discard_packets(dev);
+
+ /* Reset state. */
+ info->num_needed_small_buffers = 0;
+ info->num_needed_large_buffers = 0;
+
+ /* Cancel egress timer. */
+ del_timer(&info->egress_timer);
+ info->egress_timer_scheduled = false;
+ }
+
+
+ /*
+ * Helper function for "tile_net_stop()".
+ *
+ * Also used to handle registration failure in "tile_net_open_inner()",
+ * when the various extra steps in "tile_net_stop()" are not necessary.
+ */
+ static void tile_net_stop_aux(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int i;
+
+ int dummy = 0;
+
+ /*
+ * Unregister all tiles, so LIPP will stop delivering packets.
+ * Also, delete all the "napi" objects (sequentially, to protect
+ * "dev->napi_list").
+ */
+ on_each_cpu(tile_net_unregister, (void *)dev, 1);
+ for_each_online_cpu(i) {
+ struct tile_net_cpu *info = priv->cpu[i];
+ if (info != NULL && info->registered) {
+ netif_napi_del(&info->napi);
+ info->registered = false;
+ }
+ }
+
+ /* Stop LIPP/LEPP. */
+ if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+ sizeof(dummy), NETIO_IPP_STOP_SHIM_OFF) < 0)
+ panic("Failed to stop LIPP/LEPP!\n");
+
+ priv->partly_opened = 0;
+ }
+
+
+ /*
+ * Disable NAPI for the given device on the current cpu.
+ */
+ static void tile_net_stop_disable(void *dev_ptr)
+ {
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+ /* Disable NAPI if needed. */
+ if (info != NULL && info->napi_enabled) {
+ napi_disable(&info->napi);
+ info->napi_enabled = false;
+ }
+ }
+
+
+ /*
+ * Enable NAPI and the ingress interrupt for the given device
+ * on the current cpu.
+ *
+ * ISSUE: Only do this for "network cpus"?
+ */
+ static void tile_net_open_enable(void *dev_ptr)
+ {
+ struct net_device *dev = (struct net_device *)dev_ptr;
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+ /* Enable NAPI. */
+ napi_enable(&info->napi);
+ info->napi_enabled = true;
+
+ /* Enable the ingress interrupt. */
+ enable_percpu_irq(priv->intr_id);
+ }
+
+
+ /*
+ * tile_net_open_inner does most of the work of bringing up the interface.
+ * It's called from tile_net_open(), and also from tile_net_retry_open().
+ * The return value is 0 if the interface was brought up, < 0 if
+ * tile_net_open() should return the return value as an error, and > 0 if
+ * tile_net_open() should return success and schedule a work item to
+ * periodically retry the bringup.
+ */
+ static int tile_net_open_inner(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info;
+ struct tile_netio_queue *queue;
+ int result = 0;
+ int i;
+ int dummy = 0;
+
+ /*
+ * First try to register just on the local CPU, and handle any
+ * semi-expected "link down" failure specially. Note that we
+ * do NOT call "tile_net_stop_aux()", unlike below.
+ */
+ tile_net_register(dev);
+ info = priv->cpu[my_cpu];
+ if (!info->registered) {
+ if (info->link_down)
+ return 1;
+ return -EAGAIN;
+ }
+
+ /*
+ * Now register everywhere else. If any registration fails,
+ * even for "link down" (which might not be possible), we
+ * clean up using "tile_net_stop_aux()". Also, add all the
+ * "napi" objects (sequentially, to protect "dev->napi_list").
+ * ISSUE: Only use "netif_napi_add()" for "network cpus"?
+ */
+ smp_call_function(tile_net_register, (void *)dev, 1);
+ for_each_online_cpu(i) {
+ struct tile_net_cpu *info = priv->cpu[i];
+ if (info->registered)
+ netif_napi_add(dev, &info->napi, tile_net_poll, 64);
+ else
+ result = -EAGAIN;
+ }
+ if (result != 0) {
+ tile_net_stop_aux(dev);
+ return result;
+ }
+
+ queue = &info->queue;
+
+ if (priv->intr_id == 0) {
+ unsigned int irq;
+
+ /*
+ * Acquire the irq allocated by the hypervisor. Every
+ * queue gets the same irq. The "__intr_id" field is
+ * "1 << irq", so we use "__ffs()" to extract "irq".
+ */
+ priv->intr_id = queue->__system_part->__intr_id;
+ BUG_ON(priv->intr_id == 0);
+ irq = __ffs(priv->intr_id);
+
+ /*
+ * Register the ingress interrupt handler for this
+ * device, permanently.
+ *
+ * We used to call "free_irq()" in "tile_net_stop()",
+ * and then re-register the handler here every time,
+ * but that caused DNP errors in "handle_IRQ_event()"
+ * because "desc->action" was NULL. See bug 9143.
+ */
+ tile_irq_activate(irq, TILE_IRQ_PERCPU);
+ BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt,
+ 0, dev->name, (void *)dev) != 0);
+ }
+
+ {
+ /* Allocate initial buffers. */
+
+ int max_buffers =
+ priv->network_cpus_count * priv->network_cpus_credits;
+
+ info->num_needed_small_buffers =
+ min(LIPP_SMALL_BUFFERS, max_buffers);
+
+ info->num_needed_large_buffers =
+ min(LIPP_LARGE_BUFFERS, max_buffers);
+
+ tile_net_provide_needed_buffers(info);
+
+ if (info->num_needed_small_buffers != 0 ||
+ info->num_needed_large_buffers != 0)
+ panic("Insufficient memory for buffer stack!");
+ }
+
+ /* We are about to be active. */
+ priv->active = true;
+
+ /* Make sure "active" is visible to all tiles. */
+ mb();
+
+ /* On each tile, enable NAPI and the ingress interrupt. */
+ on_each_cpu(tile_net_open_enable, (void *)dev, 1);
+
+ /* Start LIPP/LEPP and activate "ingress" at the shim. */
+ if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+ sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0)
+ panic("Failed to activate the LIPP Shim!\n");
+
+ /* Start our transmit queue. */
+ netif_start_queue(dev);
+
+ return 0;
+ }
+
+
+ /*
+ * Called periodically to retry bringing up the NetIO interface,
+ * if it doesn't come up cleanly during tile_net_open().
+ */
+ static void tile_net_open_retry(struct work_struct *w)
+ {
+ struct delayed_work *dw =
+ container_of(w, struct delayed_work, work);
+
+ struct tile_net_priv *priv =
+ container_of(dw, struct tile_net_priv, retry_work);
+
+ /*
+ * Try to bring the NetIO interface up. If it fails, reschedule
+ * ourselves to try again later; otherwise, tell Linux we now have
+ * a working link. ISSUE: What if the return value is negative?
+ */
+ if (tile_net_open_inner(priv->dev) != 0)
+ schedule_delayed_work(&priv->retry_work,
+ TILE_NET_RETRY_INTERVAL);
+ else
+ netif_carrier_on(priv->dev);
+ }
+
+
+ /*
+ * Called when a network interface is made active.
+ *
+ * Returns 0 on success, negative value on failure.
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS (if needed), the watchdog timer
+ * is started, and the stack is notified that the interface is ready.
+ *
+ * If the actual link is not available yet, then we tell Linux that
+ * we have no carrier, and we keep checking until the link comes up.
+ */
+ static int tile_net_open(struct net_device *dev)
+ {
+ int ret = 0;
+ struct tile_net_priv *priv = netdev_priv(dev);
+
+ /*
+ * We rely on priv->partly_opened to tell us if this is the
+ * first time this interface is being brought up. If it is
+ * set, the IPP was already initialized and should not be
+ * initialized again.
+ */
+ if (!priv->partly_opened) {
+
+ int count;
+ int credits;
+
+ /* Initialize LIPP/LEPP, and start the Shim. */
+ ret = tile_net_open_aux(dev);
+ if (ret < 0) {
+ pr_err("tile_net_open_aux failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Analyze the network cpus. */
+
+ if (network_cpus_used)
+ cpumask_copy(&priv->network_cpus_map,
+ &network_cpus_map);
+ else
+ cpumask_copy(&priv->network_cpus_map, cpu_online_mask);
+
+
+ count = cpumask_weight(&priv->network_cpus_map);
+
+ /* Limit credits to available buffers, and apply min. */
+ credits = max(16, (LIPP_LARGE_BUFFERS / count) & ~1);
+
+ /* Apply "GBE" max limit. */
+ /* ISSUE: Use higher limit for XGBE? */
+ credits = min(NETIO_MAX_RECEIVE_PKTS, credits);
+
+ priv->network_cpus_count = count;
+ priv->network_cpus_credits = credits;
+
+ #ifdef TILE_NET_DEBUG
+ pr_info("Using %d network cpus, with %d credits each\n",
+ priv->network_cpus_count, priv->network_cpus_credits);
+ #endif
+
+ priv->partly_opened = 1;
+
+ } else {
+ /* FIXME: Is this possible? */
+ /* printk("Already partly opened.\n"); */
+ }
+
+ /*
+ * Attempt to bring up the link.
+ */
+ ret = tile_net_open_inner(dev);
+ if (ret <= 0) {
+ if (ret == 0)
+ netif_carrier_on(dev);
+ return ret;
+ }
+
+ /*
+ * We were unable to bring up the NetIO interface, but we want to
+ * try again in a little bit. Tell Linux that we have no carrier
+ * so it doesn't try to use the interface before the link comes up
+ * and then remember to try again later.
+ */
+ netif_carrier_off(dev);
+ schedule_delayed_work(&priv->retry_work, TILE_NET_RETRY_INTERVAL);
+
+ return 0;
+ }
+
+
+ static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv)
+ {
+ int n = 0;
+
+ /* Drain all the LIPP buffers. */
+ while (true) {
+ int buffer;
+
+ /* NOTE: This should never fail. */
+ if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer,
+ sizeof(buffer), NETIO_IPP_DRAIN_OFF) < 0)
+ break;
+
+ /* Stop when done. */
+ if (buffer == 0)
+ break;
+
+ {
+ /* Convert "linux_buffer_t" to "va". */
+ void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+ /* Acquire the associated "skb". */
+ struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+ struct sk_buff *skb = *skb_ptr;
+
+ kfree_skb(skb);
+ }
+
+ n++;
+ }
+
+ return n;
+ }
+
+
+ /*
+ * Disables a network interface.
+ *
+ * Returns 0, this is not allowed to fail.
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ *
+ * ISSUE: How closely does "netif_running(dev)" mirror "priv->active"?
+ *
+ * Before we are called by "__dev_close()", "netif_running()" will
+ * have been cleared, so no NEW calls to "tile_net_poll()" will be
+ * made by "netpoll_poll_dev()".
+ *
+ * Often, this can cause some tiles to still have packets in their
+ * queues, so we must call "tile_net_discard_packets()" later.
+ *
+ * Note that some other tile may still be INSIDE "tile_net_poll()",
+ * and in fact, many will be, if there is heavy network load.
+ *
+ * Calling "on_each_cpu(tile_net_stop_disable, (void *)dev, 1)" when
+ * any tile is still "napi_schedule()"'d will induce a horrible crash
+ * when "msleep()" is called. This includes tiles which are inside
+ * "tile_net_poll()" which have not yet called "napi_complete()".
+ *
+ * So, we must first try to wait long enough for other tiles to finish
+ * with any current "tile_net_poll()" call, and, hopefully, to clear
+ * the "scheduled" flag. ISSUE: It is unclear what happens to tiles
+ * which have called "napi_schedule()" but which had not yet tried to
+ * call "tile_net_poll()", or which exhausted their budget inside
+ * "tile_net_poll()" just before this function was called.
+ */
+ static int tile_net_stop(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+
+ PDEBUG("tile_net_stop()\n");
+
+ /* Start discarding packets. */
+ priv->active = false;
+
+ /* Make sure "active" is visible to all tiles. */
+ mb();
+
+ /*
+ * On each tile, make sure no NEW packets get delivered, and
+ * disable the ingress interrupt.
+ *
+ * Note that the ingress interrupt can fire AFTER this,
+ * presumably due to packets which were recently delivered,
+ * but it will have no effect.
+ */
+ on_each_cpu(tile_net_deregister, (void *)dev, 1);
+
+ /* Optimistically drain LIPP buffers. */
+ (void)tile_net_drain_lipp_buffers(priv);
+
+ /* ISSUE: Only needed if not yet fully open. */
+ cancel_delayed_work_sync(&priv->retry_work);
+
+ /* Can't transmit any more. */
+ netif_stop_queue(dev);
+
+ /* Disable NAPI on each tile. */
+ on_each_cpu(tile_net_stop_disable, (void *)dev, 1);
+
+ /*
+ * Drain any remaining LIPP buffers. NOTE: This "printk()"
+ * has never been observed, but in theory it could happen.
+ */
+ if (tile_net_drain_lipp_buffers(priv) != 0)
+ printk("Had to drain some extra LIPP buffers!\n");
+
+ /* Stop LIPP/LEPP. */
+ tile_net_stop_aux(dev);
+
+ /*
+ * ISSUE: It appears that, in practice anyway, by the time we
+ * get here, there are no pending completions, but just in case,
+ * we free (all of) them anyway.
+ */
+ while (tile_net_lepp_free_comps(dev, true))
+ /* loop */;
+
+ /* Wipe the EPP queue, and wait till the stores hit the EPP. */
+ memset(priv->eq, 0, sizeof(lepp_queue_t));
+ mb();
+
+ return 0;
+ }
+
+
+ /*
+ * Prepare the "frags" info for the resulting LEPP command.
+ *
+ * If needed, flush the memory used by the frags.
+ */
+ static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
+ struct sk_buff *skb,
+ void *b_data, unsigned int b_len)
+ {
+ unsigned int i, n = 0;
+
+ struct skb_shared_info *sh = skb_shinfo(skb);
+
+ phys_addr_t cpa;
+
+ if (b_len != 0) {
+
+ if (!hash_default)
+ finv_buffer_remote(b_data, b_len, 0);
+
+ cpa = __pa(b_data);
+ frags[n].cpa_lo = cpa;
+ frags[n].cpa_hi = cpa >> 32;
+ frags[n].length = b_len;
+ frags[n].hash_for_home = hash_default;
+ n++;
+ }
+
+ for (i = 0; i < sh->nr_frags; i++) {
+
+ skb_frag_t *f = &sh->frags[i];
+ unsigned long pfn = page_to_pfn(f->page);
+
+ /* FIXME: Compute "hash_for_home" properly. */
+ /* ISSUE: The hypervisor checks CHIP_HAS_REV1_DMA_PACKETS(). */
+ int hash_for_home = hash_default;
+
+ /* FIXME: Hmmm. */
+ if (!hash_default) {
+ void *va = pfn_to_kaddr(pfn) + f->page_offset;
+ BUG_ON(PageHighMem(f->page));
+ finv_buffer_remote(va, f->size, 0);
+ }
+
+ cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
+ frags[n].cpa_lo = cpa;
+ frags[n].cpa_hi = cpa >> 32;
+ frags[n].length = skb_frag_size(f);
+ frags[n].hash_for_home = hash_for_home;
+ n++;
+ }
+
+ return n;
+ }
+
+
+ /*
+ * This function takes "skb", consisting of a header template and a
+ * payload, and hands it to LEPP, to emit as one or more segments,
+ * each consisting of a possibly modified header, plus a piece of the
+ * payload, via a process known as "tcp segmentation offload".
+ *
+ * Usually, "data" will contain the header template, of size "sh_len",
+ * and "sh->frags" will contain "skb->data_len" bytes of payload, and
+ * there will be "sh->gso_segs" segments.
+ *
+ * Sometimes, if "sendfile()" requires copying, we will be called with
+ * "data" containing the header and payload, with "frags" being empty.
+ *
+ * In theory, "sh->nr_frags" could be 3, but in practice, it seems
+ * that this will never actually happen.
+ *
+ * See "emulate_large_send_offload()" for some reference code, which
+ * does not handle checksumming.
+ *
+ * ISSUE: How do we make sure that high memory DMA does not migrate?
+ */
+ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+ struct tile_net_stats_t *stats = &info->stats;
+
+ struct skb_shared_info *sh = skb_shinfo(skb);
+
+ unsigned char *data = skb->data;
+
+ /* The ip header follows the ethernet header. */
+ struct iphdr *ih = ip_hdr(skb);
+ unsigned int ih_len = ih->ihl * 4;
+
+ /* Note that "nh == ih", by definition. */
+ unsigned char *nh = skb_network_header(skb);
+ unsigned int eh_len = nh - data;
+
+ /* The tcp header follows the ip header. */
+ struct tcphdr *th = (struct tcphdr *)(nh + ih_len);
+ unsigned int th_len = th->doff * 4;
+
+ /* The total number of header bytes. */
+ /* NOTE: This may be less than skb_headlen(skb). */
+ unsigned int sh_len = eh_len + ih_len + th_len;
+
+ /* The number of payload bytes at "skb->data + sh_len". */
+ /* This is non-zero for sendfile() without HIGHDMA. */
+ unsigned int b_len = skb_headlen(skb) - sh_len;
+
+ /* The total number of payload bytes. */
+ unsigned int d_len = b_len + skb->data_len;
+
+ /* The maximum payload size. */
+ unsigned int p_len = sh->gso_size;
+
+ /* The total number of segments. */
+ unsigned int num_segs = sh->gso_segs;
+
+ /* The temporary copy of the command. */
+ u32 cmd_body[(LEPP_MAX_CMD_SIZE + 3) / 4];
+ lepp_tso_cmd_t *cmd = (lepp_tso_cmd_t *)cmd_body;
+
+ /* Analyze the "frags". */
+ unsigned int num_frags =
+ tile_net_tx_frags(cmd->frags, skb, data + sh_len, b_len);
+
+ /* The size of the command, including frags and header. */
+ size_t cmd_size = LEPP_TSO_CMD_SIZE(num_frags, sh_len);
+
+ /* The command header. */
+ lepp_tso_cmd_t cmd_init = {
+ .tso = true,
+ .header_size = sh_len,
+ .ip_offset = eh_len,
+ .tcp_offset = eh_len + ih_len,
+ .payload_size = p_len,
+ .num_frags = num_frags,
+ };
+
+ unsigned long irqflags;
+
+ lepp_queue_t *eq = priv->eq;
+
+ struct sk_buff *olds[8];
+ unsigned int wanted = 8;
+ unsigned int i, nolds = 0;
+
+ unsigned int cmd_head, cmd_tail, cmd_next;
+ unsigned int comp_tail;
+
+
+ /* Paranoia. */
+ BUG_ON(skb->protocol != htons(ETH_P_IP));
+ BUG_ON(ih->protocol != IPPROTO_TCP);
+ BUG_ON(skb->ip_summed != CHECKSUM_PARTIAL);
+ BUG_ON(num_frags > LEPP_MAX_FRAGS);
+ /*--BUG_ON(num_segs != (d_len + (p_len - 1)) / p_len); */
+ BUG_ON(num_segs <= 1);
+
+
+ /* Finish preparing the command. */
+
+ /* Copy the command header. */
+ *cmd = cmd_init;
+
+ /* Copy the "header". */
+ memcpy(&cmd->frags[num_frags], data, sh_len);
+
+
+ /* Prefetch and wait, to minimize time spent holding the spinlock. */
+ prefetch_L1(&eq->comp_tail);
+ prefetch_L1(&eq->cmd_tail);
+ mb();
+
+
+ /* Enqueue the command. */
+
+ spin_lock_irqsave(&priv->eq_lock, irqflags);
+
+ /*
+ * Handle completions if needed to make room.
+ * HACK: Spin until there is sufficient room.
+ */
+ if (lepp_num_free_comp_slots(eq) == 0) {
+ nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+ if (nolds == 0) {
+ busy:
+ spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+ cmd_head = eq->cmd_head;
+ cmd_tail = eq->cmd_tail;
+
+ /* Prepare to advance, detecting full queue. */
+ cmd_next = cmd_tail + cmd_size;
+ if (cmd_tail < cmd_head && cmd_next >= cmd_head)
+ goto busy;
+ if (cmd_next > LEPP_CMD_LIMIT) {
+ cmd_next = 0;
+ if (cmd_next == cmd_head)
+ goto busy;
+ }
+
+ /* Copy the command. */
+ memcpy(&eq->cmds[cmd_tail], cmd, cmd_size);
+
+ /* Advance. */
+ cmd_tail = cmd_next;
+
+ /* Record "skb" for eventual freeing. */
+ comp_tail = eq->comp_tail;
+ eq->comps[comp_tail] = skb;
+ LEPP_QINC(comp_tail);
+ eq->comp_tail = comp_tail;
+
+ /* Flush before allowing LEPP to handle the command. */
+ /* ISSUE: Is this the optimal location for the flush? */
+ __insn_mf();
+
+ eq->cmd_tail = cmd_tail;
+
+ /* NOTE: Using "4" here is more efficient than "0" or "2", */
+ /* and, strangely, more efficient than pre-checking the number */
+ /* of available completions, and comparing it to 4. */
+ if (nolds == 0)
+ nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4);
+
+ spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+
+ /* Handle completions. */
+ for (i = 0; i < nolds; i++)
+ kfree_skb(olds[i]);
+
+ /* Update stats. */
+ stats->tx_packets += num_segs;
+ stats->tx_bytes += (num_segs * sh_len) + d_len;
+
+ /* Make sure the egress timer is scheduled. */
+ tile_net_schedule_egress_timer(info);
+
+ return NETDEV_TX_OK;
+ }
+
+
+ /*
+ * Transmit a packet (called by the kernel via "hard_start_xmit" hook).
+ */
+ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+ int my_cpu = smp_processor_id();
+ struct tile_net_cpu *info = priv->cpu[my_cpu];
+ struct tile_net_stats_t *stats = &info->stats;
+
+ unsigned long irqflags;
+
+ struct skb_shared_info *sh = skb_shinfo(skb);
+
+ unsigned int len = skb->len;
+ unsigned char *data = skb->data;
+
+ unsigned int csum_start = skb_checksum_start_offset(skb);
+
+ lepp_frag_t frags[LEPP_MAX_FRAGS];
+
+ unsigned int num_frags;
+
+ lepp_queue_t *eq = priv->eq;
+
+ struct sk_buff *olds[8];
+ unsigned int wanted = 8;
+ unsigned int i, nolds = 0;
+
+ unsigned int cmd_size = sizeof(lepp_cmd_t);
+
+ unsigned int cmd_head, cmd_tail, cmd_next;
+ unsigned int comp_tail;
+
+ lepp_cmd_t cmds[LEPP_MAX_FRAGS];
+
+
+ /*
+ * This is paranoia, since we think that if the link doesn't come
+ * up, telling Linux we have no carrier will keep it from trying
+ * to transmit. If it does, though, we can't execute this routine,
+ * since data structures we depend on aren't set up yet.
+ */
+ if (!info->registered)
+ return NETDEV_TX_BUSY;
+
+
+ /* Save the timestamp. */
+ dev->trans_start = jiffies;
+
+
+ #ifdef TILE_NET_PARANOIA
+ #if CHIP_HAS_CBOX_HOME_MAP()
+ if (hash_default) {
+ HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)data);
+ if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
+ panic("Non-HFH egress buffer! VA=%p Mode=%d PTE=%llx",
+ data, hv_pte_get_mode(pte), hv_pte_val(pte));
+ }
+ #endif
+ #endif
+
+
+ #ifdef TILE_NET_DUMP_PACKETS
+ /* ISSUE: Does not dump the "frags". */
+ dump_packet(data, skb_headlen(skb), "tx");
+ #endif /* TILE_NET_DUMP_PACKETS */
+
+
+ if (sh->gso_size != 0)
+ return tile_net_tx_tso(skb, dev);
+
+
+ /* Prepare the commands. */
+
+ num_frags = tile_net_tx_frags(frags, skb, data, skb_headlen(skb));
+
+ for (i = 0; i < num_frags; i++) {
+
+ bool final = (i == num_frags - 1);
+
+ lepp_cmd_t cmd = {
+ .cpa_lo = frags[i].cpa_lo,
+ .cpa_hi = frags[i].cpa_hi,
+ .length = frags[i].length,
+ .hash_for_home = frags[i].hash_for_home,
+ .send_completion = final,
+ .end_of_packet = final
+ };
+
+ if (i == 0 && skb->ip_summed == CHECKSUM_PARTIAL) {
+ cmd.compute_checksum = 1;
+ cmd.checksum_data.bits.start_byte = csum_start;
+ cmd.checksum_data.bits.count = len - csum_start;
+ cmd.checksum_data.bits.destination_byte =
+ csum_start + skb->csum_offset;
+ }
+
+ cmds[i] = cmd;
+ }
+
+
+ /* Prefetch and wait, to minimize time spent holding the spinlock. */
+ prefetch_L1(&eq->comp_tail);
+ prefetch_L1(&eq->cmd_tail);
+ mb();
+
+
+ /* Enqueue the commands. */
+
+ spin_lock_irqsave(&priv->eq_lock, irqflags);
+
+ /*
+ * Handle completions if needed to make room.
+ * HACK: Spin until there is sufficient room.
+ */
+ if (lepp_num_free_comp_slots(eq) == 0) {
+ nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+ if (nolds == 0) {
+ busy:
+ spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+ cmd_head = eq->cmd_head;
+ cmd_tail = eq->cmd_tail;
+
+ /* Copy the commands, or fail. */
+ for (i = 0; i < num_frags; i++) {
+
+ /* Prepare to advance, detecting full queue. */
+ cmd_next = cmd_tail + cmd_size;
+ if (cmd_tail < cmd_head && cmd_next >= cmd_head)
+ goto busy;
+ if (cmd_next > LEPP_CMD_LIMIT) {
+ cmd_next = 0;
+ if (cmd_next == cmd_head)
+ goto busy;
+ }
+
+ /* Copy the command. */
+ *(lepp_cmd_t *)&eq->cmds[cmd_tail] = cmds[i];
+
+ /* Advance. */
+ cmd_tail = cmd_next;
+ }
+
+ /* Record "skb" for eventual freeing. */
+ comp_tail = eq->comp_tail;
+ eq->comps[comp_tail] = skb;
+ LEPP_QINC(comp_tail);
+ eq->comp_tail = comp_tail;
+
+ /* Flush before allowing LEPP to handle the command. */
+ /* ISSUE: Is this the optimal location for the flush? */
+ __insn_mf();
+
+ eq->cmd_tail = cmd_tail;
+
+ /* NOTE: Using "4" here is more efficient than "0" or "2", */
+ /* and, strangely, more efficient than pre-checking the number */
+ /* of available completions, and comparing it to 4. */
+ if (nolds == 0)
+ nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4);
+
+ spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+
+ /* Handle completions. */
+ for (i = 0; i < nolds; i++)
+ kfree_skb(olds[i]);
+
+ /* HACK: Track "expanded" size for short packets (e.g. 42 < 60). */
+ stats->tx_packets++;
+ stats->tx_bytes += ((len >= ETH_ZLEN) ? len : ETH_ZLEN);
+
+ /* Make sure the egress timer is scheduled. */
+ tile_net_schedule_egress_timer(info);
+
+ return NETDEV_TX_OK;
+ }
+
+
+ /*
+ * Deal with a transmit timeout.
+ */
+ static void tile_net_tx_timeout(struct net_device *dev)
+ {
+ PDEBUG("tile_net_tx_timeout()\n");
+ PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies,
+ jiffies - dev->trans_start);
+
+ /* XXX: ISSUE: This doesn't seem useful for us. */
+ netif_wake_queue(dev);
+ }
+
+
+ /*
+ * Ioctl commands.
+ */
+ static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+ return -EOPNOTSUPP;
+ }
+
+
+ /*
+ * Get System Network Statistics.
+ *
+ * Returns the address of the device statistics structure.
+ */
+ static struct net_device_stats *tile_net_get_stats(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+ u32 rx_packets = 0;
+ u32 tx_packets = 0;
+ u32 rx_bytes = 0;
+ u32 tx_bytes = 0;
+ int i;
+
+ for_each_online_cpu(i) {
+ if (priv->cpu[i]) {
+ rx_packets += priv->cpu[i]->stats.rx_packets;
+ rx_bytes += priv->cpu[i]->stats.rx_bytes;
+ tx_packets += priv->cpu[i]->stats.tx_packets;
+ tx_bytes += priv->cpu[i]->stats.tx_bytes;
+ }
+ }
+
+ priv->stats.rx_packets = rx_packets;
+ priv->stats.rx_bytes = rx_bytes;
+ priv->stats.tx_packets = tx_packets;
+ priv->stats.tx_bytes = tx_bytes;
+
+ return &priv->stats;
+ }
+
+
+ /*
+ * Change the "mtu".
+ *
+ * The "change_mtu" method is usually not needed.
+ * If you need it, it must be like this.
+ */
+ static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
+ {
+ PDEBUG("tile_net_change_mtu()\n");
+
+ /* Check ranges. */
+ if ((new_mtu < 68) || (new_mtu > 1500))
+ return -EINVAL;
+
+ /* Accept the value. */
+ dev->mtu = new_mtu;
+
+ return 0;
+ }
+
+
+ /*
+ * Change the Ethernet Address of the NIC.
+ *
+ * The hypervisor driver does not support changing MAC address. However,
+ * the IPP does not do anything with the MAC address, so the address which
+ * gets used on outgoing packets, and which is accepted on incoming packets,
+ * is completely up to the NetIO program or kernel driver which is actually
+ * handling them.
+ *
+ * Returns 0 on success, negative on failure.
+ */
+ static int tile_net_set_mac_address(struct net_device *dev, void *p)
+ {
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
+ /* ISSUE: Note that "dev_addr" is now a pointer. */
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ return 0;
+ }
+
+
+ /*
+ * Obtain the MAC address from the hypervisor.
+ * This must be done before opening the device.
+ */
+ static int tile_net_get_mac(struct net_device *dev)
+ {
+ struct tile_net_priv *priv = netdev_priv(dev);
+
+ char hv_dev_name[32];
+ int len;
+
+ __netio_getset_offset_t offset = { .word = NETIO_IPP_PARAM_OFF };
+
+ int ret;
+
+ /* For example, "xgbe0". */
+ strcpy(hv_dev_name, dev->name);
+ len = strlen(hv_dev_name);
+
+ /* For example, "xgbe/0". */
+ hv_dev_name[len] = hv_dev_name[len - 1];
+ hv_dev_name[len - 1] = '/';
+ len++;
+
+ /* For example, "xgbe/0/native_hash". */
+ strcpy(hv_dev_name + len, hash_default ? "/native_hash" : "/native");
+
+ /* Get the hypervisor handle for this device. */
+ priv->hv_devhdl = hv_dev_open((HV_VirtAddr)hv_dev_name, 0);
+ PDEBUG("hv_dev_open(%s) returned %d %p\n",
+ hv_dev_name, priv->hv_devhdl, &priv->hv_devhdl);
+ if (priv->hv_devhdl < 0) {
+ if (priv->hv_devhdl == HV_ENODEV)
+ printk(KERN_DEBUG "Ignoring unconfigured device %s\n",
+ hv_dev_name);
+ else
+ printk(KERN_DEBUG "hv_dev_open(%s) returned %d\n",
+ hv_dev_name, priv->hv_devhdl);
+ return -1;
+ }
+
+ /*
+ * Read the hardware address from the hypervisor.
+ * ISSUE: Note that "dev_addr" is now a pointer.
+ */
+ offset.bits.class = NETIO_PARAM;
+ offset.bits.addr = NETIO_PARAM_MAC;
+ ret = hv_dev_pread(priv->hv_devhdl, 0,
+ (HV_VirtAddr)dev->dev_addr, dev->addr_len,
+ offset.word);
+ PDEBUG("hv_dev_pread(NETIO_PARAM_MAC) returned %d\n", ret);
+ if (ret <= 0) {
+ printk(KERN_DEBUG "hv_dev_pread(NETIO_PARAM_MAC) %s failed\n",
+ dev->name);
+ /*
+ * Since the device is configured by the hypervisor but we
+ * can't get its MAC address, we are most likely running
+ * the simulator, so let's generate a random MAC address.
+ */
+ random_ether_addr(dev->dev_addr);
+ }
+
+ return 0;
+ }
+
+
+ static struct net_device_ops tile_net_ops = {
+ .ndo_open = tile_net_open,
+ .ndo_stop = tile_net_stop,
+ .ndo_start_xmit = tile_net_tx,
+ .ndo_do_ioctl = tile_net_ioctl,
+ .ndo_get_stats = tile_net_get_stats,
+ .ndo_change_mtu = tile_net_change_mtu,
+ .ndo_tx_timeout = tile_net_tx_timeout,
+ .ndo_set_mac_address = tile_net_set_mac_address
+ };
+
+
+ /*
+ * The setup function.
+ *
+ * This uses ether_setup() to assign various fields in dev, including
+ * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields.
+ */
+ static void tile_net_setup(struct net_device *dev)
+ {
+ PDEBUG("tile_net_setup()\n");
+
+ ether_setup(dev);
+
+ dev->netdev_ops = &tile_net_ops;
+
+ dev->watchdog_timeo = TILE_NET_TIMEOUT;
+
+ /* We want lockless xmit. */
+ dev->features |= NETIF_F_LLTX;
+
+ /* We support hardware tx checksums. */
+ dev->features |= NETIF_F_HW_CSUM;
+
+ /* We support scatter/gather. */
+ dev->features |= NETIF_F_SG;
+
+ /* We support TSO. */
+ dev->features |= NETIF_F_TSO;
+
+ #ifdef TILE_NET_GSO
+ /* We support GSO. */
+ dev->features |= NETIF_F_GSO;
+ #endif
+
+ if (hash_default)
+ dev->features |= NETIF_F_HIGHDMA;
+
+ /* ISSUE: We should support NETIF_F_UFO. */
+
+ dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN;
+
+ dev->mtu = TILE_NET_MTU;
+ }
+
+
+ /*
+ * Allocate the device structure, register the device, and obtain the
+ * MAC address from the hypervisor.
+ */
+ static struct net_device *tile_net_dev_init(const char *name)
+ {
+ int ret;
+ struct net_device *dev;
+ struct tile_net_priv *priv;
+
+ /*
+ * Allocate the device structure. This allocates "priv", calls
+ * tile_net_setup(), and saves "name". Normally, "name" is a
+ * template, instantiated by register_netdev(), but not for us.
+ */
+ dev = alloc_netdev(sizeof(*priv), name, tile_net_setup);
+ if (!dev) {
+ pr_err("alloc_netdev(%s) failed\n", name);
+ return NULL;
+ }
+
+ priv = netdev_priv(dev);
+
+ /* Initialize "priv". */
+
+ memset(priv, 0, sizeof(*priv));
+
+ /* Save "dev" for "tile_net_open_retry()". */
+ priv->dev = dev;
+
+ INIT_DELAYED_WORK(&priv->retry_work, tile_net_open_retry);
+
+ spin_lock_init(&priv->eq_lock);
+
+ /* Allocate "eq". */
+ priv->eq_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, EQ_ORDER);
+ if (!priv->eq_pages) {
+ free_netdev(dev);
+ return NULL;
+ }
+ priv->eq = page_address(priv->eq_pages);
+
+ /* Register the network device. */
+ ret = register_netdev(dev);
+ if (ret) {
+ pr_err("register_netdev %s failed %d\n", dev->name, ret);
+ __free_pages(priv->eq_pages, EQ_ORDER);
+ free_netdev(dev);
+ return NULL;
+ }
+
+ /* Get the MAC address. */
+ ret = tile_net_get_mac(dev);
+ if (ret < 0) {
+ unregister_netdev(dev);
+ __free_pages(priv->eq_pages, EQ_ORDER);
+ free_netdev(dev);
+ return NULL;
+ }
+
+ return dev;
+ }
+
+
+ /*
+ * Module cleanup.
+ *
+ * FIXME: If compiled as a module, this module cannot be "unloaded",
+ * because the "ingress interrupt handler" is registered permanently.
+ */
+ static void tile_net_cleanup(void)
+ {
+ int i;
+
+ for (i = 0; i < TILE_NET_DEVS; i++) {
+ if (tile_net_devs[i]) {
+ struct net_device *dev = tile_net_devs[i];
+ struct tile_net_priv *priv = netdev_priv(dev);
+ unregister_netdev(dev);
+ finv_buffer_remote(priv->eq, EQ_SIZE, 0);
+ __free_pages(priv->eq_pages, EQ_ORDER);
+ free_netdev(dev);
+ }
+ }
+ }
+
+
+ /*
+ * Module initialization.
+ */
+ static int tile_net_init_module(void)
+ {
+ pr_info("Tilera IPP Net Driver\n");
+
+ tile_net_devs[0] = tile_net_dev_init("xgbe0");
+ tile_net_devs[1] = tile_net_dev_init("xgbe1");
+ tile_net_devs[2] = tile_net_dev_init("gbe0");
+ tile_net_devs[3] = tile_net_dev_init("gbe1");
+
+ return 0;
+ }
+
+
+ module_init(tile_net_init_module);
+ module_exit(tile_net_cleanup);
+
+
+ #ifndef MODULE
+
+ /*
+ * The "network_cpus" boot argument specifies the cpus that are dedicated
+ * to handle ingress packets.
+ *
+ * The parameter should be in the form "network_cpus=m-n[,x-y]", where
+ * m, n, x, y are integer numbers that represent the cpus that can be
+ * neither a dedicated cpu nor a dataplane cpu.
+ */
+ static int __init network_cpus_setup(char *str)
+ {
+ int rc = cpulist_parse_crop(str, &network_cpus_map);
+ if (rc != 0) {
+ pr_warning("network_cpus=%s: malformed cpu list\n",
+ str);
+ } else {
+
+ /* Remove dedicated cpus. */
+ cpumask_and(&network_cpus_map, &network_cpus_map,
+ cpu_possible_mask);
+
+
+ if (cpumask_empty(&network_cpus_map)) {
+ pr_warning("Ignoring network_cpus='%s'.\n",
+ str);
+ } else {
+ char buf[1024];
+ cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map);
+ pr_info("Linux network CPUs: %s\n", buf);
+ network_cpus_used = true;
+ }
+ }
+
+ return 0;
+ }
+ __setup("network_cpus=", network_cpus_setup);
+
+ #endif
const void *ns,
const unsigned char *name)
{
- struct sysfs_dirent *sd;
+ struct rb_node *p = parent_sd->s_dir.name_tree.rb_node;
+ struct sysfs_dirent *found = NULL;
- for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) {
- if (sd->s_ns != ns)
- continue;
- if (!strcmp(sd->s_name, name))
- return sd;
+ if (!!sysfs_ns_type(parent_sd) != !!ns) {
+ WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
+ sysfs_ns_type(parent_sd)? "required": "invalid",
+ parent_sd->s_name, name);
+ return NULL;
+ }
+
+ while (p) {
+ int c;
+#define node rb_entry(p, struct sysfs_dirent, name_node)
+ c = strcmp(name, node->s_name);
+ if (c < 0) {
+ p = node->name_node.rb_left;
+ } else if (c > 0) {
+ p = node->name_node.rb_right;
+ } else {
+ found = node;
+ p = node->name_node.rb_left;
+ }
+#undef node
}
- return NULL;
+
+ if (found && ns) {
+ while (found->s_ns && found->s_ns != ns) {
+ p = rb_next(&found->name_node);
+ if (!p)
+ return NULL;
+ found = rb_entry(p, struct sysfs_dirent, name_node);
+ if (strcmp(name, found->s_name))
+ return NULL;
+ }
+ }
+
+ return found;
}
/**