Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 257021 Details for
Bug 249382
[PATCH] Attansic L2 Fast Ethernet adapter does not work (10/100M)
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Driver
linux-2.6.18-atl2-1.0.40.2.patch (text/plain), 231.54 KB, created by
Andy Shevchenko
on 2007-11-13 16:33:06 UTC
(
hide
)
Description:
Driver
Filename:
MIME Type:
Creator:
Andy Shevchenko
Created:
2007-11-13 16:33:06 UTC
Size:
231.54 KB
patch
obsolete
>diff -ruN -a -p old/drivers/net/atl2/at_ethtool.c new/drivers/net/atl2/at_ethtool.c >--- old/drivers/net/atl2/at_ethtool.c 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at_ethtool.c 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,431 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+/* ethtool support for at */ >+ >+#include <linux/netdevice.h> >+ >+#ifdef SIOCETHTOOL >+#include <linux/ethtool.h> >+ >+#include "at.h" >+ >+#ifdef ETHTOOL_OPS_COMPAT >+#include "kcompat_ethtool.c" >+#endif >+ >+extern char at_driver_name[]; >+extern char at_driver_version[]; >+ >+extern int at_up(struct at_adapter *adapter); >+extern void at_down(struct at_adapter *adapter); >+extern void at_reinit_locked(struct at_adapter *adapter); >+extern int32_t at_reset_hw(struct at_hw *hw); >+ >+static int >+at_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw *hw = &adapter->hw; >+ >+ ecmd->supported = (SUPPORTED_10baseT_Half | >+ SUPPORTED_10baseT_Full | >+ SUPPORTED_100baseT_Half | >+ SUPPORTED_100baseT_Full | >+ SUPPORTED_Autoneg | >+ SUPPORTED_TP); >+ ecmd->advertising = ADVERTISED_TP; >+ >+ ecmd->advertising |= ADVERTISED_Autoneg; >+ ecmd->advertising |= hw->autoneg_advertised; >+ >+ ecmd->port = PORT_TP; >+ ecmd->phy_address = 0; >+ ecmd->transceiver = XCVR_INTERNAL; >+ >+ if (adapter->link_speed != SPEED_0) { >+ ecmd->speed = adapter->link_speed; >+ if (adapter->link_duplex == FULL_DUPLEX) >+ ecmd->duplex = DUPLEX_FULL; >+ else >+ ecmd->duplex = DUPLEX_HALF; >+ } else { >+ ecmd->speed = -1; >+ ecmd->duplex = -1; >+ } >+ >+ ecmd->autoneg = AUTONEG_ENABLE; >+ return 0; >+} >+ >+static int >+at_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw *hw = &adapter->hw; >+ >+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) >+ msleep(1); >+ >+ if (ecmd->autoneg == AUTONEG_ENABLE) { >+ >+#define MY_ADV_MASK (ADVERTISE_10_HALF| \ >+ ADVERTISE_10_FULL| \ >+ ADVERTISE_100_HALF| \ >+ ADVERTISE_100_FULL) >+ >+ if ((ecmd->advertising&MY_ADV_MASK) == MY_ADV_MASK) { >+ hw->MediaType = MEDIA_TYPE_AUTO_SENSOR; >+ hw->autoneg_advertised = MY_ADV_MASK; >+ } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_100_FULL) { >+ hw->MediaType = MEDIA_TYPE_100M_FULL; >+ hw->autoneg_advertised = ADVERTISE_100_FULL; >+ } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_100_HALF) { >+ hw->MediaType = MEDIA_TYPE_100M_HALF; >+ hw->autoneg_advertised = ADVERTISE_100_HALF; >+ } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_10_FULL) { >+ hw->MediaType = MEDIA_TYPE_10M_FULL; >+ hw->autoneg_advertised = ADVERTISE_10_FULL; >+ } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_10_HALF) { >+ hw->MediaType = MEDIA_TYPE_10M_HALF; >+ hw->autoneg_advertised = ADVERTISE_10_HALF; >+ } else { >+ clear_bit(__AT_RESETTING, &adapter->flags); >+ return -EINVAL; >+ } >+ ecmd->advertising = hw->autoneg_advertised >+ | ADVERTISED_TP | ADVERTISED_Autoneg; >+ } else { >+ clear_bit(__AT_RESETTING, &adapter->flags); >+ return -EINVAL; >+ } >+ >+ /* reset the link */ >+ >+ if (netif_running(adapter->netdev)) { >+ at_down(adapter); >+ at_up(adapter); >+ } else >+ at_reset_hw(&adapter->hw); >+ >+ clear_bit(__AT_RESETTING, &adapter->flags); >+ return 0; >+} >+ >+ >+static u32 >+at_get_tx_csum(struct net_device *netdev) >+{ >+ return (netdev->features & NETIF_F_HW_CSUM) != 0; >+} >+ >+static u32 >+at_get_msglevel(struct net_device *netdev) >+{ >+#if DBG >+ return 1; >+#else >+ return 0; >+#endif >+} >+ >+ >+static void >+at_set_msglevel(struct net_device *netdev, u32 data) >+{ >+} >+ >+static int >+at_get_regs_len(struct net_device *netdev) >+{ >+#define AT_REGS_LEN 42 >+ return AT_REGS_LEN * sizeof(u32); >+} >+ >+static void >+at_get_regs(struct net_device *netdev, >+ struct ethtool_regs *regs, void *p) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw *hw = &adapter->hw; >+ u32 *regs_buff = p; >+ u16 phy_data; >+ >+ memset(p, 0, AT_REGS_LEN * sizeof(u32)); >+ >+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; >+ >+ regs_buff[0] = AT_READ_REG(hw, REG_VPD_CAP); >+ regs_buff[1] = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); >+ regs_buff[2] = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG); >+ regs_buff[3] = AT_READ_REG(hw, REG_TWSI_CTRL); >+ regs_buff[4] = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); >+ regs_buff[5] = AT_READ_REG(hw, REG_MASTER_CTRL); >+ regs_buff[6] = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT); >+ regs_buff[7] = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); >+ regs_buff[8] = AT_READ_REG(hw, REG_PHY_ENABLE); >+ regs_buff[9] = AT_READ_REG(hw, REG_CMBDISDMA_TIMER); >+ regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS); >+ regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL); >+ regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK); >+ regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL); >+ regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG); >+ regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR); >+ regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4); >+ regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE); >+ regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4); >+ regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); >+ regs_buff[20] = AT_READ_REG(hw, REG_MTU); >+ regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL); >+ regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TXRAM_END); >+ regs_buff[23] = AT_READ_REG(hw, REG_DESC_BASE_ADDR_HI); >+ regs_buff[24] = AT_READ_REG(hw, REG_TXD_BASE_ADDR_LO); >+ regs_buff[25] = AT_READ_REG(hw, REG_TXD_MEM_SIZE); >+ regs_buff[26] = AT_READ_REG(hw, REG_TXS_BASE_ADDR_LO); >+ regs_buff[27] = AT_READ_REG(hw, REG_TXS_MEM_SIZE); >+ regs_buff[28] = AT_READ_REG(hw, REG_RXD_BASE_ADDR_LO); >+ regs_buff[29] = AT_READ_REG(hw, REG_RXD_BUF_NUM); >+ regs_buff[30] = AT_READ_REG(hw, REG_DMAR); >+ regs_buff[31] = AT_READ_REG(hw, REG_TX_CUT_THRESH); >+ regs_buff[32] = AT_READ_REG(hw, REG_DMAW); >+ regs_buff[33] = AT_READ_REG(hw, REG_PAUSE_ON_TH); >+ regs_buff[34] = AT_READ_REG(hw, REG_PAUSE_OFF_TH); >+ regs_buff[35] = AT_READ_REG(hw, REG_MB_TXD_WR_IDX); >+ regs_buff[36] = AT_READ_REG(hw, REG_MB_RXD_RD_IDX); >+ regs_buff[38] = AT_READ_REG(hw, REG_ISR); >+ regs_buff[39] = AT_READ_REG(hw, REG_IMR); >+ >+ at_read_phy_reg(hw, MII_BMCR, &phy_data); >+ regs_buff[40] = (u32)phy_data; >+ at_read_phy_reg(hw, MII_BMSR, &phy_data); >+ regs_buff[41] = (u32)phy_data; >+} >+ >+static int >+at_get_eeprom_len(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+ if (!check_eeprom_exist(&adapter->hw)) { >+ return 512; >+ } else >+ return 0; >+} >+ >+static int >+at_get_eeprom(struct net_device *netdev, >+ struct ethtool_eeprom *eeprom, u8 *bytes) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw *hw = &adapter->hw; >+ u32 *eeprom_buff; >+ int first_dword, last_dword; >+ int ret_val = 0; >+ int i; >+ >+ if (eeprom->len == 0) >+ return -EINVAL; >+ >+ if (check_eeprom_exist(hw)) { >+ return -EINVAL; >+ } >+ >+ eeprom->magic = hw->vendor_id | (hw->device_id << 16); >+ >+ first_dword = eeprom->offset >> 2; >+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2; >+ >+ eeprom_buff = kmalloc(sizeof(u32) * >+ (last_dword - first_dword + 1), GFP_KERNEL); >+ if (!eeprom_buff) >+ return -ENOMEM; >+ >+ for (i=first_dword; i < last_dword; i++) { >+ if (!read_eeprom(hw, i*4, &(eeprom_buff[i-first_dword]))) >+ return -EIO; >+ } >+ >+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), >+ eeprom->len); >+ kfree(eeprom_buff); >+ >+ return ret_val; >+} >+ >+static int >+at_set_eeprom(struct net_device *netdev, >+ struct ethtool_eeprom *eeprom, u8 *bytes) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw *hw = &adapter->hw; >+ u32 *eeprom_buff; >+ u32 *ptr; >+ int max_len, first_dword, last_dword, ret_val = 0; >+ int i; >+ >+ if (eeprom->len == 0) >+ return -EOPNOTSUPP; >+ >+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) >+ return -EFAULT; >+ >+ max_len = 512; >+ >+ first_dword = eeprom->offset >> 2; >+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2; >+ eeprom_buff = kmalloc(max_len, GFP_KERNEL); >+ if (!eeprom_buff) >+ return -ENOMEM; >+ >+ ptr = (u32 *)eeprom_buff; >+ >+ if (eeprom->offset & 3) { >+ /* need read/modify/write of first changed EEPROM word */ >+ /* only the second byte of the word is being modified */ >+ if (!read_eeprom(hw, first_dword*4, &(eeprom_buff[0]))) >+ return -EIO; >+ ptr++; >+ } >+ if (((eeprom->offset + eeprom->len) & 3) ) { >+ /* need read/modify/write of last changed EEPROM word */ >+ /* only the first byte of the word is being modified */ >+ >+ if (!read_eeprom(hw, last_dword*4, &(eeprom_buff[last_dword - first_dword]))) >+ return -EIO; >+ } >+ >+ /* Device's eeprom is always little-endian, word addressable */ >+ memcpy(ptr, bytes, eeprom->len); >+ >+ for (i = 0; i < last_dword - first_dword + 1; i++) { >+ if (!write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i])) >+ return -EIO; >+ } >+ >+ kfree(eeprom_buff); >+ return ret_val; >+} >+ >+static void >+at_get_drvinfo(struct net_device *netdev, >+ struct ethtool_drvinfo *drvinfo) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+ strncpy(drvinfo->driver, at_driver_name, 32); >+ strncpy(drvinfo->version, at_driver_version, 32); >+ strncpy(drvinfo->fw_version, "L2", 32); >+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); >+ drvinfo->n_stats = 0; >+ drvinfo->testinfo_len = 0; >+ drvinfo->regdump_len = at_get_regs_len(netdev); >+ drvinfo->eedump_len = at_get_eeprom_len(netdev); >+} >+ >+static void >+at_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+ wol->supported = WAKE_MAGIC; >+ wol->wolopts = 0; >+ >+ if (adapter->wol & AT_WUFC_EX) >+ wol->wolopts |= WAKE_UCAST; >+ if (adapter->wol & AT_WUFC_MC) >+ wol->wolopts |= WAKE_MCAST; >+ if (adapter->wol & AT_WUFC_BC) >+ wol->wolopts |= WAKE_BCAST; >+ if (adapter->wol & AT_WUFC_MAG) >+ wol->wolopts |= WAKE_MAGIC; >+ >+ return; >+} >+ >+static int >+at_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) >+ return -EOPNOTSUPP; >+ >+ if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST)) { >+ AT_DBG("Interface does not support broadcast/multicast frame wake-up packets\n"); >+ return -EOPNOTSUPP; >+ } >+ >+ /* these settings will always override what we currently have */ >+ adapter->wol = 0; >+ >+ if (wol->wolopts & WAKE_MAGIC) >+ adapter->wol |= AT_WUFC_MAG; >+ >+ return 0; >+} >+ >+static int >+at_nway_reset(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ if (netif_running(netdev)) >+ at_reinit_locked(adapter); >+ return 0; >+} >+ >+ >+static struct ethtool_ops at_ethtool_ops = { >+ .get_settings = at_get_settings, >+ .set_settings = at_set_settings, >+ .get_drvinfo = at_get_drvinfo, >+ .get_regs_len = at_get_regs_len, >+ .get_regs = at_get_regs, >+ .get_wol = at_get_wol, >+ .set_wol = at_set_wol, >+ .get_msglevel = at_get_msglevel, >+ .set_msglevel = at_set_msglevel, >+ .nway_reset = at_nway_reset, >+ .get_link = ethtool_op_get_link, >+ .get_eeprom_len = at_get_eeprom_len, >+ .get_eeprom = at_get_eeprom, >+ .set_eeprom = at_set_eeprom, >+ .get_tx_csum = at_get_tx_csum, >+ .get_sg = ethtool_op_get_sg, >+ .set_sg = ethtool_op_set_sg, >+#ifdef NETIF_F_TSO >+ .get_tso = ethtool_op_get_tso, >+#endif >+#ifdef ETHTOOL_GPERMADDR >+ .get_perm_addr = ethtool_op_get_perm_addr, >+#endif >+}; >+ >+void at_set_ethtool_ops(struct net_device *netdev) >+{ >+ SET_ETHTOOL_OPS(netdev, &at_ethtool_ops); >+} >+#endif /* SIOCETHTOOL */ >+ >diff -ruN -a -p old/drivers/net/atl2/at.h new/drivers/net/atl2/at.h >--- old/drivers/net/atl2/at.h 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at.h 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,146 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#ifndef _ATTANSIC_H__ >+#define _ATTANSIC_H__ >+ >+#include "kcompat.h" >+ >+ >+#define BAR_0 0 >+#define BAR_1 1 >+#define BAR_5 5 >+ >+ >+#define ATTANSIC_ETHERNET_DEVICE(device_id) {\ >+ PCI_DEVICE(0x1969, device_id)} >+ >+ >+struct at_adapter; >+ >+#include "at_hw.h" >+ >+#if DBG >+#define AT_DBG(args...) printk(KERN_DEBUG "attansic: " args) >+#else >+#define AT_DBG(args...) >+#endif >+ >+#define AT_ERR(args...) printk(KERN_ERR "attansic: " args) >+ >+ >+struct at_ring_header { >+ /* pointer to the descriptor ring memory */ >+ void *desc; >+ /* physical adress of the descriptor ring */ >+ dma_addr_t dma; >+ /* length of descriptor ring in bytes */ >+ unsigned int size; >+}; >+ >+/* board specific private data structure */ >+ >+struct at_adapter { >+ /* OS defined structs */ >+ struct net_device *netdev; >+ struct pci_dev *pdev; >+ struct net_device_stats net_stats; >+ >+#ifdef NETIF_F_HW_VLAN_TX >+ struct vlan_group *vlgrp;// >+#endif >+ u32 wol; >+ u16 link_speed; >+ u16 link_duplex; >+ spinlock_t stats_lock; >+ spinlock_t tx_lock; >+ atomic_t irq_sem;// >+ struct work_struct reset_task;// >+ struct work_struct link_chg_task;// >+ struct timer_list watchdog_timer; >+ struct timer_list phy_config_timer; >+ boolean_t phy_timer_pending; >+ >+ boolean_t mac_disabled; >+ >+ >+ // All Descriptor memory >+ dma_addr_t ring_dma; >+ void* ring_vir_addr; >+ int ring_size; >+ >+ tx_pkt_header_t* txd_ring; >+ dma_addr_t txd_dma; >+ >+ tx_pkt_status_t* txs_ring; >+ dma_addr_t txs_dma; >+ >+ rx_desc_t* rxd_ring; >+ dma_addr_t rxd_dma; >+ >+ u32 txd_ring_size; // bytes per unit >+ u32 txs_ring_size; // dwords per unit >+ u32 rxd_ring_size; // 1536bytes per unit >+ >+ // read /write ptr: >+ // host >+ u32 txd_write_ptr; >+ u32 txs_next_clear; >+ u32 rxd_read_ptr; >+ >+ // nic >+ atomic_t txd_read_ptr; >+ atomic_t txs_write_ptr; >+ u32 rxd_write_ptr; >+ >+ >+ /* Interrupt Moderator timer ( 2us resolution) */ >+ u16 imt; >+ /* Interrupt Clear timer (2us resolution) */ >+ u16 ict; >+ >+ unsigned long flags; >+ /* structs defined in at_hw.h */ >+ u32 bd_number; // board number; >+ boolean_t pci_using_64; >+ struct at_hw hw; >+ >+ u32 usr_cmd; >+// u32 regs_buff[AT_REGS_LEN]; >+ u32 pci_state[16]; >+ >+ u32* config_space; >+}; >+ >+enum at_state_t { >+ __AT_TESTING, >+ __AT_RESETTING, >+ __AT_DOWN >+}; >+ >+ >+#endif//_ATTANSIC_H__ >+ >diff -ruN -a -p old/drivers/net/atl2/at_hw.c new/drivers/net/atl2/at_hw.c >--- old/drivers/net/atl2/at_hw.c 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at_hw.c 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,890 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#include "at.h" >+#ifdef SIOCGMIIPHY >+#include <linux/mii.h> >+#endif >+ >+#define LBYTESWAP( a ) ( ( ( (a) & 0x00ff00ff ) << 8 ) | ( ( (a) & 0xff00ff00 ) >> 8 ) ) >+#define LONGSWAP( a ) ( ( LBYTESWAP( a ) << 16 ) | ( LBYTESWAP( a ) >> 16 ) ) >+#define SHORTSWAP( a ) ( ( (a) << 8 ) | ( (a) >> 8 ) ) >+ >+ >+ >+extern inline void at_irq_enable(struct at_adapter* adapter); >+extern inline void at_irq_disable(struct at_adapter* adapter); >+ >+ >+void at_init_pcie(struct at_hw *hw); >+ >+/* >+ * The little-endian AUTODIN II ethernet CRC calculations. >+ * A big-endian version is also available. >+ * This is slow but compact code. Do not use this routine >+ * for bulk data, use a table-based routine instead. >+ * This is common code and should be moved to net/core/crc.c. >+ * Chips may use the upper or lower CRC bits, and may reverse >+ * and/or invert them. Select the endian-ness that results >+ * in minimal calculations. >+ */ >+u32 >+ether_crc_le(int length, unsigned char *data) >+{ >+ u32 crc = ~0; /* Initial value. */ >+ while(--length >= 0) { >+ unsigned char current_octet = *data++; >+ int bit; >+ for (bit = 8; --bit >= 0; current_octet >>= 1) { >+ if ((crc ^ current_octet) & 1) { >+ crc >>= 1; >+ crc ^= 0xedb88320; >+ } >+ else >+ crc >>= 1; >+ } >+ } >+ return ~crc; >+} >+ >+/******************************************************************** >+* Reset the transmit and receive units; mask and clear all interrupts. >+* >+* hw - Struct containing variables accessed by shared code >+* return : AT_SUCCESS or idle status (if error) >+********************************************************************/ >+int32_t >+at_reset_hw(struct at_hw *hw) >+{ >+ u32 icr; >+ u16 pci_cfg_cmd_word; >+ int i; >+ >+ DEBUGFUNC("at_reset_hw"); >+ >+ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ >+ at_read_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word); >+ if ((pci_cfg_cmd_word& >+ (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) >+ != (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) { >+ pci_cfg_cmd_word |= >+ (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER); >+ at_write_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word); >+ } >+ >+ >+ /* Clear Interrupt mask to stop board from generating >+ * interrupts & Clear any pending interrupt events >+ */ >+// AT_WRITE_REG(hw, REG_IMR, 0); >+// AT_WRITE_REG(hw, REG_ISR, 0xffffffff); >+ >+ /* 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. >+ */ >+ AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); >+ wmb(); >+ >+ >+ msec_delay(1); // delay about 1ms >+ >+ /* Wait at least 10ms for All module to be Idle >+ */ >+ for (i=0; i < 10; i++) >+ { >+ icr = AT_READ_REG(hw, REG_IDLE_STATUS); >+ if (!icr) >+ break; >+ msec_delay(1); // delay 1 ms >+ cpu_relax(); >+ } >+ >+ if (icr) >+ { >+ DEBUGOUT("MAC state machine cann't be idle since disabled for 10ms second\n"); >+ return icr; >+ } >+ >+ return AT_SUCCESS; >+} >+ >+ >+/********************************************************************* >+* Reads the adapter's MAC address from the EEPROM >+* >+* hw - Struct containing variables accessed by shared code >+*********************************************************************/ >+int32_t >+at_read_mac_addr(struct at_hw * hw) >+{ >+ u16 i; >+ >+ DEBUGFUNC("at_read_mac_addr"); >+ >+ if (get_permanent_address(hw)) { >+ // for test >+ hw->perm_mac_addr[0] = 0x00; >+ hw->perm_mac_addr[1] = 0x13; >+ hw->perm_mac_addr[2] = 0x74; >+ hw->perm_mac_addr[3] = 0x00; >+ hw->perm_mac_addr[4] = 0x5c; >+ hw->perm_mac_addr[5] = 0x38; >+ } >+ >+ for(i = 0; i < NODE_ADDRESS_SIZE; i++) >+ hw->mac_addr[i] = hw->perm_mac_addr[i]; >+ return AT_SUCCESS; >+} >+ >+/********************************************************************* >+* 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 >+*********************************************************************/ >+/* >+ * at_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 >+ */ >+u32 >+at_hash_mc_addr( >+ struct at_hw *hw, >+ u8 *mc_addr) >+{ >+ u32 crc32, value=0; >+ int i; >+ >+ crc32 = ether_crc_le(6, mc_addr); >+ crc32 = ~crc32; >+ 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 >+********************************************************************/ >+void >+at_hash_set( >+ struct at_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 = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); >+ >+ mta |= (1 << hash_bit); >+ >+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); >+} >+ >+/******************************************************************** >+* 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) >+********************************************************************/ >+ >+int32_t >+at_phy_leave_power_saving(struct at_hw* hw) >+{ >+ >+ int32_t ret; >+ >+// DEBUGFUNC("at_phy_leave_power_saving!"); >+ >+ >+ if ((ret = at_write_phy_reg(hw, 29, 0x0029))) >+ return ret; >+ >+ return at_write_phy_reg(hw, 30, 0); >+} >+ >+int32_t >+at_phy_enter_power_saving(struct at_hw* hw) >+{ >+// int32_t ret_val; >+// u16 phy_data; >+ >+ DEBUGFUNC("at_phy_enter_power_saving"); >+/* >+ ret_val = at_write_phy_reg(hw, ...); >+ ret_val = at_write_phy_reg(hw, ...); >+ .... >+*/ >+ return AT_SUCCESS; >+} >+ >+ >+/* >+ * at_init_pcie - init PCIE module >+ */ >+void at_init_pcie(struct at_hw *hw) >+{ >+ u32 value; >+ value = 0x6500; >+ AT_WRITE_REG(hw, 0x12FC, value); >+ /* pcie flow control mode change */ >+ value = AT_READ_REG(hw, 0x1008); >+ value |= 0x8000; >+ AT_WRITE_REG(hw, 0x1008, value); >+} >+ >+/******************************************************************** >+* 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. >+********************************************************************/ >+int32_t >+at_init_hw(struct at_hw *hw) >+{ >+ u32 ret_val = 0; >+ >+ DEBUGFUNC("at_init_hw"); >+ >+ at_init_pcie(hw); >+ >+ >+ /* Zero out the Multicast HASH table */ >+// DEBUGOUT("Zeroing the MTA"); >+ /* clear the old settings from the multicast hash table */ >+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); >+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); >+ >+ init_flash_opcode(hw); >+ >+ ret_val = at_phy_init(hw); >+ >+ DEBUGOUT1("at_init_hw: ret: %d", ret_val); >+ >+ 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 >+*****************************************************************************/ >+int32_t >+at_get_speed_and_duplex( >+ struct at_hw *hw, >+ u16 *speed, >+ u16 *duplex) >+{ >+ int32_t ret_val; >+ u16 phy_data; >+ >+// DEBUGFUNC("at_get_speed_and_duplex"); >+ >+ // ; --- Read PHY Specific Status Register (17) >+ ret_val = at_read_phy_reg(hw, MII_AT001_PSSR, &phy_data); >+ if (ret_val) >+ return ret_val; >+ >+ if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED)) >+ return AT_ERR_PHY_RES; >+ >+ switch(phy_data&MII_AT001_PSSR_SPEED) { >+ case MII_AT001_PSSR_100MBS: >+ *speed = SPEED_100; >+// DEBUGOUT("100 Mbs, "); >+ break; >+ case MII_AT001_PSSR_10MBS: >+ *speed = SPEED_10; >+// DEBUGOUT("10 Mbs, "); >+ break; >+ default: >+ DEBUGOUT("Error Speed !\n"); >+ return AT_ERR_PHY_SPEED; >+ break; >+ } >+ >+ if (phy_data & MII_AT001_PSSR_DPLX) { >+ *duplex = FULL_DUPLEX; >+// DEBUGOUT("Full Duplex"); >+ } else { >+ *duplex = HALF_DUPLEX; >+// DEBUGOUT(" Half Duplex"); >+ } >+ >+ return AT_SUCCESS; >+} >+ >+/********************************************************************* >+* Reads the value from a PHY register >+* hw - Struct containing variables accessed by shared code >+* reg_addr - address of the PHY register to read >+*********************************************************************/ >+int32_t >+at_read_phy_reg( >+ struct at_hw *hw, >+ u16 reg_addr, >+ u16 *phy_data) >+{ >+ u32 val; >+ int i; >+ >+// DEBUGFUNC("at_read_phy_reg"); >+ >+ 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; >+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); >+ >+ wmb(); >+ >+ for (i=0; i<MDIO_WAIT_TIMES; i++) { >+ usec_delay(2); >+ val = AT_READ_REG(hw, REG_MDIO_CTRL); >+ if (!(val&(MDIO_START|MDIO_BUSY))) { >+ break; >+ } >+ wmb(); >+ } >+ if (!(val&(MDIO_START|MDIO_BUSY))) { >+ *phy_data = (u16)val; >+ return AT_SUCCESS; >+ } >+ >+ return AT_ERR_PHY; >+} >+ >+/******************************************************************** >+* 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 >+********************************************************************/ >+int32_t >+at_write_phy_reg( >+ struct at_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; >+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); >+// DEBUGOUT1("phy write 0x%x <- 0x%x, value = 0x%x", i >+// reg_addr, >+// phy_data, >+// val); >+ >+ wmb(); >+ >+ for (i=0; i<MDIO_WAIT_TIMES; i++) { >+ usec_delay(2); >+ val = AT_READ_REG(hw, REG_MDIO_CTRL); >+ if (!(val&(MDIO_START|MDIO_BUSY))) { >+ break; >+ } >+ wmb(); >+ } >+ >+ if (!(val&(MDIO_START|MDIO_BUSY))) >+ return AT_SUCCESS; >+ >+ return AT_ERR_PHY; >+} >+ >+/******************************************************************** >+* Configures PHY autoneg and flow control advertisement settings >+* >+* hw - Struct containing variables accessed by shared code >+********************************************************************/ >+int32_t >+at_phy_setup_autoneg_adv(struct at_hw *hw) >+{ >+ int32_t ret_val; >+ int16_t mii_autoneg_adv_reg; >+ >+ DEBUGFUNC("at_phy_setup_autoneg_adv"); >+ >+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */ >+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK; >+ >+ /* Need to parse autoneg_advertised and set up >+ * the appropriate PHY registers. First we will parse for >+ * autoneg_advertised software override. Since we can advertise >+ * a plethora of combinations, we need to check each bit >+ * individually. >+ */ >+ >+ /* 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; >+ >+ /* Need to parse MediaType and setup the >+ * appropriate PHY registers. >+ */ >+ switch (hw->MediaType) >+ { >+ 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); >+ hw->autoneg_advertised = ADVERTISE_10_HALF| >+ ADVERTISE_10_FULL | >+ ADVERTISE_100_HALF| >+ ADVERTISE_100_FULL; >+ break; >+ >+ case MEDIA_TYPE_100M_FULL: >+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS; >+ hw->autoneg_advertised = ADVERTISE_100_FULL; >+ break; >+ >+ case MEDIA_TYPE_100M_HALF: >+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS; >+ hw->autoneg_advertised = ADVERTISE_100_HALF; >+ break; >+ >+ case MEDIA_TYPE_10M_FULL: >+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS; >+ hw->autoneg_advertised = ADVERTISE_10_FULL; >+ break; >+ >+ default: >+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS; >+ hw->autoneg_advertised = ADVERTISE_10_HALF; >+ 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; >+ >+ ret_val = at_write_phy_reg(hw, >+ MII_ADVERTISE, >+ mii_autoneg_adv_reg); >+ if(ret_val) >+ return ret_val; >+ >+ return AT_SUCCESS; >+} >+ >+int32_t >+at_phy_init(struct at_hw* hw) >+{ >+ int32_t ret_val; >+ u16 phy_val; >+ >+ >+// if (hw->phy_configured) >+// return 0; >+ >+ /* Enable (G)PHY */ >+ AT_WRITE_REGW(hw, REG_PHY_ENABLE, 1); >+ AT_WRITE_FLUSH(hw); >+ usec_delay(10); >+ >+ /* make PHY out of power-saving state */ >+ ret_val = at_phy_leave_power_saving(hw); >+ if (ret_val) >+ return ret_val; >+ >+ /*Enable PHY LinkChange Interrupt */ >+ ret_val = at_write_phy_reg(hw, 18, 0xC00); >+ if (ret_val) >+ return ret_val; >+ >+ /* setup AutoNeg parameters */ >+ ret_val = at_phy_setup_autoneg_adv(hw); >+ if(ret_val) { >+ DEBUGOUT("Error Setting up Auto-Negotiation"); >+ return ret_val; >+ } >+ >+ /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/ >+ DEBUGOUT("Restarting Auto-Neg"); >+ ret_val = at_phy_commit(hw); >+ if (ret_val) { >+ DEBUGOUT("Error Resetting the phy"); >+ return ret_val; >+ } >+ >+ hw->phy_configured = TRUE; >+ >+ return ret_val; >+} >+ >+/******************************************************************* >+* 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) >+*******************************************************************/ >+int32_t >+at_phy_commit(struct at_hw *hw) >+{ >+ int32_t ret_val; >+ u16 phy_data; >+ >+ DEBUGFUNC("at_phy_commit"); >+ >+ if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR) { >+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN; >+ } else { >+ switch (hw->MediaType) >+ { >+ 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 = at_write_phy_reg(hw, MII_BMCR, phy_data); >+ if (ret_val) { // bug fixed >+ u32 val; >+ int i; >+ /************************************** >+ * pcie serdes link may be down ! >+ **************************************/ >+ DEBUGOUT("Auto-Neg make pcie phy link down !"); >+ >+ for (i=0; i < 25; i++) { >+ msec_delay(1); >+ val = AT_READ_REG(hw, REG_MDIO_CTRL); >+ if (!(val&(MDIO_START|MDIO_BUSY))) { >+ break; >+ } >+ } >+ >+ if (0 != (val&(MDIO_START|MDIO_BUSY))) { >+ AT_ERR("pcie linkdown at least for 25ms !\n"); >+ return ret_val; >+ >+ DEBUGOUT1("pcie linkup after %dms", i); >+ } >+ } >+ return AT_SUCCESS; >+} >+ >+void >+set_mac_addr(struct at_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]) ) ; >+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); >+ // hight dword >+ value = (((u32)hw->mac_addr[0]) << 8 ) | >+ (((u32)hw->mac_addr[1]) ) ; >+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); >+} >+ >+ >+/*************************************** function about EEPROM **********************************/ >+/* >+ * check_eeprom_exist >+ * return 0 if eeprom exist >+ */ >+int >+check_eeprom_exist(struct at_hw* hw) >+{ >+ u32 value; >+ >+ value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); >+ if (value & SPI_FLASH_CTRL_EN_VPD) >+ { >+ value &= ~SPI_FLASH_CTRL_EN_VPD; >+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); >+ } >+ value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST); >+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1; >+} >+ >+/* >+ * get_permanent_address >+ * return 0 if get valid mac address, >+ */ >+int >+get_permanent_address(struct at_hw* hw) >+{ >+ u32 Addr[2]; >+ u32 i, Control; >+ u16 Register; >+ u8 EthAddr[NODE_ADDRESS_SIZE]; >+ boolean_t KeyValid; >+ >+ if (is_valid_ether_addr(hw->perm_mac_addr)) >+ return 0; >+ >+ // init >+ Addr[0] = Addr[1] = 0; >+ >+ if (!check_eeprom_exist(hw)) { // eeprom exist >+ Register = 0; >+ KeyValid = FALSE; >+ // >+ // Read out all EEPROM content >+ // >+ i = 0; >+ while (1) { >+ if (read_eeprom(hw, i+0x100, &Control)) { >+ if (KeyValid) { >+ if (Register == REG_MAC_STA_ADDR) >+ Addr[0] = Control; >+ else if (Register == (REG_MAC_STA_ADDR+4)) { >+ Addr[1] = Control; >+ } >+ KeyValid = FALSE; >+ } else if ((Control&0xff) == 0x5A) { >+ KeyValid = TRUE; >+ Register = (u16) (Control >> 16); >+ } else { >+ break; // assume data end while encount an invalid KEYWORD >+ } >+ } else { >+ break; // read error >+ } >+ i += 4; >+ } >+ >+ *(u32*) &EthAddr[2] = LONGSWAP(Addr[0]); >+ *(u16*) &EthAddr[0] = SHORTSWAP(*(u16*)&Addr[1]); >+ >+ if (is_valid_ether_addr(EthAddr)) { >+ memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); >+ return 0; >+ } >+ return 1; >+ } >+ >+ // see if SPI FLAHS exist ? >+ Addr[0] = Addr[1] = 0 ; >+ Register = 0; >+ KeyValid = FALSE; >+ i = 0; >+ while (1) { >+ if (spi_read(hw, i+0x1f000, &Control)) { >+ if (KeyValid) { >+ if (Register == REG_MAC_STA_ADDR) >+ Addr[0] = Control; >+ else if (Register == (REG_MAC_STA_ADDR+4)) { >+ Addr[1] = Control; >+ } >+ KeyValid = FALSE; >+ } else if ((Control&0xff) == 0x5A) { >+ KeyValid = TRUE; >+ Register = (u16) (Control >> 16); >+ } else { >+ break; // data end >+ } >+ } else { >+ break; // read error >+ } >+ i += 4; >+ } >+ >+ *(u32*) &EthAddr[2] = LONGSWAP(Addr[0]); >+ *(u16*) &EthAddr[0] = SHORTSWAP(*(u16*)&Addr[1]); >+ if (is_valid_ether_addr(EthAddr)) { >+ memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); >+ return 0; >+ } >+ /* maybe MAC-address is from BIOS */ >+ Addr[0] = AT_READ_REG(hw,REG_MAC_STA_ADDR); >+ Addr[1] = AT_READ_REG(hw,REG_MAC_STA_ADDR+4); >+ *(u32*) &EthAddr[2] = LONGSWAP(Addr[0]); >+ *(u16*) &EthAddr[0] = SHORTSWAP(*(u16*)&Addr[1]); >+ >+ if (is_valid_ether_addr(EthAddr)) { >+ memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); >+ return 0; >+ } >+ >+ return 1; >+} >+ >+boolean_t >+write_eeprom(struct at_hw* hw, u32 offset, u32 value) >+{ >+ return TRUE; >+} >+ >+boolean_t >+read_eeprom(struct at_hw* hw, u32 Offset, u32* pValue) >+{ >+ int i; >+ u32 Control; >+ >+ if (Offset&3) return FALSE; //address do not align >+ >+ AT_WRITE_REG(hw, REG_VPD_DATA, 0); >+ Control = (Offset&VPD_CAP_VPD_ADDR_MASK)<<VPD_CAP_VPD_ADDR_SHIFT; >+ AT_WRITE_REG(hw, REG_VPD_CAP, Control); >+ >+ for (i=0; i < 10; i++) >+ { >+ msec_delay(2); >+ Control = AT_READ_REG(hw, REG_VPD_CAP); >+ if (Control & VPD_CAP_VPD_FLAG) >+ break; >+ } >+ if (Control & VPD_CAP_VPD_FLAG) >+ { >+ *pValue = AT_READ_REG(hw, REG_VPD_DATA); >+ return TRUE; >+ } >+ return FALSE; // timeout >+} >+ >+spi_flash_dev flash_table[] = >+{ >+// manu_name WRSR READ PROGRAM WREN WRDI RDSR RDID SECTOR_ERASE CHIP_ERASE >+ {"Atmel", 0x0, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62 }, >+ {"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60 }, >+ {"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7 }, >+}; >+ >+ >+#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 >+ >+ >+ >+void >+init_flash_opcode(struct at_hw* hw) >+{ >+ if (hw->flash_vendor >= sizeof(flash_table)/sizeof(flash_table[0])) { >+ hw->flash_vendor = 0; // ATMEL >+ } >+ // Init OP table >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_PROGRAM, flash_table[hw->flash_vendor].cmdPROGRAM); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_SC_ERASE, flash_table[hw->flash_vendor].cmdSECTOR_ERASE); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_CHIP_ERASE, flash_table[hw->flash_vendor].cmdCHIP_ERASE); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDID, flash_table[hw->flash_vendor].cmdRDID); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_WREN, flash_table[hw->flash_vendor].cmdWREN); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDSR, flash_table[hw->flash_vendor].cmdRDSR); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_WRSR, flash_table[hw->flash_vendor].cmdWRSR); >+ AT_WRITE_REGB(hw, REG_SPI_FLASH_OP_READ, flash_table[hw->flash_vendor].cmdREAD); >+} >+ >+boolean_t >+spi_read(struct at_hw* hw, u32 addr, u32* buf) >+{ >+ int i; >+ u32 value; >+ >+ AT_WRITE_REG(hw, REG_SPI_DATA, 0); >+ AT_WRITE_REG(hw, REG_SPI_ADDR, 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; >+ >+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); >+ >+ value |= SPI_FLASH_CTRL_START; >+ >+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); >+ >+ for (i = 0; i < 10; i++) >+ { >+ msec_delay(1); // 1ms >+ value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); >+ if (!(value & SPI_FLASH_CTRL_START)) >+ break; >+ } >+ >+ if (value & SPI_FLASH_CTRL_START) >+ return FALSE; >+ >+ *buf = AT_READ_REG(hw, REG_SPI_DATA); >+ >+ return TRUE; >+} >+ >diff -ruN -a -p old/drivers/net/atl2/at_hw.h new/drivers/net/atl2/at_hw.h >--- old/drivers/net/atl2/at_hw.h 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at_hw.h 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,752 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#ifndef _ATTANSIC_HW_H__ >+#define _ATTANSIC_HW_H__ >+ >+#include "at_osdep.h" >+ >+#define _AT_ATTRIB_PACK_ __attribute__ ((packed)) >+ >+struct at_adapter; >+struct at_hw; >+ >+/* function prototype */ >+ >+int32_t at_reset_hw(struct at_hw* hw); >+int32_t at_read_mac_addr(struct at_hw* hw); >+int32_t at_init_hw(struct at_hw* hw); >+int32_t at_phy_setup_autoneg_adv(struct at_hw *hw); >+int32_t at_phy_commit(struct at_hw *hw); >+int32_t at_get_speed_and_duplex(struct at_hw *hw, u16 *speed, u16 *duplex); >+u32 at_auto_get_fc(struct at_adapter* adapter, u16 duplex); >+u32 at_hash_mc_addr(struct at_hw *hw, u8 *mc_addr); >+void at_hash_set(struct at_hw *hw, u32 hash_value); >+int32_t at_read_phy_reg(struct at_hw *hw, u16 reg_addr, u16 *phy_data); >+int32_t at_write_phy_reg(struct at_hw *hw, u32 reg_addr, u16 phy_data); >+void at_read_pci_cfg(struct at_hw* hw, u32 reg, u16 *value); >+void at_write_pci_cfg(struct at_hw* hw, u32 reg, u16 *value); >+int32_t at_validate_mdi_setting(struct at_hw* hw); >+void set_mac_addr(struct at_hw* hw); >+int get_permanent_address(struct at_hw* hw); >+boolean_t read_eeprom(struct at_hw* hw, u32 Offset, u32* pValue); >+boolean_t write_eeprom(struct at_hw* hw, u32 offset, u32 value); >+void init_flash_opcode(struct at_hw* hw); >+boolean_t spi_read(struct at_hw* hw, u32 addr, u32* buf); >+int32_t at_phy_enter_power_saving(struct at_hw* hw); >+int32_t at_phy_leave_power_saving(struct at_hw* hw); >+int32_t at_phy_init(struct at_hw* hw); >+int check_eeprom_exist(struct at_hw* hw); >+ >+ >+/* register definition */ >+ >+/* register definition */ >+#define REG_PM_CTRLSTAT 0x44 >+ >+#define REG_PCIE_CAP_LIST 0x58 >+ >+#define REG_VPD_CAP 0x6C >+#define VPD_CAP_ID_MASK 0xff >+#define VPD_CAP_ID_SHIFT 0 >+#define VPD_CAP_NEXT_PTR_MASK 0xFF >+#define VPD_CAP_NEXT_PTR_SHIFT 8 >+#define VPD_CAP_VPD_ADDR_MASK 0x7FFF >+#define VPD_CAP_VPD_ADDR_SHIFT 16 >+#define VPD_CAP_VPD_FLAG 0x80000000 >+ >+#define REG_VPD_DATA 0x70 >+ >+#define REG_SPI_FLASH_CTRL 0x200 >+#define SPI_FLASH_CTRL_STS_NON_RDY 0x1 >+#define SPI_FLASH_CTRL_STS_WEN 0x2 >+#define SPI_FLASH_CTRL_STS_WPEN 0x80 >+#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF >+#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0 >+#define SPI_FLASH_CTRL_INS_MASK 0x7 >+#define SPI_FLASH_CTRL_INS_SHIFT 8 >+#define SPI_FLASH_CTRL_START 0x800 >+#define SPI_FLASH_CTRL_EN_VPD 0x2000 >+#define SPI_FLASH_CTRL_LDSTART 0x8000 >+#define SPI_FLASH_CTRL_CS_HI_MASK 0x3 >+#define SPI_FLASH_CTRL_CS_HI_SHIFT 16 >+#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3 >+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18 >+#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3 >+#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20 >+#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3 >+#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22 >+#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3 >+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24 >+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3 >+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26 >+#define SPI_FLASH_CTRL_WAIT_READY 0x10000000 >+ >+#define REG_SPI_ADDR 0x204 >+ >+#define REG_SPI_DATA 0x208 >+ >+#define REG_SPI_FLASH_CONFIG 0x20C >+#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF >+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0 >+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3 >+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24 >+#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000 >+ >+ >+#define REG_SPI_FLASH_OP_PROGRAM 0x210 >+#define REG_SPI_FLASH_OP_SC_ERASE 0x211 >+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212 >+#define REG_SPI_FLASH_OP_RDID 0x213 >+#define REG_SPI_FLASH_OP_WREN 0x214 >+#define REG_SPI_FLASH_OP_RDSR 0x215 >+#define REG_SPI_FLASH_OP_WRSR 0x216 >+#define REG_SPI_FLASH_OP_READ 0x217 >+ >+#define REG_TWSI_CTRL 0x218 >+#define TWSI_CTRL_LD_OFFSET_MASK 0xFF >+#define TWSI_CTRL_LD_OFFSET_SHIFT 0 >+#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 >+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 >+#define TWSI_CTRL_SW_LDSTART 0x800 >+#define TWSI_CTRL_HW_LDSTART 0x1000 >+#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F >+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 >+#define TWSI_CTRL_LD_EXIST 0x400000 >+#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 >+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 >+#define TWSI_CTRL_FREQ_SEL_100K 0 >+#define TWSI_CTRL_FREQ_SEL_200K 1 >+#define TWSI_CTRL_FREQ_SEL_300K 2 >+#define TWSI_CTRL_FREQ_SEL_400K 3 >+#define TWSI_CTRL_SMB_SLV_ADDR >+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 >+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 >+ >+ >+#define REG_PCIE_DEV_MISC_CTRL 0x21C >+#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2 >+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1 >+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4 >+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8 >+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10 >+ >+#define REG_PCIE_PHYMISC 0x1000 >+#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 >+ >+// Selene Master Control Register >+#define REG_MASTER_CTRL 0x1400 >+#define MASTER_CTRL_SOFT_RST 0x1 >+#define MASTER_CTRL_MTIMER_EN 0x2 >+#define MASTER_CTRL_ITIMER_EN 0x4 >+#define MASTER_CTRL_MANUAL_INT 0x8 >+#define MASTER_CTRL_REV_NUM_SHIFT 16 >+#define MASTER_CTRL_REV_NUM_MASK 0xff >+#define MASTER_CTRL_DEV_ID_SHIFT 24 >+#define MASTER_CTRL_DEV_ID_MASK 0xff >+ >+// Timer Initial Value Register >+#define REG_MANUAL_TIMER_INIT 0x1404 >+ >+// IRQ ModeratorTimer Initial Value Register >+#define REG_IRQ_MODU_TIMER_INIT 0x1408 >+ >+ >+#define REG_PHY_ENABLE 0x140C >+// IRQ Anti-Lost Timer Initial Value Register >+//#define REG_IRQ_CLR_TIMER 0x140c // Maximum allowance for software to clear the interrupt. >+// IRQ Anti-Lost Timer Initial Value Register >+#define REG_CMBDISDMA_TIMER 0x140E >+ >+ >+ >+// Block IDLE Status Register >+#define REG_IDLE_STATUS 0x1410 >+#define IDLE_STATUS_RXMAC 1 // 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling >+#define IDLE_STATUS_TXMAC 2 // 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling >+#define IDLE_STATUS_DMAR 8 // 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling >+#define IDLE_STATUS_DMAW 4 // 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling >+ >+// MDIO Control Register >+#define REG_MDIO_CTRL 0x1414 >+#define MDIO_DATA_MASK 0xffff // On MDIO write, the 16-bit control data to write to PHY MII management register; >+#define MDIO_DATA_SHIFT 0 // On MDIO read, the 16-bit status data that was read from the PHY MII management register. >+#define MDIO_REG_ADDR_MASK 0x1f // MDIO register address >+#define MDIO_REG_ADDR_SHIFT 16 >+#define MDIO_RW 0x200000 // 1: read, 0: write >+#define MDIO_SUP_PREAMBLE 0x400000 // Suppress preamble >+#define MDIO_START 0x800000 // Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle. >+#define MDIO_CLK_SEL_SHIFT 24 >+#define MDIO_CLK_25_4 0 >+#define MDIO_CLK_25_6 2 >+#define MDIO_CLK_25_8 3 >+#define MDIO_CLK_25_10 4 >+#define MDIO_CLK_25_14 5 >+#define MDIO_CLK_25_20 6 >+#define MDIO_CLK_25_28 7 >+#define MDIO_BUSY 0x8000000 >+#define MDIO_WAIT_TIMES 10 >+ >+// SerDes Lock Detect Control and Status Register >+#define REG_SERDES_LOCK 0x1424 >+#define SERDES_LOCK_DETECT 1 // 1: SerDes lock detected . This signal comes from Analog SerDes. >+#define SERDES_LOCK_DETECT_EN 2 // 1: Enable SerDes Lock detect function. >+ >+// MAC Control Register >+#define REG_MAC_CTRL 0x1480 >+#define MAC_CTRL_TX_EN 1 // 1: Transmit Enable >+#define MAC_CTRL_RX_EN 2 // 1: Receive Enable >+#define MAC_CTRL_TX_FLOW 4 // 1: Transmit Flow Control Enable >+#define MAC_CTRL_RX_FLOW 8 // 1: Receive Flow Control Enable >+#define MAC_CTRL_LOOPBACK 0x10 // 1: Loop back at G/MII Interface >+#define MAC_CTRL_DUPLX 0x20 // 1: Full-duplex mode 0: Half-duplex mode >+#define MAC_CTRL_ADD_CRC 0x40 // 1: Instruct MAC to attach CRC on all egress Ethernet frames >+#define MAC_CTRL_PAD 0x80 // 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN >+#define MAC_CTRL_PRMLEN_SHIFT 10 // Preamble length, it?¡¥s 0x07 by standard >+#define MAC_CTRL_PRMLEN_MASK 0xf >+#define MAC_CTRL_RMV_VLAN 0x4000 // 1: to remove VLAN Tag automatically from all receive packets >+#define MAC_CTRL_PROMIS_EN 0x8000 // 1: Promiscuous Mode Enable >+#define MAC_CTRL_DBG_TX_BKPRESURE 0x100000 // 1: transmit maximum backoff (half-duplex test bit) >+#define MAC_CTRL_MC_ALL_EN 0x2000000 // 1: upload all multicast frame without error to system >+#define MAC_CTRL_BC_EN 0x4000000 // 1: upload all broadcast frame without error to system >+#define MAC_CTRL_MACLP_CLK_PHY 0x8000000 // 1: MAC-LoopBack clock from phy, 0:from sys_25M >+#define MAC_CTRL_HALF_LEFT_BUF_SHIFT 28 >+#define MAC_CTRL_HALF_LEFT_BUF_MASK 0xF // When half-duplex mode, should hold some bytes for mac retry . (8*4bytes unit) >+ >+// MAC IPG/IFG Control Register >+#define REG_MAC_IPG_IFG 0x1484 >+#define MAC_IPG_IFG_IPGT_SHIFT 0 // Desired back to back inter-packet gap. The default is 96-bit time. >+#define MAC_IPG_IFG_IPGT_MASK 0x7f >+#define MAC_IPG_IFG_MIFG_SHIFT 8 // Minimum number of IFG to enforce in between RX frames. >+#define MAC_IPG_IFG_MIFG_MASK 0xff // Frame gap below such IFP is dropped. >+#define MAC_IPG_IFG_IPGR1_SHIFT 16 // 64bit Carrier-Sense window >+#define MAC_IPG_IFG_IPGR1_MASK 0x7f // >+#define MAC_IPG_IFG_IPGR2_SHIFT 24 // 96-bit IPG window >+#define MAC_IPG_IFG_IPGR2_MASK 0x7f >+ >+// MAC STATION ADDRESS >+#define REG_MAC_STA_ADDR 0x1488 >+ >+// Hash table for multicast address >+#define REG_RX_HASH_TABLE 0x1490 >+ >+ >+// MAC Half-Duplex Control Register >+#define REG_MAC_HALF_DUPLX_CTRL 0x1498 >+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 // Collision Window. >+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff >+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 // Retransmission maximum, afterwards the packet will be discarded. >+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf >+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 // 1: Allow the transmission of a packet which has been excessively deferred >+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 // 1: No back-off on collision, immediately start the retransmission. >+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 // 1: No back-off on backpressure, immediately start the transmission after back pressure >+#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 // 1: Alternative Binary Exponential Back-off Enabled >+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 // Maximum binary exponential number. >+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf >+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 // IPG to start JAM for collision based flow control in half-duplex >+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf // mode. In unit of 8-bit time. >+ >+// Maximum Frame Length Control Register >+#define REG_MTU 0x149c >+ >+// Wake-On-Lan control register >+#define REG_WOL_CTRL 0x14a0 >+#define WOL_PATTERN_EN 0x00000001 >+#define WOL_PATTERN_PME_EN 0x00000002 >+#define WOL_MAGIC_EN 0x00000004 >+#define WOL_MAGIC_PME_EN 0x00000008 >+#define WOL_LINK_CHG_EN 0x00000010 >+#define WOL_LINK_CHG_PME_EN 0x00000020 >+#define WOL_PATTERN_ST 0x00000100 >+#define WOL_MAGIC_ST 0x00000200 >+#define WOL_LINKCHG_ST 0x00000400 >+#define WOL_PT0_EN 0x00010000 >+#define WOL_PT1_EN 0x00020000 >+#define WOL_PT2_EN 0x00040000 >+#define WOL_PT3_EN 0x00080000 >+#define WOL_PT4_EN 0x00100000 >+#define WOL_PT0_MATCH 0x01000000 >+#define WOL_PT1_MATCH 0x02000000 >+#define WOL_PT2_MATCH 0x04000000 >+#define WOL_PT3_MATCH 0x08000000 >+#define WOL_PT4_MATCH 0x10000000 >+ >+ >+ >+// Internal SRAM Partition Register >+#define REG_SRAM_TXRAM_END 0x1500 // Internal tail address of TXRAM default: 2byte*1024 >+#define REG_SRAM_RXRAM_END 0x1502 // Internal tail address of RXRAM default: 2byte*1024 >+ >+/* >+ >+#define REG_SRAM_TCPH_PATH_ADDR (REG_SRAM_RFD_ADDR+48) >+#define SRAM_TCPH_ADDR_MASK 0x0fff >+#define SRAM_TCPH_ADDR_SHIFT 0 >+#define SRAM_PATH_ADDR_MASK 0x0fff >+#define SRAM_PATH_ADDR_SHIFT 16 >+*/ >+ >+// Descriptor Control register >+#define REG_DESC_BASE_ADDR_HI 0x1540 >+#define REG_TXD_BASE_ADDR_LO 0x1544 // The base address of the Transmit Data Memory low 32-bit(dword align) >+#define REG_TXD_MEM_SIZE 0x1548 // Transmit Data Memory size(by double word , max 256KB) >+#define REG_TXS_BASE_ADDR_LO 0x154C // The base address of the Transmit Status Memory low 32-bit(dword word align) >+#define REG_TXS_MEM_SIZE 0x1550 // double word unit, max 4*2047 bytes. >+#define REG_RXD_BASE_ADDR_LO 0x1554 // The base address of the Transmit Status Memory low 32-bit(unit 8 bytes) >+#define REG_RXD_BUF_NUM 0x1558 // Receive Data & Status Memory buffer number (unit 1536bytes, >+ // max 1536*2047) >+// DMAR Control Register >+#define REG_DMAR 0x1580 >+#define DMAR_EN 0x1 // 1: Enable DMAR >+ >+ >+// TX Cur-Through (early tx threshold) Control Register >+#define REG_TX_CUT_THRESH 0x1590 // TxMac begin transmit packet threshold(unit word) >+ >+// DMAW Control Register >+#define REG_DMAW 0x15A0 >+#define DMAW_EN 0x1 >+ >+// Flow control register >+#define REG_PAUSE_ON_TH 0x15A8 // RXD high watermark of overflow threshold configuration register >+ // (unit buffer index number) >+#define REG_PAUSE_OFF_TH 0x15AA // RXD lower watermark of overflow threshold configuration register >+ // (unit buffer index number) >+ >+// Mailbox Register >+#define REG_MB_TXD_WR_IDX 0x15f0 // double word align >+#define REG_MB_RXD_RD_IDX 0x15F4 // RXD Read index (unit: 1536byets) >+ >+ >+// Interrupt Status Register >+#define REG_ISR 0x1600 >+#define ISR_TIMER 1 // Interrupt when Timer is counted down to zero >+#define ISR_MANUAL 2 // Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set in Table 51 Selene Master Control Register (Offset 0x1400). >+#define ISR_RXF_OV 4 // RXF overflow interrupt >+#define ISR_TXF_UR 8 // TXF underrun interrupt >+#define ISR_TXS_OV 0x10 // Internal transmit status buffer full interrupt >+#define ISR_RXS_OV 0x20 // Internal receive status buffer ful interrupt >+#define ISR_LINK_CHG 0x40 // Link Status Change Interrupt >+#define ISR_HOST_TXD_UR 0x80 >+#define ISR_HOST_RXD_OV 0x100 // Host rx data memory full , one pulse >+//#define ISR_HOST_TXS_OV 0x200 // Host tx status memory full , one pulse >+#define ISR_DMAR_TO_RST 0x200 // DMAR op timeout interrupt. SW should do Reset >+#define ISR_DMAW_TO_RST 0x400 >+#define ISR_PHY 0x800 // phy interrupt >+#define ISR_TS_UPDATE 0x10000 // interrupt after new tx pkt status written to host >+#define ISR_RS_UPDATE 0x20000 // interrupt ater new rx pkt status written to host. >+#define ISR_TX_EARLY 0x40000 // interrupt when txmac begin transmit one packet >+#define ISR_UR_DETECTED 0x1000000 >+#define ISR_FERR_DETECTED 0x2000000 >+#define ISR_NFERR_DETECTED 0x4000000 >+#define ISR_CERR_DETECTED 0x8000000 >+#define ISR_PHY_LINKDOWN 0x10000000 >+#define ISR_DIS_INT 0x80000000 >+ >+#define ISR_TX_EVENT (ISR_TXF_UR|ISR_TXS_OV|ISR_HOST_TXD_UR|ISR_TS_UPDATE|ISR_TX_EARLY) >+#define ISR_RX_EVENT (ISR_RXF_OV|ISR_RXS_OV|ISR_HOST_RXD_OV|ISR_RS_UPDATE) >+ >+// Interrupt Mask Register >+#define REG_IMR 0x1604 >+ >+#define IMR_NORMAL_MASK (\ >+ /*ISR_LINK_CHG |*/\ >+ ISR_DMAR_TO_RST |\ >+ ISR_DMAW_TO_RST |\ >+ ISR_PHY |\ >+ ISR_PHY_LINKDOWN |\ >+ ISR_TS_UPDATE |\ >+ ISR_RS_UPDATE ) >+ >+ >+ >+// Receive MAC Statistics Registers >+#define REG_STS_RX_PAUSE 0x1700 // The number of Pause packet received >+#define REG_STS_RXD_OV 0x1704 // The number of frame dropped due to occurrence of RX FIFO overflow >+#define REG_STS_RXS_OV 0x1708 // The number of frame dropped due to occerrence of RX Status Buffer Overflow >+#define REG_STS_RX_FILTER 0x170C // The number of packet dropped due to address filtering >+ >+ >+/***************************** MII definition ***************************************/ >+/* PHY Common Register */ >+#define MII_BMCR 0x00 >+#define MII_BMSR 0x01 >+#define MII_PHYSID1 0x02 >+#define MII_PHYSID2 0x03 >+#define MII_ADVERTISE 0x04 >+#define MII_LPA 0x05 >+#define MII_EXPANSION 0x06 >+#define MII_AT001_CR 0x09 >+#define MII_AT001_SR 0x0A >+#define MII_AT001_ESR 0x0F >+#define MII_AT001_PSCR 0x10 >+#define MII_AT001_PSSR 0x11 >+#define MII_DCOUNTER 0x12 >+#define MII_FCSCOUNTER 0x13 >+#define MII_SMARTSPEED 0x14 >+#define MII_RERRCOUNTER 0x15 >+#define MII_SREVISION 0x16 >+#define MII_RESV1 0x17 >+#define MII_LBRERROR 0x18 >+#define MII_PHYADDR 0x19 >+#define MII_RESV2 0x1a >+#define MII_TPISTATUS 0x1b >+#define MII_NCONFIG 0x1c >+ >+ >+/* PHY Control Register */ >+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ >+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ >+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ >+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ >+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ >+#define MII_CR_POWER_DOWN 0x0800 /* Power down */ >+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ >+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ >+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ >+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ >+#define MII_CR_SPEED_MASK 0x2040 >+#define MII_CR_SPEED_1000 0x0040 >+#define MII_CR_SPEED_100 0x2000 >+#define MII_CR_SPEED_10 0x0000 >+ >+ >+/* PHY Status Register */ >+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ >+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ >+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ >+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ >+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ >+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ >+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ >+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ >+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ >+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ >+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ >+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ >+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ >+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ >+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ >+ >+/* Link partner ability register. */ >+#define MII_LPA_SLCT 0x001f /* Same as advertise selector */ >+#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ >+#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */ >+#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */ >+#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ >+#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */ >+#define MII_LPA_PAUSE 0x0400 /* PAUSE */ >+#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */ >+#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */ >+#define MII_LPA_LPACK 0x4000 /* Link partner acked us */ >+#define MII_LPA_NPAGE 0x8000 /* Next page bit */ >+ >+/* Autoneg Advertisement Register */ >+#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ >+#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ >+#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ >+#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ >+#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ >+#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ >+#define MII_AR_PAUSE 0x0400 /* Pause operation desired */ >+#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ >+#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ >+#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ >+#define MII_AR_SPEED_MASK 0x01E0 >+#define MII_AR_DEFAULT_CAP_MASK 0x0DE0 >+ >+/* 1000BASE-T Control Register */ >+#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ >+#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ >+#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ >+ /* 0=DTE device */ >+#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ >+ /* 0=Configure PHY as Slave */ >+#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ >+ /* 0=Automatic Master/Slave config */ >+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ >+#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ >+#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ >+#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ >+#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ >+#define MII_AT001_CR_1000T_SPEED_MASK 0x0300 >+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300 >+ >+/* 1000BASE-T Status Register */ >+#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ >+#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ >+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ >+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ >+#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ >+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ >+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12 >+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13 >+ >+/* Extended Status Register */ >+#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ >+#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ >+#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ >+#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ >+ >+/* AT001 PHY Specific Control Register */ >+#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ >+#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ >+#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled *// >+#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008 >+#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, >+ * 0=CLK125 toggling >+ */ >+#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ >+ /* Manual MDI configuration */ >+#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ >+#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, >+ * 100BASE-TX/10BASE-T: >+ * MDI Mode >+ */ >+#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled >+ * all speeds. >+ */ >+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080 >+ /* 1=Enable Extended 10BASE-T distance >+ * (Lower 10BASE-T RX Threshold) >+ * 0=Normal 10BASE-T RX Threshold */ >+#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100 >+ /* 1=5-Bit interface in 100BASE-TX >+ * 0=MII interface in 100BASE-TX */ >+#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ >+#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ >+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ >+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1 >+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5 >+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 >+ >+ >+/* AT001 PHY Specific Status Register */ >+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ >+#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ >+#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ >+#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */ >+#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */ >+#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ >+ >+/*********************PCI Command Register ******************************/ >+// PCI Command Register Bit Definitions >+#define PCI_REG_COMMAND 0x04 // PCI Command Register >+#define CMD_IO_SPACE 0x0001 >+#define CMD_MEMORY_SPACE 0x0002 >+#define CMD_BUS_MASTER 0x0004 >+ >+/* Wake Up Filter Control */ >+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ >+#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ >+#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ >+#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ >+#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ >+ >+/************************************************************************************************************************/ >+ >+/* Error Codes */ >+ >+#define AT_SUCCESS 0 >+#define AT_ERR_EEPROM 1 >+#define AT_ERR_PHY 2 >+#define AT_ERR_CONFIG 3 >+#define AT_ERR_PARAM 4 >+#define AT_ERR_MAC_TYPE 5 >+#define AT_ERR_PHY_TYPE 6 >+#define AT_ERR_PHY_SPEED 7 >+#define AT_ERR_PHY_RES 8 >+ >+#define SPEED_0 0xffff >+#define SPEED_10 10 >+#define SPEED_100 100 >+#define HALF_DUPLEX 1 >+#define FULL_DUPLEX 2 >+ >+#define MEDIA_TYPE_AUTO_SENSOR 0 >+#define MEDIA_TYPE_100M_FULL 1 >+#define MEDIA_TYPE_100M_HALF 2 >+#define MEDIA_TYPE_10M_FULL 3 >+#define MEDIA_TYPE_10M_HALF 4 >+ >+#define ADVERTISE_10_HALF 0x0001 >+#define ADVERTISE_10_FULL 0x0002 >+#define ADVERTISE_100_HALF 0x0004 >+#define ADVERTISE_100_FULL 0x0008 >+#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ >+#define ADVERTISE_1000_FULL 0x0020 >+ >+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */ >+#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ >+#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ >+ >+ >+/* The size (in bytes) of a ethernet packet */ >+#define ENET_HEADER_SIZE 14 >+#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */ >+#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */ >+#define ETHERNET_FCS_SIZE 4 >+#define MAX_JUMBO_FRAME_SIZE 0x2000 >+#define VLAN_SIZE 4 >+ >+#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ >+#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ >+ >+/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */ >+#define EEPROM_SUM 0xBABA >+#define NODE_ADDRESS_SIZE 6 >+ >+ >+typedef struct _tx_pkt_header { >+ unsigned pkt_size : 11; >+ unsigned : 4; // reserved >+ unsigned ins_vlan : 1; // txmac should insert vlan >+ unsigned short vlan ; // vlan tag >+} _AT_ATTRIB_PACK_ tx_pkt_header_t; >+ >+typedef struct _tx_pkt_status { >+ unsigned pkt_size : 11; >+ unsigned : 5; // reserved >+ unsigned ok : 1; // current packet is transmitted ok without error >+ unsigned bcast : 1; // current packet is broadcast >+ unsigned mcast : 1; // current packet is multicast >+ unsigned pause : 1; // transmiited a pause frame >+ unsigned ctrl : 1; >+ unsigned defer : 1; // current packet is xmitted with defer. >+ unsigned exc_defer : 1; >+ unsigned single_col : 1; >+ unsigned multi_col : 1; >+ unsigned late_col : 1; >+ unsigned abort_col : 1; >+ unsigned underun : 1; // current packet is abort due to txram underrun. >+ unsigned : 3; // reserved >+ unsigned update : 1; // always 1'b1 in tx_status_buf. >+} _AT_ATTRIB_PACK_ tx_pkt_status_t; >+ >+typedef struct _rx_pkt_status { >+ unsigned pkt_size : 11; // packet size, max 2047bytes >+ unsigned : 5; // reserved >+ unsigned ok : 1; // current packet is received ok without error. >+ unsigned bcast : 1; // current packet is broadcast. >+ unsigned mcast : 1; // current packet is multicast. >+ unsigned pause : 1; >+ unsigned ctrl : 1; >+ unsigned crc : 1; // received a packet with crc error. >+ unsigned code : 1; // received a packet with code error. >+ unsigned runt : 1; // received a packet less than 64bytes with good crc >+ unsigned frag : 1; // ....................................with bad crc >+ unsigned trunc : 1; // current frame is cutted due to rxram full. >+ unsigned align : 1; // this packet is alignment error. >+ unsigned vlan : 1; // this packet has vlan >+ unsigned : 3; // reserved >+ unsigned update : 1; >+ unsigned short vtag ; // vlan tag >+ unsigned : 16; >+} _AT_ATTRIB_PACK_ rx_pkt_status_t; >+ >+typedef struct _rx_desc { >+ rx_pkt_status_t status; >+ unsigned char packet[1536-sizeof(rx_pkt_status_t)]; >+} _AT_ATTRIB_PACK_ rx_desc_t; >+ >+typedef enum { >+ at_10_half = 0, >+ at_10_full = 1, >+ at_100_half = 2, >+ at_100_full = 3 >+} at_speed_duplex_type; >+ >+ >+ >+typedef struct _spi_flash_dev { >+ const char* manu_name; // manufacturer id >+ // op-code >+ u8 cmdWRSR; >+ u8 cmdREAD; >+ u8 cmdPROGRAM; >+ u8 cmdWREN; >+ u8 cmdWRDI; >+ u8 cmdRDSR; >+ u8 cmdRDID; >+ u8 cmdSECTOR_ERASE; >+ u8 cmdCHIP_ERASE; >+} spi_flash_dev; >+ >+ >+/* Structure containing variables used by the shared code (at_hw.c) */ >+struct at_hw { >+ u8 *hw_addr; // >+ void *back; // >+ >+ >+ u8 preamble_len; >+ u8 max_retry; // Retransmission maximum , afterwards the packet will be discarded. >+ u8 jam_ipg; // IPG to start JAM for collision based flow control in half-duplex mode. In unit of 8-bit time. >+ u8 ipgt; // Desired back to back inter-packet gap. The default is 96-bit time. >+ u8 min_ifg; // Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped. >+ u8 ipgr1; // 64bit Carrier-Sense window >+ u8 ipgr2; // 96-bit IPG window >+ u8 retry_buf; // When half-duplex mode, should hold some bytes for mac retry . (8*4bytes unit) >+ >+ u16 fc_rxd_hi; >+ u16 fc_rxd_lo; >+ u16 lcol; // Collision Window >+ u16 max_frame_size; >+ >+ u16 MediaType; >+ u16 autoneg_advertised; >+ u16 pci_cmd_word; >+ >+ u16 mii_autoneg_adv_reg; >+ >+ u32 mem_rang; >+ u32 txcw; >+ u32 mc_filter_type; >+ u32 num_mc_addrs; >+ u32 collision_delta; >+ u32 tx_packet_delta; >+ u16 phy_spd_default; >+ >+ u16 device_id; // >+ u16 vendor_id; // >+ u16 subsystem_id; // >+ u16 subsystem_vendor_id;// >+ u8 revision_id; // >+ >+ >+ // spi flash >+ u8 flash_vendor; >+ >+ u8 dma_fairness; >+ u8 mac_addr[NODE_ADDRESS_SIZE];// >+ u8 perm_mac_addr[NODE_ADDRESS_SIZE];// >+ >+// boolean_t phy_preamble_sup; >+ boolean_t phy_configured; >+ >+}; >+ >+#endif//_ATTANSIC_HW_H__ >diff -ruN -a -p old/drivers/net/atl2/at_main.c new/drivers/net/atl2/at_main.c >--- old/drivers/net/atl2/at_main.c 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at_main.c 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,2393 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+ >+#include "at.h" >+ >+ >+char at_driver_name[] = "ATL2"; >+char at_driver_string[] = "Attansic(R) L2 Ethernet Network Driver"; >+#define DRV_VERSION "1.0.40.2" >+char at_driver_version[] = DRV_VERSION; >+char at_copyright[] = "Copyright (c) 2006 Attansic Corporation."; >+ >+ >+/* >+ * at_pci_tbl - PCI Device ID Table >+ * >+ * Wildcard entries (PCI_ANY_ID) should come last >+ * Last entry must be all 0s >+ * >+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, >+ * Class, Class Mask, private data (not used) } >+ */ >+static struct pci_device_id at_pci_tbl[] = { >+ ATTANSIC_ETHERNET_DEVICE(0x2048), >+ /* required last entry */ >+ {0,} >+}; >+ >+MODULE_DEVICE_TABLE(pci, at_pci_tbl); >+ >+int at_up(struct at_adapter *adapter); >+void at_down(struct at_adapter *adapter); >+int at_reset(struct at_adapter *adapter); >+int32_t at_setup_ring_resources(struct at_adapter *adapter); >+void at_free_ring_resources(struct at_adapter *adapter); >+void at_reinit_locked(struct at_adapter *adapter); >+ >+/* Local Function Prototypes */ >+static int at_init_module(void); >+static void at_exit_module(void); >+static int at_probe(struct pci_dev *pdev, const struct pci_device_id *ent); >+static void __devexit at_remove(struct pci_dev *pdev); >+static int at_sw_init(struct at_adapter *adapter); >+static int at_open(struct net_device *netdev); >+static int at_close(struct net_device *netdev); >+static int at_xmit_frame(struct sk_buff *skb, struct net_device *netdev); >+static struct net_device_stats * at_get_stats(struct net_device *netdev); >+static int at_change_mtu(struct net_device *netdev, int new_mtu); >+static void at_set_multi(struct net_device *netdev); >+static int at_set_mac(struct net_device *netdev, void *p); >+static int at_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); >+static void at_tx_timeout(struct net_device *dev); >+static irqreturn_t at_intr(int irq, void *data); >+static void at_intr_rx(struct at_adapter* adapter); >+static void at_intr_tx(struct at_adapter* adapter); >+void at_power_up_phy(struct at_adapter *adapter); >+static void at_power_down_phy(struct at_adapter *adapter); >+static void at_watchdog(unsigned long data); >+static void at_phy_config(unsigned long data); >+static void at_reset_task(struct work_struct *work); >+static void at_link_chg_task(struct work_struct *work); >+static void at_check_for_link(struct at_adapter* adapter); >+void at_set_ethtool_ops(struct net_device *netdev); >+static int at_check_link(struct at_adapter* adapter); >+void init_ring_ptrs(struct at_adapter *adapter); >+static int at_configure(struct at_adapter *adapter); >+ >+#define COPYBREAK_DEFAULT 256 >+static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; >+module_param(copybreak, uint, 0644); >+MODULE_PARM_DESC(copybreak, >+ "Maximum size of packet that is copied to a new buffer on receive"); >+ >+ >+#ifdef SIOCGMIIPHY >+static int at_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); >+#endif >+ >+ >+#ifdef NETIF_F_HW_VLAN_TX >+static void at_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); >+static void at_vlan_rx_add_vid(struct net_device *netdev, u16 vid); >+static void at_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); >+static void at_restore_vlan(struct at_adapter *adapter); >+#endif >+ >+static int at_suspend(struct pci_dev *pdev, pm_message_t state); >+#ifdef CONFIG_PM >+static int at_resume(struct pci_dev *pdev); >+#endif >+ >+#ifndef USE_REBOOT_NOTIFIER >+static void at_shutdown(struct pci_dev *pdev); >+#else >+static int at_notify_reboot(struct notifier_block *nb, unsigned long event, void *p); >+ >+struct notifier_block at_notifier_reboot = { >+ .notifier_call = at_notify_reboot, >+ .next = NULL, >+ .priority = 0 >+}; >+#endif >+ >+/* Exported from other modules */ >+ >+extern void at_check_options(struct at_adapter *adapter); >+//extern int at_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr); >+#ifdef SIOCDEVPRIVATE >+extern int at_priv_ioctl(struct net_device* netdev, struct ifreq* ifr); >+#endif >+ >+#ifdef CONFIG_AT_PCI_ERS >+static pci_ers_result_t at_io_error_detected(struct pci_dev *pdev, >+ pci_channel_state_t state); >+static pci_ers_result_t at_io_slot_reset(struct pci_dev *pdev); >+static void at_io_resume(struct pci_dev *pdev); >+ >+static struct pci_error_handlers at_err_handler = { >+ .error_detected = at_io_error_detected, >+ .slot_reset = at_io_slot_reset, >+ .resume = at_io_resume, >+}; >+#endif >+ >+static struct pci_driver at_driver = { >+ .name = at_driver_name, >+ .id_table = at_pci_tbl, >+ .probe = at_probe, >+ .remove = __devexit_p(at_remove), >+ /* Power Managment Hooks */ >+#ifdef CONFIG_PM >+ .suspend = at_suspend, >+ .resume = at_resume, >+#endif >+#ifndef USE_REBOOT_NOTIFIER >+ .shutdown = at_shutdown, >+#endif >+#ifdef CONFIG_AT_PCI_ERS >+ .err_handler = &at_err_handler >+#endif >+ >+}; >+ >+MODULE_AUTHOR("Attansic Corporation, <xiong_huang@attansic.com>"); >+MODULE_DESCRIPTION("Attansic 100M Ethernet Network Driver"); >+MODULE_LICENSE("GPL"); >+MODULE_VERSION(DRV_VERSION); >+ >+/** >+ * at_init_module - Driver Registration Routine >+ * >+ * at_init_module is the first routine called when the driver is >+ * loaded. All it does is register with the PCI subsystem. >+ **/ >+ >+static int __init >+at_init_module(void) >+{ >+ int ret; >+ printk(KERN_INFO "%s - version %s\n", >+ at_driver_string, at_driver_version); >+ >+ printk(KERN_INFO "%s\n", at_copyright); >+ >+ ret = pci_register_driver(&at_driver); >+#ifdef USE_REBOOT_NOTIFIER >+ if (ret >= 0) { >+ register_reboot_notifier(&at_notifier_reboot); >+ } >+#endif >+ if (copybreak != COPYBREAK_DEFAULT) { >+ if (copybreak == 0) >+ printk(KERN_INFO "ATL2: copybreak disabled\n"); >+ else >+ printk(KERN_INFO "ATL2: copybreak enabled for " >+ "packets <= %u bytes\n", copybreak); >+ } >+ return ret; >+} >+ >+module_init(at_init_module); >+ >+/** >+ * at_exit_module - Driver Exit Cleanup Routine >+ * >+ * at_exit_module is called just before the driver is removed >+ * from memory. >+ **/ >+ >+static void __exit >+at_exit_module(void) >+{ >+#ifdef USE_REBOOT_NOTIFIER >+ unregister_reboot_notifier(&at_notifier_reboot); >+#endif >+ pci_unregister_driver(&at_driver); >+ >+} >+ >+module_exit(at_exit_module); >+ >+ >+ >+static int at_request_irq(struct at_adapter *adapter) >+{ >+ struct net_device *netdev = adapter->netdev; >+ int flags, err = 0; >+ >+ flags = IRQF_SHARED; >+ if ((err = request_irq(adapter->pdev->irq, &at_intr, flags, >+ netdev->name, netdev))) { >+ AT_DBG("Unable to allocate interrupt Error: %d\n", err); >+ } >+ >+ return err; >+} >+ >+ >+static void at_setup_pcicmd(struct pci_dev* pdev) >+{ >+ u16 cmd; >+ >+ pci_read_config_word(pdev, PCI_COMMAND, &cmd); >+ >+ if (cmd & PCI_COMMAND_INTX_DISABLE) >+ cmd &= ~PCI_COMMAND_INTX_DISABLE; >+ if (cmd & PCI_COMMAND_IO) >+ cmd &= ~PCI_COMMAND_IO; >+ if (0 == (cmd & PCI_COMMAND_MEMORY)) >+ cmd |= PCI_COMMAND_MEMORY; >+ if (0 == (cmd & PCI_COMMAND_MASTER)) >+ cmd |= PCI_COMMAND_MASTER; >+ pci_write_config_word(pdev, PCI_COMMAND, cmd); >+ >+ /* >+ * some motherboards BIOS(PXE/EFI) driver may set PME >+ * while they transfer control to OS (Windows/Linux) >+ * so we should clear this bit before NIC work normally >+ */ >+ pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0); >+} >+ >+ >+ >+ >+/** >+ * at_probe - Device Initialization Routine >+ * @pdev: PCI device information struct >+ * @ent: entry in at_pci_tbl >+ * >+ * Returns 0 on success, negative on failure >+ * >+ * at_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 >+at_probe(struct pci_dev *pdev, >+ const struct pci_device_id *ent) >+{ >+ struct net_device *netdev; >+ struct at_adapter *adapter; >+ static int cards_found = 0; >+ unsigned long mmio_start; >+ int mmio_len; >+ boolean_t pci_using_64 = TRUE; >+ int err; >+ >+ DEBUGFUNC("at_probe !"); >+ >+ if((err = pci_enable_device(pdev))) >+ return err; >+ >+ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) && >+ !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { >+ pci_using_64 = TRUE; >+ } else { >+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) && >+ (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) { >+ AT_ERR("No usable DMA configuration, aborting\n"); >+ goto err_dma; >+ } >+ pci_using_64 = FALSE; >+ } >+ >+ >+ // Mark all PCI regions associated with PCI device >+ // pdev as being reserved by owner at_driver_name >+ if((err = pci_request_regions(pdev, at_driver_name))) >+ goto err_pci_reg; >+ >+ // Enables bus-mastering on the device and calls >+ // pcibios_set_master to do the needed arch specific settings >+ pci_set_master(pdev); >+ >+ err = -ENOMEM; >+ netdev = alloc_etherdev(sizeof(struct at_adapter)); >+ if(!netdev) >+ goto err_alloc_etherdev; >+ >+ SET_MODULE_OWNER(netdev); >+ 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; >+ >+ mmio_start = pci_resource_start(pdev, BAR_0); >+ mmio_len = pci_resource_len(pdev, BAR_0); >+ >+ AT_DBG("base memory = %lx memory length = %x \n", >+ mmio_start, mmio_len); >+ adapter->hw.mem_rang = (u32)mmio_len; >+ adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); >+ if(!adapter->hw.hw_addr) { >+ err = -EIO; >+ goto err_ioremap; >+ } >+ >+ at_setup_pcicmd(pdev); >+ >+ netdev->open = &at_open; >+ netdev->stop = &at_close; >+ netdev->hard_start_xmit = &at_xmit_frame; >+ netdev->get_stats = &at_get_stats; >+ netdev->set_multicast_list = &at_set_multi; >+ netdev->set_mac_address = &at_set_mac; >+ netdev->change_mtu = &at_change_mtu; >+ netdev->do_ioctl = &at_ioctl; >+ at_set_ethtool_ops(netdev); >+ >+#ifdef HAVE_TX_TIMEOUT >+ netdev->tx_timeout = &at_tx_timeout; >+ netdev->watchdog_timeo = 5 * HZ; >+#endif >+#ifdef NETIF_F_HW_VLAN_TX >+ netdev->vlan_rx_register = at_vlan_rx_register; >+ netdev->vlan_rx_add_vid = at_vlan_rx_add_vid; >+ netdev->vlan_rx_kill_vid = at_vlan_rx_kill_vid; >+#endif >+ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); >+ >+ >+ >+ netdev->mem_start = mmio_start; >+ netdev->mem_end = mmio_start + mmio_len; >+ //netdev->base_addr = adapter->io_base; >+ adapter->bd_number = cards_found; >+ adapter->pci_using_64 = pci_using_64; >+ >+ /* setup the private structure */ >+ >+ if((err = at_sw_init(adapter))) >+ goto err_sw_init; >+ >+ err = -EIO; >+ >+#ifdef NETIF_F_HW_VLAN_TX >+ netdev->features |= >+ (NETIF_F_HW_VLAN_TX | >+ NETIF_F_HW_VLAN_RX ); >+#endif >+ >+ if(pci_using_64) { >+ netdev->features |= NETIF_F_HIGHDMA; >+ AT_DBG("pci using 64bit address\n"); >+ } >+#ifdef NETIF_F_LLTX >+ netdev->features |= NETIF_F_LLTX; >+#endif >+ >+ >+ /* reset the controller to >+ * put the device in a known good starting state */ >+ >+ if (at_reset_hw(&adapter->hw)) { >+ err = -EIO; >+ goto err_reset; >+ } >+ >+ /* copy the MAC address out of the EEPROM */ >+ >+ at_read_mac_addr(&adapter->hw); >+ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); >+#ifdef ETHTOOL_GPERMADDR >+ memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); >+ >+ if (!is_valid_ether_addr(netdev->perm_addr)) { >+#else >+ if (!is_valid_ether_addr(netdev->dev_addr)) { >+#endif >+ AT_DBG("Invalid MAC Address\n"); >+ err = -EIO; >+ goto err_eeprom; >+ } >+ AT_DBG("mac address : %02x-%02x-%02x-%02x-%02x-%02x\n", >+ adapter->hw.mac_addr[0], >+ adapter->hw.mac_addr[1], >+ adapter->hw.mac_addr[2], >+ adapter->hw.mac_addr[3], >+ adapter->hw.mac_addr[4], >+ adapter->hw.mac_addr[5] ); >+ >+ at_check_options(adapter); >+ >+ /* pre-init the MAC, and setup link */ >+ >+// if ((err = at_init_hw(&adapter->hw))) { >+// err = -EIO; >+// goto err_init_hw; >+// } >+ >+ init_timer(&adapter->watchdog_timer); >+ adapter->watchdog_timer.function = &at_watchdog; >+ adapter->watchdog_timer.data = (unsigned long) adapter; >+ >+ init_timer(&adapter->phy_config_timer); >+ adapter->phy_config_timer.function = &at_phy_config; >+ adapter->phy_config_timer.data = (unsigned long) adapter; >+ adapter->phy_timer_pending = FALSE; >+ >+ INIT_WORK(&adapter->reset_task, at_reset_task); >+ INIT_WORK(&adapter->link_chg_task, at_link_chg_task); >+ >+ >+ strcpy(netdev->name, "eth%d"); // ?? >+ if((err = register_netdev(netdev))) >+ goto err_register; >+ >+ /* assume we have no link for now */ >+ netif_carrier_off(netdev); >+ netif_stop_queue(netdev); >+ >+ >+ cards_found++; >+ >+ return 0; >+ >+//err_init_hw: >+err_reset: >+err_register: >+err_sw_init: >+err_eeprom: >+ iounmap(adapter->hw.hw_addr); >+err_ioremap: >+ free_netdev(netdev); >+err_alloc_etherdev: >+ pci_release_regions(pdev); >+err_pci_reg: >+err_dma: >+ pci_disable_device(pdev); >+ return err; >+} >+ >+/** >+ * at_remove - Device Removal Routine >+ * @pdev: PCI device information struct >+ * >+ * at_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 >+at_remove(struct pci_dev *pdev) >+{ >+ struct net_device *netdev = pci_get_drvdata(pdev); >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+ DEBUGFUNC("at_remove"); >+ >+ >+ /* flush_scheduled work may reschedule our watchdog task, so >+ * explicitly disable watchdog tasks from being rescheduled */ >+ set_bit(__AT_DOWN, &adapter->flags); >+ >+ del_timer_sync(&adapter->watchdog_timer); >+ del_timer_sync(&adapter->phy_config_timer); >+ >+ flush_scheduled_work(); >+ >+ unregister_netdev(netdev); >+ >+ iounmap(adapter->hw.hw_addr); >+ pci_release_regions(pdev); >+ >+ free_netdev(netdev); >+ >+ pci_disable_device(pdev); >+} >+ >+#ifdef USE_REBOOT_NOTIFIER >+/* only want to do this for 2.4 kernels? */ >+static int >+at_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) >+{ >+ struct pci_dev *pdev = NULL; >+ >+ DEBUGFUNC("at_notify_reboot !"); >+ >+ switch(event) { >+ case SYS_DOWN: >+ case SYS_HALT: >+ case SYS_POWER_OFF: >+ while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { >+ if(pci_dev_driver(pdev) == &at_driver) >+ at_suspend(pdev, PMSG_SUSPEND); >+ } >+ } >+ return NOTIFY_DONE; >+ >+} >+#endif >+ >+#ifndef USE_REBOOT_NOTIFIER >+static void at_shutdown(struct pci_dev *pdev) >+{ >+ at_suspend(pdev, PMSG_SUSPEND); >+} >+#endif >+ >+ >+static int >+at_suspend(struct pci_dev *pdev, pm_message_t state) >+{ >+ struct net_device *netdev = pci_get_drvdata(pdev); >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw * hw = &adapter->hw; >+ u16 speed, duplex; >+ u32 ctrl = 0; >+ u32 wufc = adapter->wol; >+ >+#ifdef CONFIG_PM >+ int retval = 0; >+#endif >+ >+ DEBUGFUNC("at_suspend !"); >+ >+ >+ netif_device_detach(netdev); >+ >+ if (netif_running(netdev)) { >+ WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); >+ at_down(adapter); >+ } >+ >+#ifdef CONFIG_PM >+ retval = pci_save_state(pdev); >+ if (retval) >+ return retval; >+#endif >+ >+ >+ at_read_phy_reg(hw, MII_BMSR, (u16*)&ctrl); >+ at_read_phy_reg(hw, MII_BMSR, (u16*)&ctrl); >+ if(ctrl & BMSR_LSTATUS) >+ wufc &= ~AT_WUFC_LNKC; >+ >+ if (0 != (ctrl&BMSR_LSTATUS) && 0 != wufc) { >+ u32 ret_val; >+ /* get current link speed & duplex */ >+ ret_val = at_get_speed_and_duplex(hw, &speed, &duplex); >+ if (ret_val) { >+ printk(KERN_DEBUG "%s: get speed&duplex error while suspend\n", >+ at_driver_name); >+ goto wol_dis; >+ } >+ >+ /* if resume, let driver to re- setup link */ >+ hw->phy_configured = FALSE; >+ >+ ctrl = 0; >+ >+ /* turn on magic packet wol */ >+ if (wufc & AT_WUFC_MAG) >+ ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); >+ >+ /* ignore Link Chg event when Link is up */ >+ AT_WRITE_REG(hw, REG_WOL_CTRL, ctrl); >+ >+ AT_DBG("%s: suspend WOL=0x%x\n", at_driver_name, ctrl); >+ >+ >+ >+ /* Config MAC CTRL Register */ >+ ctrl = MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY; >+ if (FULL_DUPLEX == adapter->link_duplex) >+ ctrl |= MAC_CTRL_DUPLX; >+ ctrl |= (MAC_CTRL_ADD_CRC|MAC_CTRL_PAD); >+ ctrl |= (((u32)adapter->hw.preamble_len >+ &MAC_CTRL_PRMLEN_MASK)<< MAC_CTRL_PRMLEN_SHIFT); >+ ctrl |= (((u32)(adapter->hw.retry_buf >+ &MAC_CTRL_HALF_LEFT_BUF_MASK)) >+ << MAC_CTRL_HALF_LEFT_BUF_SHIFT); >+ if (wufc & AT_WUFC_MAG) { >+ /* magic packet maybe Broadcast&multicast&Unicast frame */ >+ ctrl |= MAC_CTRL_BC_EN; >+ } >+ AT_DBG("%s: suspend MAC=0x%x\n", at_driver_name, ctrl); >+ >+ AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl); >+ >+ /* pcie patch */ >+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); >+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; >+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); >+ >+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); >+ goto suspend_exit; >+ } >+ >+ if (0 == (ctrl&BMSR_LSTATUS) && 0 != (wufc&AT_WUFC_LNKC)) { >+ /* link is down, so only LINK CHG WOL event enable */ >+ ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); >+ AT_WRITE_REG(hw, REG_WOL_CTRL, ctrl); >+ AT_WRITE_REG(hw, REG_MAC_CTRL, 0); >+ >+ /* pcie patch */ >+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); >+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; >+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); >+ >+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); >+ >+ goto suspend_exit; >+ } >+ >+wol_dis: >+ >+ /* WOL disabled */ >+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); >+ >+ /* pcie patch */ >+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); >+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; >+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); >+ >+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); >+ >+suspend_exit: >+ >+ if (netif_running(netdev)) >+ free_irq(adapter->pdev->irq, netdev); >+ >+ pci_disable_device(pdev); >+ >+ pci_set_power_state(pdev, pci_choose_state(pdev, state)); >+ >+ return 0; >+} >+ >+ >+#ifdef CONFIG_PM >+static int >+at_resume(struct pci_dev *pdev) >+{ >+ struct net_device *netdev = pci_get_drvdata(pdev); >+ struct at_adapter *adapter = netdev_priv(netdev); >+ u32 err; >+ >+ DEBUGFUNC("at_resume !"); >+ >+ pci_set_power_state(pdev, PCI_D0); >+ pci_restore_state(pdev); >+ >+ if ((err = pci_enable_device(pdev))) { >+ printk(KERN_ERR "atl2: Cannot enable PCI device from suspend\n"); >+ return err; >+ } >+ >+ pci_set_master(pdev); >+ >+ pci_enable_wake(pdev, PCI_D3hot, 0); >+ pci_enable_wake(pdev, PCI_D3cold, 0); >+ >+ AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); >+ >+ if (netif_running(netdev) && (err = at_request_irq(adapter))) >+ return err; >+ >+ at_power_up_phy(adapter); >+ at_reset_hw(&adapter->hw); >+ >+ if(netif_running(netdev)) >+ at_up(adapter); >+ >+ netif_device_attach(netdev); >+ >+ return 0; >+} >+#endif >+ >+ >+#ifdef CONFIG_AT_PCI_ERS >+/** >+ * at_io_error_detected - called when PCI error is detected >+ * @pdev: Pointer to PCI device >+ * @state: The current pci connection state >+ * >+ * This function is called after a PCI bus error affecting >+ * this device has been detected. >+ */ >+static pci_ers_result_t at_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) >+{ >+ struct net_device *netdev = pci_get_drvdata(pdev); >+ struct at_adapter *adapter = netdev->priv; >+ >+ netif_device_detach(netdev); >+ >+ if (netif_running(netdev)) >+ at_down(adapter); >+ >+ pci_disable_device(pdev); >+ >+ /* Request a slot slot reset. */ >+ return PCI_ERS_RESULT_NEED_RESET; >+} >+ >+/** >+ * at_io_slot_reset - called after the pci bus has been reset. >+ * @pdev: Pointer to PCI device >+ * >+ * Restart the card from scratch, as if from a cold-boot. Implementation >+ * resembles the first-half of the e1000_resume routine. >+ */ >+static pci_ers_result_t at_io_slot_reset(struct pci_dev *pdev) >+{ >+ struct net_device *netdev = pci_get_drvdata(pdev); >+ struct at_adapter *adapter = netdev->priv; >+ >+ if (pci_enable_device(pdev)) { >+ printk(KERN_ERR "ATL2: Cannot re-enable PCI device after reset.\n"); >+ return PCI_ERS_RESULT_DISCONNECT; >+ } >+ pci_set_master(pdev); >+ >+ pci_enable_wake(pdev, PCI_D3hot, 0); >+ pci_enable_wake(pdev, PCI_D3cold, 0); >+ >+ at_reset_hw(&adapter->hw); >+ //AT_WRITE_REG(&adapter->hw, E1000_WUS, ~0); >+ >+ return PCI_ERS_RESULT_RECOVERED; >+} >+ >+/** >+ * at_io_resume - called when traffic can start flowing again. >+ * @pdev: Pointer to PCI device >+ * >+ * This callback is called when the error recovery driver tells us that >+ * its OK to resume normal operation. Implementation resembles the >+ * second-half of the at_resume routine. >+ */ >+static void at_io_resume(struct pci_dev *pdev) >+{ >+ struct net_device *netdev = pci_get_drvdata(pdev); >+ struct at_adapter *adapter = netdev->priv; >+ >+ if (netif_running(netdev)) { >+ if (at_up(adapter)) { >+ printk("ATL2: can't bring device back up after reset\n"); >+ return; >+ } >+ } >+ >+ netif_device_attach(netdev); >+} >+#endif /* CONFIG_AT_PCI_ERS */ >+ >+ >+ >+/** >+ * at_irq_enable - Enable default interrupt generation settings >+ * @adapter: board private structure >+ **/ >+ >+inline void >+at_irq_enable(struct at_adapter *adapter) >+{ >+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) { >+ AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK); >+ AT_WRITE_FLUSH(&adapter->hw); >+ } >+} >+ >+/** >+ * at_irq_disable - Mask off interrupt generation on the NIC >+ * @adapter: board private structure >+ **/ >+ >+inline void >+at_irq_disable(struct at_adapter *adapter) >+{ >+ atomic_inc(&adapter->irq_sem); >+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0); >+ AT_WRITE_FLUSH(&adapter->hw); >+ synchronize_irq(adapter->pdev->irq); >+} >+ >+/** >+ * at_sw_init - Initialize general software structures (struct at_adapter) >+ * @adapter: board private structure to initialize >+ * >+ * at_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 >+at_sw_init(struct at_adapter *adapter) >+{ >+ struct at_hw *hw = &adapter->hw; >+ struct pci_dev *pdev = adapter->pdev; >+ >+ /* PCI config space info */ >+ >+ hw->vendor_id = pdev->vendor; >+ hw->device_id = pdev->device; >+ hw->subsystem_vendor_id = pdev->subsystem_vendor; >+ hw->subsystem_id = pdev->subsystem_device; >+ >+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); >+ >+ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); >+ >+ adapter->wol = 0; >+ >+ 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->retry_buf = 2; >+ >+ hw->max_retry = 0xf; >+ hw->lcol = 0x37; >+ hw->jam_ipg = 7; >+ >+ hw->fc_rxd_hi = 0; >+ hw->fc_rxd_lo = 0; >+ >+ hw->max_frame_size = adapter->netdev->mtu; >+ >+ atomic_set(&adapter->irq_sem, 1); >+ spin_lock_init(&adapter->stats_lock); >+ spin_lock_init(&adapter->tx_lock); >+ >+ set_bit(__AT_DOWN, &adapter->flags); >+ >+ return 0; >+} >+ >+int >+at_reset(struct at_adapter *adapter) >+{ >+ int ret; >+ >+ if (AT_SUCCESS != (ret = at_reset_hw(&adapter->hw))) >+ return ret; >+ >+ return at_init_hw(&adapter->hw); >+} >+ >+/** >+ * at_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 >+at_open(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ int err; >+ u32 val; >+ >+ DEBUGFUNC("at_open !"); >+ >+ /* disallow open during test */ >+ if (test_bit(__AT_TESTING, &adapter->flags)) >+ return -EBUSY; >+ >+ /* allocate transmit descriptors */ >+ >+ if((err = at_setup_ring_resources(adapter))) >+ return err; >+ >+ at_power_up_phy(adapter); >+ >+ if((err = at_init_hw(&adapter->hw))) { >+ err = -EIO; >+ goto err_init_hw; >+ } >+ >+ /* hardware has been reset, we need to reload some things */ >+ >+ at_set_multi(netdev); >+ init_ring_ptrs(adapter); >+ >+#ifdef NETIF_F_HW_VLAN_TX >+ at_restore_vlan(adapter); >+#endif >+ >+ if (at_configure(adapter)) { >+ err = -EIO; >+ goto err_config; >+ } >+ >+ if ((err = at_request_irq(adapter))) >+ goto err_req_irq; >+ >+ clear_bit(__AT_DOWN, &adapter->flags); >+ >+ mod_timer(&adapter->watchdog_timer, jiffies + 4*HZ); >+ >+ val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL); >+ AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val|MASTER_CTRL_MANUAL_INT); >+ //at_check_link(adapter); >+ >+ >+ at_irq_enable(adapter); >+ >+ return 0; >+ >+err_init_hw: >+err_req_irq: >+err_config: >+ at_power_down_phy(adapter); >+ at_free_ring_resources(adapter); >+ at_reset_hw(&adapter->hw); >+ >+ return err; >+} >+ >+/** >+ * at_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 >+at_close(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ DEBUGFUNC("at_close!"); >+ >+ WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); >+ >+ at_down(adapter); >+ at_power_down_phy(adapter); >+ free_irq(adapter->pdev->irq, netdev); >+ at_free_ring_resources(adapter); >+ >+ return 0; >+} >+ >+/** >+ * at_setup_mem_resources - allocate Tx / RX descriptor resources >+ * @adapter: board private structure >+ * >+ * Return 0 on success, negative on failure >+ **/ >+ >+int32_t >+at_setup_ring_resources(struct at_adapter *adapter) >+{ >+ struct pci_dev *pdev = adapter->pdev; >+ int size; >+ u8 offset = 0; >+ >+ DEBUGFUNC("at_setup_ring_resources"); >+ >+ /* real ring DMA buffer */ >+ adapter->ring_size = size = >+ adapter->txd_ring_size * 1 + 7 // dword align >+ + adapter->txs_ring_size * 4 + 7 // dword align >+ + adapter->rxd_ring_size * 1536+ 127; // 128bytes align >+ >+ adapter->ring_vir_addr = >+ pci_alloc_consistent(pdev, size, &adapter->ring_dma); >+ if (!adapter->ring_vir_addr) { >+ DEBUGOUT1("pci_alloc_consistent failed, size = D%d", size); >+ return -ENOMEM; >+ } >+ >+ if (adapter->pci_using_64) { >+ // test whether HIDWORD dma buffer is not cross boundary >+ if ( ((adapter->ring_dma &0xffffffff00000000ULL)>>32) >+ != (((adapter->ring_dma+size)&0xffffffff00000000ULL)>>32) ) { >+ pci_free_consistent( >+ pdev, >+ adapter->ring_size, >+ adapter->ring_vir_addr, >+ adapter->ring_dma); >+ DEBUGOUT("memory allocated cross 32bit boundary !"); >+ return -ENOMEM; >+ } >+ } >+ >+// DEBUGOUT("memory allocated successfully !"); >+ >+ memset(adapter->ring_vir_addr, 0, adapter->ring_size); >+ >+ // Init TXD Ring >+ >+ adapter->txd_dma = adapter->ring_dma ; >+ offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0; >+ adapter->txd_dma += offset; >+ adapter->txd_ring = (tx_pkt_header_t*) (adapter->ring_vir_addr + offset); >+ >+ // Init TXS Ring >+ >+ adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size; >+ offset = (adapter->txs_dma & 0x7) ? (8- (adapter->txs_dma & 0x7)) : 0; >+ adapter->txs_dma += offset; >+ adapter->txs_ring = (tx_pkt_status_t*) >+ (((u8*)adapter->txd_ring) + (adapter->txd_ring_size+offset)); >+ >+ // Init RXD Ring >+ adapter->rxd_dma = adapter->txs_dma + adapter->txs_ring_size*4; >+ offset = (adapter->rxd_dma & 127) ? (128 - (adapter->rxd_dma & 127)) : 0; >+ if (offset > 7) { >+ offset -= 8; >+ } else { >+ offset += (128 - 8); >+ } >+ adapter->rxd_dma += offset; >+ adapter->rxd_ring = (rx_desc_t*) >+ (((u8*)adapter->txs_ring) + >+ (adapter->txs_ring_size*4 + offset)); >+ >+ >+ // Read / Write Ptr Initialize: >+ // init_ring_ptrs(adapter); >+ >+ return AT_SUCCESS; >+} >+ >+ >+void >+init_ring_ptrs(struct at_adapter *adapter) >+{ >+ // Read / Write Ptr Initialize: >+ adapter->txd_write_ptr = 0; >+ atomic_set(&adapter->txd_read_ptr, 0); >+ >+ adapter->rxd_read_ptr = 0; >+ adapter->rxd_write_ptr = 0; >+ >+ atomic_set(&adapter->txs_write_ptr, 0); >+ adapter->txs_next_clear = 0; >+} >+ >+/** >+ * at_free_ring_resources - Free Tx / RX descriptor Resources >+ * @adapter: board private structure >+ * >+ * Free all transmit software resources >+ **/ >+ >+void >+at_free_ring_resources(struct at_adapter *adapter) >+{ >+ struct pci_dev *pdev = adapter->pdev; >+ >+ DEBUGFUNC("at_free_ring_resources"); >+ >+ pci_free_consistent( >+ pdev, >+ adapter->ring_size, >+ adapter->ring_vir_addr, >+ adapter->ring_dma); >+ >+} >+ >+ >+int >+at_up(struct at_adapter *adapter) >+{ >+ struct net_device *netdev = adapter->netdev; >+ int err = 0; >+ u32 val; >+ >+// DEBUGFUNC("at_up !"); >+ >+ /* hardware has been reset, we need to reload some things */ >+ >+ err = at_init_hw(&adapter->hw); >+ if (err) { >+ err = -EIO; >+ return err; >+ } >+ >+ at_set_multi(netdev); >+ init_ring_ptrs(adapter); >+ >+#ifdef NETIF_F_HW_VLAN_TX >+ at_restore_vlan(adapter); >+#endif >+ >+ if (at_configure(adapter)) { >+ err = -EIO; >+ goto err_up; >+ } >+ >+ clear_bit(__AT_DOWN, &adapter->flags); >+ >+ val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL); >+ AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val|MASTER_CTRL_MANUAL_INT); >+ //at_check_link(adapter); >+ at_irq_enable(adapter); >+err_up: >+ return err; >+} >+ >+inline void >+at_setup_mac_ctrl(struct at_adapter* adapter) >+{ >+ u32 value; >+ struct at_hw* hw = &adapter->hw; >+ struct net_device* netdev = adapter->netdev; >+ >+ /* Config MAC CTRL Register */ >+ value = MAC_CTRL_TX_EN | >+ MAC_CTRL_RX_EN | >+ MAC_CTRL_MACLP_CLK_PHY; >+ // duplex >+ if (FULL_DUPLEX == adapter->link_duplex) >+ value |= MAC_CTRL_DUPLX; >+ // 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 >+ if (adapter->vlgrp) >+ value |= MAC_CTRL_RMV_VLAN; >+ >+ // 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; >+ >+ // half retry buffer >+ value |= (((u32)(adapter->hw.retry_buf >+ &MAC_CTRL_HALF_LEFT_BUF_MASK)) >+ << MAC_CTRL_HALF_LEFT_BUF_SHIFT); >+ >+ AT_WRITE_REG(hw, REG_MAC_CTRL, value); >+} >+ >+ >+static int >+at_check_link(struct at_adapter* adapter) >+{ >+ struct at_hw *hw = &adapter->hw; >+ struct net_device * netdev = adapter->netdev; >+ int ret_val; >+ u16 speed, duplex, phy_data; >+ int reconfig = 0; >+ >+// DEBUGFUNC("at_check_link !"); >+ // MII_BMSR must read twise >+ at_read_phy_reg(hw, MII_BMSR, &phy_data); >+ at_read_phy_reg(hw, MII_BMSR, &phy_data); >+ if (!(phy_data&BMSR_LSTATUS)) { // link down >+ if (netif_carrier_ok(netdev)) { // old link state: Up >+ DEBUGOUT("NIC Link is Down"); >+ adapter->link_speed = SPEED_0; >+ netif_carrier_off(netdev); >+ netif_stop_queue(netdev); >+ } >+ return AT_SUCCESS; >+ } >+ >+ // Link Up >+ ret_val = at_get_speed_and_duplex(hw, &speed, &duplex); >+ if (ret_val) return ret_val; >+ switch( hw->MediaType ) >+ { >+ 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 (0 == reconfig) >+ { >+ if (adapter->link_speed != speed || >+ adapter->link_duplex != duplex ) { >+ adapter->link_speed = speed; >+ adapter->link_duplex = duplex; >+ at_setup_mac_ctrl(adapter); >+ printk(KERN_INFO >+ "%s: %s NIC Link is Up<%d Mbps %s>\n", >+ at_driver_name, >+ 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); >+ netif_wake_queue(netdev); >+ } >+ return AT_SUCCESS; >+ } >+ >+ // change orignal link status >+ if (netif_carrier_ok(netdev)) { >+ adapter->link_speed = SPEED_0; >+ netif_carrier_off(netdev); >+ netif_stop_queue(netdev); >+ } >+ >+ if (hw->MediaType != MEDIA_TYPE_AUTO_SENSOR) { >+ switch (hw->MediaType) >+ { >+ 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; >+ } >+ at_write_phy_reg(hw, MII_BMCR, phy_data); >+ return AT_SUCCESS; >+ } >+ >+ // auto-neg, insert timer to re-config phy >+ if (!adapter->phy_timer_pending) { >+ adapter->phy_timer_pending = TRUE; >+ mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ); >+ } >+ >+ return AT_SUCCESS; >+} >+ >+ >+/** >+ * at_power_up_phy - restore link in case the phy was powered down >+ * @adapter: address of board private structure >+ * >+ * The phy may be powered down to save power and turn off link when the >+ * driver is unloaded and wake on lan is not enabled (among others) >+ * *** this routine MUST be followed by a call to at_reset *** >+ * >+ **/ >+ >+void at_power_up_phy(struct at_adapter *adapter) >+{ >+ u16 mii_reg = 0; >+ >+ DEBUGFUNC("at_power_up_phy"); >+ >+ /* Just clear the power down bit to wake the phy back up */ >+ /* according to the manual, the phy will retain its >+ * settings across a power-down/up cycle */ >+ at_read_phy_reg(&adapter->hw, MII_BMCR, &mii_reg); >+ mii_reg &= ~MII_CR_POWER_DOWN; >+ mii_reg |= MII_CR_RESET; >+ at_write_phy_reg(&adapter->hw, MII_BMCR, mii_reg); >+} >+ >+ >+static void at_power_down_phy(struct at_adapter *adapter) >+{ >+ /* Power down the PHY so no link is implied when interface is down * >+ * The PHY cannot be powered down if any of the following is TRUE * >+ * (a) WoL is enabled >+ */ >+ DEBUGFUNC("at_power_down_phy"); >+ >+ if (!adapter->wol ) { >+ u16 mii_reg = 0; >+ at_read_phy_reg(&adapter->hw, MII_BMCR, &mii_reg); >+ mii_reg |= (MII_CR_POWER_DOWN|MII_CR_RESET); >+ at_write_phy_reg(&adapter->hw, MII_BMCR, mii_reg); >+ mdelay(1); >+ } >+ >+ return; >+} >+ >+ >+ >+void >+at_down(struct at_adapter *adapter) >+{ >+ struct net_device *netdev = adapter->netdev; >+ >+// DEBUGFUNC("at_down !"); >+ >+ /* signal that we're down so the interrupt handler does not >+ * reschedule our watchdog timer */ >+ set_bit(__AT_DOWN, &adapter->flags); >+ >+#ifdef NETIF_F_LLTX >+ netif_stop_queue(netdev); >+#else >+ netif_tx_disable(netdev); >+#endif >+ >+ /* reset MAC to disable all RX/TX */ >+ at_reset_hw(&adapter->hw); >+ msleep(1); >+ >+ at_irq_disable(adapter); >+ >+ del_timer_sync(&adapter->watchdog_timer); >+ del_timer_sync(&adapter->phy_config_timer); >+ adapter->phy_timer_pending = FALSE; >+ >+ netif_carrier_off(netdev); >+ adapter->link_speed = SPEED_0; >+ adapter->link_duplex = -1; >+ >+// at_reset(adapter); >+} >+ >+ >+ >+/** >+ * at_set_multi - Multicast and Promiscuous mode set >+ * @netdev: network interface device structure >+ * >+ * The set_multi entry point is called whenever the multicast address >+ * list or the network interface flags are updated. This routine is >+ * responsible for configuring the hardware for proper multicast, >+ * promiscuous mode, and all-multi behavior. >+ **/ >+ >+static void >+at_set_multi(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw *hw = &adapter->hw; >+ struct dev_mc_list *mc_ptr; >+ u32 rctl; >+ u32 hash_value; >+ >+// DEBUGFUNC("at_set_multi !"); >+ >+ /* Check for Promiscuous and All Multicast modes */ >+ >+ rctl = AT_READ_REG(hw, REG_MAC_CTRL); >+ >+ if(netdev->flags & IFF_PROMISC) { >+ rctl |= MAC_CTRL_PROMIS_EN; >+ } else if(netdev->flags & IFF_ALLMULTI) { >+ rctl |= MAC_CTRL_MC_ALL_EN; >+ rctl &= ~MAC_CTRL_PROMIS_EN; >+ } else { >+ rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); >+ } >+ >+ AT_WRITE_REG(hw, REG_MAC_CTRL, rctl); >+ >+ /* clear the old settings from the multicast hash table */ >+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); >+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); >+ >+ /* comoute mc addresses' hash value ,and put it into hash table */ >+ >+ for(mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { >+ hash_value = at_hash_mc_addr(hw, mc_ptr->dmi_addr); >+ at_hash_set(hw, hash_value); >+ } >+} >+ >+#ifdef NETIF_F_HW_VLAN_TX >+static void >+at_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ u32 ctrl; >+ >+ // DEBUGFUNC("at_vlan_rx_register !"); >+ >+ at_irq_disable(adapter); >+ adapter->vlgrp = grp; >+ >+ if(grp) { >+ /* enable VLAN tag insert/strip */ >+ >+ ctrl = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); >+ ctrl |= MAC_CTRL_RMV_VLAN; >+ AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); >+ } else { >+ /* disable VLAN tag insert/strip */ >+ >+ ctrl = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); >+ ctrl &= ~MAC_CTRL_RMV_VLAN; >+ AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); >+ } >+ >+ at_irq_enable(adapter); >+} >+ >+static void >+at_vlan_rx_add_vid(struct net_device *netdev, u16 vid) >+{ >+ /* We don't do Vlan filtering */ >+// DEBUGFUNC("at_vlan_rx_add_vid !"); >+ return ; >+} >+ >+static void >+at_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+// DEBUGFUNC("at_vlan_rx_kill_vid !"); >+ at_irq_disable(adapter); >+ >+ if (adapter->vlgrp) { >+ adapter->vlgrp->vlan_devices[vid] = NULL; >+ } >+ >+ at_irq_enable(adapter); >+ >+ /* We don't do Vlan filtering */ >+ >+ return; >+} >+ >+static void >+at_restore_vlan(struct at_adapter *adapter) >+{ >+// DEBUGFUNC("at_restore_vlan !"); >+ at_vlan_rx_register(adapter->netdev, adapter->vlgrp); >+ >+ if(adapter->vlgrp) { >+ u16 vid; >+ for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { >+ if(!adapter->vlgrp->vlan_devices[vid]) >+ continue; >+ at_vlan_rx_add_vid(adapter->netdev, vid); >+ } >+ } >+} >+#endif >+ >+/** >+ * at_configure - Configure Transmit&Receive Unit after Reset >+ * @adapter: board private structure >+ * >+ * Configure the Tx /Rx unit of the MAC after a reset. >+ **/ >+ >+static int >+at_configure(struct at_adapter *adapter) >+{ >+ struct at_hw * hw = &adapter->hw; >+ u32 value; >+ >+// DEBUGFUNC("at_configure !"); >+ >+ // clear interrupt status >+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0xffffffff); >+ >+ // 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]) ) ; >+ AT_WRITE_REG(hw, REG_MAC_STA_ADDR, value); >+ value = (((u32)hw->mac_addr[0]) << 8 ) | >+ (((u32)hw->mac_addr[1]) ) ; >+ AT_WRITE_REG(hw, (REG_MAC_STA_ADDR+4), value); >+ >+ // tx / rx ring : >+ >+ // HI base address >+ AT_WRITE_REG( >+ hw, >+ REG_DESC_BASE_ADDR_HI, >+ (u32)((adapter->ring_dma&0xffffffff00000000ULL) >>32)); >+ // LO base address >+ AT_WRITE_REG( >+ hw, >+ REG_TXD_BASE_ADDR_LO, >+ (u32)(adapter->txd_dma&0x00000000ffffffffULL)); >+ AT_WRITE_REG( >+ hw, >+ REG_TXS_BASE_ADDR_LO, >+ (u32)(adapter->txs_dma& 0x00000000ffffffffULL)); >+ AT_WRITE_REG(hw, >+ REG_RXD_BASE_ADDR_LO, >+ (u32)(adapter->rxd_dma& 0x00000000ffffffffULL)); >+ >+ // element count >+ AT_WRITE_REGW(hw, REG_TXD_MEM_SIZE, (u16)(adapter->txd_ring_size/4)); >+ AT_WRITE_REGW(hw, REG_TXS_MEM_SIZE, (u16)adapter->txs_ring_size); >+ AT_WRITE_REGW(hw, REG_RXD_BUF_NUM, (u16)adapter->rxd_ring_size); >+ DEBUGOUT1("txd ring size:%d, txs ring size:%d, rxd ring size:%d", >+ adapter->txd_ring_size/4, >+ adapter->txs_ring_size, >+ adapter->rxd_ring_size); >+ >+ /* config Internal SRAM */ >+/* >+ AT_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_tx_end); >+ AT_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_rx_end); >+*/ >+ >+ >+ /* 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); >+ AT_WRITE_REG(hw, REG_MAC_IPG_IFG, value); >+// DEBUGOUT1("init ipg/ifg with 0x%x", value); >+ >+ /* 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); >+ AT_WRITE_REG(hw, REG_MAC_HALF_DUPLX_CTRL, value); >+// DEBUGOUT1("init Half Duplex with 0x%x", value); >+ >+ >+ /* set Interrupt Moderator Timer */ >+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, adapter->imt); >+ AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_ITIMER_EN); >+// DEBUGOUT1("init Irq Modurator Timer with 0x%x", adapter->imt); >+ >+ /* set Interrupt Clear Timer */ >+ AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, adapter->ict); >+// DEBUGOUT1("init Irq Clear Timer with 0x%x", adapter->ict); >+ >+ /* set MTU */ >+ AT_WRITE_REG(hw, REG_MTU, >+ adapter->netdev->mtu + >+ ENET_HEADER_SIZE + >+ VLAN_SIZE + >+ ETHERNET_FCS_SIZE); >+// DEBUGOUT1("init MTU with 0x%x", hw->max_frame_size); >+ >+ /* 1590 */ >+ AT_WRITE_REG(hw, >+ REG_TX_CUT_THRESH, >+ 0x177); >+ >+ /* flow control */ >+ AT_WRITE_REGW(hw, REG_PAUSE_ON_TH, hw->fc_rxd_hi); >+ AT_WRITE_REGW(hw, REG_PAUSE_OFF_TH, hw->fc_rxd_lo); >+ >+ /* Init mailbox */ >+ AT_WRITE_REGW(hw, REG_MB_TXD_WR_IDX, (u16)adapter->txd_write_ptr); >+ AT_WRITE_REGW(hw, REG_MB_RXD_RD_IDX, (u16)adapter->rxd_read_ptr); >+ >+ /* enable DMA read/write */ >+ AT_WRITE_REGB(hw, REG_DMAR, DMAR_EN); >+ AT_WRITE_REGB(hw, REG_DMAW, DMAW_EN); >+ >+ >+ value = AT_READ_REG(&adapter->hw, REG_ISR); >+ if ((value&ISR_PHY_LINKDOWN) != 0) { >+ value = 1; // config failed >+ } else { >+ value = 0; >+ } >+ >+ // clear all interrupt status >+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0x3fffffff); >+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0); >+ return value; >+} >+ >+/** >+ * at_set_mac - Change the Ethernet Address of the NIC >+ * @netdev: network interface device structure >+ * @p: pointer to an address structure >+ * >+ * Returns 0 on success, negative on failure >+ **/ >+ >+static int >+at_set_mac(struct net_device *netdev, void *p) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct sockaddr *addr = p; >+ >+ DEBUGFUNC("at_set_mac !"); >+ >+ if (!is_valid_ether_addr(addr->sa_data)) >+ return -EADDRNOTAVAIL; >+ >+ if (netif_running(netdev)) >+ return -EBUSY; >+ >+ if(!is_valid_ether_addr(addr->sa_data)) >+ return -EADDRNOTAVAIL; >+ >+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); >+ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); >+ >+ >+ set_mac_addr(&adapter->hw); >+ >+ return 0; >+} >+ >+ >+ >+/** >+ * at_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 >+at_change_mtu(struct net_device *netdev, int new_mtu) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct at_hw* hw = &adapter->hw; >+ >+ DEBUGFUNC("at_change_mtu !"); >+ >+ if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE))) >+ return -EINVAL; >+ >+ /* set MTU */ >+ if (hw->max_frame_size != new_mtu) { >+ >+// while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) >+// msleep(1); >+ >+ netdev->mtu = new_mtu; >+ >+ AT_WRITE_REG(hw, REG_MTU, >+ new_mtu + >+ ENET_HEADER_SIZE + >+ VLAN_SIZE + >+ ETHERNET_FCS_SIZE); >+ >+// clear_bit(__AT_RESETTING, &adapter->flags); >+ } >+ >+ return 0; >+} >+ >+ >+ >+void >+at_read_pci_cfg(struct at_hw *hw, u32 reg, u16 *value) >+{ >+ struct at_adapter *adapter = hw->back; >+ >+ pci_read_config_word(adapter->pdev, reg, value); >+} >+ >+void >+at_write_pci_cfg(struct at_hw *hw, u32 reg, u16 *value) >+{ >+ struct at_adapter *adapter = hw->back; >+ >+ pci_write_config_word(adapter->pdev, reg, *value); >+} >+ >+ >+/** >+ * at_get_stats - Get System Network Statistics >+ * @netdev: network interface device structure >+ * >+ * Returns the address of the device statistics structure. >+ * The statistics are actually updated from the timer callback. >+ **/ >+ >+static struct net_device_stats * >+at_get_stats(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ u32 drop_rxd, drop_rxs; >+ unsigned long flags; >+ >+ spin_lock_irqsave(&adapter->stats_lock, flags); >+ drop_rxd = AT_READ_REG(&adapter->hw, REG_STS_RXD_OV); >+ drop_rxs = AT_READ_REG(&adapter->hw, REG_STS_RXS_OV); >+ adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs); >+ >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+ >+ return &adapter->net_stats; >+} >+ >+/** >+ * at_ioctl - >+ * @netdev: >+ * @ifreq: >+ * @cmd: >+ **/ >+ >+static int >+at_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) >+{ >+// DEBUGFUNC("at_ioctl !"); >+ switch (cmd) { >+#ifdef SIOCGMIIPHY >+ case SIOCGMIIPHY: >+ case SIOCGMIIREG: >+ case SIOCSMIIREG: >+ return at_mii_ioctl(netdev, ifr, cmd); >+#endif >+ >+#ifdef ETHTOOL_OPS_COMPAT >+ case SIOCETHTOOL: >+ return at_ethtool_ioctl(ifr); >+#endif >+ >+ default: >+ return -EOPNOTSUPP; >+ } >+} >+ >+ >+#ifdef SIOCGMIIPHY >+/** >+ * at_mii_ioctl - >+ * @netdev: >+ * @ifreq: >+ * @cmd: >+ **/ >+ >+static int >+at_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ struct mii_ioctl_data *data = if_mii(ifr); >+ unsigned long flags; >+ >+// DEBUGFUNC("at_mii_ioctl !"); >+ >+ switch (cmd) { >+ case SIOCGMIIPHY: >+ data->phy_id = 0; >+ break; >+ case SIOCGMIIREG: >+ if (!capable(CAP_NET_ADMIN)) >+ return -EPERM; >+ spin_lock_irqsave(&adapter->stats_lock, flags); >+ if (at_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, &data->val_out)) { >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+ return -EIO; >+ } >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+ break; >+ case SIOCSMIIREG: >+ if (!capable(CAP_NET_ADMIN)) >+ return -EPERM; >+ if (data->reg_num & ~(0x1F)) >+ return -EFAULT; >+ >+ spin_lock_irqsave(&adapter->stats_lock, flags); >+ DEBUGOUT1("<at_mii_ioctl> write %x %x", >+ data->reg_num, >+ data->val_in); >+ if (at_write_phy_reg(&adapter->hw, data->reg_num, data->val_in)) { >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+ return -EIO; >+ } >+ // ...... >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+ break; >+ >+ default: >+ return -EOPNOTSUPP; >+ } >+ return AT_SUCCESS; >+} >+ >+#endif >+ >+/** >+ * at_tx_timeout - Respond to a Tx Hang >+ * @netdev: network interface device structure >+ **/ >+ >+static void >+at_tx_timeout(struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ >+ DEBUGFUNC("at_tx_timeout !"); >+ >+ /* Do the reset outside of interrupt context */ >+ schedule_work(&adapter->reset_task); >+} >+ >+ >+static void >+at_reset_task(struct work_struct *work) >+{ >+ struct at_adapter *adapter; >+ adapter = container_of(work, struct at_adapter, reset_task); >+ >+ at_reinit_locked(adapter); >+} >+ >+ >+void >+at_reinit_locked(struct at_adapter *adapter) >+{ >+ >+ DEBUGFUNC("at_reinit_locked !"); >+ >+ WARN_ON(in_interrupt()); >+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) >+ msleep(1); >+ at_down(adapter); >+ at_up(adapter); >+ clear_bit(__AT_RESETTING, &adapter->flags); >+} >+ >+/** >+ * at_link_chg_task - deal with link change event Out of interrupt context >+ * @netdev: network interface device structure >+ **/ >+static void >+at_link_chg_task(struct work_struct *work) >+{ >+ struct at_adapter *adapter; >+ unsigned long flags; >+ >+ DEBUGFUNC("at_link_chg_task !"); >+ >+ adapter = container_of(work, struct at_adapter, link_chg_task); >+ >+ >+ spin_lock_irqsave(&adapter->stats_lock, flags); >+ at_check_link(adapter); >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+} >+ >+static void >+at_check_for_link(struct at_adapter* adapter) >+{ >+ struct net_device *netdev = adapter->netdev; >+ u16 phy_data = 0; >+ >+ DEBUGFUNC("at_check_for_link!"); >+ >+ spin_lock(&adapter->stats_lock); >+ adapter->phy_timer_pending = FALSE; >+ at_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); >+ at_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); >+ spin_unlock(&adapter->stats_lock); >+ >+ DEBUGOUT1("MII_BMSR=%x <at_check_for_link>", phy_data); >+ >+ // notify upper layer link down ASAP >+ if (!(phy_data&BMSR_LSTATUS)) { // Link Down >+ if (netif_carrier_ok(netdev)) { // old link state: Up >+ printk(KERN_INFO >+ "%s: %s NIC Link is Down\n", >+ at_driver_name, >+ netdev->name ); >+ adapter->link_speed = SPEED_0; >+ netif_carrier_off(netdev); >+ netif_stop_queue(netdev); >+ } >+ } >+ schedule_work(&adapter->link_chg_task); >+} >+ >+static inline void >+at_clear_phy_int(struct at_adapter* adapter) >+{ >+ u16 phy_data; >+ >+ spin_lock(&adapter->stats_lock); >+ at_read_phy_reg(&adapter->hw, 19, &phy_data); >+ spin_unlock(&adapter->stats_lock); >+} >+ >+ >+/** >+ * at_intr - Interrupt Handler >+ * @irq: interrupt number >+ * @data: pointer to a network interface device structure >+ * @pt_regs: CPU registers structure >+ **/ >+ >+static irqreturn_t >+at_intr(int irq, void *data) >+{ >+ struct at_adapter *adapter = netdev_priv(data); >+ struct at_hw *hw = &adapter->hw; >+ u32 status; >+ >+ >+ status = AT_READ_REG(hw, REG_ISR); >+ if (0 == status) >+ return IRQ_NONE; >+ >+ // link event >+ if (status&ISR_PHY) { >+ at_clear_phy_int(adapter); >+ } >+ >+ // clear ISR status, and Enable CMB DMA/Disable Interrupt >+ AT_WRITE_REG(hw, REG_ISR, status|ISR_DIS_INT); >+ >+ >+ // check if PCIE PHY Link down >+ if (status&ISR_PHY_LINKDOWN) { >+ DEBUGOUT1("pcie phy linkdown %x", status); >+ if(netif_running(adapter->netdev)) { // reset MAC >+ AT_WRITE_REG(hw, REG_ISR, 0); >+ AT_WRITE_REG(hw, REG_IMR, 0); >+ AT_WRITE_FLUSH(hw); >+ schedule_work(&adapter->reset_task); >+ return IRQ_HANDLED; >+ } >+ } >+ >+ // check if DMA read/write error ? >+ if (status&(ISR_DMAR_TO_RST|ISR_DMAW_TO_RST)) >+ { >+ DEBUGOUT1("PCIE DMA RW error (status = 0x%x) !", status); >+ //AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); >+ AT_WRITE_REG(hw, REG_ISR, 0); >+ AT_WRITE_REG(hw, REG_IMR, 0); >+ AT_WRITE_FLUSH(hw); >+ schedule_work(&adapter->reset_task); >+ return IRQ_HANDLED; >+ } >+ >+ // link event >+ if (status&(ISR_PHY|ISR_MANUAL)) >+ { >+ adapter->net_stats.tx_carrier_errors++; >+ at_check_for_link(adapter); >+ } >+ >+ >+ // transmit event >+ if ( status&ISR_TX_EVENT ) { >+ at_intr_tx(adapter); >+ } >+ >+ // rx exception >+ if ( status& ISR_RX_EVENT ) { >+ at_intr_rx(adapter); >+ } >+ >+ // re-enable Interrupt >+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0); >+ return IRQ_HANDLED; >+} >+ >+static void >+at_intr_tx(struct at_adapter* adapter) >+{ >+ u32 txd_read_ptr; >+ u32 txs_write_ptr; >+ tx_pkt_status_t* txs; >+ tx_pkt_header_t* txph; >+ int free_hole = 0; >+ >+// DEBUGFUNC("at_intr_tx"); >+ >+ do { >+ txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr); >+ txs = adapter->txs_ring + txs_write_ptr; >+ if (!txs->update) >+ break; // tx stop here >+ >+ free_hole = 1; >+ txs->update = 0; >+ >+ if (++txs_write_ptr == adapter->txs_ring_size) >+ txs_write_ptr = 0; >+ atomic_set(&adapter->txs_write_ptr, (int)txs_write_ptr); >+ >+ txd_read_ptr = (u32) atomic_read(&adapter->txd_read_ptr); >+ txph = (tx_pkt_header_t*) >+ (((u8*)adapter->txd_ring) + txd_read_ptr); >+ >+ if ( txph->pkt_size != txs->pkt_size) { >+ >+ tx_pkt_status_t* old_txs = txs; >+ printk(KERN_WARNING >+ "%s: txs packet size do not coinsist with txd" >+ " txd_:0x%08x, txs_:0x%08x!\n", >+ adapter->netdev->name, >+ *(u32*)txph, *(u32*)txs); >+ printk(KERN_WARNING >+ "txd read ptr: 0x%x\n", >+ txd_read_ptr); >+ txs = adapter->txs_ring + txs_write_ptr; >+ printk(KERN_WARNING >+ "txs-behind:0x%08x\n", >+ *(u32*)txs); >+ if (txs_write_ptr < 2) { >+ txs = adapter->txs_ring + (adapter->txs_ring_size+ >+ txs_write_ptr - 2); >+ } else { >+ txs = adapter->txs_ring + (txs_write_ptr - 2); >+ } >+ printk(KERN_WARNING >+ "txs-before:0x%08x\n", >+ *(u32*)txs); >+ txs = old_txs; >+ } >+ >+ txd_read_ptr += (((u32)(txph->pkt_size)+7)& ~3);//4for TPH >+ if (txd_read_ptr >= adapter->txd_ring_size) >+ txd_read_ptr -= adapter->txd_ring_size; >+ >+ atomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr); >+ >+ // tx statistics: >+ if (txs->ok) adapter->net_stats.tx_packets++; >+ else adapter->net_stats.tx_errors++; >+ if (txs->defer) adapter->net_stats.collisions++; >+ if (txs->abort_col) adapter->net_stats.tx_aborted_errors++; >+ if (txs->late_col) adapter->net_stats.tx_window_errors++; >+ if (txs->underun) adapter->net_stats.tx_fifo_errors++; >+ } while (1); >+ >+ if (free_hole) { >+ if(netif_queue_stopped(adapter->netdev) && >+ netif_carrier_ok(adapter->netdev)) >+ netif_wake_queue(adapter->netdev); >+ } >+} >+ >+ >+static void >+at_intr_rx(struct at_adapter* adapter) >+{ >+ struct net_device *netdev = adapter->netdev; >+ rx_desc_t* rxd; >+ struct sk_buff* skb; >+ >+ >+ do { >+ rxd = adapter->rxd_ring+adapter->rxd_write_ptr; >+ if (!rxd->status.update) >+ break; // end of tx >+ // clear this flag at once >+ rxd->status.update = 0; >+ >+ if (rxd->status.ok && rxd->status.pkt_size >= 60) { >+ int rx_size = (int)(rxd->status.pkt_size-4); >+ // alloc new buffer >+ skb = netdev_alloc_skb(netdev, rx_size+NET_IP_ALIGN); >+ if (NULL == skb) { >+ printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n", >+ netdev->name); >+ /* We should check that some rx space is free. >+ If not, free one and mark stats->rx_dropped++. */ >+ adapter->net_stats.rx_dropped++; >+ break; >+ } >+/* >+ if (rx_size > 1400) { >+ int s,c; >+ c = 0; >+ printk("rx_size= %d\n", rx_size); >+ for (s=0; s < 800; s++) { >+ if (0 == c) { >+ printk("%04x ", s); >+ } >+ printk("%02x ", rxd->packet[s]); >+ if (++c == 16) { >+ c = 0; >+ printk("\n"); >+ } >+ } >+ printk(KERN_WARNING"\n"); >+ } >+*/ >+ >+ skb_reserve(skb, NET_IP_ALIGN); >+ skb->dev = netdev; >+ eth_copy_and_sum( >+ skb, >+ rxd->packet, >+ rx_size, 0); >+ skb_put(skb, rx_size); >+ /* >+ memcpy(skb_put(skb, rx_size), >+ rxd->packet, >+ rx_size); >+ */ >+ skb->protocol = eth_type_trans(skb, netdev); >+#ifdef NETIF_F_HW_VLAN_TX >+ >+ if(adapter->vlgrp && (rxd->status.vlan)) { >+ u16 vlan_tag = >+ (rxd->status.vtag>>4) | >+ ((rxd->status.vtag&7) << 13) | >+ ((rxd->status.vtag&8) << 9) ; >+ DEBUGOUT1("RXD VLAN TAG<RRD>=0x%04x", rxd->status.vtag); >+ vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); >+ } else >+#endif >+ netif_rx(skb); >+ adapter->net_stats.rx_bytes += rx_size; >+ adapter->net_stats.rx_packets++; >+ netdev->last_rx = jiffies; >+ >+ } else { >+ >+ adapter->net_stats.rx_errors++; >+ >+ if (rxd->status.ok && rxd->status.pkt_size <= 60) { >+ adapter->net_stats.rx_length_errors++; >+ } >+ if (rxd->status.mcast) adapter->net_stats.multicast++; >+ if (rxd->status.crc) adapter->net_stats.rx_crc_errors++; >+ if (rxd->status.align) adapter->net_stats.rx_frame_errors++; >+ } >+ >+ // advance write ptr >+ if (++adapter->rxd_write_ptr == adapter->rxd_ring_size) >+ adapter->rxd_write_ptr = 0; >+ } while (1); >+ >+ >+ // update mailbox ? >+ adapter->rxd_read_ptr = adapter->rxd_write_ptr; >+ AT_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr); >+} >+ >+inline >+int >+TxsFreeUnit(struct at_adapter* adapter) >+{ >+ u32 txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr); >+ >+ return >+ (adapter->txs_next_clear >= txs_write_ptr) ? >+ (int) (adapter->txs_ring_size - adapter->txs_next_clear >+ + txs_write_ptr - 1) : >+ (int) (txs_write_ptr - adapter->txs_next_clear - 1); >+} >+ >+inline >+int >+TxdFreeBytes(struct at_adapter* adapter) >+{ >+ u32 txd_read_ptr = (u32)atomic_read(&adapter->txd_read_ptr); >+ >+ return (adapter->txd_write_ptr >= txd_read_ptr) ? >+ (int) (adapter->txd_ring_size - adapter->txd_write_ptr >+ + txd_read_ptr - 1): >+ (int) (txd_read_ptr - adapter->txd_write_ptr - 1); >+} >+ >+ >+ >+static int >+at_xmit_frame(struct sk_buff *skb, struct net_device *netdev) >+{ >+ struct at_adapter *adapter = netdev_priv(netdev); >+ unsigned long flags; >+ tx_pkt_header_t* txph; >+ u32 offset, copy_len; >+ int txs_unused; >+ int txbuf_unused; >+ >+ //DEBUGFUNC("at_xmit_frame"); >+ >+ if (test_bit(__AT_DOWN, &adapter->flags)) { >+ dev_kfree_skb_any(skb); >+ return NETDEV_TX_OK; >+ } >+ >+ if (unlikely(skb->len <= 0)) { >+ dev_kfree_skb_any(skb); >+ return NETDEV_TX_OK; >+ } >+ >+#ifdef NETIF_F_LLTX >+ local_irq_save(flags); >+ if (!spin_trylock(&adapter->tx_lock)) { >+ /* Collision - tell upper layer to requeue */ >+ local_irq_restore(flags); >+ return NETDEV_TX_LOCKED; >+ } >+#else >+ spin_lock_irqsave(&adapter->tx_lock, flags); >+#endif >+ txs_unused = TxsFreeUnit(adapter); >+ txbuf_unused = TxdFreeBytes(adapter); >+ >+ if (txs_unused < 1 || skb->len > txbuf_unused) { >+ // no enough resource >+ netif_stop_queue(netdev); >+ spin_unlock_irqrestore(&adapter->tx_lock, flags); >+ DEBUGOUT("tx busy!!"); >+ return NETDEV_TX_BUSY; >+ } >+ >+ offset = adapter->txd_write_ptr; >+ >+ txph = (tx_pkt_header_t*) >+ (((u8*)adapter->txd_ring)+offset); >+ >+ *(u32*)txph = 0; >+ txph->pkt_size = skb->len; >+ >+ offset += 4; >+ if (offset >= adapter->txd_ring_size) >+ offset -= adapter->txd_ring_size; >+ copy_len = adapter->txd_ring_size - offset; >+ if (copy_len >= skb->len) { >+ memcpy(((u8*)adapter->txd_ring)+offset, >+ skb->data, >+ skb->len); >+ offset += ((u32)(skb->len+3)&~3); >+ } else { >+ memcpy(((u8*)adapter->txd_ring)+offset, >+ skb->data, >+ copy_len); >+ memcpy((u8*)adapter->txd_ring, >+ skb->data+copy_len, >+ skb->len-copy_len); >+ offset = ((u32)(skb->len-copy_len+3)&~3); >+ } >+ >+#ifdef NETIF_F_HW_VLAN_TX >+ if (adapter->vlgrp && vlan_tx_tag_present(skb)) { >+ u16 vlan_tag = vlan_tx_tag_get(skb); >+ vlan_tag = (vlan_tag << 4) | >+ (vlan_tag >> 13) | >+ ((vlan_tag >>9) & 0x8) ; >+ txph->ins_vlan = 1; >+ txph->vlan = vlan_tag; >+ DEBUGOUT1("TXD VLAN TAG<TPD>=%04x", vlan_tag); >+ } >+#endif >+ if (offset >= adapter->txd_ring_size) >+ offset -= adapter->txd_ring_size; >+ adapter->txd_write_ptr = offset; >+ >+ // clear txs before send >+ adapter->txs_ring[adapter->txs_next_clear].update = 0; >+ if (++adapter->txs_next_clear == adapter->txs_ring_size) >+ adapter->txs_next_clear = 0; >+/* >+ printk("txd header: 0x%08x, txd write ptr: %08x\n", >+ *(u32*)txph, >+ adapter->txd_write_ptr); >+*/ >+ >+ AT_WRITE_REGW( &adapter->hw, >+ REG_MB_TXD_WR_IDX, >+ (adapter->txd_write_ptr>>2)); >+ >+ spin_unlock_irqrestore(&adapter->tx_lock, flags); >+ >+ netdev->trans_start = jiffies; >+ dev_kfree_skb_any(skb); >+ return NETDEV_TX_OK; >+} >+ >+/** >+ * at_phy_config - Timer Call-back >+ * @data: pointer to netdev cast into an unsigned long >+ **/ >+ >+static void >+at_phy_config(unsigned long data) >+{ >+ struct at_adapter *adapter = (struct at_adapter *) data; >+ struct at_hw *hw = &adapter->hw; >+ unsigned long flags; >+ >+ DEBUGFUNC("at_phy_reconfig!"); >+ >+ spin_lock_irqsave(&adapter->stats_lock, flags); >+ adapter->phy_timer_pending = FALSE; >+ at_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); >+ DEBUGOUT("4 register written"); >+ at_write_phy_reg(hw, MII_BMCR, MII_CR_RESET|MII_CR_AUTO_NEG_EN); >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+} >+ >+ >+/** >+ * at_watchdog - Timer Call-back >+ * @data: pointer to netdev cast into an unsigned long >+ **/ >+ >+static void >+at_watchdog(unsigned long data) >+{ >+ struct at_adapter *adapter = (struct at_adapter *) data; >+ u32 drop_rxd, drop_rxs; >+ unsigned long flags; >+ >+ spin_lock_irqsave(&adapter->stats_lock, flags); >+ drop_rxd = AT_READ_REG(&adapter->hw, REG_STS_RXD_OV); >+ drop_rxs = AT_READ_REG(&adapter->hw, REG_STS_RXS_OV); >+ adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs); >+ >+ spin_unlock_irqrestore(&adapter->stats_lock, flags); >+ >+ /* Reset the timer */ >+ mod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ); >+} >+ >+ >+ >diff -ruN -a -p old/drivers/net/atl2/at_osdep.h new/drivers/net/atl2/at_osdep.h >--- old/drivers/net/atl2/at_osdep.h 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at_osdep.h 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,112 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#ifndef _ATTANSIC_OS_DEP_H_ >+#define _ATTANSIC_OS_DEP_H_ >+ >+#include <linux/pci.h> >+#include <linux/delay.h> >+#include <linux/interrupt.h> >+#include <linux/if_ether.h> >+ >+#include "kcompat.h" >+ >+#define usec_delay(x) udelay(x) >+#ifndef msec_delay >+#define msec_delay(x) do { if(in_interrupt()) { \ >+ /* Don't mdelay in interrupt context! */ \ >+ BUG(); \ >+ } else { \ >+ msleep(x); \ >+ } } while (0) >+ >+/* Some workarounds require millisecond delays and are run during interrupt >+ * context. Most notably, when establishing link, the phy may need tweaking >+ * but cannot process phy register reads/writes faster than millisecond >+ * intervals...and we establish link due to a "link status change" interrupt. >+ */ >+#define msec_delay_irq(x) mdelay(x) >+#endif >+ >+ >+#define PCI_COMMAND_REGISTER PCI_COMMAND >+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE >+#define ETH_ADDR_LEN ETH_ALEN >+ >+typedef enum { >+#undef FALSE >+ FALSE = 0, >+#undef TRUE >+ TRUE = 1 >+} boolean_t; >+ >+ >+ >+#if DBG >+#define DEBUGOUT(S) printk(KERN_DEBUG S "\n") >+#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A) >+#else >+#define DEBUGOUT(S) >+#define DEBUGOUT1(S, A...) >+#endif >+ >+#define DEBUGFUNC(F) DEBUGOUT(F) >+#define DEBUGOUT2 DEBUGOUT1 >+#define DEBUGOUT3 DEBUGOUT2 >+#define DEBUGOUT7 DEBUGOUT3 >+ >+ >+#define AT_WRITE_REG(a, reg, value) ( \ >+ writel((value), ((a)->hw_addr + reg))) >+ >+#define AT_WRITE_FLUSH(a) (\ >+ readl((a)->hw_addr)) >+ >+#define AT_READ_REG(a, reg) ( \ >+ readl((a)->hw_addr + reg )) >+ >+ >+#define AT_WRITE_REGB(a, reg, value) (\ >+ writeb((value), ((a)->hw_addr + reg))) >+ >+#define AT_READ_REGB(a, reg) (\ >+ readb((a)->hw_addr + reg)) >+ >+#define AT_WRITE_REGW(a, reg, value) (\ >+ writew((value), ((a)->hw_addr + reg))) >+ >+#define AT_READ_REGW(a, reg) (\ >+ readw((a)->hw_addr + reg)) >+ >+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ >+ writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) >+ >+#define AT_READ_REG_ARRAY(a, reg, offset) ( \ >+ readl(((a)->hw_addr + reg) + ((offset) << 2))) >+ >+ >+#endif//_ATTANSIC_OS_DEP_H_ >+ >diff -ruN -a -p old/drivers/net/atl2/at_param.c new/drivers/net/atl2/at_param.c >--- old/drivers/net/atl2/at_param.c 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/at_param.c 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,353 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#include <linux/netdevice.h> >+#include "at.h" >+ >+/* This is the only thing that needs to be changed to adjust the >+ * maximum number of ports that the driver can manage. >+ */ >+ >+#define AT_MAX_NIC 32 >+ >+#define OPTION_UNSET -1 >+#define OPTION_DISABLED 0 >+#define OPTION_ENABLED 1 >+ >+ >+ >+ /* All parameters are treated the same, as an integer array of values. >+ * This macro just reduces the need to repeat the same declaration code >+ * over and over (plus this helps to avoid typo bugs). >+ */ >+#define AT_PARAM_INIT { [0 ... AT_MAX_NIC] = OPTION_UNSET } >+#ifndef module_param_array >+/* Module Parameters are always initialized to -1, so that the driver >+ * can tell the difference between no user specified value or the >+ * user asking for the default value. >+ * The true default values are loaded in when at_check_options is called. >+ * >+ * This is a GCC extension to ANSI C. >+ * See the item "Labeled Elements in Initializers" in the section >+ * "Extensions to the C Language Family" of the GCC documentation. >+ */ >+ >+#define AT_PARAM(X, desc) \ >+ static const int __devinitdata X[AT_MAX_NIC+1] = AT_PARAM_INIT; \ >+ MODULE_PARM(X, "1-" __MODULE_STRING(AT_MAX_NIC) "i"); \ >+ MODULE_PARM_DESC(X, desc); >+#else >+#define AT_PARAM(X, desc) \ >+ static int __devinitdata X[AT_MAX_NIC+1] = AT_PARAM_INIT; \ >+ static int num_##X = 0; \ >+ module_param_array_named(X, X, int, &num_##X, 0); \ >+ MODULE_PARM_DESC(X, desc); >+#endif >+ >+/* Transmit Memory Size >+ * >+ * Valid Range: 64-2048 >+ * >+ * Default Value: 128 >+ */ >+#define AT_MIN_TX_MEMSIZE 4 // 4KB >+#define AT_MAX_TX_MEMSIZE 64 // 64KB >+#define AT_DEFAULT_TX_MEMSIZE 8 // 8KB >+AT_PARAM(TxMemSize, "Bytes of Transmit Memory"); >+ >+/* Receive Memory Block Count >+ * >+ * Valid Range: 16-512 >+ * >+ * Default Value: 128 >+ */ >+#define AT_MIN_RXD_COUNT 16 >+#define AT_MAX_RXD_COUNT 512 >+#define AT_DEFAULT_RXD_COUNT 64 >+AT_PARAM(RxMemBlock, "Number of receive memory block"); >+ >+/* User Specified MediaType Override >+ * >+ * Valid Range: 0-5 >+ * - 0 - auto-negotiate at all supported speeds >+ * - 1 - only link at 1000Mbps Full Duplex >+ * - 2 - only link at 100Mbps Full Duplex >+ * - 3 - only link at 100Mbps Half Duplex >+ * - 4 - only link at 10Mbps Full Duplex >+ * - 5 - only link at 10Mbps Half Duplex >+ * Default Value: 0 >+ */ >+ >+AT_PARAM(MediaType, "MediaType Select"); >+ >+/* Interrupt Moderate Timer in units of 2 us >+ * >+ * Valid Range: 10-65535 >+ * >+ * Default Value: 45000(90ms) >+ */ >+#define INT_MOD_DEFAULT_CNT 100 // 200us >+#define INT_MOD_MAX_CNT 65000 >+#define INT_MOD_MIN_CNT 50 >+AT_PARAM(IntModTimer, "Interrupt Moderator Timer"); >+ >+ >+ >+/* FlashVendor >+ * Valid Range: 0-2 >+ * 0 - Atmel >+ * 1 - SST >+ * 2 - ST >+ */ >+ >+AT_PARAM(FlashVendor, "SPI Flash Vendor"); >+ >+ >+ >+#define AUTONEG_ADV_DEFAULT 0x2F >+#define AUTONEG_ADV_MASK 0x2F >+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL >+ >+ >+ >+#define FLASH_VENDOR_DEFAULT 0 >+#define FLASH_VENDOR_MIN 0 >+#define FLASH_VENDOR_MAX 2 >+ >+ >+struct at_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 at_opt_list { int i; char *str; } *p; >+ } l; >+ } arg; >+}; >+ >+static int __devinit >+at_validate_option(int *value, struct at_option *opt) >+{ >+ if(*value == OPTION_UNSET) { >+ *value = opt->def; >+ return 0; >+ } >+ >+ switch (opt->type) { >+ case enable_option: >+ switch (*value) { >+ case OPTION_ENABLED: >+ printk(KERN_INFO "%s Enabled\n", opt->name); >+ return 0; >+ case OPTION_DISABLED: >+ printk(KERN_INFO "%s Disabled\n", opt->name); >+ return 0; >+ } >+ break; >+ case range_option: >+ if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) { >+ printk(KERN_INFO "%s set to %i\n", opt->name, *value); >+ return 0; >+ } >+ break; >+ case list_option: { >+ int i; >+ struct at_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') >+ printk(KERN_INFO "%s\n", ent->str); >+ return 0; >+ } >+ } >+ } >+ break; >+ default: >+ BUG(); >+ } >+ >+ printk(KERN_INFO "Invalid %s specified (%i) %s\n", >+ opt->name, *value, opt->err); >+ *value = opt->def; >+ return -1; >+} >+ >+/** >+ * at_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. >+ **/ >+ >+void __devinit >+at_check_options(struct at_adapter *adapter) >+{ >+ int bd = adapter->bd_number; >+ if(bd >= AT_MAX_NIC) { >+ printk(KERN_NOTICE >+ "Warning: no configuration for board #%i\n", bd); >+ printk(KERN_NOTICE "Using defaults for all values\n"); >+#ifndef module_param_array >+ bd = AT_MAX_NIC; >+#endif >+ } >+ >+ { /* Bytes of Transmit Memory */ >+ struct at_option opt = { >+ .type = range_option, >+ .name = "Bytes of Transmit Memory", >+ .err = "using default of " >+ __MODULE_STRING(AT_DEFAULT_TX_MEMSIZE), >+ .def = AT_DEFAULT_TX_MEMSIZE, >+ .arg = { .r = { .min = AT_MIN_TX_MEMSIZE, .max = AT_MAX_TX_MEMSIZE }} >+ }; >+ int val; >+#ifdef module_param_array >+ if(num_TxMemSize > bd) { >+#endif >+ val = TxMemSize[bd]; >+ at_validate_option(&val, &opt); >+ adapter->txd_ring_size = ((u32) val) * 1024; >+#ifdef module_param_array >+ } else { >+ adapter->txd_ring_size = ((u32)opt.def) * 1024; >+ } >+#endif >+ // txs ring size: >+ adapter->txs_ring_size = adapter->txd_ring_size / 128; >+ if (adapter->txs_ring_size > 160) >+ adapter->txs_ring_size = 160; >+ } >+ >+ { /* Receive Memory Block Count */ >+ struct at_option opt = { >+ .type = range_option, >+ .name = "Number of receive memory block", >+ .err = "using default of " >+ __MODULE_STRING(AT_DEFAULT_RXD_COUNT), >+ .def = AT_DEFAULT_RXD_COUNT, >+ .arg = { .r = { .min = AT_MIN_RXD_COUNT, .max = AT_MAX_RXD_COUNT }} >+ }; >+ int val; >+#ifdef module_param_array >+ if(num_RxMemBlock > bd) { >+#endif >+ val = RxMemBlock[bd]; >+ at_validate_option(&val, &opt); >+ adapter->rxd_ring_size = (u32)val; //((u16)val)&~1; // even number >+#ifdef module_param_array >+ } else { >+ adapter->rxd_ring_size = (u32)opt.def; >+ } >+#endif >+ >+ // init RXD Flow control value >+ adapter->hw.fc_rxd_hi = (adapter->rxd_ring_size/8)*7; >+ adapter->hw.fc_rxd_lo = (AT_MIN_RXD_COUNT/8) > (adapter->rxd_ring_size/12) ? >+ (AT_MIN_RXD_COUNT/8) : (adapter->rxd_ring_size/12); >+ } >+ >+ { /* Interrupt Moderate Timer */ >+ struct at_option opt = { >+ .type = range_option, >+ .name = "Interrupt Moderate Timer", >+ .err = "using default of " __MODULE_STRING(INT_MOD_DEFAULT_CNT), >+ .def = INT_MOD_DEFAULT_CNT, >+ .arg = { .r = { .min = INT_MOD_MIN_CNT, .max = INT_MOD_MAX_CNT }} >+ } ; >+ int val; >+#ifdef module_param_array >+ if(num_IntModTimer > bd) { >+#endif >+ val = IntModTimer[bd]; >+ at_validate_option(&val, &opt); >+ adapter->imt = (u16) val; >+#ifdef module_param_array >+ } else { >+ adapter->imt = (u16)(opt.def); >+ } >+#endif >+ } >+ >+ { /* Flash Vendor */ >+ struct at_option opt = { >+ .type = range_option, >+ .name = "SPI Flash Vendor", >+ .err = "using default of " __MODULE_STRING(FLASH_VENDOR_DEFAULT), >+ .def = FLASH_VENDOR_DEFAULT, >+ .arg = { .r = { .min = FLASH_VENDOR_MIN, .max = FLASH_VENDOR_MAX }} >+ } ; >+ int val; >+#ifdef module_param_array >+ if(num_FlashVendor > bd) { >+#endif >+ val = FlashVendor[bd]; >+ at_validate_option(&val, &opt); >+ adapter->hw.flash_vendor = (u8) val; >+#ifdef module_param_array >+ } else { >+ adapter->hw.flash_vendor = (u8)(opt.def); >+ } >+#endif >+ } >+ >+ { /* MediaType */ >+ struct at_option opt = { >+ .type = range_option, >+ .name = "Speed/Duplex Selection", >+ .err = "using default of " __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR), >+ .def = MEDIA_TYPE_AUTO_SENSOR, >+ .arg = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR, .max = MEDIA_TYPE_10M_HALF }} >+ } ; >+ int val; >+#ifdef module_param_array >+ if(num_MediaType > bd) { >+#endif >+ val = MediaType[bd]; >+ at_validate_option(&val, &opt); >+ adapter->hw.MediaType = (u16) val; >+#ifdef module_param_array >+ } else { >+ adapter->hw.MediaType = (u16)(opt.def); >+ } >+#endif >+ } >+} >+ >+ >+ >diff -ruN -a -p old/drivers/net/atl2/kcompat.c new/drivers/net/atl2/kcompat.c >--- old/drivers/net/atl2/kcompat.c 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/kcompat.c 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,227 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#include "kcompat.h" >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) >+ >+/**************************************/ >+/* PCI DMA MAPPING */ >+ >+#if defined(CONFIG_HIGHMEM) >+ >+#ifndef PCI_DRAM_OFFSET >+#define PCI_DRAM_OFFSET 0 >+#endif >+ >+u64 >+_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, >+ size_t size, int direction) >+{ >+ return (((u64) (page - mem_map) << PAGE_SHIFT) + offset + >+ PCI_DRAM_OFFSET); >+} >+ >+#else /* CONFIG_HIGHMEM */ >+ >+u64 >+_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, >+ size_t size, int direction) >+{ >+ return pci_map_single(dev, (void *)page_address(page) + offset, size, >+ direction); >+} >+ >+#endif /* CONFIG_HIGHMEM */ >+ >+void >+_kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, >+ int direction) >+{ >+ return pci_unmap_single(dev, dma_addr, size, direction); >+} >+ >+#endif /* 2.4.13 => 2.4.3 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) >+ >+/**************************************/ >+/* PCI DRIVER API */ >+ >+int >+_kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) >+{ >+ if (!pci_dma_supported(dev, mask)) >+ return -EIO; >+ dev->dma_mask = mask; >+ return 0; >+} >+ >+int >+_kc_pci_request_regions(struct pci_dev *dev, char *res_name) >+{ >+ int i; >+ >+ for (i = 0; i < 6; i++) { >+ if (pci_resource_len(dev, i) == 0) >+ continue; >+ >+ if (pci_resource_flags(dev, i) & IORESOURCE_IO) { >+ if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { >+ pci_release_regions(dev); >+ return -EBUSY; >+ } >+ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { >+ if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { >+ pci_release_regions(dev); >+ return -EBUSY; >+ } >+ } >+ } >+ return 0; >+} >+ >+void >+_kc_pci_release_regions(struct pci_dev *dev) >+{ >+ int i; >+ >+ for (i = 0; i < 6; i++) { >+ if (pci_resource_len(dev, i) == 0) >+ continue; >+ >+ if (pci_resource_flags(dev, i) & IORESOURCE_IO) >+ release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); >+ >+ else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) >+ release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); >+ } >+} >+ >+/**************************************/ >+/* NETWORK DRIVER API */ >+ >+struct net_device * >+_kc_alloc_etherdev(int sizeof_priv) >+{ >+ struct net_device *dev; >+ int alloc_size; >+ >+ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31; >+ dev = kmalloc(alloc_size, GFP_KERNEL); >+ if (!dev) >+ return NULL; >+ memset(dev, 0, alloc_size); >+ >+ if (sizeof_priv) >+ dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); >+ dev->name[0] = '\0'; >+ ether_setup(dev); >+ >+ return dev; >+} >+ >+int >+_kc_is_valid_ether_addr(u8 *addr) >+{ >+ const char zaddr[6] = { 0, }; >+ >+ return !(addr[0] & 1) && memcmp(addr, zaddr, 6); >+} >+ >+#endif /* 2.4.3 => 2.4.0 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) >+ >+int >+_kc_pci_set_power_state(struct pci_dev *dev, int state) >+{ >+ return 0; >+} >+ >+int >+_kc_pci_save_state(struct pci_dev *dev, u32 *buffer) >+{ >+ return 0; >+} >+ >+int >+_kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) >+{ >+ return 0; >+} >+ >+int >+_kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) >+{ >+ return 0; >+} >+ >+#endif /* 2.4.6 => 2.4.3 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) >+void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, >+ int off, int size) >+{ >+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; >+ frag->page = page; >+ frag->page_offset = off; >+ frag->size = size; >+ skb_shinfo(skb)->nr_frags = i + 1; >+} >+ >+#endif /* 2.6.0 => 2.4.6 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) >+void *_kc_kzalloc(size_t size, int flags) >+{ >+ void *ret = kmalloc(size, flags); >+ if (ret) >+ memset(ret, 0, size); >+ return ret; >+} >+#endif /* <= 2.6.13 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) >+struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, >+ unsigned int length) >+{ >+ /* 16 == NET_PAD_SKB */ >+ struct sk_buff *skb; >+ skb = alloc_skb(length + 16, GFP_ATOMIC); >+ if (likely(skb != NULL)) { >+ skb_reserve(skb, 16); >+ skb->dev = dev; >+ } >+ return skb; >+} >+#endif /* <= 2.6.17 */ >diff -ruN -a -p old/drivers/net/atl2/kcompat_ethtool.c new/drivers/net/atl2/kcompat_ethtool.c >--- old/drivers/net/atl2/kcompat_ethtool.c 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/kcompat_ethtool.c 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,1161 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+/* >+ * net/core/ethtool.c - Ethtool ioctl handler >+ * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx> >+ * >+ * This file is where we call all the ethtool_ops commands to get >+ * the information ethtool needs. We fall back to calling do_ioctl() >+ * for drivers which haven't been converted to ethtool_ops yet. >+ * >+ * It's GPL, stupid. >+ * >+ * Modification by sfeldma@pobox.com to work as backward compat >+ * solution for pre-ethtool_ops kernels. >+ * - copied struct ethtool_ops from ethtool.h >+ * - defined SET_ETHTOOL_OPS >+ * - put in some #ifndef NETIF_F_xxx wrappers >+ * - changes refs to dev->ethtool_ops to ethtool_ops >+ * - changed dev_ethtool to ethtool_ioctl >+ * - remove EXPORT_SYMBOL()s >+ * - added _kc_ prefix in built-in ethtool_op_xxx ops. >+ */ >+ >+#include <linux/module.h> >+#include <linux/types.h> >+#include <linux/errno.h> >+#include <linux/mii.h> >+#include <linux/ethtool.h> >+#include <linux/netdevice.h> >+#include <asm/uaccess.h> >+ >+#include "kcompat.h" >+ >+#undef SUPPORTED_10000baseT_Full >+#define SUPPORTED_10000baseT_Full (1 << 12) >+#undef ADVERTISED_10000baseT_Full >+#define ADVERTISED_10000baseT_Full (1 << 12) >+#undef SPEED_10000 >+#define SPEED_10000 10000 >+ >+#undef ethtool_ops >+#define ethtool_ops _kc_ethtool_ops >+ >+struct _kc_ethtool_ops { >+ int (*get_settings)(struct net_device *, struct ethtool_cmd *); >+ int (*set_settings)(struct net_device *, struct ethtool_cmd *); >+ void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); >+ int (*get_regs_len)(struct net_device *); >+ void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); >+ void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); >+ int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); >+ u32 (*get_msglevel)(struct net_device *); >+ void (*set_msglevel)(struct net_device *, u32); >+ int (*nway_reset)(struct net_device *); >+ u32 (*get_link)(struct net_device *); >+ int (*get_eeprom_len)(struct net_device *); >+ int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); >+ int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); >+ int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); >+ int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); >+ void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); >+ int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); >+ void (*get_pauseparam)(struct net_device *, >+ struct ethtool_pauseparam*); >+ int (*set_pauseparam)(struct net_device *, >+ struct ethtool_pauseparam*); >+ u32 (*get_rx_csum)(struct net_device *); >+ int (*set_rx_csum)(struct net_device *, u32); >+ u32 (*get_tx_csum)(struct net_device *); >+ int (*set_tx_csum)(struct net_device *, u32); >+ u32 (*get_sg)(struct net_device *); >+ int (*set_sg)(struct net_device *, u32); >+ u32 (*get_tso)(struct net_device *); >+ int (*set_tso)(struct net_device *, u32); >+ int (*self_test_count)(struct net_device *); >+ void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); >+ void (*get_strings)(struct net_device *, u32 stringset, u8 *); >+ int (*phys_id)(struct net_device *, u32); >+ int (*get_stats_count)(struct net_device *); >+ void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, >+ u64 *); >+} *ethtool_ops = NULL; >+ >+#undef SET_ETHTOOL_OPS >+#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) >+ >+/* >+ * Some useful ethtool_ops methods that are device independent. If we find that >+ * all drivers want to do the same thing here, we can turn these into dev_() >+ * function calls. >+ */ >+ >+#undef ethtool_op_get_link >+#define ethtool_op_get_link _kc_ethtool_op_get_link >+u32 _kc_ethtool_op_get_link(struct net_device *dev) >+{ >+ return netif_carrier_ok(dev) ? 1 : 0; >+} >+ >+#undef ethtool_op_get_tx_csum >+#define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum >+u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev) >+{ >+#ifdef NETIF_F_IP_CSUM >+ return (dev->features & NETIF_F_IP_CSUM) != 0; >+#else >+ return 0; >+#endif >+} >+ >+#undef ethtool_op_set_tx_csum >+#define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum >+int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) >+{ >+#ifdef NETIF_F_IP_CSUM >+ if (data) >+ dev->features |= NETIF_F_IP_CSUM; >+ else >+ dev->features &= ~NETIF_F_IP_CSUM; >+#endif >+ >+ return 0; >+} >+ >+#undef ethtool_op_get_sg >+#define ethtool_op_get_sg _kc_ethtool_op_get_sg >+u32 _kc_ethtool_op_get_sg(struct net_device *dev) >+{ >+#ifdef NETIF_F_SG >+ return (dev->features & NETIF_F_SG) != 0; >+#else >+ return 0; >+#endif >+} >+ >+#undef ethtool_op_set_sg >+#define ethtool_op_set_sg _kc_ethtool_op_set_sg >+int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) >+{ >+#ifdef NETIF_F_SG >+ if (data) >+ dev->features |= NETIF_F_SG; >+ else >+ dev->features &= ~NETIF_F_SG; >+#endif >+ >+ return 0; >+} >+ >+#undef ethtool_op_get_tso >+#define ethtool_op_get_tso _kc_ethtool_op_get_tso >+u32 _kc_ethtool_op_get_tso(struct net_device *dev) >+{ >+#ifdef NETIF_F_TSO >+ return (dev->features & NETIF_F_TSO) != 0; >+#else >+ return 0; >+#endif >+} >+ >+#undef ethtool_op_set_tso >+#define ethtool_op_set_tso _kc_ethtool_op_set_tso >+int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data) >+{ >+#ifdef NETIF_F_TSO >+ if (data) >+ dev->features |= NETIF_F_TSO; >+ else >+ dev->features &= ~NETIF_F_TSO; >+#endif >+ >+ return 0; >+} >+ >+/* Handlers for each ethtool command */ >+ >+static int ethtool_get_settings(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_cmd cmd = { ETHTOOL_GSET }; >+ int err; >+ >+ if (!ethtool_ops->get_settings) >+ return -EOPNOTSUPP; >+ >+ err = ethtool_ops->get_settings(dev, &cmd); >+ if (err < 0) >+ return err; >+ >+ if (copy_to_user(useraddr, &cmd, sizeof(cmd))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_settings(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_cmd cmd; >+ >+ if (!ethtool_ops->set_settings) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&cmd, useraddr, sizeof(cmd))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_settings(dev, &cmd); >+} >+ >+static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_drvinfo info; >+ struct ethtool_ops *ops = ethtool_ops; >+ >+ if (!ops->get_drvinfo) >+ return -EOPNOTSUPP; >+ >+ memset(&info, 0, sizeof(info)); >+ info.cmd = ETHTOOL_GDRVINFO; >+ ops->get_drvinfo(dev, &info); >+ >+ if (ops->self_test_count) >+ info.testinfo_len = ops->self_test_count(dev); >+ if (ops->get_stats_count) >+ info.n_stats = ops->get_stats_count(dev); >+ if (ops->get_regs_len) >+ info.regdump_len = ops->get_regs_len(dev); >+ if (ops->get_eeprom_len) >+ info.eedump_len = ops->get_eeprom_len(dev); >+ >+ if (copy_to_user(useraddr, &info, sizeof(info))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_get_regs(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_regs regs; >+ struct ethtool_ops *ops = ethtool_ops; >+ void *regbuf; >+ int reglen, ret; >+ >+ if (!ops->get_regs || !ops->get_regs_len) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(®s, useraddr, sizeof(regs))) >+ return -EFAULT; >+ >+ reglen = ops->get_regs_len(dev); >+ if (regs.len > reglen) >+ regs.len = reglen; >+ >+ regbuf = kmalloc(reglen, GFP_USER); >+ if (!regbuf) >+ return -ENOMEM; >+ >+ ops->get_regs(dev, ®s, regbuf); >+ >+ ret = -EFAULT; >+ if (copy_to_user(useraddr, ®s, sizeof(regs))) >+ goto out; >+ useraddr += offsetof(struct ethtool_regs, data); >+ if (copy_to_user(useraddr, regbuf, reglen)) >+ goto out; >+ ret = 0; >+ >+out: >+ kfree(regbuf); >+ return ret; >+} >+ >+static int ethtool_get_wol(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; >+ >+ if (!ethtool_ops->get_wol) >+ return -EOPNOTSUPP; >+ >+ ethtool_ops->get_wol(dev, &wol); >+ >+ if (copy_to_user(useraddr, &wol, sizeof(wol))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_wol(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_wolinfo wol; >+ >+ if (!ethtool_ops->set_wol) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&wol, useraddr, sizeof(wol))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_wol(dev, &wol); >+} >+ >+static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata = { ETHTOOL_GMSGLVL }; >+ >+ if (!ethtool_ops->get_msglevel) >+ return -EOPNOTSUPP; >+ >+ edata.data = ethtool_ops->get_msglevel(dev); >+ >+ if (copy_to_user(useraddr, &edata, sizeof(edata))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata; >+ >+ if (!ethtool_ops->set_msglevel) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&edata, useraddr, sizeof(edata))) >+ return -EFAULT; >+ >+ ethtool_ops->set_msglevel(dev, edata.data); >+ return 0; >+} >+ >+static int ethtool_nway_reset(struct net_device *dev) >+{ >+ if (!ethtool_ops->nway_reset) >+ return -EOPNOTSUPP; >+ >+ return ethtool_ops->nway_reset(dev); >+} >+ >+static int ethtool_get_link(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_value edata = { ETHTOOL_GLINK }; >+ >+ if (!ethtool_ops->get_link) >+ return -EOPNOTSUPP; >+ >+ edata.data = ethtool_ops->get_link(dev); >+ >+ if (copy_to_user(useraddr, &edata, sizeof(edata))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_eeprom eeprom; >+ struct ethtool_ops *ops = ethtool_ops; >+ u8 *data; >+ int ret; >+ >+ if (!ops->get_eeprom || !ops->get_eeprom_len) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) >+ return -EFAULT; >+ >+ /* Check for wrap and zero */ >+ if (eeprom.offset + eeprom.len <= eeprom.offset) >+ return -EINVAL; >+ >+ /* Check for exceeding total eeprom len */ >+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) >+ return -EINVAL; >+ >+ data = kmalloc(eeprom.len, GFP_USER); >+ if (!data) >+ return -ENOMEM; >+ >+ ret = -EFAULT; >+ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) >+ goto out; >+ >+ ret = ops->get_eeprom(dev, &eeprom, data); >+ if (ret) >+ goto out; >+ >+ ret = -EFAULT; >+ if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) >+ goto out; >+ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) >+ goto out; >+ ret = 0; >+ >+out: >+ kfree(data); >+ return ret; >+} >+ >+static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_eeprom eeprom; >+ struct ethtool_ops *ops = ethtool_ops; >+ u8 *data; >+ int ret; >+ >+ if (!ops->set_eeprom || !ops->get_eeprom_len) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) >+ return -EFAULT; >+ >+ /* Check for wrap and zero */ >+ if (eeprom.offset + eeprom.len <= eeprom.offset) >+ return -EINVAL; >+ >+ /* Check for exceeding total eeprom len */ >+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) >+ return -EINVAL; >+ >+ data = kmalloc(eeprom.len, GFP_USER); >+ if (!data) >+ return -ENOMEM; >+ >+ ret = -EFAULT; >+ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) >+ goto out; >+ >+ ret = ops->set_eeprom(dev, &eeprom, data); >+ if (ret) >+ goto out; >+ >+ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) >+ ret = -EFAULT; >+ >+out: >+ kfree(data); >+ return ret; >+} >+ >+static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; >+ >+ if (!ethtool_ops->get_coalesce) >+ return -EOPNOTSUPP; >+ >+ ethtool_ops->get_coalesce(dev, &coalesce); >+ >+ if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_coalesce coalesce; >+ >+ if (!ethtool_ops->get_coalesce) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_coalesce(dev, &coalesce); >+} >+ >+static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; >+ >+ if (!ethtool_ops->get_ringparam) >+ return -EOPNOTSUPP; >+ >+ ethtool_ops->get_ringparam(dev, &ringparam); >+ >+ if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_ringparam ringparam; >+ >+ if (!ethtool_ops->get_ringparam) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_ringparam(dev, &ringparam); >+} >+ >+static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; >+ >+ if (!ethtool_ops->get_pauseparam) >+ return -EOPNOTSUPP; >+ >+ ethtool_ops->get_pauseparam(dev, &pauseparam); >+ >+ if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_pauseparam pauseparam; >+ >+ if (!ethtool_ops->get_pauseparam) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_pauseparam(dev, &pauseparam); >+} >+ >+static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata = { ETHTOOL_GRXCSUM }; >+ >+ if (!ethtool_ops->get_rx_csum) >+ return -EOPNOTSUPP; >+ >+ edata.data = ethtool_ops->get_rx_csum(dev); >+ >+ if (copy_to_user(useraddr, &edata, sizeof(edata))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata; >+ >+ if (!ethtool_ops->set_rx_csum) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&edata, useraddr, sizeof(edata))) >+ return -EFAULT; >+ >+ ethtool_ops->set_rx_csum(dev, edata.data); >+ return 0; >+} >+ >+static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata = { ETHTOOL_GTXCSUM }; >+ >+ if (!ethtool_ops->get_tx_csum) >+ return -EOPNOTSUPP; >+ >+ edata.data = ethtool_ops->get_tx_csum(dev); >+ >+ if (copy_to_user(useraddr, &edata, sizeof(edata))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata; >+ >+ if (!ethtool_ops->set_tx_csum) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&edata, useraddr, sizeof(edata))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_tx_csum(dev, edata.data); >+} >+ >+static int ethtool_get_sg(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata = { ETHTOOL_GSG }; >+ >+ if (!ethtool_ops->get_sg) >+ return -EOPNOTSUPP; >+ >+ edata.data = ethtool_ops->get_sg(dev); >+ >+ if (copy_to_user(useraddr, &edata, sizeof(edata))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_sg(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata; >+ >+ if (!ethtool_ops->set_sg) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&edata, useraddr, sizeof(edata))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_sg(dev, edata.data); >+} >+ >+static int ethtool_get_tso(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata = { ETHTOOL_GTSO }; >+ >+ if (!ethtool_ops->get_tso) >+ return -EOPNOTSUPP; >+ >+ edata.data = ethtool_ops->get_tso(dev); >+ >+ if (copy_to_user(useraddr, &edata, sizeof(edata))) >+ return -EFAULT; >+ return 0; >+} >+ >+static int ethtool_set_tso(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_value edata; >+ >+ if (!ethtool_ops->set_tso) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&edata, useraddr, sizeof(edata))) >+ return -EFAULT; >+ >+ return ethtool_ops->set_tso(dev, edata.data); >+} >+ >+static int ethtool_self_test(struct net_device *dev, char *useraddr) >+{ >+ struct ethtool_test test; >+ struct ethtool_ops *ops = ethtool_ops; >+ u64 *data; >+ int ret; >+ >+ if (!ops->self_test || !ops->self_test_count) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&test, useraddr, sizeof(test))) >+ return -EFAULT; >+ >+ test.len = ops->self_test_count(dev); >+ data = kmalloc(test.len * sizeof(u64), GFP_USER); >+ if (!data) >+ return -ENOMEM; >+ >+ ops->self_test(dev, &test, data); >+ >+ ret = -EFAULT; >+ if (copy_to_user(useraddr, &test, sizeof(test))) >+ goto out; >+ useraddr += sizeof(test); >+ if (copy_to_user(useraddr, data, test.len * sizeof(u64))) >+ goto out; >+ ret = 0; >+ >+out: >+ kfree(data); >+ return ret; >+} >+ >+static int ethtool_get_strings(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_gstrings gstrings; >+ struct ethtool_ops *ops = ethtool_ops; >+ u8 *data; >+ int ret; >+ >+ if (!ops->get_strings) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) >+ return -EFAULT; >+ >+ switch (gstrings.string_set) { >+ case ETH_SS_TEST: >+ if (!ops->self_test_count) >+ return -EOPNOTSUPP; >+ gstrings.len = ops->self_test_count(dev); >+ break; >+ case ETH_SS_STATS: >+ if (!ops->get_stats_count) >+ return -EOPNOTSUPP; >+ gstrings.len = ops->get_stats_count(dev); >+ break; >+ default: >+ return -EINVAL; >+ } >+ >+ data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); >+ if (!data) >+ return -ENOMEM; >+ >+ ops->get_strings(dev, gstrings.string_set, data); >+ >+ ret = -EFAULT; >+ if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) >+ goto out; >+ useraddr += sizeof(gstrings); >+ if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) >+ goto out; >+ ret = 0; >+ >+out: >+ kfree(data); >+ return ret; >+} >+ >+static int ethtool_phys_id(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_value id; >+ >+ if (!ethtool_ops->phys_id) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&id, useraddr, sizeof(id))) >+ return -EFAULT; >+ >+ return ethtool_ops->phys_id(dev, id.data); >+} >+ >+static int ethtool_get_stats(struct net_device *dev, void *useraddr) >+{ >+ struct ethtool_stats stats; >+ struct ethtool_ops *ops = ethtool_ops; >+ u64 *data; >+ int ret; >+ >+ if (!ops->get_ethtool_stats || !ops->get_stats_count) >+ return -EOPNOTSUPP; >+ >+ if (copy_from_user(&stats, useraddr, sizeof(stats))) >+ return -EFAULT; >+ >+ stats.n_stats = ops->get_stats_count(dev); >+ data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); >+ if (!data) >+ return -ENOMEM; >+ >+ ops->get_ethtool_stats(dev, &stats, data); >+ >+ ret = -EFAULT; >+ if (copy_to_user(useraddr, &stats, sizeof(stats))) >+ goto out; >+ useraddr += sizeof(stats); >+ if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) >+ goto out; >+ ret = 0; >+ >+out: >+ kfree(data); >+ return ret; >+} >+ >+/* The main entry point in this file. Called from net/core/dev.c */ >+ >+#define ETHTOOL_OPS_COMPAT >+int ethtool_ioctl(struct ifreq *ifr) >+{ >+ struct net_device *dev = __dev_get_by_name(ifr->ifr_name); >+ void *useraddr = (void *) ifr->ifr_data; >+ u32 ethcmd; >+ >+ /* >+ * XXX: This can be pushed down into the ethtool_* handlers that >+ * need it. Keep existing behaviour for the moment. >+ */ >+ if (!capable(CAP_NET_ADMIN)) >+ return -EPERM; >+ >+ if (!dev || !netif_device_present(dev)) >+ return -ENODEV; >+ >+ if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) >+ return -EFAULT; >+ >+ switch (ethcmd) { >+ case ETHTOOL_GSET: >+ return ethtool_get_settings(dev, useraddr); >+ case ETHTOOL_SSET: >+ return ethtool_set_settings(dev, useraddr); >+ case ETHTOOL_GDRVINFO: >+ return ethtool_get_drvinfo(dev, useraddr); >+ case ETHTOOL_GREGS: >+ return ethtool_get_regs(dev, useraddr); >+ case ETHTOOL_GWOL: >+ return ethtool_get_wol(dev, useraddr); >+ case ETHTOOL_SWOL: >+ return ethtool_set_wol(dev, useraddr); >+ case ETHTOOL_GMSGLVL: >+ return ethtool_get_msglevel(dev, useraddr); >+ case ETHTOOL_SMSGLVL: >+ return ethtool_set_msglevel(dev, useraddr); >+ case ETHTOOL_NWAY_RST: >+ return ethtool_nway_reset(dev); >+ case ETHTOOL_GLINK: >+ return ethtool_get_link(dev, useraddr); >+ case ETHTOOL_GEEPROM: >+ return ethtool_get_eeprom(dev, useraddr); >+ case ETHTOOL_SEEPROM: >+ return ethtool_set_eeprom(dev, useraddr); >+ case ETHTOOL_GCOALESCE: >+ return ethtool_get_coalesce(dev, useraddr); >+ case ETHTOOL_SCOALESCE: >+ return ethtool_set_coalesce(dev, useraddr); >+ case ETHTOOL_GRINGPARAM: >+ return ethtool_get_ringparam(dev, useraddr); >+ case ETHTOOL_SRINGPARAM: >+ return ethtool_set_ringparam(dev, useraddr); >+ case ETHTOOL_GPAUSEPARAM: >+ return ethtool_get_pauseparam(dev, useraddr); >+ case ETHTOOL_SPAUSEPARAM: >+ return ethtool_set_pauseparam(dev, useraddr); >+ case ETHTOOL_GRXCSUM: >+ return ethtool_get_rx_csum(dev, useraddr); >+ case ETHTOOL_SRXCSUM: >+ return ethtool_set_rx_csum(dev, useraddr); >+ case ETHTOOL_GTXCSUM: >+ return ethtool_get_tx_csum(dev, useraddr); >+ case ETHTOOL_STXCSUM: >+ return ethtool_set_tx_csum(dev, useraddr); >+ case ETHTOOL_GSG: >+ return ethtool_get_sg(dev, useraddr); >+ case ETHTOOL_SSG: >+ return ethtool_set_sg(dev, useraddr); >+ case ETHTOOL_GTSO: >+ return ethtool_get_tso(dev, useraddr); >+ case ETHTOOL_STSO: >+ return ethtool_set_tso(dev, useraddr); >+ case ETHTOOL_TEST: >+ return ethtool_self_test(dev, useraddr); >+ case ETHTOOL_GSTRINGS: >+ return ethtool_get_strings(dev, useraddr); >+ case ETHTOOL_PHYS_ID: >+ return ethtool_phys_id(dev, useraddr); >+ case ETHTOOL_GSTATS: >+ return ethtool_get_stats(dev, useraddr); >+ default: >+ return -EOPNOTSUPP; >+ } >+ >+ return -EOPNOTSUPP; >+} >+ >+#define mii_if_info _kc_mii_if_info >+struct _kc_mii_if_info { >+ int phy_id; >+ int advertising; >+ int phy_id_mask; >+ int reg_num_mask; >+ >+ unsigned int full_duplex : 1; /* is full duplex? */ >+ unsigned int force_media : 1; /* is autoneg. disabled? */ >+ >+ struct net_device *dev; >+ int (*mdio_read) (struct net_device *dev, int phy_id, int location); >+ void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val); >+}; >+ >+struct ethtool_cmd; >+struct mii_ioctl_data; >+ >+#undef mii_link_ok >+#define mii_link_ok _kc_mii_link_ok >+#undef mii_nway_restart >+#define mii_nway_restart _kc_mii_nway_restart >+#undef mii_ethtool_gset >+#define mii_ethtool_gset _kc_mii_ethtool_gset >+#undef mii_ethtool_sset >+#define mii_ethtool_sset _kc_mii_ethtool_sset >+#undef mii_check_link >+#define mii_check_link _kc_mii_check_link >+#undef generic_mii_ioctl >+#define generic_mii_ioctl _kc_generic_mii_ioctl >+extern int _kc_mii_link_ok (struct mii_if_info *mii); >+extern int _kc_mii_nway_restart (struct mii_if_info *mii); >+extern int _kc_mii_ethtool_gset(struct mii_if_info *mii, >+ struct ethtool_cmd *ecmd); >+extern int _kc_mii_ethtool_sset(struct mii_if_info *mii, >+ struct ethtool_cmd *ecmd); >+extern void _kc_mii_check_link (struct mii_if_info *mii); >+extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, >+ struct mii_ioctl_data *mii_data, int cmd, >+ unsigned int *duplex_changed); >+ >+ >+struct _kc_pci_dev_ext { >+ struct pci_dev *dev; >+ void *pci_drvdata; >+ struct pci_driver *driver; >+}; >+ >+struct _kc_net_dev_ext { >+ struct net_device *dev; >+ unsigned int carrier; >+}; >+ >+ >+/**************************************/ >+/* mii support */ >+ >+int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) >+{ >+ struct net_device *dev = mii->dev; >+ u32 advert, bmcr, lpa, nego; >+ >+ ecmd->supported = >+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | >+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | >+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); >+ >+ /* only supports twisted-pair */ >+ ecmd->port = PORT_MII; >+ >+ /* only supports internal transceiver */ >+ ecmd->transceiver = XCVR_INTERNAL; >+ >+ /* this isn't fully supported at higher layers */ >+ ecmd->phy_address = mii->phy_id; >+ >+ ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; >+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); >+ if (advert & ADVERTISE_10HALF) >+ ecmd->advertising |= ADVERTISED_10baseT_Half; >+ if (advert & ADVERTISE_10FULL) >+ ecmd->advertising |= ADVERTISED_10baseT_Full; >+ if (advert & ADVERTISE_100HALF) >+ ecmd->advertising |= ADVERTISED_100baseT_Half; >+ if (advert & ADVERTISE_100FULL) >+ ecmd->advertising |= ADVERTISED_100baseT_Full; >+ >+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); >+ lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); >+ if (bmcr & BMCR_ANENABLE) { >+ ecmd->advertising |= ADVERTISED_Autoneg; >+ ecmd->autoneg = AUTONEG_ENABLE; >+ >+ nego = mii_nway_result(advert & lpa); >+ if (nego == LPA_100FULL || nego == LPA_100HALF) >+ ecmd->speed = SPEED_100; >+ else >+ ecmd->speed = SPEED_10; >+ if (nego == LPA_100FULL || nego == LPA_10FULL) { >+ ecmd->duplex = DUPLEX_FULL; >+ mii->full_duplex = 1; >+ } else { >+ ecmd->duplex = DUPLEX_HALF; >+ mii->full_duplex = 0; >+ } >+ } else { >+ ecmd->autoneg = AUTONEG_DISABLE; >+ >+ ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; >+ ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; >+ } >+ >+ /* ignore maxtxpkt, maxrxpkt for now */ >+ >+ return 0; >+} >+ >+int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) >+{ >+ struct net_device *dev = mii->dev; >+ >+ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) >+ return -EINVAL; >+ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) >+ return -EINVAL; >+ if (ecmd->port != PORT_MII) >+ return -EINVAL; >+ if (ecmd->transceiver != XCVR_INTERNAL) >+ return -EINVAL; >+ if (ecmd->phy_address != mii->phy_id) >+ return -EINVAL; >+ if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) >+ return -EINVAL; >+ >+ /* ignore supported, maxtxpkt, maxrxpkt */ >+ >+ if (ecmd->autoneg == AUTONEG_ENABLE) { >+ u32 bmcr, advert, tmp; >+ >+ if ((ecmd->advertising & (ADVERTISED_10baseT_Half | >+ ADVERTISED_10baseT_Full | >+ ADVERTISED_100baseT_Half | >+ ADVERTISED_100baseT_Full)) == 0) >+ return -EINVAL; >+ >+ /* advertise only what has been requested */ >+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); >+ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); >+ if (ADVERTISED_10baseT_Half) >+ tmp |= ADVERTISE_10HALF; >+ if (ADVERTISED_10baseT_Full) >+ tmp |= ADVERTISE_10FULL; >+ if (ADVERTISED_100baseT_Half) >+ tmp |= ADVERTISE_100HALF; >+ if (ADVERTISED_100baseT_Full) >+ tmp |= ADVERTISE_100FULL; >+ if (advert != tmp) { >+ mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); >+ mii->advertising = tmp; >+ } >+ >+ /* turn on autonegotiation, and force a renegotiate */ >+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); >+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); >+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); >+ >+ mii->force_media = 0; >+ } else { >+ u32 bmcr, tmp; >+ >+ /* turn off auto negotiation, set speed and duplexity */ >+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); >+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX); >+ if (ecmd->speed == SPEED_100) >+ tmp |= BMCR_SPEED100; >+ if (ecmd->duplex == DUPLEX_FULL) { >+ tmp |= BMCR_FULLDPLX; >+ mii->full_duplex = 1; >+ } else >+ mii->full_duplex = 0; >+ if (bmcr != tmp) >+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); >+ >+ mii->force_media = 1; >+ } >+ return 0; >+} >+ >+int _kc_mii_link_ok (struct mii_if_info *mii) >+{ >+ /* first, a dummy read, needed to latch some MII phys */ >+ mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); >+ if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) >+ return 1; >+ return 0; >+} >+ >+int _kc_mii_nway_restart (struct mii_if_info *mii) >+{ >+ int bmcr; >+ int r = -EINVAL; >+ >+ /* if autoneg is off, it's an error */ >+ bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); >+ >+ if (bmcr & BMCR_ANENABLE) { >+ bmcr |= BMCR_ANRESTART; >+ mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); >+ r = 0; >+ } >+ >+ return r; >+} >+ >+void _kc_mii_check_link (struct mii_if_info *mii) >+{ >+ int cur_link = mii_link_ok(mii); >+ int prev_link = netif_carrier_ok(mii->dev); >+ >+ if (cur_link && !prev_link) >+ netif_carrier_on(mii->dev); >+ else if (prev_link && !cur_link) >+ netif_carrier_off(mii->dev); >+} >+ >+int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, >+ struct mii_ioctl_data *mii_data, int cmd, >+ unsigned int *duplex_chg_out) >+{ >+ int rc = 0; >+ unsigned int duplex_changed = 0; >+ >+ if (duplex_chg_out) >+ *duplex_chg_out = 0; >+ >+ mii_data->phy_id &= mii_if->phy_id_mask; >+ mii_data->reg_num &= mii_if->reg_num_mask; >+ >+ switch(cmd) { >+ case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */ >+ case SIOCGMIIPHY: >+ mii_data->phy_id = mii_if->phy_id; >+ /* fall through */ >+ >+ case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */ >+ case SIOCGMIIREG: >+ mii_data->val_out = >+ mii_if->mdio_read(mii_if->dev, mii_data->phy_id, >+ mii_data->reg_num); >+ break; >+ >+ case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */ >+ case SIOCSMIIREG: { >+ u16 val = mii_data->val_in; >+ >+ if (!capable(CAP_NET_ADMIN)) >+ return -EPERM; >+ >+ if (mii_data->phy_id == mii_if->phy_id) { >+ switch(mii_data->reg_num) { >+ case MII_BMCR: { >+ unsigned int new_duplex = 0; >+ if (val & (BMCR_RESET|BMCR_ANENABLE)) >+ mii_if->force_media = 0; >+ else >+ mii_if->force_media = 1; >+ if (mii_if->force_media && >+ (val & BMCR_FULLDPLX)) >+ new_duplex = 1; >+ if (mii_if->full_duplex != new_duplex) { >+ duplex_changed = 1; >+ mii_if->full_duplex = new_duplex; >+ } >+ break; >+ } >+ case MII_ADVERTISE: >+ mii_if->advertising = val; >+ break; >+ default: >+ /* do nothing */ >+ break; >+ } >+ } >+ >+ mii_if->mdio_write(mii_if->dev, mii_data->phy_id, >+ mii_data->reg_num, val); >+ break; >+ } >+ >+ default: >+ rc = -EOPNOTSUPP; >+ break; >+ } >+ >+ if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) >+ *duplex_chg_out = 1; >+ >+ return rc; >+} >+ >diff -ruN -a -p old/drivers/net/atl2/kcompat.h new/drivers/net/atl2/kcompat.h >--- old/drivers/net/atl2/kcompat.h 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/kcompat.h 2007-11-12 18:53:41.000000000 +0200 >@@ -0,0 +1,1166 @@ >+/* >+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. >+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.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. >+ * >+ * There are a lot of defines in here that are unused and/or have cryptic >+ * names. Please leave them alone, as they're the closest thing we have >+ * to a spec from Attansic at present. *ahem* -- CHS >+ */ >+ >+#ifndef _KCOMPAT_H_ >+#define _KCOMPAT_H_ >+ >+#include <linux/version.h> >+#include <linux/init.h> >+#include <linux/types.h> >+#include <linux/errno.h> >+#include <linux/module.h> >+#include <linux/pci.h> >+#include <linux/netdevice.h> >+#include <linux/etherdevice.h> >+#include <linux/skbuff.h> >+#include <linux/ioport.h> >+#include <linux/slab.h> >+#include <linux/list.h> >+#include <linux/delay.h> >+#include <linux/sched.h> >+#include <linux/in.h> >+#include <linux/ip.h> >+#include <linux/ipv6.h> >+#include <linux/udp.h> >+//#include <linux/mii.h> >+#include <asm/io.h> >+ >+ >+#include <linux/vmalloc.h> >+#include <linux/pagemap.h> >+#ifdef NETIF_F_TSO >+#include <net/checksum.h> >+#ifdef NETIF_F_TSO6 >+#include <net/ip6_checksum.h> >+#endif >+#endif >+#ifdef SIOCGMIIPHY >+#include <linux/mii.h> >+#endif >+#ifdef SIOCETHTOOL >+#include <linux/ethtool.h> >+#endif >+#ifdef NETIF_F_HW_VLAN_TX >+#include <linux/if_vlan.h> >+#endif >+ >+ >+/* general compatibility flags unclassified per kernel */ >+#ifdef DISABLE_PCI_MSI >+#undef CONFIG_PCI_MSI >+#endif >+ >+#ifdef DISABLE_PM >+#undef CONFIG_PM >+#endif >+ >+#ifdef DISABLE_NET_POLL_CONTROLLER >+#undef CONFIG_NET_POLL_CONTROLLER >+#endif >+ >+#ifndef PMSG_SUSPEND >+#define PMSG_SUSPEND 3 >+#endif >+ >+#ifndef module_param >+#define module_param(v,t,p) MODULE_PARM(v, "i"); >+#endif >+ >+#ifndef DMA_64BIT_MASK >+#define DMA_64BIT_MASK 0xffffffffffffffffULL >+#endif >+ >+#ifndef DMA_32BIT_MASK >+#define DMA_32BIT_MASK 0x00000000ffffffffULL >+#endif >+ >+#ifndef PCI_CAP_ID_EXP >+#define PCI_CAP_ID_EXP 0x10 >+#endif >+ >+#ifndef mmiowb >+#ifdef CONFIG_IA64 >+#define mmiowb() asm volatile ("mf.a" ::: "memory") >+#else >+#define mmiowb() >+#endif >+#endif >+ >+#ifndef IRQ_HANDLED >+#define irqreturn_t void >+#define IRQ_HANDLED >+#define IRQ_NONE >+#endif >+ >+#ifndef SET_NETDEV_DEV >+#define SET_NETDEV_DEV(net, pdev) >+#endif >+ >+#ifndef HAVE_FREE_NETDEV >+#define free_netdev(x) kfree(x) >+#endif >+ >+#ifdef HAVE_POLL_CONTROLLER >+#define CONFIG_NET_POLL_CONTROLLER >+#endif >+ >+#ifndef NETDEV_TX_OK >+#define NETDEV_TX_OK 0 >+#endif >+ >+#ifndef NETDEV_TX_BUSY >+#define NETDEV_TX_BUSY 1 >+#endif >+ >+#ifndef NETDEV_TX_LOCKED >+#define NETDEV_TX_LOCKED -1 >+#endif >+ >+#ifndef SKB_DATAREF_SHIFT >+/* if we do not have the infrastructure to detect if skb_header is cloned >+ just return false in all cases */ >+#define skb_header_cloned(x) 0 >+#endif >+ >+#ifndef NETIF_F_GSO >+#define gso_size tso_size >+#define gso_segs tso_segs >+#endif >+ >+#ifndef CHECKSUM_PARTIAL >+#define CHECKSUM_PARTIAL CHECKSUM_HW >+#define CHECKSUM_COMPLETE CHECKSUM_HW >+#endif >+ >+#ifndef __read_mostly >+#define __read_mostly >+#endif >+ >+#ifndef HAVE_NETIF_MSG >+#define HAVE_NETIF_MSG 1 >+enum { >+ NETIF_MSG_DRV = 0x0001, >+ NETIF_MSG_PROBE = 0x0002, >+ NETIF_MSG_LINK = 0x0004, >+ NETIF_MSG_TIMER = 0x0008, >+ NETIF_MSG_IFDOWN = 0x0010, >+ NETIF_MSG_IFUP = 0x0020, >+ NETIF_MSG_RX_ERR = 0x0040, >+ NETIF_MSG_TX_ERR = 0x0080, >+ NETIF_MSG_TX_QUEUED = 0x0100, >+ NETIF_MSG_INTR = 0x0200, >+ NETIF_MSG_TX_DONE = 0x0400, >+ NETIF_MSG_RX_STATUS = 0x0800, >+ NETIF_MSG_PKTDATA = 0x1000, >+ NETIF_MSG_HW = 0x2000, >+ NETIF_MSG_WOL = 0x4000, >+}; >+ >+#else >+#define NETIF_MSG_HW 0x2000 >+#define NETIF_MSG_WOL 0x4000 >+#endif /* HAVE_NETIF_MSG */ >+ >+#ifndef MII_RESV1 >+#define MII_RESV1 0x17 /* Reserved... */ >+#endif >+ >+#ifndef unlikely >+#define unlikely(_x) _x >+#define likely(_x) _x >+#endif >+ >+#ifndef WARN_ON >+#define WARN_ON(x) >+#endif >+ >+#ifndef PCI_DEVICE >+#define PCI_DEVICE(vend,dev) \ >+ .vendor = (vend), .device = (dev), \ >+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID >+#endif >+ >+#ifndef num_online_cpus >+#define num_online_cpus() smp_num_cpus >+#endif >+ >+#ifndef _LINUX_RANDOM_H >+#include <linux/random.h> >+#endif >+ >+/*****************************************************************************/ >+/* Installations with ethtool version without eeprom, adapter id, or statistics >+ * support */ >+ >+#ifndef ETH_GSTRING_LEN >+#define ETH_GSTRING_LEN 32 >+#endif >+ >+#ifndef ETHTOOL_GSTATS >+#define ETHTOOL_GSTATS 0x1d >+#undef ethtool_drvinfo >+#define ethtool_drvinfo k_ethtool_drvinfo >+struct k_ethtool_drvinfo { >+ u32 cmd; >+ char driver[32]; >+ char version[32]; >+ char fw_version[32]; >+ char bus_info[32]; >+ char reserved1[32]; >+ char reserved2[16]; >+ u32 n_stats; >+ u32 testinfo_len; >+ u32 eedump_len; >+ u32 regdump_len; >+}; >+ >+struct ethtool_stats { >+ u32 cmd; >+ u32 n_stats; >+ u64 data[0]; >+}; >+#endif /* ETHTOOL_GSTATS */ >+ >+#ifndef ETHTOOL_PHYS_ID >+#define ETHTOOL_PHYS_ID 0x1c >+#endif /* ETHTOOL_PHYS_ID */ >+ >+#ifndef ETHTOOL_GSTRINGS >+#define ETHTOOL_GSTRINGS 0x1b >+enum ethtool_stringset { >+ ETH_SS_TEST = 0, >+ ETH_SS_STATS, >+}; >+struct ethtool_gstrings { >+ u32 cmd; /* ETHTOOL_GSTRINGS */ >+ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ >+ u32 len; /* number of strings in the string set */ >+ u8 data[0]; >+}; >+#endif /* ETHTOOL_GSTRINGS */ >+ >+#ifndef ETHTOOL_TEST >+#define ETHTOOL_TEST 0x1a >+enum ethtool_test_flags { >+ ETH_TEST_FL_OFFLINE = (1 << 0), >+ ETH_TEST_FL_FAILED = (1 << 1), >+}; >+struct ethtool_test { >+ u32 cmd; >+ u32 flags; >+ u32 reserved; >+ u32 len; >+ u64 data[0]; >+}; >+#endif /* ETHTOOL_TEST */ >+ >+#ifndef ETHTOOL_GEEPROM >+#define ETHTOOL_GEEPROM 0xb >+#undef ETHTOOL_GREGS >+struct ethtool_eeprom { >+ u32 cmd; >+ u32 magic; >+ u32 offset; >+ u32 len; >+ u8 data[0]; >+}; >+ >+struct ethtool_value { >+ u32 cmd; >+ u32 data; >+}; >+#endif /* ETHTOOL_GEEPROM */ >+ >+#ifndef ETHTOOL_GLINK >+#define ETHTOOL_GLINK 0xa >+#endif /* ETHTOOL_GLINK */ >+ >+#ifndef ETHTOOL_GREGS >+#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ >+#define ethtool_regs _kc_ethtool_regs >+/* for passing big chunks of data */ >+struct _kc_ethtool_regs { >+ u32 cmd; >+ u32 version; /* driver-specific, indicates different chips/revs */ >+ u32 len; /* bytes */ >+ u8 data[0]; >+}; >+#endif /* ETHTOOL_GREGS */ >+ >+#ifndef ETHTOOL_GMSGLVL >+#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ >+#endif >+#ifndef ETHTOOL_SMSGLVL >+#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ >+#endif >+#ifndef ETHTOOL_NWAY_RST >+#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ >+#endif >+#ifndef ETHTOOL_GLINK >+#define ETHTOOL_GLINK 0x0000000a /* Get link status */ >+#endif >+#ifndef ETHTOOL_GEEPROM >+#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ >+#endif >+#ifndef ETHTOOL_SEEPROM >+#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ >+#endif >+#ifndef ETHTOOL_GCOALESCE >+#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ >+/* for configuring coalescing parameters of chip */ >+#define ethtool_coalesce _kc_ethtool_coalesce >+struct _kc_ethtool_coalesce { >+ u32 cmd; /* ETHTOOL_{G,S}COALESCE */ >+ >+ /* How many usecs to delay an RX interrupt after >+ * a packet arrives. If 0, only rx_max_coalesced_frames >+ * is used. >+ */ >+ u32 rx_coalesce_usecs; >+ >+ /* How many packets to delay an RX interrupt after >+ * a packet arrives. If 0, only rx_coalesce_usecs is >+ * used. It is illegal to set both usecs and max frames >+ * to zero as this would cause RX interrupts to never be >+ * generated. >+ */ >+ u32 rx_max_coalesced_frames; >+ >+ /* Same as above two parameters, except that these values >+ * apply while an IRQ is being serviced by the host. Not >+ * all cards support this feature and the values are ignored >+ * in that case. >+ */ >+ u32 rx_coalesce_usecs_irq; >+ u32 rx_max_coalesced_frames_irq; >+ >+ /* How many usecs to delay a TX interrupt after >+ * a packet is sent. If 0, only tx_max_coalesced_frames >+ * is used. >+ */ >+ u32 tx_coalesce_usecs; >+ >+ /* How many packets to delay a TX interrupt after >+ * a packet is sent. If 0, only tx_coalesce_usecs is >+ * used. It is illegal to set both usecs and max frames >+ * to zero as this would cause TX interrupts to never be >+ * generated. >+ */ >+ u32 tx_max_coalesced_frames; >+ >+ /* Same as above two parameters, except that these values >+ * apply while an IRQ is being serviced by the host. Not >+ * all cards support this feature and the values are ignored >+ * in that case. >+ */ >+ u32 tx_coalesce_usecs_irq; >+ u32 tx_max_coalesced_frames_irq; >+ >+ /* How many usecs to delay in-memory statistics >+ * block updates. Some drivers do not have an in-memory >+ * statistic block, and in such cases this value is ignored. >+ * This value must not be zero. >+ */ >+ u32 stats_block_coalesce_usecs; >+ >+ /* Adaptive RX/TX coalescing is an algorithm implemented by >+ * some drivers to improve latency under low packet rates and >+ * improve throughput under high packet rates. Some drivers >+ * only implement one of RX or TX adaptive coalescing. Anything >+ * not implemented by the driver causes these values to be >+ * silently ignored. >+ */ >+ u32 use_adaptive_rx_coalesce; >+ u32 use_adaptive_tx_coalesce; >+ >+ /* When the packet rate (measured in packets per second) >+ * is below pkt_rate_low, the {rx,tx}_*_low parameters are >+ * used. >+ */ >+ u32 pkt_rate_low; >+ u32 rx_coalesce_usecs_low; >+ u32 rx_max_coalesced_frames_low; >+ u32 tx_coalesce_usecs_low; >+ u32 tx_max_coalesced_frames_low; >+ >+ /* When the packet rate is below pkt_rate_high but above >+ * pkt_rate_low (both measured in packets per second) the >+ * normal {rx,tx}_* coalescing parameters are used. >+ */ >+ >+ /* When the packet rate is (measured in packets per second) >+ * is above pkt_rate_high, the {rx,tx}_*_high parameters are >+ * used. >+ */ >+ u32 pkt_rate_high; >+ u32 rx_coalesce_usecs_high; >+ u32 rx_max_coalesced_frames_high; >+ u32 tx_coalesce_usecs_high; >+ u32 tx_max_coalesced_frames_high; >+ >+ /* How often to do adaptive coalescing packet rate sampling, >+ * measured in seconds. Must not be zero. >+ */ >+ u32 rate_sample_interval; >+}; >+#endif /* ETHTOOL_GCOALESCE */ >+ >+#ifndef ETHTOOL_SCOALESCE >+#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ >+#endif >+#ifndef ETHTOOL_GRINGPARAM >+#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ >+/* for configuring RX/TX ring parameters */ >+#define ethtool_ringparam _kc_ethtool_ringparam >+struct _kc_ethtool_ringparam { >+ u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ >+ >+ /* Read only attributes. These indicate the maximum number >+ * of pending RX/TX ring entries the driver will allow the >+ * user to set. >+ */ >+ u32 rx_max_pending; >+ u32 rx_mini_max_pending; >+ u32 rx_jumbo_max_pending; >+ u32 tx_max_pending; >+ >+ /* Values changeable by the user. The valid values are >+ * in the range 1 to the "*_max_pending" counterpart above. >+ */ >+ u32 rx_pending; >+ u32 rx_mini_pending; >+ u32 rx_jumbo_pending; >+ u32 tx_pending; >+}; >+#endif /* ETHTOOL_GRINGPARAM */ >+ >+#ifndef ETHTOOL_SRINGPARAM >+#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ >+#endif >+#ifndef ETHTOOL_GPAUSEPARAM >+#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ >+/* for configuring link flow control parameters */ >+#define ethtool_pauseparam _kc_ethtool_pauseparam >+struct _kc_ethtool_pauseparam { >+ u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ >+ >+ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg >+ * being true) the user may set 'autonet' here non-zero to have the >+ * pause parameters be auto-negotiated too. In such a case, the >+ * {rx,tx}_pause values below determine what capabilities are >+ * advertised. >+ * >+ * If 'autoneg' is zero or the link is not being auto-negotiated, >+ * then {rx,tx}_pause force the driver to use/not-use pause >+ * flow control. >+ */ >+ u32 autoneg; >+ u32 rx_pause; >+ u32 tx_pause; >+}; >+#endif /* ETHTOOL_GPAUSEPARAM */ >+ >+#ifndef ETHTOOL_SPAUSEPARAM >+#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ >+#endif >+#ifndef ETHTOOL_GRXCSUM >+#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ >+#endif >+#ifndef ETHTOOL_SRXCSUM >+#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ >+#endif >+#ifndef ETHTOOL_GTXCSUM >+#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ >+#endif >+#ifndef ETHTOOL_STXCSUM >+#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ >+#endif >+#ifndef ETHTOOL_GSG >+#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable >+ * (ethtool_value) */ >+#endif >+#ifndef ETHTOOL_SSG >+#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable >+ * (ethtool_value). */ >+#endif >+#ifndef ETHTOOL_TEST >+#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ >+#endif >+#ifndef ETHTOOL_GSTRINGS >+#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ >+#endif >+#ifndef ETHTOOL_PHYS_ID >+#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ >+#endif >+#ifndef ETHTOOL_GSTATS >+#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ >+#endif >+#ifndef ETHTOOL_GTSO >+#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ >+#endif >+#ifndef ETHTOOL_STSO >+#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ >+#endif >+ >+#ifndef ETHTOOL_BUSINFO_LEN >+#define ETHTOOL_BUSINFO_LEN 32 >+#endif >+ >+/*****************************************************************************/ >+/* 2.4.3 => 2.4.0 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) >+ >+/**************************************/ >+/* PCI DRIVER API */ >+ >+#ifndef pci_set_dma_mask >+#define pci_set_dma_mask _kc_pci_set_dma_mask >+extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); >+#endif >+ >+#ifndef pci_request_regions >+#define pci_request_regions _kc_pci_request_regions >+extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); >+#endif >+ >+#ifndef pci_release_regions >+#define pci_release_regions _kc_pci_release_regions >+extern void _kc_pci_release_regions(struct pci_dev *pdev); >+#endif >+ >+/**************************************/ >+/* NETWORK DRIVER API */ >+ >+#ifndef alloc_etherdev >+#define alloc_etherdev _kc_alloc_etherdev >+extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); >+#endif >+ >+#ifndef is_valid_ether_addr >+#define is_valid_ether_addr _kc_is_valid_ether_addr >+extern int _kc_is_valid_ether_addr(u8 *addr); >+#endif >+ >+/**************************************/ >+/* MISCELLANEOUS */ >+ >+#ifndef INIT_TQUEUE >+#define INIT_TQUEUE(_tq, _routine, _data) \ >+ do { \ >+ INIT_LIST_HEAD(&(_tq)->list); \ >+ (_tq)->sync = 0; \ >+ (_tq)->routine = _routine; \ >+ (_tq)->data = _data; \ >+ } while (0) >+#endif >+ >+#endif /* 2.4.3 => 2.4.0 */ >+ >+/*****************************************************************************/ >+/* 2.4.6 => 2.4.3 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) >+ >+#ifndef pci_set_power_state >+#define pci_set_power_state _kc_pci_set_power_state >+extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); >+#endif >+ >+#ifndef pci_save_state >+#define pci_save_state _kc_pci_save_state >+extern int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer); >+#endif >+ >+#ifndef pci_restore_state >+#define pci_restore_state _kc_pci_restore_state >+extern int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer); >+#endif >+ >+#ifndef pci_enable_wake >+#define pci_enable_wake _kc_pci_enable_wake >+extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); >+#endif >+ >+#ifndef pci_disable_device >+#define pci_disable_device _kc_pci_disable_device >+extern void _kc_pci_disable_device(struct pci_dev *pdev); >+#endif >+ >+/* PCI PM entry point syntax changed, so don't support suspend/resume */ >+#undef CONFIG_PM >+ >+#endif /* 2.4.6 => 2.4.3 */ >+ >+/*****************************************************************************/ >+/* 2.4.9 => 2.4.6 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) ) >+#ifndef HAVE_PCI_SET_MWI >+#define pci_set_mwi(X) pci_write_config_word(X, \ >+ PCI_COMMAND, adapter->hw.pci_cmd_word | \ >+ PCI_COMMAND_INVALIDATE); >+#define pci_clear_mwi(X) pci_write_config_word(X, \ >+ PCI_COMMAND, adapter->hw.pci_cmd_word & \ >+ ~PCI_COMMAND_INVALIDATE); >+#endif >+#endif /* 2.4.9 => 2.4.6 */ >+ >+/*****************************************************************************/ >+/* 2.4.10 => 2.4.9 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) >+ >+/**************************************/ >+/* MODULE API */ >+ >+#ifndef MODULE_LICENSE >+ #define MODULE_LICENSE(X) >+#endif >+ >+/**************************************/ >+/* OTHER */ >+ >+#undef min >+#define min(x,y) ({ \ >+ const typeof(x) _x = (x); \ >+ const typeof(y) _y = (y); \ >+ (void) (&_x == &_y); \ >+ _x < _y ? _x : _y; }) >+ >+#undef max >+#define max(x,y) ({ \ >+ const typeof(x) _x = (x); \ >+ const typeof(y) _y = (y); \ >+ (void) (&_x == &_y); \ >+ _x > _y ? _x : _y; }) >+ >+#ifndef list_for_each_safe >+#define list_for_each_safe(pos, n, head) \ >+ for (pos = (head)->next, n = pos->next; pos != (head); \ >+ pos = n, n = pos->next) >+#endif >+ >+#endif /* 2.4.10 -> 2.4.6 */ >+ >+ >+/*****************************************************************************/ >+/* 2.4.13 => 2.4.10 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) >+ >+/**************************************/ >+/* PCI DMA MAPPING */ >+ >+#ifndef virt_to_page >+ #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) >+#endif >+ >+#ifndef pci_map_page >+#define pci_map_page _kc_pci_map_page >+extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); >+#endif >+ >+#ifndef pci_unmap_page >+#define pci_unmap_page _kc_pci_unmap_page >+extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); >+#endif >+ >+/* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ >+ >+#undef DMA_32BIT_MASK >+#define DMA_32BIT_MASK 0xffffffff >+#undef DMA_64BIT_MASK >+#define DMA_64BIT_MASK 0xffffffff >+ >+/**************************************/ >+/* OTHER */ >+ >+#ifndef cpu_relax >+#define cpu_relax() rep_nop() >+#endif >+ >+#endif /* 2.4.13 => 2.4.10 */ >+ >+/*****************************************************************************/ >+/* 2.4.17 => 2.4.12 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) >+ >+#ifndef __devexit_p >+ #define __devexit_p(x) &(x) >+#endif >+ >+#ifndef VLAN_HLEN >+#define VLAN_HLEN 4 >+#endif >+ >+#ifndef VLAN_ETH_HLEN >+#define VLAN_ETH_HLEN 18 >+#endif >+ >+#ifndef VLAN_ETH_FRAME_LEN >+#define VLAN_ETH_FRAME_LEN 1518 >+#endif >+ >+#endif /* 2.4.17 => 2.4.13 */ >+ >+/*****************************************************************************/ >+/* 2.4.20 => 2.4.19 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) ) >+ >+ >+#endif /* 2.4.20 => 2.4.19 */ >+/*****************************************************************************/ >+/* 2.4.22 => 2.4.17 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) >+#define pci_name(x) ((x)->slot_name) >+#endif >+ >+/*****************************************************************************/ >+/* 2.4.23 => 2.4.22 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) >+/*****************************************************************************/ >+#ifdef NAPI >+#ifndef netif_poll_disable >+#define netif_poll_disable(x) _kc_netif_poll_disable(x) >+static inline void _kc_netif_poll_disable(struct net_device *netdev) >+{ >+ while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { >+ /* No hurry */ >+ current->state = TASK_INTERRUPTIBLE; >+ schedule_timeout(1); >+ } >+} >+#endif >+ >+#ifndef netif_poll_enable >+#define netif_poll_enable(x) _kc_netif_poll_enable(x) >+static inline void _kc_netif_poll_enable(struct net_device *netdev) >+{ >+ clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); >+} >+#endif >+#endif /* NAPI */ >+#ifndef netif_tx_disable >+#define netif_tx_disable(x) _kc_netif_tx_disable(x) >+static inline void _kc_netif_tx_disable(struct net_device *dev) >+{ >+ spin_lock_bh(&dev->xmit_lock); >+ netif_stop_queue(dev); >+ spin_unlock_bh(&dev->xmit_lock); >+} >+#endif >+#endif /* 2.4.23 => 2.4.22 */ >+ >+/*****************************************************************************/ >+/* 2.6.4 => 2.6.0 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ >+ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ >+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) >+#define ETHTOOL_OPS_COMPAT >+#endif /* 2.6.4 => 2.6.0 */ >+ >+/*****************************************************************************/ >+/* 2.5.71 => 2.4.x */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) ) >+#define sk_protocol protocol >+#endif /* 2.5.70 => 2.4.x */ >+ >+/*****************************************************************************/ >+/* < 2.4.27 or 2.6.0 <= 2.6.5 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) || \ >+ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ >+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ) >+ >+#ifndef netif_msg_init >+#define netif_msg_init _kc_netif_msg_init >+static inline u32 _kc_netif_msg_init(int debug_value, int default_msg_enable_bits) >+{ >+ /* use default */ >+ if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) >+ return default_msg_enable_bits; >+ if (debug_value == 0) /* no output */ >+ return 0; >+ /* set low N bits */ >+ return (1 << debug_value) -1; >+} >+#endif >+ >+#endif /* < 2.4.27 or 2.6.0 <= 2.6.5 */ >+/*****************************************************************************/ >+#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ >+ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ >+ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) >+#define netdev_priv(x) x->priv >+#endif >+ >+/*****************************************************************************/ >+/* <= 2.5.0 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) >+#undef pci_register_driver >+#define pci_register_driver pci_module_init >+#endif /* <= 2.5.0 */ >+ >+/*****************************************************************************/ >+/* 2.5.28 => 2.4.23 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) >+ >+static inline void _kc_synchronize_irq(void) >+{ >+ synchronize_irq(); >+} >+#undef synchronize_irq >+#define synchronize_irq(X) _kc_synchronize_irq() >+ >+#include <linux/tqueue.h> >+#define work_struct tq_struct >+#undef INIT_WORK >+#define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a) >+#undef container_of >+#define container_of list_entry >+#define schedule_work schedule_task >+#define flush_scheduled_work flush_scheduled_tasks >+ >+#endif /* 2.5.28 => 2.4.17 */ >+ >+/*****************************************************************************/ >+/* 2.6.0 => 2.5.28 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) >+#define MODULE_INFO(version, _version) >+ >+#define pci_set_consistent_dma_mask(dev,mask) 1 >+ >+#undef dev_put >+#define dev_put(dev) __dev_put(dev) >+ >+#ifndef skb_fill_page_desc >+#define skb_fill_page_desc _kc_skb_fill_page_desc >+extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); >+#endif >+ >+#ifndef pci_dma_mapping_error >+#define pci_dma_mapping_error _kc_pci_dma_mapping_error >+static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) >+{ >+ return dma_addr == 0; >+} >+#endif >+ >+#endif /* 2.6.0 => 2.5.28 */ >+ >+/*****************************************************************************/ >+/* 2.6.4 => 2.6.0 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) >+#define MODULE_VERSION(_version) MODULE_INFO(version, _version) >+#endif /* 2.6.4 => 2.6.0 */ >+ >+/*****************************************************************************/ >+/* 2.6.5 => 2.6.0 */ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) >+#define pci_dma_sync_single_for_cpu pci_dma_sync_single >+#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu >+#endif /* 2.6.5 => 2.6.0 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ) >+#undef if_mii >+#define if_mii _kc_if_mii >+static inline struct mii_ioctl_data *_kc_if_mii(struct ifreq *rq) >+{ >+ return (struct mii_ioctl_data *) &rq->ifr_ifru; >+} >+#endif /* < 2.6.7 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) >+#define msleep(x) do { set_current_state(TASK_UNINTERRUPTIBLE); \ >+ schedule_timeout((x * HZ)/1000 + 2); \ >+ } while (0) >+#endif >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) >+#define __iomem >+ >+#ifndef kcalloc >+#define kcalloc(n, size, flags) _kc_kzalloc(((n) * (size)), flags) >+extern void *_kc_kzalloc(size_t size, int flags); >+#endif >+#define MSEC_PER_SEC 1000L >+static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) >+{ >+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) >+ return (MSEC_PER_SEC / HZ) * j; >+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) >+ return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); >+#else >+ return (j * MSEC_PER_SEC) / HZ; >+#endif >+} >+static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) >+{ >+ if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) >+ return MAX_JIFFY_OFFSET; >+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) >+ return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); >+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) >+ return m * (HZ / MSEC_PER_SEC); >+#else >+ return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; >+#endif >+} >+ >+#define msleep_interruptible _kc_msleep_interruptible >+static inline unsigned long _kc_msleep_interruptible(unsigned int msecs) >+{ >+ unsigned long timeout = _kc_msecs_to_jiffies(msecs) + 1; >+ >+ while (timeout && !signal_pending(current)) { >+ __set_current_state(TASK_INTERRUPTIBLE); >+ timeout = schedule_timeout(timeout); >+ } >+ return _kc_jiffies_to_msecs(timeout); >+} >+#endif /* < 2.6.9 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) && \ >+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) >+#ifdef pci_save_state >+#undef pci_save_state >+#endif >+#define pci_save_state(X) { \ >+ int i; \ >+ if (adapter->pci_state) { \ >+ for (i = 0; i < 16; i++) { \ >+ pci_read_config_dword((X), \ >+ i * 4, \ >+ &adapter->pci_state[i]); \ >+ } \ >+ } \ >+} >+ >+#ifdef pci_restore_state >+#undef pci_restore_state >+#endif >+#define pci_restore_state(X) { \ >+ int i; \ >+ if (adapter->pci_state) { \ >+ for (i = 0; i < 16; i++) { \ >+ pci_write_config_dword((X), \ >+ i * 4, \ >+ adapter->pci_state[i]); \ >+ } \ >+ } else { \ >+ for (i = 0; i < 6; i++) { \ >+ pci_write_config_dword((X), \ >+ PCI_BASE_ADDRESS_0 + (i * 4), \ >+ (X)->resource[i].start); \ >+ } \ >+ } \ >+} >+#endif /* 2.4.6 <= x < 2.6.10 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) >+#ifdef module_param_array_named >+#undef module_param_array_named >+#define module_param_array_named(name, array, type, nump, perm) \ >+ static struct kparam_array __param_arr_##name \ >+ = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type, \ >+ sizeof(array[0]), array }; \ >+ module_param_call(name, param_array_set, param_array_get, \ >+ &__param_arr_##name, perm) >+#endif /* module_param_array_named */ >+#endif /* < 2.6.10 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) >+#define PCI_D0 0 >+#define PCI_D1 1 >+#define PCI_D2 2 >+#define PCI_D3hot 3 >+#define PCI_D3cold 4 >+#define pci_choose_state(pdev,state) state >+#define PMSG_SUSPEND 3 >+ >+#undef NETIF_F_LLTX >+ >+#ifndef ARCH_HAS_PREFETCH >+#define prefetch(X) >+#endif >+ >+#ifndef NET_IP_ALIGN >+#define NET_IP_ALIGN 2 >+#endif >+ >+#endif /* < 2.6.11 */ >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) >+#include <linux/reboot.h> >+#define USE_REBOOT_NOTIFIER >+#endif >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) >+#define pm_message_t u32 >+#ifndef kzalloc >+#define kzalloc _kc_kzalloc >+extern void *_kc_kzalloc(size_t size, int flags); >+#endif >+#endif >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) >+#undef CONFIG_AT_PCI_ERS >+#else >+#define CONFIG_AT_PCI_ERS >+#endif >+ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) >+ >+#ifndef IRQF_PROBE_SHARED >+#ifdef SA_PROBEIRQ >+#define IRQF_PROBE_SHARED SA_PROBEIRQ >+#else >+#define IRQF_PROBE_SHARED 0 >+#endif >+#endif >+ >+#ifndef IRQF_SHARED >+#define IRQF_SHARED SA_SHIRQ >+#endif >+ >+#ifndef ARRAY_SIZE >+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) >+#endif >+ >+#ifndef netdev_alloc_skb >+#define netdev_alloc_skb _kc_netdev_alloc_skb >+extern struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, >+ unsigned int length); >+#endif >+ >+#ifndef skb_is_gso >+#ifdef NETIF_F_TSO >+#define skb_is_gso _kc_skb_is_gso >+static inline int _kc_skb_is_gso(const struct sk_buff *skb) >+{ >+ return skb_shinfo(skb)->gso_size; >+} >+#endif >+#endif >+ >+#endif /* < 2.6.18 */ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) >+ >+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) >+typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); >+typedef irqreturn_t (*new_handler_t)(int, void*); >+static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) >+#else /* 2.4.x */ >+typedef void (*irq_handler_t)(int, void*, struct pt_regs *); >+typedef void (*new_handler_t)(int, void*); >+static inline int _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) >+#endif >+{ >+ irq_handler_t new_handler = (irq_handler_t) handler; >+ return request_irq(irq, new_handler, flags, devname, dev_id); >+} >+ >+#undef request_irq >+#define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) >+ >+/* pci_restore_state and pci_save_state handles MSI/PCIE from 2.6.19 */ >+#define PCIE_CONFIG_SPACE_LEN 256 >+#define PCI_CONFIG_SPACE_LEN 64 >+#define PCIE_LINK_STATUS 0x12 >+#undef pci_save_state >+#define pci_save_state(pdev) _kc_pci_save_state(adapter) >+#define _kc_pci_save_state(adapter) 0; { \ >+ int size, i; \ >+ u16 pcie_link_status; \ >+ \ >+ u16 cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); \ >+ if (cap_offset) { \ >+ if (pci_read_config_word(pdev, cap_offset + PCIE_LINK_STATUS, &pcie_link_status)) \ >+ size = PCI_CONFIG_SPACE_LEN; \ >+ else \ >+ size = PCIE_CONFIG_SPACE_LEN; \ >+ WARN_ON(adapter->config_space != NULL); \ >+ adapter->config_space = kmalloc(size, GFP_KERNEL); \ >+ if (!adapter->config_space) { \ >+ printk(KERN_ERR "Out of memory in pci_save_msi_state\n"); \ >+ return -ENOMEM; \ >+ } \ >+ for (i = 0; i < (size / 4); i++) \ >+ pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]); \ >+ } \ >+} >+#undef pci_restore_state >+#define pci_restore_state(pdev) _kc_pci_restore_state(adapter) >+#define _kc_pci_restore_state(adapter) { \ >+ int size, i; \ >+ u16 pcie_link_status; \ >+ \ >+ u16 cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); \ >+ if (cap_offset) { \ >+ if (adapter->config_space == NULL) { \ >+ if (pci_read_config_word(pdev, cap_offset + PCIE_LINK_STATUS, &pcie_link_status)) \ >+ size = PCI_CONFIG_SPACE_LEN; \ >+ else \ >+ size = PCIE_CONFIG_SPACE_LEN; \ >+ \ >+ for (i = 0; i < (size / 4); i++) \ >+ pci_write_config_dword(pdev, i * 4, adapter->config_space[i]); \ >+ kfree(adapter->config_space); \ >+ adapter->config_space = NULL; \ >+ } \ >+ } \ >+} >+ >+#endif /* < 2.6.19 */ >+/*****************************************************************************/ >+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) >+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) >+#undef INIT_WORK >+#define INIT_WORK(_work, _func) \ >+do { \ >+ INIT_LIST_HEAD(&(_work)->entry); \ >+ (_work)->pending = 0; \ >+ (_work)->func = (void (*)(void *))_func; \ >+ (_work)->data = _work; \ >+ init_timer(&(_work)->timer); \ >+} while (0) >+#endif >+ >+#ifndef round_jiffies >+#define round_jiffies(x) x >+#endif >+ >+#endif /* < 2.6.20 */ >+/*****************************************************************************/ >+ >+#endif /* _KCOMPAT_H_ */ >+ >diff -ruN -a -p old/drivers/net/atl2/Makefile new/drivers/net/atl2/Makefile >--- old/drivers/net/atl2/Makefile 1970-01-01 03:00:00.000000000 +0300 >+++ new/drivers/net/atl2/Makefile 2007-11-13 15:47:34.000000000 +0200 >@@ -0,0 +1,2 @@ >+atl2-objs := at_main.o at_hw.o at_param.o at_ethtool.o kcompat.o >+obj-$(CONFIG_ATL2) := atl2.o >diff -ruN -a -p old/drivers/net/Kconfig new/drivers/net/Kconfig >--- old/drivers/net/Kconfig 2007-11-13 15:15:11.000000000 +0200 >+++ new/drivers/net/Kconfig 2007-11-13 15:56:26.000000000 +0200 >@@ -1499,6 +1499,16 @@ config LNE390 > <file:Documentation/networking/net-modules.txt>. The module > will be called lne390. > >+config ATL2 >+ tristate "Attansic L2 Fast Ethernet support" >+ depends on NET_PCI && PCI >+ help >+ This driver supports Attansic L2 fast ethernet cards. >+ >+ To compile this driver as a module, choose M here and read >+ <file:Documentation/networking/net-modules.txt>. The module >+ will be called atl2. >+ > config FEALNX > tristate "Myson MTD-8xx PCI Ethernet support" > depends on NET_PCI && PCI >diff -ruN -a -p old/drivers/net/Makefile new/drivers/net/Makefile >--- old/drivers/net/Makefile 2007-11-13 15:15:11.000000000 +0200 >+++ new/drivers/net/Makefile 2007-11-13 15:56:53.000000000 +0200 >@@ -63,6 +63,7 @@ obj-$(CONFIG_ISERIES_VETH) += iseries_ve > obj-$(CONFIG_NATSEMI) += natsemi.o > obj-$(CONFIG_NS83820) += ns83820.o > obj-$(CONFIG_STNIC) += stnic.o 8390.o >+obj-$(CONFIG_ATL2) += atl2/ > obj-$(CONFIG_FEALNX) += fealnx.o > obj-$(CONFIG_TIGON3) += tg3.o > obj-$(CONFIG_BNX2) += bnx2.o
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 249382
:
200671
|
200681
|
200701
| 257021 |
257031
|
287941
|
290365