Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,83 @@
#
# Atheros device configuration
#
config NET_VENDOR_ATHEROS
bool "Atheros devices"
default y
depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about Atheros devices. If you say Y, you will be asked
for your specific card in the following questions.
if NET_VENDOR_ATHEROS
config ATL2
tristate "Atheros L2 Fast Ethernet support"
depends on PCI
select CRC32
select MII
---help---
This driver supports the Atheros L2 fast ethernet adapter.
To compile this driver as a module, choose M here. The module
will be called atl2.
config ATL1
tristate "Atheros/Attansic L1 Gigabit Ethernet support"
depends on PCI
select CRC32
select MII
---help---
This driver supports the Atheros/Attansic L1 gigabit ethernet
adapter.
To compile this driver as a module, choose M here. The module
will be called atl1.
config ATL1E
tristate "Atheros L1E Gigabit Ethernet support"
depends on PCI
select CRC32
select MII
---help---
This driver supports the Atheros L1E gigabit ethernet adapter.
To compile this driver as a module, choose M here. The module
will be called atl1e.
config ATL1C
tristate "Atheros L1C Gigabit Ethernet support"
depends on PCI
select CRC32
select MII
---help---
This driver supports the Atheros L1C gigabit ethernet adapter.
To compile this driver as a module, choose M here. The module
will be called atl1c.
config ALX
tristate "Qualcomm Atheros AR816x/AR817x support"
depends on PCI
select CRC32
select MDIO
help
This driver supports the Qualcomm Atheros L1F ethernet adapter,
i.e. the following chipsets:
1969:1091 - AR8161 Gigabit Ethernet
1969:1090 - AR8162 Fast Ethernet
1969:10A1 - AR8171 Gigabit Ethernet
1969:10A0 - AR8172 Fast Ethernet
To compile this driver as a module, choose M here. The module
will be called alx.
endif # NET_VENDOR_ATHEROS

View file

@ -0,0 +1,9 @@
#
# Makefile for the Atheros network device drivers.
#
obj-$(CONFIG_ATL1) += atlx/
obj-$(CONFIG_ATL2) += atlx/
obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_ATL1C) += atl1c/
obj-$(CONFIG_ALX) += alx/

View file

@ -0,0 +1,3 @@
obj-$(CONFIG_ALX) += alx.o
alx-objs := main.o ethtool.o hw.o
ccflags-y += -D__CHECK_ENDIAN__

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net>
*
* This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _ALX_H_
#define _ALX_H_
#include <linux/types.h>
#include <linux/etherdevice.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include "hw.h"
#define ALX_WATCHDOG_TIME (5 * HZ)
struct alx_buffer {
struct sk_buff *skb;
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(size);
};
struct alx_rx_queue {
struct alx_rrd *rrd;
dma_addr_t rrd_dma;
struct alx_rfd *rfd;
dma_addr_t rfd_dma;
struct alx_buffer *bufs;
u16 write_idx, read_idx;
u16 rrd_read_idx;
};
#define ALX_RX_ALLOC_THRESH 32
struct alx_tx_queue {
struct alx_txd *tpd;
dma_addr_t tpd_dma;
struct alx_buffer *bufs;
u16 write_idx, read_idx;
};
#define ALX_DEFAULT_TX_WORK 128
enum alx_device_quirks {
ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG = BIT(0),
};
struct alx_priv {
struct net_device *dev;
struct alx_hw hw;
/* all descriptor memory */
struct {
dma_addr_t dma;
void *virt;
unsigned int size;
} descmem;
/* protect int_mask updates */
spinlock_t irq_lock;
u32 int_mask;
unsigned int tx_ringsz;
unsigned int rx_ringsz;
unsigned int rxbuf_size;
struct napi_struct napi;
struct alx_tx_queue txq;
struct alx_rx_queue rxq;
struct work_struct link_check_wk;
struct work_struct reset_wk;
u16 msg_enable;
bool msi;
/* protects hw.stats */
spinlock_t stats_lock;
};
extern const struct ethtool_ops alx_ethtool_ops;
extern const char alx_drv_name[];
#endif

View file

@ -0,0 +1,313 @@
/*
* Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net>
*
* This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/pci.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mdio.h>
#include <linux/interrupt.h>
#include <asm/byteorder.h>
#include "alx.h"
#include "reg.h"
#include "hw.h"
/* The order of these strings must match the order of the fields in
* struct alx_hw_stats
* See hw.h
*/
static const char alx_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_packets",
"rx_bcast_packets",
"rx_mcast_packets",
"rx_pause_packets",
"rx_ctrl_packets",
"rx_fcs_errors",
"rx_length_errors",
"rx_bytes",
"rx_runt_packets",
"rx_fragments",
"rx_64B_or_less_packets",
"rx_65B_to_127B_packets",
"rx_128B_to_255B_packets",
"rx_256B_to_511B_packets",
"rx_512B_to_1023B_packets",
"rx_1024B_to_1518B_packets",
"rx_1519B_to_mtu_packets",
"rx_oversize_packets",
"rx_rxf_ov_drop_packets",
"rx_rrd_ov_drop_packets",
"rx_align_errors",
"rx_bcast_bytes",
"rx_mcast_bytes",
"rx_address_errors",
"tx_packets",
"tx_bcast_packets",
"tx_mcast_packets",
"tx_pause_packets",
"tx_exc_defer_packets",
"tx_ctrl_packets",
"tx_defer_packets",
"tx_bytes",
"tx_64B_or_less_packets",
"tx_65B_to_127B_packets",
"tx_128B_to_255B_packets",
"tx_256B_to_511B_packets",
"tx_512B_to_1023B_packets",
"tx_1024B_to_1518B_packets",
"tx_1519B_to_mtu_packets",
"tx_single_collision",
"tx_multiple_collisions",
"tx_late_collision",
"tx_abort_collision",
"tx_underrun",
"tx_trd_eop",
"tx_length_errors",
"tx_trunc_packets",
"tx_bcast_bytes",
"tx_mcast_bytes",
"tx_update",
};
#define ALX_NUM_STATS ARRAY_SIZE(alx_gstrings_stats)
static u32 alx_get_supported_speeds(struct alx_hw *hw)
{
u32 supported = SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full;
if (alx_hw_giga(hw))
supported |= SUPPORTED_1000baseT_Full;
BUILD_BUG_ON(SUPPORTED_10baseT_Half != ADVERTISED_10baseT_Half);
BUILD_BUG_ON(SUPPORTED_10baseT_Full != ADVERTISED_10baseT_Full);
BUILD_BUG_ON(SUPPORTED_100baseT_Half != ADVERTISED_100baseT_Half);
BUILD_BUG_ON(SUPPORTED_100baseT_Full != ADVERTISED_100baseT_Full);
BUILD_BUG_ON(SUPPORTED_1000baseT_Full != ADVERTISED_1000baseT_Full);
return supported;
}
static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
ecmd->supported = SUPPORTED_Autoneg |
SUPPORTED_TP |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause;
if (alx_hw_giga(hw))
ecmd->supported |= SUPPORTED_1000baseT_Full;
ecmd->supported |= alx_get_supported_speeds(hw);
ecmd->advertising = ADVERTISED_TP;
if (hw->adv_cfg & ADVERTISED_Autoneg)
ecmd->advertising |= hw->adv_cfg;
ecmd->port = PORT_TP;
ecmd->phy_address = 0;
if (hw->adv_cfg & ADVERTISED_Autoneg)
ecmd->autoneg = AUTONEG_ENABLE;
else
ecmd->autoneg = AUTONEG_DISABLE;
ecmd->transceiver = XCVR_INTERNAL;
if (hw->flowctrl & ALX_FC_ANEG && hw->adv_cfg & ADVERTISED_Autoneg) {
if (hw->flowctrl & ALX_FC_RX) {
ecmd->advertising |= ADVERTISED_Pause;
if (!(hw->flowctrl & ALX_FC_TX))
ecmd->advertising |= ADVERTISED_Asym_Pause;
} else if (hw->flowctrl & ALX_FC_TX) {
ecmd->advertising |= ADVERTISED_Asym_Pause;
}
}
ethtool_cmd_speed_set(ecmd, hw->link_speed);
ecmd->duplex = hw->duplex;
return 0;
}
static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
u32 adv_cfg;
ASSERT_RTNL();
if (ecmd->autoneg == AUTONEG_ENABLE) {
if (ecmd->advertising & ~alx_get_supported_speeds(hw))
return -EINVAL;
adv_cfg = ecmd->advertising | ADVERTISED_Autoneg;
} else {
adv_cfg = alx_speed_to_ethadv(ethtool_cmd_speed(ecmd),
ecmd->duplex);
if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full)
return -EINVAL;
}
hw->adv_cfg = adv_cfg;
return alx_setup_speed_duplex(hw, adv_cfg, hw->flowctrl);
}
static void alx_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG &&
hw->adv_cfg & ADVERTISED_Autoneg);
pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX);
pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX);
}
static int alx_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
int err = 0;
bool reconfig_phy = false;
u8 fc = 0;
if (pause->tx_pause)
fc |= ALX_FC_TX;
if (pause->rx_pause)
fc |= ALX_FC_RX;
if (pause->autoneg)
fc |= ALX_FC_ANEG;
ASSERT_RTNL();
/* restart auto-neg for auto-mode */
if (hw->adv_cfg & ADVERTISED_Autoneg) {
if (!((fc ^ hw->flowctrl) & ALX_FC_ANEG))
reconfig_phy = true;
if (fc & hw->flowctrl & ALX_FC_ANEG &&
(fc ^ hw->flowctrl) & (ALX_FC_RX | ALX_FC_TX))
reconfig_phy = true;
}
if (reconfig_phy) {
err = alx_setup_speed_duplex(hw, hw->adv_cfg, fc);
if (err)
return err;
}
/* flow control on mac */
if ((fc ^ hw->flowctrl) & (ALX_FC_RX | ALX_FC_TX))
alx_cfg_mac_flowcontrol(hw, fc);
hw->flowctrl = fc;
return 0;
}
static u32 alx_get_msglevel(struct net_device *netdev)
{
struct alx_priv *alx = netdev_priv(netdev);
return alx->msg_enable;
}
static void alx_set_msglevel(struct net_device *netdev, u32 data)
{
struct alx_priv *alx = netdev_priv(netdev);
alx->msg_enable = data;
}
static void alx_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *estats, u64 *data)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
spin_lock(&alx->stats_lock);
alx_update_hw_stats(hw);
BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
ALX_NUM_STATS * sizeof(u64));
memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
spin_unlock(&alx->stats_lock);
}
static void alx_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
{
switch (stringset) {
case ETH_SS_STATS:
memcpy(buf, &alx_gstrings_stats, sizeof(alx_gstrings_stats));
break;
default:
WARN_ON(1);
break;
}
}
static int alx_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
case ETH_SS_STATS:
return ALX_NUM_STATS;
default:
return -EINVAL;
}
}
const struct ethtool_ops alx_ethtool_ops = {
.get_settings = alx_get_settings,
.set_settings = alx_set_settings,
.get_pauseparam = alx_get_pauseparam,
.set_pauseparam = alx_set_pauseparam,
.get_msglevel = alx_get_msglevel,
.set_msglevel = alx_set_msglevel,
.get_link = ethtool_op_get_link,
.get_strings = alx_get_strings,
.get_sset_count = alx_get_sset_count,
.get_ethtool_stats = alx_get_ethtool_stats,
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,581 @@
/*
* Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net>
*
* This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ALX_HW_H_
#define ALX_HW_H_
#include <linux/types.h>
#include <linux/mdio.h>
#include <linux/pci.h>
#include "reg.h"
/* Transmit Packet Descriptor, contains 4 32-bit words.
*
* 31 16 0
* +----------------+----------------+
* | vlan-tag | buf length |
* +----------------+----------------+
* | Word 1 |
* +----------------+----------------+
* | Word 2: buf addr lo |
* +----------------+----------------+
* | Word 3: buf addr hi |
* +----------------+----------------+
*
* Word 2 and 3 combine to form a 64-bit buffer address
*
* Word 1 has three forms, depending on the state of bit 8/12/13:
* if bit8 =='1', the definition is just for custom checksum offload.
* if bit8 == '0' && bit12 == '1' && bit13 == '1', the *FIRST* descriptor
* for the skb is special for LSO V2, Word 2 become total skb length ,
* Word 3 is meaningless.
* other condition, the definition is for general skb or ip/tcp/udp
* checksum or LSO(TSO) offload.
*
* Here is the depiction:
*
* 0-+ 0-+
* 1 | 1 |
* 2 | 2 |
* 3 | Payload offset 3 | L4 header offset
* 4 | (7:0) 4 | (7:0)
* 5 | 5 |
* 6 | 6 |
* 7-+ 7-+
* 8 Custom csum enable = 1 8 Custom csum enable = 0
* 9 General IPv4 checksum 9 General IPv4 checksum
* 10 General TCP checksum 10 General TCP checksum
* 11 General UDP checksum 11 General UDP checksum
* 12 Large Send Segment enable 12 Large Send Segment enable
* 13 Large Send Segment type 13 Large Send Segment type
* 14 VLAN tagged 14 VLAN tagged
* 15 Insert VLAN tag 15 Insert VLAN tag
* 16 IPv4 packet 16 IPv4 packet
* 17 Ethernet frame type 17 Ethernet frame type
* 18-+ 18-+
* 19 | 19 |
* 20 | 20 |
* 21 | Custom csum offset 21 |
* 22 | (25:18) 22 |
* 23 | 23 | MSS (30:18)
* 24 | 24 |
* 25-+ 25 |
* 26-+ 26 |
* 27 | 27 |
* 28 | Reserved 28 |
* 29 | 29 |
* 30-+ 30-+
* 31 End of packet 31 End of packet
*/
struct alx_txd {
__le16 len;
__le16 vlan_tag;
__le32 word1;
union {
__le64 addr;
struct {
__le32 pkt_len;
__le32 resvd;
} l;
} adrl;
} __packed;
/* tpd word 1 */
#define TPD_CXSUMSTART_MASK 0x00FF
#define TPD_CXSUMSTART_SHIFT 0
#define TPD_L4HDROFFSET_MASK 0x00FF
#define TPD_L4HDROFFSET_SHIFT 0
#define TPD_CXSUM_EN_MASK 0x0001
#define TPD_CXSUM_EN_SHIFT 8
#define TPD_IP_XSUM_MASK 0x0001
#define TPD_IP_XSUM_SHIFT 9
#define TPD_TCP_XSUM_MASK 0x0001
#define TPD_TCP_XSUM_SHIFT 10
#define TPD_UDP_XSUM_MASK 0x0001
#define TPD_UDP_XSUM_SHIFT 11
#define TPD_LSO_EN_MASK 0x0001
#define TPD_LSO_EN_SHIFT 12
#define TPD_LSO_V2_MASK 0x0001
#define TPD_LSO_V2_SHIFT 13
#define TPD_VLTAGGED_MASK 0x0001
#define TPD_VLTAGGED_SHIFT 14
#define TPD_INS_VLTAG_MASK 0x0001
#define TPD_INS_VLTAG_SHIFT 15
#define TPD_IPV4_MASK 0x0001
#define TPD_IPV4_SHIFT 16
#define TPD_ETHTYPE_MASK 0x0001
#define TPD_ETHTYPE_SHIFT 17
#define TPD_CXSUMOFFSET_MASK 0x00FF
#define TPD_CXSUMOFFSET_SHIFT 18
#define TPD_MSS_MASK 0x1FFF
#define TPD_MSS_SHIFT 18
#define TPD_EOP_MASK 0x0001
#define TPD_EOP_SHIFT 31
#define DESC_GET(_x, _name) ((_x) >> _name##SHIFT & _name##MASK)
/* Receive Free Descriptor */
struct alx_rfd {
__le64 addr; /* data buffer address, length is
* declared in register --- every
* buffer has the same size
*/
} __packed;
/* Receive Return Descriptor, contains 4 32-bit words.
*
* 31 16 0
* +----------------+----------------+
* | Word 0 |
* +----------------+----------------+
* | Word 1: RSS Hash value |
* +----------------+----------------+
* | Word 2 |
* +----------------+----------------+
* | Word 3 |
* +----------------+----------------+
*
* Word 0 depiction & Word 2 depiction:
*
* 0--+ 0--+
* 1 | 1 |
* 2 | 2 |
* 3 | 3 |
* 4 | 4 |
* 5 | 5 |
* 6 | 6 |
* 7 | IP payload checksum 7 | VLAN tag
* 8 | (15:0) 8 | (15:0)
* 9 | 9 |
* 10 | 10 |
* 11 | 11 |
* 12 | 12 |
* 13 | 13 |
* 14 | 14 |
* 15-+ 15-+
* 16-+ 16-+
* 17 | Number of RFDs 17 |
* 18 | (19:16) 18 |
* 19-+ 19 | Protocol ID
* 20-+ 20 | (23:16)
* 21 | 21 |
* 22 | 22 |
* 23 | 23-+
* 24 | 24 | Reserved
* 25 | Start index of RFD-ring 25-+
* 26 | (31:20) 26 | RSS Q-num (27:25)
* 27 | 27-+
* 28 | 28-+
* 29 | 29 | RSS Hash algorithm
* 30 | 30 | (31:28)
* 31-+ 31-+
*
* Word 3 depiction:
*
* 0--+
* 1 |
* 2 |
* 3 |
* 4 |
* 5 |
* 6 |
* 7 | Packet length (include FCS)
* 8 | (13:0)
* 9 |
* 10 |
* 11 |
* 12 |
* 13-+
* 14 L4 Header checksum error
* 15 IPv4 checksum error
* 16 VLAN tagged
* 17-+
* 18 | Protocol ID (19:17)
* 19-+
* 20 Receive error summary
* 21 FCS(CRC) error
* 22 Frame alignment error
* 23 Truncated packet
* 24 Runt packet
* 25 Incomplete packet due to insufficient rx-desc
* 26 Broadcast packet
* 27 Multicast packet
* 28 Ethernet type (EII or 802.3)
* 29 FIFO overflow
* 30 Length error (for 802.3, length field mismatch with actual len)
* 31 Updated, indicate to driver that this RRD is refreshed.
*/
struct alx_rrd {
__le32 word0;
__le32 rss_hash;
__le32 word2;
__le32 word3;
} __packed;
/* rrd word 0 */
#define RRD_XSUM_MASK 0xFFFF
#define RRD_XSUM_SHIFT 0
#define RRD_NOR_MASK 0x000F
#define RRD_NOR_SHIFT 16
#define RRD_SI_MASK 0x0FFF
#define RRD_SI_SHIFT 20
/* rrd word 2 */
#define RRD_VLTAG_MASK 0xFFFF
#define RRD_VLTAG_SHIFT 0
#define RRD_PID_MASK 0x00FF
#define RRD_PID_SHIFT 16
/* non-ip packet */
#define RRD_PID_NONIP 0
/* ipv4(only) */
#define RRD_PID_IPV4 1
/* tcp/ipv6 */
#define RRD_PID_IPV6TCP 2
/* tcp/ipv4 */
#define RRD_PID_IPV4TCP 3
/* udp/ipv6 */
#define RRD_PID_IPV6UDP 4
/* udp/ipv4 */
#define RRD_PID_IPV4UDP 5
/* ipv6(only) */
#define RRD_PID_IPV6 6
/* LLDP packet */
#define RRD_PID_LLDP 7
/* 1588 packet */
#define RRD_PID_1588 8
#define RRD_RSSQ_MASK 0x0007
#define RRD_RSSQ_SHIFT 25
#define RRD_RSSALG_MASK 0x000F
#define RRD_RSSALG_SHIFT 28
#define RRD_RSSALG_TCPV6 0x1
#define RRD_RSSALG_IPV6 0x2
#define RRD_RSSALG_TCPV4 0x4
#define RRD_RSSALG_IPV4 0x8
/* rrd word 3 */
#define RRD_PKTLEN_MASK 0x3FFF
#define RRD_PKTLEN_SHIFT 0
#define RRD_ERR_L4_MASK 0x0001
#define RRD_ERR_L4_SHIFT 14
#define RRD_ERR_IPV4_MASK 0x0001
#define RRD_ERR_IPV4_SHIFT 15
#define RRD_VLTAGGED_MASK 0x0001
#define RRD_VLTAGGED_SHIFT 16
#define RRD_OLD_PID_MASK 0x0007
#define RRD_OLD_PID_SHIFT 17
#define RRD_ERR_RES_MASK 0x0001
#define RRD_ERR_RES_SHIFT 20
#define RRD_ERR_FCS_MASK 0x0001
#define RRD_ERR_FCS_SHIFT 21
#define RRD_ERR_FAE_MASK 0x0001
#define RRD_ERR_FAE_SHIFT 22
#define RRD_ERR_TRUNC_MASK 0x0001
#define RRD_ERR_TRUNC_SHIFT 23
#define RRD_ERR_RUNT_MASK 0x0001
#define RRD_ERR_RUNT_SHIFT 24
#define RRD_ERR_ICMP_MASK 0x0001
#define RRD_ERR_ICMP_SHIFT 25
#define RRD_BCAST_MASK 0x0001
#define RRD_BCAST_SHIFT 26
#define RRD_MCAST_MASK 0x0001
#define RRD_MCAST_SHIFT 27
#define RRD_ETHTYPE_MASK 0x0001
#define RRD_ETHTYPE_SHIFT 28
#define RRD_ERR_FIFOV_MASK 0x0001
#define RRD_ERR_FIFOV_SHIFT 29
#define RRD_ERR_LEN_MASK 0x0001
#define RRD_ERR_LEN_SHIFT 30
#define RRD_UPDATED_MASK 0x0001
#define RRD_UPDATED_SHIFT 31
#define ALX_MAX_SETUP_LNK_CYCLE 50
/* for FlowControl */
#define ALX_FC_RX 0x01
#define ALX_FC_TX 0x02
#define ALX_FC_ANEG 0x04
/* for sleep control */
#define ALX_SLEEP_WOL_PHY 0x00000001
#define ALX_SLEEP_WOL_MAGIC 0x00000002
#define ALX_SLEEP_CIFS 0x00000004
#define ALX_SLEEP_ACTIVE (ALX_SLEEP_WOL_PHY | \
ALX_SLEEP_WOL_MAGIC | \
ALX_SLEEP_CIFS)
/* for RSS hash type */
#define ALX_RSS_HASH_TYPE_IPV4 0x1
#define ALX_RSS_HASH_TYPE_IPV4_TCP 0x2
#define ALX_RSS_HASH_TYPE_IPV6 0x4
#define ALX_RSS_HASH_TYPE_IPV6_TCP 0x8
#define ALX_RSS_HASH_TYPE_ALL (ALX_RSS_HASH_TYPE_IPV4 | \
ALX_RSS_HASH_TYPE_IPV4_TCP | \
ALX_RSS_HASH_TYPE_IPV6 | \
ALX_RSS_HASH_TYPE_IPV6_TCP)
#define ALX_DEF_RXBUF_SIZE 1536
#define ALX_MAX_JUMBO_PKT_SIZE (9*1024)
#define ALX_MAX_TSO_PKT_SIZE (7*1024)
#define ALX_MAX_FRAME_SIZE ALX_MAX_JUMBO_PKT_SIZE
#define ALX_MIN_FRAME_SIZE 68
#define ALX_RAW_MTU(_mtu) (_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN)
#define ALX_MAX_RX_QUEUES 8
#define ALX_MAX_TX_QUEUES 4
#define ALX_MAX_HANDLED_INTRS 5
#define ALX_ISR_MISC (ALX_ISR_PCIE_LNKDOWN | \
ALX_ISR_DMAW | \
ALX_ISR_DMAR | \
ALX_ISR_SMB | \
ALX_ISR_MANU | \
ALX_ISR_TIMER)
#define ALX_ISR_FATAL (ALX_ISR_PCIE_LNKDOWN | \
ALX_ISR_DMAW | ALX_ISR_DMAR)
#define ALX_ISR_ALERT (ALX_ISR_RXF_OV | \
ALX_ISR_TXF_UR | \
ALX_ISR_RFD_UR)
#define ALX_ISR_ALL_QUEUES (ALX_ISR_TX_Q0 | \
ALX_ISR_TX_Q1 | \
ALX_ISR_TX_Q2 | \
ALX_ISR_TX_Q3 | \
ALX_ISR_RX_Q0 | \
ALX_ISR_RX_Q1 | \
ALX_ISR_RX_Q2 | \
ALX_ISR_RX_Q3 | \
ALX_ISR_RX_Q4 | \
ALX_ISR_RX_Q5 | \
ALX_ISR_RX_Q6 | \
ALX_ISR_RX_Q7)
/* Statistics counters collected by the MAC
*
* The order of the fields must match the strings in alx_gstrings_stats
* All stats fields should be u64
* See ethtool.c
*/
struct alx_hw_stats {
/* rx */
u64 rx_ok; /* good RX packets */
u64 rx_bcast; /* good RX broadcast packets */
u64 rx_mcast; /* good RX multicast packets */
u64 rx_pause; /* RX pause frames */
u64 rx_ctrl; /* RX control packets other than pause frames */
u64 rx_fcs_err; /* RX packets with bad FCS */
u64 rx_len_err; /* RX packets with length != actual size */
u64 rx_byte_cnt; /* good bytes received. FCS is NOT included */
u64 rx_runt; /* RX packets < 64 bytes with good FCS */
u64 rx_frag; /* RX packets < 64 bytes with bad FCS */
u64 rx_sz_64B; /* 64 byte RX packets */
u64 rx_sz_127B; /* 65-127 byte RX packets */
u64 rx_sz_255B; /* 128-255 byte RX packets */
u64 rx_sz_511B; /* 256-511 byte RX packets */
u64 rx_sz_1023B; /* 512-1023 byte RX packets */
u64 rx_sz_1518B; /* 1024-1518 byte RX packets */
u64 rx_sz_max; /* 1519 byte to MTU RX packets */
u64 rx_ov_sz; /* truncated RX packets, size > MTU */
u64 rx_ov_rxf; /* frames dropped due to RX FIFO overflow */
u64 rx_ov_rrd; /* frames dropped due to RRD overflow */
u64 rx_align_err; /* alignment errors */
u64 rx_bc_byte_cnt; /* RX broadcast bytes, excluding FCS */
u64 rx_mc_byte_cnt; /* RX multicast bytes, excluding FCS */
u64 rx_err_addr; /* packets dropped due to address filtering */
/* tx */
u64 tx_ok; /* good TX packets */
u64 tx_bcast; /* good TX broadcast packets */
u64 tx_mcast; /* good TX multicast packets */
u64 tx_pause; /* TX pause frames */
u64 tx_exc_defer; /* TX packets deferred excessively */
u64 tx_ctrl; /* TX control frames, excluding pause frames */
u64 tx_defer; /* TX packets deferred */
u64 tx_byte_cnt; /* bytes transmitted, FCS is NOT included */
u64 tx_sz_64B; /* 64 byte TX packets */
u64 tx_sz_127B; /* 65-127 byte TX packets */
u64 tx_sz_255B; /* 128-255 byte TX packets */
u64 tx_sz_511B; /* 256-511 byte TX packets */
u64 tx_sz_1023B; /* 512-1023 byte TX packets */
u64 tx_sz_1518B; /* 1024-1518 byte TX packets */
u64 tx_sz_max; /* 1519 byte to MTU TX packets */
u64 tx_single_col; /* packets TX after a single collision */
u64 tx_multi_col; /* packets TX after multiple collisions */
u64 tx_late_col; /* TX packets with late collisions */
u64 tx_abort_col; /* TX packets aborted w/excessive collisions */
u64 tx_underrun; /* TX packets aborted due to TX FIFO underrun
* or TRD FIFO underrun
*/
u64 tx_trd_eop; /* reads beyond the EOP into the next frame
* when TRD was not written timely
*/
u64 tx_len_err; /* TX packets where length != actual size */
u64 tx_trunc; /* TX packets truncated due to size > MTU */
u64 tx_bc_byte_cnt; /* broadcast bytes transmitted, excluding FCS */
u64 tx_mc_byte_cnt; /* multicast bytes transmitted, excluding FCS */
u64 update;
};
/* maximum interrupt vectors for msix */
#define ALX_MAX_MSIX_INTRS 16
#define ALX_GET_FIELD(_data, _field) \
(((_data) >> _field ## _SHIFT) & _field ## _MASK)
#define ALX_SET_FIELD(_data, _field, _value) do { \
(_data) &= ~(_field ## _MASK << _field ## _SHIFT); \
(_data) |= ((_value) & _field ## _MASK) << _field ## _SHIFT;\
} while (0)
struct alx_hw {
struct pci_dev *pdev;
u8 __iomem *hw_addr;
/* current & permanent mac addr */
u8 mac_addr[ETH_ALEN];
u8 perm_addr[ETH_ALEN];
u16 mtu;
u16 imt;
u8 dma_chnl;
u8 max_dma_chnl;
/* tpd threshold to trig INT */
u32 ith_tpd;
u32 rx_ctrl;
u32 mc_hash[2];
u32 smb_timer;
/* SPEED_* + DUPLEX_*, SPEED_UNKNOWN if link is down */
int link_speed;
u8 duplex;
/* auto-neg advertisement or force mode config */
u8 flowctrl;
u32 adv_cfg;
spinlock_t mdio_lock;
struct mdio_if_info mdio;
u16 phy_id[2];
/* PHY link patch flag */
bool lnk_patch;
/* cumulated stats from the hardware (registers are cleared on read) */
struct alx_hw_stats stats;
};
static inline int alx_hw_revision(struct alx_hw *hw)
{
return hw->pdev->revision >> ALX_PCI_REVID_SHIFT;
}
static inline bool alx_hw_with_cr(struct alx_hw *hw)
{
return hw->pdev->revision & 1;
}
static inline bool alx_hw_giga(struct alx_hw *hw)
{
return hw->pdev->device & 1;
}
static inline void alx_write_mem8(struct alx_hw *hw, u32 reg, u8 val)
{
writeb(val, hw->hw_addr + reg);
}
static inline void alx_write_mem16(struct alx_hw *hw, u32 reg, u16 val)
{
writew(val, hw->hw_addr + reg);
}
static inline u16 alx_read_mem16(struct alx_hw *hw, u32 reg)
{
return readw(hw->hw_addr + reg);
}
static inline void alx_write_mem32(struct alx_hw *hw, u32 reg, u32 val)
{
writel(val, hw->hw_addr + reg);
}
static inline u32 alx_read_mem32(struct alx_hw *hw, u32 reg)
{
return readl(hw->hw_addr + reg);
}
static inline void alx_post_write(struct alx_hw *hw)
{
readl(hw->hw_addr);
}
int alx_get_perm_macaddr(struct alx_hw *hw, u8 *addr);
void alx_reset_phy(struct alx_hw *hw);
void alx_reset_pcie(struct alx_hw *hw);
void alx_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en);
int alx_setup_speed_duplex(struct alx_hw *hw, u32 ethadv, u8 flowctrl);
void alx_post_phy_link(struct alx_hw *hw);
int alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data);
int alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data);
int alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata);
int alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data);
int alx_read_phy_link(struct alx_hw *hw);
int alx_clear_phy_intr(struct alx_hw *hw);
void alx_cfg_mac_flowcontrol(struct alx_hw *hw, u8 fc);
void alx_start_mac(struct alx_hw *hw);
int alx_reset_mac(struct alx_hw *hw);
void alx_set_macaddr(struct alx_hw *hw, const u8 *addr);
bool alx_phy_configured(struct alx_hw *hw);
void alx_configure_basic(struct alx_hw *hw);
void alx_disable_rss(struct alx_hw *hw);
bool alx_get_phy_info(struct alx_hw *hw);
void alx_update_hw_stats(struct alx_hw *hw);
static inline u32 alx_speed_to_ethadv(int speed, u8 duplex)
{
if (speed == SPEED_1000 && duplex == DUPLEX_FULL)
return ADVERTISED_1000baseT_Full;
if (speed == SPEED_100 && duplex == DUPLEX_FULL)
return ADVERTISED_100baseT_Full;
if (speed == SPEED_100 && duplex== DUPLEX_HALF)
return ADVERTISED_100baseT_Half;
if (speed == SPEED_10 && duplex == DUPLEX_FULL)
return ADVERTISED_10baseT_Full;
if (speed == SPEED_10 && duplex == DUPLEX_HALF)
return ADVERTISED_10baseT_Half;
return 0;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,854 @@
/*
* Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net>
*
* This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ALX_REG_H
#define ALX_REG_H
#define ALX_DEV_ID_AR8161 0x1091
#define ALX_DEV_ID_E2200 0xe091
#define ALX_DEV_ID_AR8162 0x1090
#define ALX_DEV_ID_AR8171 0x10A1
#define ALX_DEV_ID_AR8172 0x10A0
/* rev definition,
* bit(0): with xD support
* bit(1): with Card Reader function
* bit(7:2): real revision
*/
#define ALX_PCI_REVID_SHIFT 3
#define ALX_REV_A0 0
#define ALX_REV_A1 1
#define ALX_REV_B0 2
#define ALX_REV_C0 3
#define ALX_DEV_CTRL 0x0060
#define ALX_DEV_CTRL_MAXRRS_MIN 2
#define ALX_MSIX_MASK 0x0090
#define ALX_UE_SVRT 0x010C
#define ALX_UE_SVRT_FCPROTERR BIT(13)
#define ALX_UE_SVRT_DLPROTERR BIT(4)
/* eeprom & flash load register */
#define ALX_EFLD 0x0204
#define ALX_EFLD_F_EXIST BIT(10)
#define ALX_EFLD_E_EXIST BIT(9)
#define ALX_EFLD_STAT BIT(5)
#define ALX_EFLD_START BIT(0)
/* eFuse load register */
#define ALX_SLD 0x0218
#define ALX_SLD_STAT BIT(12)
#define ALX_SLD_START BIT(11)
#define ALX_SLD_MAX_TO 100
#define ALX_PDLL_TRNS1 0x1104
#define ALX_PDLL_TRNS1_D3PLLOFF_EN BIT(11)
#define ALX_PMCTRL 0x12F8
#define ALX_PMCTRL_HOTRST_WTEN BIT(31)
/* bit30: L0s/L1 controlled by MAC based on throughput(setting in 15A0) */
#define ALX_PMCTRL_ASPM_FCEN BIT(30)
#define ALX_PMCTRL_SADLY_EN BIT(29)
#define ALX_PMCTRL_LCKDET_TIMER_MASK 0xF
#define ALX_PMCTRL_LCKDET_TIMER_SHIFT 24
#define ALX_PMCTRL_LCKDET_TIMER_DEF 0xC
/* bit[23:20] if pm_request_l1 time > @, then enter L0s not L1 */
#define ALX_PMCTRL_L1REQ_TO_MASK 0xF
#define ALX_PMCTRL_L1REQ_TO_SHIFT 20
#define ALX_PMCTRL_L1REG_TO_DEF 0xF
#define ALX_PMCTRL_TXL1_AFTER_L0S BIT(19)
#define ALX_PMCTRL_L1_TIMER_MASK 0x7
#define ALX_PMCTRL_L1_TIMER_SHIFT 16
#define ALX_PMCTRL_L1_TIMER_16US 4
#define ALX_PMCTRL_RCVR_WT_1US BIT(15)
/* bit13: enable pcie clk switch in L1 state */
#define ALX_PMCTRL_L1_CLKSW_EN BIT(13)
#define ALX_PMCTRL_L0S_EN BIT(12)
#define ALX_PMCTRL_RXL1_AFTER_L0S BIT(11)
#define ALX_PMCTRL_L1_BUFSRX_EN BIT(7)
/* bit6: power down serdes RX */
#define ALX_PMCTRL_L1_SRDSRX_PWD BIT(6)
#define ALX_PMCTRL_L1_SRDSPLL_EN BIT(5)
#define ALX_PMCTRL_L1_SRDS_EN BIT(4)
#define ALX_PMCTRL_L1_EN BIT(3)
/*******************************************************/
/* following registers are mapped only to memory space */
/*******************************************************/
#define ALX_MASTER 0x1400
/* bit12: 1:alwys select pclk from serdes, not sw to 25M */
#define ALX_MASTER_PCLKSEL_SRDS BIT(12)
/* bit11: irq moduration for rx */
#define ALX_MASTER_IRQMOD2_EN BIT(11)
/* bit10: irq moduration for tx/rx */
#define ALX_MASTER_IRQMOD1_EN BIT(10)
#define ALX_MASTER_SYSALVTIMER_EN BIT(7)
#define ALX_MASTER_OOB_DIS BIT(6)
/* bit5: wakeup without pcie clk */
#define ALX_MASTER_WAKEN_25M BIT(5)
/* bit0: MAC & DMA reset */
#define ALX_MASTER_DMA_MAC_RST BIT(0)
#define ALX_DMA_MAC_RST_TO 50
#define ALX_IRQ_MODU_TIMER 0x1408
#define ALX_IRQ_MODU_TIMER1_MASK 0xFFFF
#define ALX_IRQ_MODU_TIMER1_SHIFT 0
#define ALX_PHY_CTRL 0x140C
#define ALX_PHY_CTRL_100AB_EN BIT(17)
/* bit14: affect MAC & PHY, go to low power sts */
#define ALX_PHY_CTRL_POWER_DOWN BIT(14)
/* bit13: 1:pll always ON, 0:can switch in lpw */
#define ALX_PHY_CTRL_PLL_ON BIT(13)
#define ALX_PHY_CTRL_RST_ANALOG BIT(12)
#define ALX_PHY_CTRL_HIB_PULSE BIT(11)
#define ALX_PHY_CTRL_HIB_EN BIT(10)
#define ALX_PHY_CTRL_IDDQ BIT(7)
#define ALX_PHY_CTRL_GATE_25M BIT(5)
#define ALX_PHY_CTRL_LED_MODE BIT(2)
/* bit0: out of dsp RST state */
#define ALX_PHY_CTRL_DSPRST_OUT BIT(0)
#define ALX_PHY_CTRL_DSPRST_TO 80
#define ALX_PHY_CTRL_CLS (ALX_PHY_CTRL_LED_MODE | \
ALX_PHY_CTRL_100AB_EN | \
ALX_PHY_CTRL_PLL_ON)
#define ALX_MAC_STS 0x1410
#define ALX_MAC_STS_TXQ_BUSY BIT(3)
#define ALX_MAC_STS_RXQ_BUSY BIT(2)
#define ALX_MAC_STS_TXMAC_BUSY BIT(1)
#define ALX_MAC_STS_RXMAC_BUSY BIT(0)
#define ALX_MAC_STS_IDLE (ALX_MAC_STS_TXQ_BUSY | \
ALX_MAC_STS_RXQ_BUSY | \
ALX_MAC_STS_TXMAC_BUSY | \
ALX_MAC_STS_RXMAC_BUSY)
#define ALX_MDIO 0x1414
#define ALX_MDIO_MODE_EXT BIT(30)
#define ALX_MDIO_BUSY BIT(27)
#define ALX_MDIO_CLK_SEL_MASK 0x7
#define ALX_MDIO_CLK_SEL_SHIFT 24
#define ALX_MDIO_CLK_SEL_25MD4 0
#define ALX_MDIO_CLK_SEL_25MD128 7
#define ALX_MDIO_START BIT(23)
#define ALX_MDIO_SPRES_PRMBL BIT(22)
/* bit21: 1:read,0:write */
#define ALX_MDIO_OP_READ BIT(21)
#define ALX_MDIO_REG_MASK 0x1F
#define ALX_MDIO_REG_SHIFT 16
#define ALX_MDIO_DATA_MASK 0xFFFF
#define ALX_MDIO_DATA_SHIFT 0
#define ALX_MDIO_MAX_AC_TO 120
#define ALX_MDIO_EXTN 0x1448
#define ALX_MDIO_EXTN_DEVAD_MASK 0x1F
#define ALX_MDIO_EXTN_DEVAD_SHIFT 16
#define ALX_MDIO_EXTN_REG_MASK 0xFFFF
#define ALX_MDIO_EXTN_REG_SHIFT 0
#define ALX_SERDES 0x1424
#define ALX_SERDES_PHYCLK_SLWDWN BIT(18)
#define ALX_SERDES_MACCLK_SLWDWN BIT(17)
#define ALX_LPI_CTRL 0x1440
#define ALX_LPI_CTRL_EN BIT(0)
/* for B0+, bit[13..] for C0+ */
#define ALX_HRTBT_EXT_CTRL 0x1AD0
#define L1F_HRTBT_EXT_CTRL_PERIOD_HIGH_MASK 0x3F
#define L1F_HRTBT_EXT_CTRL_PERIOD_HIGH_SHIFT 24
#define L1F_HRTBT_EXT_CTRL_SWOI_STARTUP_PKT_EN BIT(23)
#define L1F_HRTBT_EXT_CTRL_IOAC_2_FRAGMENTED BIT(22)
#define L1F_HRTBT_EXT_CTRL_IOAC_1_FRAGMENTED BIT(21)
#define L1F_HRTBT_EXT_CTRL_IOAC_1_KEEPALIVE_EN BIT(20)
#define L1F_HRTBT_EXT_CTRL_IOAC_1_HAS_VLAN BIT(19)
#define L1F_HRTBT_EXT_CTRL_IOAC_1_IS_8023 BIT(18)
#define L1F_HRTBT_EXT_CTRL_IOAC_1_IS_IPV6 BIT(17)
#define L1F_HRTBT_EXT_CTRL_IOAC_2_KEEPALIVE_EN BIT(16)
#define L1F_HRTBT_EXT_CTRL_IOAC_2_HAS_VLAN BIT(15)
#define L1F_HRTBT_EXT_CTRL_IOAC_2_IS_8023 BIT(14)
#define L1F_HRTBT_EXT_CTRL_IOAC_2_IS_IPV6 BIT(13)
#define ALX_HRTBT_EXT_CTRL_NS_EN BIT(12)
#define ALX_HRTBT_EXT_CTRL_FRAG_LEN_MASK 0xFF
#define ALX_HRTBT_EXT_CTRL_FRAG_LEN_SHIFT 4
#define ALX_HRTBT_EXT_CTRL_IS_8023 BIT(3)
#define ALX_HRTBT_EXT_CTRL_IS_IPV6 BIT(2)
#define ALX_HRTBT_EXT_CTRL_WAKEUP_EN BIT(1)
#define ALX_HRTBT_EXT_CTRL_ARP_EN BIT(0)
#define ALX_HRTBT_REM_IPV4_ADDR 0x1AD4
#define ALX_HRTBT_HOST_IPV4_ADDR 0x1478
#define ALX_HRTBT_REM_IPV6_ADDR3 0x1AD8
#define ALX_HRTBT_REM_IPV6_ADDR2 0x1ADC
#define ALX_HRTBT_REM_IPV6_ADDR1 0x1AE0
#define ALX_HRTBT_REM_IPV6_ADDR0 0x1AE4
/* 1B8C ~ 1B94 for C0+ */
#define ALX_SWOI_ACER_CTRL 0x1B8C
#define ALX_SWOI_ORIG_ACK_NAK_EN BIT(20)
#define ALX_SWOI_ORIG_ACK_NAK_PKT_LEN_MASK 0XFF
#define ALX_SWOI_ORIG_ACK_NAK_PKT_LEN_SHIFT 12
#define ALX_SWOI_ORIG_ACK_ADDR_MASK 0XFFF
#define ALX_SWOI_ORIG_ACK_ADDR_SHIFT 0
#define ALX_SWOI_IOAC_CTRL_2 0x1B90
#define ALX_SWOI_IOAC_CTRL_2_SWOI_1_FRAG_LEN_MASK 0xFF
#define ALX_SWOI_IOAC_CTRL_2_SWOI_1_FRAG_LEN_SHIFT 24
#define ALX_SWOI_IOAC_CTRL_2_SWOI_1_PKT_LEN_MASK 0xFFF
#define ALX_SWOI_IOAC_CTRL_2_SWOI_1_PKT_LEN_SHIFT 12
#define ALX_SWOI_IOAC_CTRL_2_SWOI_1_HDR_ADDR_MASK 0xFFF
#define ALX_SWOI_IOAC_CTRL_2_SWOI_1_HDR_ADDR_SHIFT 0
#define ALX_SWOI_IOAC_CTRL_3 0x1B94
#define ALX_SWOI_IOAC_CTRL_3_SWOI_2_FRAG_LEN_MASK 0xFF
#define ALX_SWOI_IOAC_CTRL_3_SWOI_2_FRAG_LEN_SHIFT 24
#define ALX_SWOI_IOAC_CTRL_3_SWOI_2_PKT_LEN_MASK 0xFFF
#define ALX_SWOI_IOAC_CTRL_3_SWOI_2_PKT_LEN_SHIFT 12
#define ALX_SWOI_IOAC_CTRL_3_SWOI_2_HDR_ADDR_MASK 0xFFF
#define ALX_SWOI_IOAC_CTRL_3_SWOI_2_HDR_ADDR_SHIFT 0
/* for B0 */
#define ALX_IDLE_DECISN_TIMER 0x1474
/* 1ms */
#define ALX_IDLE_DECISN_TIMER_DEF 0x400
#define ALX_MAC_CTRL 0x1480
#define ALX_MAC_CTRL_FAST_PAUSE BIT(31)
#define ALX_MAC_CTRL_WOLSPED_SWEN BIT(30)
/* bit29: 1:legacy(hi5b), 0:marvl(lo5b)*/
#define ALX_MAC_CTRL_MHASH_ALG_HI5B BIT(29)
#define ALX_MAC_CTRL_BRD_EN BIT(26)
#define ALX_MAC_CTRL_MULTIALL_EN BIT(25)
#define ALX_MAC_CTRL_SPEED_MASK 0x3
#define ALX_MAC_CTRL_SPEED_SHIFT 20
#define ALX_MAC_CTRL_SPEED_10_100 1
#define ALX_MAC_CTRL_SPEED_1000 2
#define ALX_MAC_CTRL_PROMISC_EN BIT(15)
#define ALX_MAC_CTRL_VLANSTRIP BIT(14)
#define ALX_MAC_CTRL_PRMBLEN_MASK 0xF
#define ALX_MAC_CTRL_PRMBLEN_SHIFT 10
#define ALX_MAC_CTRL_PCRCE BIT(7)
#define ALX_MAC_CTRL_CRCE BIT(6)
#define ALX_MAC_CTRL_FULLD BIT(5)
#define ALX_MAC_CTRL_RXFC_EN BIT(3)
#define ALX_MAC_CTRL_TXFC_EN BIT(2)
#define ALX_MAC_CTRL_RX_EN BIT(1)
#define ALX_MAC_CTRL_TX_EN BIT(0)
#define ALX_STAD0 0x1488
#define ALX_STAD1 0x148C
#define ALX_HASH_TBL0 0x1490
#define ALX_HASH_TBL1 0x1494
#define ALX_MTU 0x149C
#define ALX_MTU_JUMBO_TH 1514
#define ALX_MTU_STD_ALGN 1536
#define ALX_SRAM5 0x1524
#define ALX_SRAM_RXF_LEN_MASK 0xFFF
#define ALX_SRAM_RXF_LEN_SHIFT 0
#define ALX_SRAM_RXF_LEN_8K (8*1024)
#define ALX_SRAM9 0x1534
#define ALX_SRAM_LOAD_PTR BIT(0)
#define ALX_RX_BASE_ADDR_HI 0x1540
#define ALX_TX_BASE_ADDR_HI 0x1544
#define ALX_RFD_ADDR_LO 0x1550
#define ALX_RFD_RING_SZ 0x1560
#define ALX_RFD_BUF_SZ 0x1564
#define ALX_RRD_ADDR_LO 0x1568
#define ALX_RRD_RING_SZ 0x1578
/* pri3: highest, pri0: lowest */
#define ALX_TPD_PRI3_ADDR_LO 0x14E4
#define ALX_TPD_PRI2_ADDR_LO 0x14E0
#define ALX_TPD_PRI1_ADDR_LO 0x157C
#define ALX_TPD_PRI0_ADDR_LO 0x1580
/* producer index is 16bit */
#define ALX_TPD_PRI3_PIDX 0x1618
#define ALX_TPD_PRI2_PIDX 0x161A
#define ALX_TPD_PRI1_PIDX 0x15F0
#define ALX_TPD_PRI0_PIDX 0x15F2
/* consumer index is 16bit */
#define ALX_TPD_PRI3_CIDX 0x161C
#define ALX_TPD_PRI2_CIDX 0x161E
#define ALX_TPD_PRI1_CIDX 0x15F4
#define ALX_TPD_PRI0_CIDX 0x15F6
#define ALX_TPD_RING_SZ 0x1584
#define ALX_TXQ0 0x1590
#define ALX_TXQ0_TXF_BURST_PREF_MASK 0xFFFF
#define ALX_TXQ0_TXF_BURST_PREF_SHIFT 16
#define ALX_TXQ_TXF_BURST_PREF_DEF 0x200
#define ALX_TXQ0_LSO_8023_EN BIT(7)
#define ALX_TXQ0_MODE_ENHANCE BIT(6)
#define ALX_TXQ0_EN BIT(5)
#define ALX_TXQ0_SUPT_IPOPT BIT(4)
#define ALX_TXQ0_TPD_BURSTPREF_MASK 0xF
#define ALX_TXQ0_TPD_BURSTPREF_SHIFT 0
#define ALX_TXQ_TPD_BURSTPREF_DEF 5
#define ALX_TXQ1 0x1594
/* bit11: drop large packet, len > (rfd buf) */
#define ALX_TXQ1_ERRLGPKT_DROP_EN BIT(11)
#define ALX_TXQ1_JUMBO_TSO_TH (7*1024)
#define ALX_RXQ0 0x15A0
#define ALX_RXQ0_EN BIT(31)
#define ALX_RXQ0_RSS_HASH_EN BIT(29)
#define ALX_RXQ0_RSS_MODE_MASK 0x3
#define ALX_RXQ0_RSS_MODE_SHIFT 26
#define ALX_RXQ0_RSS_MODE_DIS 0
#define ALX_RXQ0_RSS_MODE_MQMI 3
#define ALX_RXQ0_NUM_RFD_PREF_MASK 0x3F
#define ALX_RXQ0_NUM_RFD_PREF_SHIFT 20
#define ALX_RXQ0_NUM_RFD_PREF_DEF 8
#define ALX_RXQ0_IDT_TBL_SIZE_MASK 0x1FF
#define ALX_RXQ0_IDT_TBL_SIZE_SHIFT 8
#define ALX_RXQ0_IDT_TBL_SIZE_DEF 0x100
#define ALX_RXQ0_IDT_TBL_SIZE_NORMAL 128
#define ALX_RXQ0_IPV6_PARSE_EN BIT(7)
#define ALX_RXQ0_RSS_HSTYP_MASK 0xF
#define ALX_RXQ0_RSS_HSTYP_SHIFT 2
#define ALX_RXQ0_RSS_HSTYP_IPV6_TCP_EN BIT(5)
#define ALX_RXQ0_RSS_HSTYP_IPV6_EN BIT(4)
#define ALX_RXQ0_RSS_HSTYP_IPV4_TCP_EN BIT(3)
#define ALX_RXQ0_RSS_HSTYP_IPV4_EN BIT(2)
#define ALX_RXQ0_RSS_HSTYP_ALL (ALX_RXQ0_RSS_HSTYP_IPV6_TCP_EN | \
ALX_RXQ0_RSS_HSTYP_IPV4_TCP_EN | \
ALX_RXQ0_RSS_HSTYP_IPV6_EN | \
ALX_RXQ0_RSS_HSTYP_IPV4_EN)
#define ALX_RXQ0_ASPM_THRESH_MASK 0x3
#define ALX_RXQ0_ASPM_THRESH_SHIFT 0
#define ALX_RXQ0_ASPM_THRESH_100M 3
#define ALX_RXQ2 0x15A8
#define ALX_RXQ2_RXF_XOFF_THRESH_MASK 0xFFF
#define ALX_RXQ2_RXF_XOFF_THRESH_SHIFT 16
#define ALX_RXQ2_RXF_XON_THRESH_MASK 0xFFF
#define ALX_RXQ2_RXF_XON_THRESH_SHIFT 0
/* Size = tx-packet(1522) + IPG(12) + SOF(8) + 64(Pause) + IPG(12) + SOF(8) +
* rx-packet(1522) + delay-of-link(64)
* = 3212.
*/
#define ALX_RXQ2_RXF_FLOW_CTRL_RSVD 3212
#define ALX_DMA 0x15C0
#define ALX_DMA_RCHNL_SEL_MASK 0x3
#define ALX_DMA_RCHNL_SEL_SHIFT 26
#define ALX_DMA_WDLY_CNT_MASK 0xF
#define ALX_DMA_WDLY_CNT_SHIFT 16
#define ALX_DMA_WDLY_CNT_DEF 4
#define ALX_DMA_RDLY_CNT_MASK 0x1F
#define ALX_DMA_RDLY_CNT_SHIFT 11
#define ALX_DMA_RDLY_CNT_DEF 15
/* bit10: 0:tpd with pri, 1: data */
#define ALX_DMA_RREQ_PRI_DATA BIT(10)
#define ALX_DMA_RREQ_BLEN_MASK 0x7
#define ALX_DMA_RREQ_BLEN_SHIFT 4
#define ALX_DMA_RORDER_MODE_MASK 0x7
#define ALX_DMA_RORDER_MODE_SHIFT 0
#define ALX_DMA_RORDER_MODE_OUT 4
#define ALX_WOL0 0x14A0
#define ALX_WOL0_PME_LINK BIT(5)
#define ALX_WOL0_LINK_EN BIT(4)
#define ALX_WOL0_PME_MAGIC_EN BIT(3)
#define ALX_WOL0_MAGIC_EN BIT(2)
#define ALX_RFD_PIDX 0x15E0
#define ALX_RFD_CIDX 0x15F8
/* MIB */
#define ALX_MIB_BASE 0x1700
#define ALX_MIB_RX_OK (ALX_MIB_BASE + 0)
#define ALX_MIB_RX_BCAST (ALX_MIB_BASE + 4)
#define ALX_MIB_RX_MCAST (ALX_MIB_BASE + 8)
#define ALX_MIB_RX_PAUSE (ALX_MIB_BASE + 12)
#define ALX_MIB_RX_CTRL (ALX_MIB_BASE + 16)
#define ALX_MIB_RX_FCS_ERR (ALX_MIB_BASE + 20)
#define ALX_MIB_RX_LEN_ERR (ALX_MIB_BASE + 24)
#define ALX_MIB_RX_BYTE_CNT (ALX_MIB_BASE + 28)
#define ALX_MIB_RX_RUNT (ALX_MIB_BASE + 32)
#define ALX_MIB_RX_FRAG (ALX_MIB_BASE + 36)
#define ALX_MIB_RX_SZ_64B (ALX_MIB_BASE + 40)
#define ALX_MIB_RX_SZ_127B (ALX_MIB_BASE + 44)
#define ALX_MIB_RX_SZ_255B (ALX_MIB_BASE + 48)
#define ALX_MIB_RX_SZ_511B (ALX_MIB_BASE + 52)
#define ALX_MIB_RX_SZ_1023B (ALX_MIB_BASE + 56)
#define ALX_MIB_RX_SZ_1518B (ALX_MIB_BASE + 60)
#define ALX_MIB_RX_SZ_MAX (ALX_MIB_BASE + 64)
#define ALX_MIB_RX_OV_SZ (ALX_MIB_BASE + 68)
#define ALX_MIB_RX_OV_RXF (ALX_MIB_BASE + 72)
#define ALX_MIB_RX_OV_RRD (ALX_MIB_BASE + 76)
#define ALX_MIB_RX_ALIGN_ERR (ALX_MIB_BASE + 80)
#define ALX_MIB_RX_BCCNT (ALX_MIB_BASE + 84)
#define ALX_MIB_RX_MCCNT (ALX_MIB_BASE + 88)
#define ALX_MIB_RX_ERRADDR (ALX_MIB_BASE + 92)
#define ALX_MIB_TX_OK (ALX_MIB_BASE + 96)
#define ALX_MIB_TX_BCAST (ALX_MIB_BASE + 100)
#define ALX_MIB_TX_MCAST (ALX_MIB_BASE + 104)
#define ALX_MIB_TX_PAUSE (ALX_MIB_BASE + 108)
#define ALX_MIB_TX_EXC_DEFER (ALX_MIB_BASE + 112)
#define ALX_MIB_TX_CTRL (ALX_MIB_BASE + 116)
#define ALX_MIB_TX_DEFER (ALX_MIB_BASE + 120)
#define ALX_MIB_TX_BYTE_CNT (ALX_MIB_BASE + 124)
#define ALX_MIB_TX_SZ_64B (ALX_MIB_BASE + 128)
#define ALX_MIB_TX_SZ_127B (ALX_MIB_BASE + 132)
#define ALX_MIB_TX_SZ_255B (ALX_MIB_BASE + 136)
#define ALX_MIB_TX_SZ_511B (ALX_MIB_BASE + 140)
#define ALX_MIB_TX_SZ_1023B (ALX_MIB_BASE + 144)
#define ALX_MIB_TX_SZ_1518B (ALX_MIB_BASE + 148)
#define ALX_MIB_TX_SZ_MAX (ALX_MIB_BASE + 152)
#define ALX_MIB_TX_SINGLE_COL (ALX_MIB_BASE + 156)
#define ALX_MIB_TX_MULTI_COL (ALX_MIB_BASE + 160)
#define ALX_MIB_TX_LATE_COL (ALX_MIB_BASE + 164)
#define ALX_MIB_TX_ABORT_COL (ALX_MIB_BASE + 168)
#define ALX_MIB_TX_UNDERRUN (ALX_MIB_BASE + 172)
#define ALX_MIB_TX_TRD_EOP (ALX_MIB_BASE + 176)
#define ALX_MIB_TX_LEN_ERR (ALX_MIB_BASE + 180)
#define ALX_MIB_TX_TRUNC (ALX_MIB_BASE + 184)
#define ALX_MIB_TX_BCCNT (ALX_MIB_BASE + 188)
#define ALX_MIB_TX_MCCNT (ALX_MIB_BASE + 192)
#define ALX_MIB_UPDATE (ALX_MIB_BASE + 196)
#define ALX_ISR 0x1600
#define ALX_ISR_DIS BIT(31)
#define ALX_ISR_RX_Q7 BIT(30)
#define ALX_ISR_RX_Q6 BIT(29)
#define ALX_ISR_RX_Q5 BIT(28)
#define ALX_ISR_RX_Q4 BIT(27)
#define ALX_ISR_PCIE_LNKDOWN BIT(26)
#define ALX_ISR_RX_Q3 BIT(19)
#define ALX_ISR_RX_Q2 BIT(18)
#define ALX_ISR_RX_Q1 BIT(17)
#define ALX_ISR_RX_Q0 BIT(16)
#define ALX_ISR_TX_Q0 BIT(15)
#define ALX_ISR_PHY BIT(12)
#define ALX_ISR_DMAW BIT(10)
#define ALX_ISR_DMAR BIT(9)
#define ALX_ISR_TXF_UR BIT(8)
#define ALX_ISR_TX_Q3 BIT(7)
#define ALX_ISR_TX_Q2 BIT(6)
#define ALX_ISR_TX_Q1 BIT(5)
#define ALX_ISR_RFD_UR BIT(4)
#define ALX_ISR_RXF_OV BIT(3)
#define ALX_ISR_MANU BIT(2)
#define ALX_ISR_TIMER BIT(1)
#define ALX_ISR_SMB BIT(0)
#define ALX_IMR 0x1604
/* re-send assert msg if SW no response */
#define ALX_INT_RETRIG 0x1608
/* 40ms */
#define ALX_INT_RETRIG_TO 20000
#define ALX_SMB_TIMER 0x15C4
#define ALX_TINT_TPD_THRSHLD 0x15C8
#define ALX_TINT_TIMER 0x15CC
#define ALX_CLK_GATE 0x1814
#define ALX_CLK_GATE_RXMAC BIT(5)
#define ALX_CLK_GATE_TXMAC BIT(4)
#define ALX_CLK_GATE_RXQ BIT(3)
#define ALX_CLK_GATE_TXQ BIT(2)
#define ALX_CLK_GATE_DMAR BIT(1)
#define ALX_CLK_GATE_DMAW BIT(0)
#define ALX_CLK_GATE_ALL (ALX_CLK_GATE_RXMAC | \
ALX_CLK_GATE_TXMAC | \
ALX_CLK_GATE_RXQ | \
ALX_CLK_GATE_TXQ | \
ALX_CLK_GATE_DMAR | \
ALX_CLK_GATE_DMAW)
/* interop between drivers */
#define ALX_DRV 0x1804
#define ALX_DRV_PHY_AUTO BIT(28)
#define ALX_DRV_PHY_1000 BIT(27)
#define ALX_DRV_PHY_100 BIT(26)
#define ALX_DRV_PHY_10 BIT(25)
#define ALX_DRV_PHY_DUPLEX BIT(24)
/* bit23: adv Pause */
#define ALX_DRV_PHY_PAUSE BIT(23)
/* bit22: adv Asym Pause */
#define ALX_DRV_PHY_MASK 0xFF
#define ALX_DRV_PHY_SHIFT 21
#define ALX_DRV_PHY_UNKNOWN 0
/* flag of phy inited */
#define ALX_PHY_INITED 0x003F
/* reg 1830 ~ 186C for C0+, 16 bit map patterns and wake packet detection */
#define ALX_WOL_CTRL2 0x1830
#define ALX_WOL_CTRL2_DATA_STORE BIT(3)
#define ALX_WOL_CTRL2_PTRN_EVT BIT(2)
#define ALX_WOL_CTRL2_PME_PTRN_EN BIT(1)
#define ALX_WOL_CTRL2_PTRN_EN BIT(0)
#define ALX_WOL_CTRL3 0x1834
#define ALX_WOL_CTRL3_PTRN_ADDR_MASK 0xFFFFF
#define ALX_WOL_CTRL3_PTRN_ADDR_SHIFT 0
#define ALX_WOL_CTRL4 0x1838
#define ALX_WOL_CTRL4_PT15_MATCH BIT(31)
#define ALX_WOL_CTRL4_PT14_MATCH BIT(30)
#define ALX_WOL_CTRL4_PT13_MATCH BIT(29)
#define ALX_WOL_CTRL4_PT12_MATCH BIT(28)
#define ALX_WOL_CTRL4_PT11_MATCH BIT(27)
#define ALX_WOL_CTRL4_PT10_MATCH BIT(26)
#define ALX_WOL_CTRL4_PT9_MATCH BIT(25)
#define ALX_WOL_CTRL4_PT8_MATCH BIT(24)
#define ALX_WOL_CTRL4_PT7_MATCH BIT(23)
#define ALX_WOL_CTRL4_PT6_MATCH BIT(22)
#define ALX_WOL_CTRL4_PT5_MATCH BIT(21)
#define ALX_WOL_CTRL4_PT4_MATCH BIT(20)
#define ALX_WOL_CTRL4_PT3_MATCH BIT(19)
#define ALX_WOL_CTRL4_PT2_MATCH BIT(18)
#define ALX_WOL_CTRL4_PT1_MATCH BIT(17)
#define ALX_WOL_CTRL4_PT0_MATCH BIT(16)
#define ALX_WOL_CTRL4_PT15_EN BIT(15)
#define ALX_WOL_CTRL4_PT14_EN BIT(14)
#define ALX_WOL_CTRL4_PT13_EN BIT(13)
#define ALX_WOL_CTRL4_PT12_EN BIT(12)
#define ALX_WOL_CTRL4_PT11_EN BIT(11)
#define ALX_WOL_CTRL4_PT10_EN BIT(10)
#define ALX_WOL_CTRL4_PT9_EN BIT(9)
#define ALX_WOL_CTRL4_PT8_EN BIT(8)
#define ALX_WOL_CTRL4_PT7_EN BIT(7)
#define ALX_WOL_CTRL4_PT6_EN BIT(6)
#define ALX_WOL_CTRL4_PT5_EN BIT(5)
#define ALX_WOL_CTRL4_PT4_EN BIT(4)
#define ALX_WOL_CTRL4_PT3_EN BIT(3)
#define ALX_WOL_CTRL4_PT2_EN BIT(2)
#define ALX_WOL_CTRL4_PT1_EN BIT(1)
#define ALX_WOL_CTRL4_PT0_EN BIT(0)
#define ALX_WOL_CTRL5 0x183C
#define ALX_WOL_CTRL5_PT3_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT3_LEN_SHIFT 24
#define ALX_WOL_CTRL5_PT2_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT2_LEN_SHIFT 16
#define ALX_WOL_CTRL5_PT1_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT1_LEN_SHIFT 8
#define ALX_WOL_CTRL5_PT0_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT0_LEN_SHIFT 0
#define ALX_WOL_CTRL6 0x1840
#define ALX_WOL_CTRL5_PT7_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT7_LEN_SHIFT 24
#define ALX_WOL_CTRL5_PT6_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT6_LEN_SHIFT 16
#define ALX_WOL_CTRL5_PT5_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT5_LEN_SHIFT 8
#define ALX_WOL_CTRL5_PT4_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT4_LEN_SHIFT 0
#define ALX_WOL_CTRL7 0x1844
#define ALX_WOL_CTRL5_PT11_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT11_LEN_SHIFT 24
#define ALX_WOL_CTRL5_PT10_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT10_LEN_SHIFT 16
#define ALX_WOL_CTRL5_PT9_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT9_LEN_SHIFT 8
#define ALX_WOL_CTRL5_PT8_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT8_LEN_SHIFT 0
#define ALX_WOL_CTRL8 0x1848
#define ALX_WOL_CTRL5_PT15_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT15_LEN_SHIFT 24
#define ALX_WOL_CTRL5_PT14_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT14_LEN_SHIFT 16
#define ALX_WOL_CTRL5_PT13_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT13_LEN_SHIFT 8
#define ALX_WOL_CTRL5_PT12_LEN_MASK 0xFF
#define ALX_WOL_CTRL5_PT12_LEN_SHIFT 0
#define ALX_ACER_FIXED_PTN0 0x1850
#define ALX_ACER_FIXED_PTN0_MASK 0xFFFFFFFF
#define ALX_ACER_FIXED_PTN0_SHIFT 0
#define ALX_ACER_FIXED_PTN1 0x1854
#define ALX_ACER_FIXED_PTN1_MASK 0xFFFF
#define ALX_ACER_FIXED_PTN1_SHIFT 0
#define ALX_ACER_RANDOM_NUM0 0x1858
#define ALX_ACER_RANDOM_NUM0_MASK 0xFFFFFFFF
#define ALX_ACER_RANDOM_NUM0_SHIFT 0
#define ALX_ACER_RANDOM_NUM1 0x185C
#define ALX_ACER_RANDOM_NUM1_MASK 0xFFFFFFFF
#define ALX_ACER_RANDOM_NUM1_SHIFT 0
#define ALX_ACER_RANDOM_NUM2 0x1860
#define ALX_ACER_RANDOM_NUM2_MASK 0xFFFFFFFF
#define ALX_ACER_RANDOM_NUM2_SHIFT 0
#define ALX_ACER_RANDOM_NUM3 0x1864
#define ALX_ACER_RANDOM_NUM3_MASK 0xFFFFFFFF
#define ALX_ACER_RANDOM_NUM3_SHIFT 0
#define ALX_ACER_MAGIC 0x1868
#define ALX_ACER_MAGIC_EN BIT(31)
#define ALX_ACER_MAGIC_PME_EN BIT(30)
#define ALX_ACER_MAGIC_MATCH BIT(29)
#define ALX_ACER_MAGIC_FF_CHECK BIT(10)
#define ALX_ACER_MAGIC_RAN_LEN_MASK 0x1F
#define ALX_ACER_MAGIC_RAN_LEN_SHIFT 5
#define ALX_ACER_MAGIC_FIX_LEN_MASK 0x1F
#define ALX_ACER_MAGIC_FIX_LEN_SHIFT 0
#define ALX_ACER_TIMER 0x186C
#define ALX_ACER_TIMER_EN BIT(31)
#define ALX_ACER_TIMER_PME_EN BIT(30)
#define ALX_ACER_TIMER_MATCH BIT(29)
#define ALX_ACER_TIMER_THRES_MASK 0x1FFFF
#define ALX_ACER_TIMER_THRES_SHIFT 0
#define ALX_ACER_TIMER_THRES_DEF 1
/* RSS definitions */
#define ALX_RSS_KEY0 0x14B0
#define ALX_RSS_KEY1 0x14B4
#define ALX_RSS_KEY2 0x14B8
#define ALX_RSS_KEY3 0x14BC
#define ALX_RSS_KEY4 0x14C0
#define ALX_RSS_KEY5 0x14C4
#define ALX_RSS_KEY6 0x14C8
#define ALX_RSS_KEY7 0x14CC
#define ALX_RSS_KEY8 0x14D0
#define ALX_RSS_KEY9 0x14D4
#define ALX_RSS_IDT_TBL0 0x1B00
#define ALX_MSI_MAP_TBL1 0x15D0
#define ALX_MSI_MAP_TBL1_TXQ1_SHIFT 20
#define ALX_MSI_MAP_TBL1_TXQ0_SHIFT 16
#define ALX_MSI_MAP_TBL1_RXQ3_SHIFT 12
#define ALX_MSI_MAP_TBL1_RXQ2_SHIFT 8
#define ALX_MSI_MAP_TBL1_RXQ1_SHIFT 4
#define ALX_MSI_MAP_TBL1_RXQ0_SHIFT 0
#define ALX_MSI_MAP_TBL2 0x15D8
#define ALX_MSI_MAP_TBL2_TXQ3_SHIFT 20
#define ALX_MSI_MAP_TBL2_TXQ2_SHIFT 16
#define ALX_MSI_MAP_TBL2_RXQ7_SHIFT 12
#define ALX_MSI_MAP_TBL2_RXQ6_SHIFT 8
#define ALX_MSI_MAP_TBL2_RXQ5_SHIFT 4
#define ALX_MSI_MAP_TBL2_RXQ4_SHIFT 0
#define ALX_MSI_ID_MAP 0x15D4
#define ALX_MSI_RETRANS_TIMER 0x1920
/* bit16: 1:line,0:standard */
#define ALX_MSI_MASK_SEL_LINE BIT(16)
#define ALX_MSI_RETRANS_TM_MASK 0xFFFF
#define ALX_MSI_RETRANS_TM_SHIFT 0
/* CR DMA ctrl */
/* TX QoS */
#define ALX_WRR 0x1938
#define ALX_WRR_PRI_MASK 0x3
#define ALX_WRR_PRI_SHIFT 29
#define ALX_WRR_PRI_RESTRICT_NONE 3
#define ALX_WRR_PRI3_MASK 0x1F
#define ALX_WRR_PRI3_SHIFT 24
#define ALX_WRR_PRI2_MASK 0x1F
#define ALX_WRR_PRI2_SHIFT 16
#define ALX_WRR_PRI1_MASK 0x1F
#define ALX_WRR_PRI1_SHIFT 8
#define ALX_WRR_PRI0_MASK 0x1F
#define ALX_WRR_PRI0_SHIFT 0
#define ALX_HQTPD 0x193C
#define ALX_HQTPD_BURST_EN BIT(31)
#define ALX_HQTPD_Q3_NUMPREF_MASK 0xF
#define ALX_HQTPD_Q3_NUMPREF_SHIFT 8
#define ALX_HQTPD_Q2_NUMPREF_MASK 0xF
#define ALX_HQTPD_Q2_NUMPREF_SHIFT 4
#define ALX_HQTPD_Q1_NUMPREF_MASK 0xF
#define ALX_HQTPD_Q1_NUMPREF_SHIFT 0
#define ALX_MISC 0x19C0
#define ALX_MISC_PSW_OCP_MASK 0x7
#define ALX_MISC_PSW_OCP_SHIFT 21
#define ALX_MISC_PSW_OCP_DEF 0x7
#define ALX_MISC_ISO_EN BIT(12)
#define ALX_MISC_INTNLOSC_OPEN BIT(3)
#define ALX_MSIC2 0x19C8
#define ALX_MSIC2_CALB_START BIT(0)
#define ALX_MISC3 0x19CC
/* bit1: 1:Software control 25M */
#define ALX_MISC3_25M_BY_SW BIT(1)
/* bit0: 25M switch to intnl OSC */
#define ALX_MISC3_25M_NOTO_INTNL BIT(0)
/* MSIX tbl in memory space */
#define ALX_MSIX_ENTRY_BASE 0x2000
/********************* PHY regs definition ***************************/
/* PHY Specific Status Register */
#define ALX_MII_GIGA_PSSR 0x11
#define ALX_GIGA_PSSR_SPD_DPLX_RESOLVED 0x0800
#define ALX_GIGA_PSSR_DPLX 0x2000
#define ALX_GIGA_PSSR_SPEED 0xC000
#define ALX_GIGA_PSSR_10MBS 0x0000
#define ALX_GIGA_PSSR_100MBS 0x4000
#define ALX_GIGA_PSSR_1000MBS 0x8000
/* PHY Interrupt Enable Register */
#define ALX_MII_IER 0x12
#define ALX_IER_LINK_UP 0x0400
#define ALX_IER_LINK_DOWN 0x0800
/* PHY Interrupt Status Register */
#define ALX_MII_ISR 0x13
#define ALX_MII_DBG_ADDR 0x1D
#define ALX_MII_DBG_DATA 0x1E
/***************************** debug port *************************************/
#define ALX_MIIDBG_ANACTRL 0x00
#define ALX_ANACTRL_DEF 0x02EF
#define ALX_MIIDBG_SYSMODCTRL 0x04
/* en half bias */
#define ALX_SYSMODCTRL_IECHOADJ_DEF 0xBB8B
#define ALX_MIIDBG_SRDSYSMOD 0x05
#define ALX_SRDSYSMOD_DEEMP_EN 0x0040
#define ALX_SRDSYSMOD_DEF 0x2C46
#define ALX_MIIDBG_HIBNEG 0x0B
#define ALX_HIBNEG_PSHIB_EN 0x8000
#define ALX_HIBNEG_HIB_PSE 0x1000
#define ALX_HIBNEG_DEF 0xBC40
#define ALX_HIBNEG_NOHIB (ALX_HIBNEG_DEF & \
~(ALX_HIBNEG_PSHIB_EN | ALX_HIBNEG_HIB_PSE))
#define ALX_MIIDBG_TST10BTCFG 0x12
#define ALX_TST10BTCFG_DEF 0x4C04
#define ALX_MIIDBG_AZ_ANADECT 0x15
#define ALX_AZ_ANADECT_DEF 0x3220
#define ALX_AZ_ANADECT_LONG 0x3210
#define ALX_MIIDBG_MSE16DB 0x18
#define ALX_MSE16DB_UP 0x05EA
#define ALX_MSE16DB_DOWN 0x02EA
#define ALX_MIIDBG_MSE20DB 0x1C
#define ALX_MSE20DB_TH_MASK 0x7F
#define ALX_MSE20DB_TH_SHIFT 2
#define ALX_MSE20DB_TH_DEF 0x2E
#define ALX_MSE20DB_TH_HI 0x54
#define ALX_MIIDBG_AGC 0x23
#define ALX_AGC_2_VGA_MASK 0x3FU
#define ALX_AGC_2_VGA_SHIFT 8
#define ALX_AGC_LONG1G_LIMT 40
#define ALX_AGC_LONG100M_LIMT 44
#define ALX_MIIDBG_LEGCYPS 0x29
#define ALX_LEGCYPS_EN 0x8000
#define ALX_LEGCYPS_DEF 0x129D
#define ALX_MIIDBG_TST100BTCFG 0x36
#define ALX_TST100BTCFG_DEF 0xE12C
#define ALX_MIIDBG_GREENCFG 0x3B
#define ALX_GREENCFG_DEF 0x7078
#define ALX_MIIDBG_GREENCFG2 0x3D
#define ALX_GREENCFG2_BP_GREEN 0x8000
#define ALX_GREENCFG2_GATE_DFSE_EN 0x0080
/******* dev 3 *********/
#define ALX_MIIEXT_PCS 3
#define ALX_MIIEXT_CLDCTRL3 0x8003
#define ALX_CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000
#define ALX_MIIEXT_CLDCTRL5 0x8005
#define ALX_CLDCTRL5_BP_VD_HLFBIAS 0x4000
#define ALX_MIIEXT_CLDCTRL6 0x8006
#define ALX_CLDCTRL6_CAB_LEN_MASK 0xFF
#define ALX_CLDCTRL6_CAB_LEN_SHIFT 0
#define ALX_CLDCTRL6_CAB_LEN_SHORT1G 116
#define ALX_CLDCTRL6_CAB_LEN_SHORT100M 152
#define ALX_MIIEXT_VDRVBIAS 0x8062
#define ALX_VDRVBIAS_DEF 0x3
/********* dev 7 **********/
#define ALX_MIIEXT_ANEG 7
#define ALX_MIIEXT_LOCAL_EEEADV 0x3C
#define ALX_LOCAL_EEEADV_1000BT 0x0004
#define ALX_LOCAL_EEEADV_100BT 0x0002
#define ALX_MIIEXT_AFE 0x801A
#define ALX_AFE_10BT_100M_TH 0x0040
#define ALX_MIIEXT_S3DIG10 0x8023
/* bit0: 1:bypass 10BT rx fifo, 0:original 10BT rx */
#define ALX_MIIEXT_S3DIG10_SL 0x0001
#define ALX_MIIEXT_S3DIG10_DEF 0
#define ALX_MIIEXT_NLP78 0x8027
#define ALX_MIIEXT_NLP78_120M_DEF 0x8A05
#endif

View file

@ -0,0 +1,2 @@
obj-$(CONFIG_ATL1C) += atl1c.o
atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o

View file

@ -0,0 +1,605 @@
/*
* Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
*
* 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.
*/
#ifndef _ATL1C_H_
#define _ATL1C_H_
#include <linux/interrupt.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 <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/tcp.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/workqueue.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
#include "atl1c_hw.h"
/* 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 */
#define AT_VLAN_TO_TAG(_vlan, _tag) \
_tag = ((((_vlan) >> 8) & 0xFF) |\
(((_vlan) & 0xFF) << 8))
#define AT_TAG_TO_VLAN(_tag, _vlan) \
_vlan = ((((_tag) >> 8) & 0xFF) |\
(((_tag) & 0xFF) << 8))
#define SPEED_0 0xffff
#define HALF_DUPLEX 1
#define FULL_DUPLEX 2
#define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
#define MAX_JUMBO_FRAME_SIZE (6*1024)
#define AT_MAX_RECEIVE_QUEUE 4
#define AT_DEF_RECEIVE_QUEUE 1
#define AT_MAX_TRANSMIT_QUEUE 2
#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL
#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL
#define AT_TX_WATCHDOG (5 * HZ)
#define AT_MAX_INT_WORK 5
#define AT_TWSI_EEPROM_TIMEOUT 100
#define AT_HW_MAX_IDLE_DELAY 10
#define AT_SUSPEND_LINK_TIMEOUT 100
#define AT_ASPM_L0S_TIMER 6
#define AT_ASPM_L1_TIMER 12
#define AT_LCKDET_TIMER 12
#define ATL1C_PCIE_L0S_L1_DISABLE 0x01
#define ATL1C_PCIE_PHY_RESET 0x02
#define ATL1C_ASPM_L0s_ENABLE 0x0001
#define ATL1C_ASPM_L1_ENABLE 0x0002
#define AT_REGS_LEN (74 * sizeof(u32))
#define AT_EEPROM_LEN 512
#define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
#define ATL1C_RFD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc)
#define ATL1C_TPD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc)
#define ATL1C_RRD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status)
/* tpd word 1 bit 0:7 General Checksum task offload */
#define TPD_L4HDR_OFFSET_MASK 0x00FF
#define TPD_L4HDR_OFFSET_SHIFT 0
/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */
#define TPD_TCPHDR_OFFSET_MASK 0x00FF
#define TPD_TCPHDR_OFFSET_SHIFT 0
/* tpd word 1 bit 0:7 Custom Checksum task offload */
#define TPD_PLOADOFFSET_MASK 0x00FF
#define TPD_PLOADOFFSET_SHIFT 0
/* tpd word 1 bit 8:17 */
#define TPD_CCSUM_EN_MASK 0x0001
#define TPD_CCSUM_EN_SHIFT 8
#define TPD_IP_CSUM_MASK 0x0001
#define TPD_IP_CSUM_SHIFT 9
#define TPD_TCP_CSUM_MASK 0x0001
#define TPD_TCP_CSUM_SHIFT 10
#define TPD_UDP_CSUM_MASK 0x0001
#define TPD_UDP_CSUM_SHIFT 11
#define TPD_LSO_EN_MASK 0x0001 /* TCP Large Send Offload */
#define TPD_LSO_EN_SHIFT 12
#define TPD_LSO_VER_MASK 0x0001
#define TPD_LSO_VER_SHIFT 13 /* 0 : ipv4; 1 : ipv4/ipv6 */
#define TPD_CON_VTAG_MASK 0x0001
#define TPD_CON_VTAG_SHIFT 14
#define TPD_INS_VTAG_MASK 0x0001
#define TPD_INS_VTAG_SHIFT 15
#define TPD_IPV4_PACKET_MASK 0x0001 /* valid when LSO VER is 1 */
#define TPD_IPV4_PACKET_SHIFT 16
#define TPD_ETH_TYPE_MASK 0x0001
#define TPD_ETH_TYPE_SHIFT 17 /* 0 : 802.3 frame; 1 : Ethernet */
/* tpd word 18:25 Custom Checksum task offload */
#define TPD_CCSUM_OFFSET_MASK 0x00FF
#define TPD_CCSUM_OFFSET_SHIFT 18
#define TPD_CCSUM_EPAD_MASK 0x0001
#define TPD_CCSUM_EPAD_SHIFT 30
/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */
#define TPD_MSS_MASK 0x1FFF
#define TPD_MSS_SHIFT 18
#define TPD_EOP_MASK 0x0001
#define TPD_EOP_SHIFT 31
struct atl1c_tpd_desc {
__le16 buffer_len; /* include 4-byte CRC */
__le16 vlan_tag;
__le32 word1;
__le64 buffer_addr;
};
struct atl1c_tpd_ext_desc {
u32 reservd_0;
__le32 word1;
__le32 pkt_len;
u32 reservd_1;
};
/* rrs word 0 bit 0:31 */
#define RRS_RX_CSUM_MASK 0xFFFF
#define RRS_RX_CSUM_SHIFT 0
#define RRS_RX_RFD_CNT_MASK 0x000F
#define RRS_RX_RFD_CNT_SHIFT 16
#define RRS_RX_RFD_INDEX_MASK 0x0FFF
#define RRS_RX_RFD_INDEX_SHIFT 20
/* rrs flag bit 0:16 */
#define RRS_HEAD_LEN_MASK 0x00FF
#define RRS_HEAD_LEN_SHIFT 0
#define RRS_HDS_TYPE_MASK 0x0003
#define RRS_HDS_TYPE_SHIFT 8
#define RRS_CPU_NUM_MASK 0x0003
#define RRS_CPU_NUM_SHIFT 10
#define RRS_HASH_FLG_MASK 0x000F
#define RRS_HASH_FLG_SHIFT 12
#define RRS_HDS_TYPE_HEAD 1
#define RRS_HDS_TYPE_DATA 2
#define RRS_IS_NO_HDS_TYPE(flag) \
((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0)
#define RRS_IS_HDS_HEAD(flag) \
((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
RRS_HDS_TYPE_HEAD)
#define RRS_IS_HDS_DATA(flag) \
((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
RRS_HDS_TYPE_DATA)
/* rrs word 3 bit 0:31 */
#define RRS_PKT_SIZE_MASK 0x3FFF
#define RRS_PKT_SIZE_SHIFT 0
#define RRS_ERR_L4_CSUM_MASK 0x0001
#define RRS_ERR_L4_CSUM_SHIFT 14
#define RRS_ERR_IP_CSUM_MASK 0x0001
#define RRS_ERR_IP_CSUM_SHIFT 15
#define RRS_VLAN_INS_MASK 0x0001
#define RRS_VLAN_INS_SHIFT 16
#define RRS_PROT_ID_MASK 0x0007
#define RRS_PROT_ID_SHIFT 17
#define RRS_RX_ERR_SUM_MASK 0x0001
#define RRS_RX_ERR_SUM_SHIFT 20
#define RRS_RX_ERR_CRC_MASK 0x0001
#define RRS_RX_ERR_CRC_SHIFT 21
#define RRS_RX_ERR_FAE_MASK 0x0001
#define RRS_RX_ERR_FAE_SHIFT 22
#define RRS_RX_ERR_TRUNC_MASK 0x0001
#define RRS_RX_ERR_TRUNC_SHIFT 23
#define RRS_RX_ERR_RUNC_MASK 0x0001
#define RRS_RX_ERR_RUNC_SHIFT 24
#define RRS_RX_ERR_ICMP_MASK 0x0001
#define RRS_RX_ERR_ICMP_SHIFT 25
#define RRS_PACKET_BCAST_MASK 0x0001
#define RRS_PACKET_BCAST_SHIFT 26
#define RRS_PACKET_MCAST_MASK 0x0001
#define RRS_PACKET_MCAST_SHIFT 27
#define RRS_PACKET_TYPE_MASK 0x0001
#define RRS_PACKET_TYPE_SHIFT 28
#define RRS_FIFO_FULL_MASK 0x0001
#define RRS_FIFO_FULL_SHIFT 29
#define RRS_802_3_LEN_ERR_MASK 0x0001
#define RRS_802_3_LEN_ERR_SHIFT 30
#define RRS_RXD_UPDATED_MASK 0x0001
#define RRS_RXD_UPDATED_SHIFT 31
#define RRS_ERR_L4_CSUM 0x00004000
#define RRS_ERR_IP_CSUM 0x00008000
#define RRS_VLAN_INS 0x00010000
#define RRS_RX_ERR_SUM 0x00100000
#define RRS_RX_ERR_CRC 0x00200000
#define RRS_802_3_LEN_ERR 0x40000000
#define RRS_RXD_UPDATED 0x80000000
#define RRS_PACKET_TYPE_802_3 1
#define RRS_PACKET_TYPE_ETH 0
#define RRS_PACKET_IS_ETH(word) \
((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \
RRS_PACKET_TYPE_ETH)
#define RRS_RXD_IS_VALID(word) \
((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \
((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1)
#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \
((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6)
struct atl1c_recv_ret_status {
__le32 word0;
__le32 rss_hash;
__le16 vlan_tag;
__le16 flag;
__le32 word3;
};
/* RFD descriptor */
struct atl1c_rx_free_desc {
__le64 buffer_addr;
};
/* DMA Order Settings */
enum atl1c_dma_order {
atl1c_dma_ord_in = 1,
atl1c_dma_ord_enh = 2,
atl1c_dma_ord_out = 4
};
enum atl1c_dma_rcb {
atl1c_rcb_64 = 0,
atl1c_rcb_128 = 1
};
enum atl1c_mac_speed {
atl1c_mac_speed_0 = 0,
atl1c_mac_speed_10_100 = 1,
atl1c_mac_speed_1000 = 2
};
enum atl1c_dma_req_block {
atl1c_dma_req_128 = 0,
atl1c_dma_req_256 = 1,
atl1c_dma_req_512 = 2,
atl1c_dma_req_1024 = 3,
atl1c_dma_req_2048 = 4,
atl1c_dma_req_4096 = 5
};
enum atl1c_nic_type {
athr_l1c = 0,
athr_l2c = 1,
athr_l2c_b,
athr_l2c_b2,
athr_l1d,
athr_l1d_2,
};
enum atl1c_trans_queue {
atl1c_trans_normal = 0,
atl1c_trans_high = 1
};
struct atl1c_hw_stats {
/* rx */
unsigned long rx_ok; /* The number of good packet received. */
unsigned long rx_bcast; /* The number of good broadcast packet received. */
unsigned long rx_mcast; /* The number of good multicast packet received. */
unsigned long rx_pause; /* The number of Pause packet received. */
unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */
unsigned long rx_fcs_err; /* The number of packets with bad FCS. */
unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */
unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */
unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */
unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */
unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */
unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */
unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */
unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */
unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */
unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */
unsigned long rx_align_err; /* Alignment Error */
unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */
/* tx */
unsigned long tx_ok; /* The number of good packet transmitted. */
unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */
unsigned long tx_mcast; /* The number of good multicast packet transmitted. */
unsigned long tx_pause; /* The number of Pause packet transmitted. */
unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */
unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */
unsigned long tx_defer; /* The number of packets transmitted that is deferred. */
unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */
unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */
unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */
unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */
unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */
unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */
unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */
unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */
unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */
};
struct atl1c_hw {
u8 __iomem *hw_addr; /* inner register address */
struct atl1c_adapter *adapter;
enum atl1c_nic_type nic_type;
enum atl1c_dma_order dma_order;
enum atl1c_dma_rcb rcb_value;
enum atl1c_dma_req_block dmar_block;
u16 device_id;
u16 vendor_id;
u16 subsystem_id;
u16 subsystem_vendor_id;
u8 revision_id;
u16 phy_id1;
u16 phy_id2;
u32 intr_mask;
u8 preamble_len;
u16 max_frame_size;
u16 min_frame_size;
enum atl1c_mac_speed mac_speed;
bool mac_duplex;
bool hibernate;
u16 media_type;
#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
u16 autoneg_advertised;
u16 mii_autoneg_adv_reg;
u16 mii_1000t_ctrl_reg;
u16 tx_imt; /* TX Interrupt Moderator timer ( 2us resolution) */
u16 rx_imt; /* RX Interrupt Moderator timer ( 2us resolution) */
u16 ict; /* Interrupt Clear timer (2us resolution) */
u16 ctrl_flags;
#define ATL1C_INTR_CLEAR_ON_READ 0x0001
#define ATL1C_INTR_MODRT_ENABLE 0x0002
#define ATL1C_CMB_ENABLE 0x0004
#define ATL1C_SMB_ENABLE 0x0010
#define ATL1C_TXQ_MODE_ENHANCE 0x0020
#define ATL1C_RX_IPV6_CHKSUM 0x0040
#define ATL1C_ASPM_L0S_SUPPORT 0x0080
#define ATL1C_ASPM_L1_SUPPORT 0x0100
#define ATL1C_ASPM_CTRL_MON 0x0200
#define ATL1C_HIB_DISABLE 0x0400
#define ATL1C_APS_MODE_ENABLE 0x0800
#define ATL1C_LINK_EXT_SYNC 0x1000
#define ATL1C_CLK_GATING_EN 0x2000
#define ATL1C_FPGA_VERSION 0x8000
u16 link_cap_flags;
#define ATL1C_LINK_CAP_1000M 0x0001
u32 smb_timer;
u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
interrupt request */
u16 tpd_thresh;
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */
u8 rfd_burst;
u32 base_cpu;
u32 indirect_tab;
u8 mac_addr[ETH_ALEN];
u8 perm_mac_addr[ETH_ALEN];
bool phy_configured;
bool re_autoneg;
bool emi_ca;
bool msi_lnkpatch; /* link patch for specific platforms */
};
/*
* atl1c_ring_header represents a single, contiguous block of DMA space
* mapped for the three descriptor rings (tpd, rfd, rrd) described below
*/
struct atl1c_ring_header {
void *desc; /* virtual address */
dma_addr_t dma; /* physical address*/
unsigned int size; /* length in bytes */
};
/*
* atl1c_buffer is wrapper around a pointer to a socket buffer
* so a DMA handle can be stored along with the skb
*/
struct atl1c_buffer {
struct sk_buff *skb; /* socket buffer */
u16 length; /* rx buffer length */
u16 flags; /* information of buffer */
#define ATL1C_BUFFER_FREE 0x0001
#define ATL1C_BUFFER_BUSY 0x0002
#define ATL1C_BUFFER_STATE_MASK 0x0003
#define ATL1C_PCIMAP_SINGLE 0x0004
#define ATL1C_PCIMAP_PAGE 0x0008
#define ATL1C_PCIMAP_TYPE_MASK 0x000C
#define ATL1C_PCIMAP_TODEVICE 0x0010
#define ATL1C_PCIMAP_FROMDEVICE 0x0020
#define ATL1C_PCIMAP_DIRECTION_MASK 0x0030
dma_addr_t dma;
};
#define ATL1C_SET_BUFFER_STATE(buff, state) do { \
((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK; \
((buff)->flags) |= (state); \
} while (0)
#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do { \
((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \
((buff)->flags) |= (type); \
((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK; \
((buff)->flags) |= (direction); \
} while (0)
/* transimit packet descriptor (tpd) ring */
struct atl1c_tpd_ring {
void *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
u16 size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
u16 next_to_use; /* this is protectd by adapter->tx_lock */
atomic_t next_to_clean;
struct atl1c_buffer *buffer_info;
};
/* receive free descriptor (rfd) ring */
struct atl1c_rfd_ring {
void *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
u16 size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
u16 next_to_use;
u16 next_to_clean;
struct atl1c_buffer *buffer_info;
};
/* receive return descriptor (rrd) ring */
struct atl1c_rrd_ring {
void *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
u16 size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
u16 next_to_use;
u16 next_to_clean;
};
/* board specific private data structure */
struct atl1c_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
struct napi_struct napi;
struct page *rx_page;
unsigned int rx_page_offset;
unsigned int rx_frag_size;
struct atl1c_hw hw;
struct atl1c_hw_stats hw_stats;
struct mii_if_info mii; /* MII interface info */
u16 rx_buffer_len;
unsigned long flags;
#define __AT_TESTING 0x0001
#define __AT_RESETTING 0x0002
#define __AT_DOWN 0x0003
unsigned long work_event;
#define ATL1C_WORK_EVENT_RESET 0
#define ATL1C_WORK_EVENT_LINK_CHANGE 1
u32 msg_enable;
bool have_msi;
u32 wol;
u16 link_speed;
u16 link_duplex;
spinlock_t mdio_lock;
spinlock_t tx_lock;
atomic_t irq_sem;
struct work_struct common_task;
struct timer_list watchdog_timer;
struct timer_list phy_config_timer;
/* All Descriptor memory */
struct atl1c_ring_header ring_header;
struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
struct atl1c_rfd_ring rfd_ring;
struct atl1c_rrd_ring rrd_ring;
u32 bd_number; /* board number;*/
};
#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, pdata) do { \
if (unlikely((a)->hibernate)) { \
readl((a)->hw_addr + reg); \
*(u32 *)pdata = readl((a)->hw_addr + reg); \
} else { \
*(u32 *)pdata = readl((a)->hw_addr + reg); \
} \
} while (0)
#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, pdata) do { \
if (unlikely((a)->hibernate)) { \
readw((a)->hw_addr + reg); \
*(u16 *)pdata = readw((a)->hw_addr + reg); \
} else { \
*(u16 *)pdata = readw((a)->hw_addr + reg); \
} \
} while (0)
#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)))
extern char atl1c_driver_name[];
extern char atl1c_driver_version[];
void atl1c_reinit_locked(struct atl1c_adapter *adapter);
s32 atl1c_reset_hw(struct atl1c_hw *hw);
void atl1c_set_ethtool_ops(struct net_device *netdev);
#endif /* _ATL1C_H_ */

View file

@ -0,0 +1,309 @@
/*
* Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
*
* 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.
*
*/
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/slab.h>
#include "atl1c.h"
static int atl1c_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP);
if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M)
ecmd->supported |= SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_TP;
ecmd->advertising |= hw->autoneg_advertised;
ecmd->port = PORT_TP;
ecmd->phy_address = 0;
ecmd->transceiver = XCVR_INTERNAL;
if (adapter->link_speed != SPEED_0) {
ethtool_cmd_speed_set(ecmd, adapter->link_speed);
if (adapter->link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
} else {
ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
ecmd->duplex = DUPLEX_UNKNOWN;
}
ecmd->autoneg = AUTONEG_ENABLE;
return 0;
}
static int atl1c_set_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
u16 autoneg_advertised;
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
if (ecmd->autoneg == AUTONEG_ENABLE) {
autoneg_advertised = ADVERTISED_Autoneg;
} else {
u32 speed = ethtool_cmd_speed(ecmd);
if (speed == SPEED_1000) {
if (ecmd->duplex != DUPLEX_FULL) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev,
"1000M half is invalid\n");
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
autoneg_advertised = ADVERTISED_1000baseT_Full;
} else if (speed == SPEED_100) {
if (ecmd->duplex == DUPLEX_FULL)
autoneg_advertised = ADVERTISED_100baseT_Full;
else
autoneg_advertised = ADVERTISED_100baseT_Half;
} else {
if (ecmd->duplex == DUPLEX_FULL)
autoneg_advertised = ADVERTISED_10baseT_Full;
else
autoneg_advertised = ADVERTISED_10baseT_Half;
}
}
if (hw->autoneg_advertised != autoneg_advertised) {
hw->autoneg_advertised = autoneg_advertised;
if (atl1c_restart_autoneg(hw) != 0) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev,
"ethtool speed/duplex setting failed\n");
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
}
clear_bit(__AT_RESETTING, &adapter->flags);
return 0;
}
static u32 atl1c_get_msglevel(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
return adapter->msg_enable;
}
static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
adapter->msg_enable = data;
}
static int atl1c_get_regs_len(struct net_device *netdev)
{
return AT_REGS_LEN;
}
static void atl1c_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
u32 *regs_buff = p;
u16 phy_data;
memset(p, 0, AT_REGS_LEN);
regs->version = 1;
AT_READ_REG(hw, REG_PM_CTRL, p++);
AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++);
AT_READ_REG(hw, REG_TWSI_CTRL, p++);
AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL, p++);
AT_READ_REG(hw, REG_MASTER_CTRL, p++);
AT_READ_REG(hw, REG_MANUAL_TIMER_INIT, p++);
AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
AT_READ_REG(hw, REG_GPHY_CTRL, p++);
AT_READ_REG(hw, REG_LINK_CTRL, p++);
AT_READ_REG(hw, REG_IDLE_STATUS, p++);
AT_READ_REG(hw, REG_MDIO_CTRL, p++);
AT_READ_REG(hw, REG_SERDES, p++);
AT_READ_REG(hw, REG_MAC_CTRL, p++);
AT_READ_REG(hw, REG_MAC_IPG_IFG, p++);
AT_READ_REG(hw, REG_MAC_STA_ADDR, p++);
AT_READ_REG(hw, REG_MAC_STA_ADDR+4, p++);
AT_READ_REG(hw, REG_RX_HASH_TABLE, p++);
AT_READ_REG(hw, REG_RX_HASH_TABLE+4, p++);
AT_READ_REG(hw, REG_RXQ_CTRL, p++);
AT_READ_REG(hw, REG_TXQ_CTRL, p++);
AT_READ_REG(hw, REG_MTU, p++);
AT_READ_REG(hw, REG_WOL_CTRL, p++);
atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data;
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data;
}
static int atl1c_get_eeprom_len(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
if (atl1c_check_eeprom_exist(&adapter->hw))
return AT_EEPROM_LEN;
else
return 0;
}
static int atl1c_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_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 (!atl1c_check_eeprom_exist(hw)) /* not exist */
return -EINVAL;
eeprom->magic = adapter->pdev->vendor |
(adapter->pdev->device << 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 == NULL)
return -ENOMEM;
for (i = first_dword; i < last_dword; i++) {
if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
kfree(eeprom_buff);
return -EIO;
}
}
memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
eeprom->len);
kfree(eeprom_buff);
return ret_val;
return 0;
}
static void atl1c_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
strlcpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver));
strlcpy(drvinfo->version, atl1c_driver_version,
sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
drvinfo->n_stats = 0;
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = atl1c_get_regs_len(netdev);
drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
}
static void atl1c_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
wol->supported = WAKE_MAGIC | WAKE_PHY;
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;
if (adapter->wol & AT_WUFC_LNKC)
wol->wolopts |= WAKE_PHY;
}
static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
return -EOPNOTSUPP;
/* these settings will always override what we currently have */
adapter->wol = 0;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= AT_WUFC_MAG;
if (wol->wolopts & WAKE_PHY)
adapter->wol |= AT_WUFC_LNKC;
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
return 0;
}
static int atl1c_nway_reset(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev))
atl1c_reinit_locked(adapter);
return 0;
}
static const struct ethtool_ops atl1c_ethtool_ops = {
.get_settings = atl1c_get_settings,
.set_settings = atl1c_set_settings,
.get_drvinfo = atl1c_get_drvinfo,
.get_regs_len = atl1c_get_regs_len,
.get_regs = atl1c_get_regs,
.get_wol = atl1c_get_wol,
.set_wol = atl1c_set_wol,
.get_msglevel = atl1c_get_msglevel,
.set_msglevel = atl1c_set_msglevel,
.nway_reset = atl1c_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = atl1c_get_eeprom_len,
.get_eeprom = atl1c_get_eeprom,
};
void atl1c_set_ethtool_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &atl1c_ethtool_ops;
}

View file

@ -0,0 +1,863 @@
/*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*/
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/crc32.h>
#include "atl1c.h"
/*
* check_eeprom_exist
* return 1 if eeprom exist
*/
int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
{
u32 data;
AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
if (data & TWSI_DEBUG_DEV_EXIST)
return 1;
AT_READ_REG(hw, REG_MASTER_CTRL, &data);
if (data & MASTER_CTRL_OTP_SEL)
return 1;
return 0;
}
void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr)
{
u32 value;
/*
* 00-0B-6A-F6-00-DC
* 0: 6AF600DC 1: 000B
* low dword
*/
value = mac_addr[2] << 24 |
mac_addr[3] << 16 |
mac_addr[4] << 8 |
mac_addr[5];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
/* hight dword */
value = mac_addr[0] << 8 |
mac_addr[1];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
}
/* read mac address from hardware register */
static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr)
{
u32 addr[2];
AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
*(u32 *) &eth_addr[2] = htonl(addr[0]);
*(u16 *) &eth_addr[0] = htons((u16)addr[1]);
return is_valid_ether_addr(eth_addr);
}
/*
* atl1c_get_permanent_address
* return 0 if get valid mac address,
*/
static int atl1c_get_permanent_address(struct atl1c_hw *hw)
{
u32 i;
u32 otp_ctrl_data;
u32 twsi_ctrl_data;
u16 phy_data;
bool raise_vol = false;
/* MAC-address from BIOS is the 1st priority */
if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
return 0;
/* init */
AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
if (atl1c_check_eeprom_exist(hw)) {
if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
/* Enable OTP CLK */
if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
otp_ctrl_data |= OTP_CTRL_CLK_EN;
AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
AT_WRITE_FLUSH(hw);
msleep(1);
}
}
/* raise voltage temporally for l2cb */
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
phy_data &= ~ANACTRL_HB_EN;
atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
phy_data |= VOLT_CTRL_SWLOWEST;
atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
udelay(20);
raise_vol = true;
}
AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
msleep(10);
AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
break;
}
if (i >= AT_TWSI_EEPROM_TIMEOUT)
return -1;
}
/* Disable OTP_CLK */
if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
msleep(1);
}
if (raise_vol) {
atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
phy_data |= ANACTRL_HB_EN;
atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
phy_data &= ~VOLT_CTRL_SWLOWEST;
atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
udelay(20);
}
if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
return 0;
return -1;
}
bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
{
int i;
bool ret = false;
u32 otp_ctrl_data;
u32 control;
u32 data;
if (offset & 3)
return ret; /* address do not align */
AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
AT_WRITE_REG(hw, REG_OTP_CTRL,
(otp_ctrl_data | OTP_CTRL_CLK_EN));
AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
for (i = 0; i < 10; i++) {
udelay(100);
AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
if (control & EEPROM_CTRL_RW)
break;
}
if (control & EEPROM_CTRL_RW) {
AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
data = data & 0xFFFF;
*p_value = swab32((data << 16) | (*p_value >> 16));
ret = true;
}
if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
return ret;
}
/*
* Reads the adapter's MAC address from the EEPROM
*
* hw - Struct containing variables accessed by shared code
*/
int atl1c_read_mac_addr(struct atl1c_hw *hw)
{
int err = 0;
err = atl1c_get_permanent_address(hw);
if (err)
eth_random_addr(hw->perm_mac_addr);
memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
return err;
}
/*
* atl1c_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 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
{
u32 crc32;
u32 value = 0;
int i;
crc32 = ether_crc_le(6, mc_addr);
for (i = 0; i < 32; i++)
value |= (((crc32 >> i) & 1) << (31 - i));
return value;
}
/*
* Sets the bit in the multicast table corresponding to the hash value.
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*/
void atl1c_hash_set(struct atl1c_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 bit 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);
}
/*
* wait mdio module be idle
* return true: idle
* false: still busy
*/
bool atl1c_wait_mdio_idle(struct atl1c_hw *hw)
{
u32 val;
int i;
for (i = 0; i < MDIO_MAX_AC_TO; i++) {
AT_READ_REG(hw, REG_MDIO_CTRL, &val);
if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START)))
break;
udelay(10);
}
return i != MDIO_MAX_AC_TO;
}
void atl1c_stop_phy_polling(struct atl1c_hw *hw)
{
if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
return;
AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
atl1c_wait_mdio_idle(hw);
}
void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)
{
u32 val;
if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
return;
val = MDIO_CTRL_SPRES_PRMBL |
FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
FIELDX(MDIO_CTRL_REG, 1) |
MDIO_CTRL_START |
MDIO_CTRL_OP_READ;
AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
atl1c_wait_mdio_idle(hw);
val |= MDIO_CTRL_AP_EN;
val &= ~MDIO_CTRL_START;
AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
udelay(30);
}
/*
* atl1c_read_phy_core
* core funtion to read register in PHY via MDIO control regsiter.
* ext: extension register (see IEEE 802.3)
* dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
* reg: reg to read
*/
int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
u16 reg, u16 *phy_data)
{
u32 val;
u16 clk_sel = MDIO_CTRL_CLK_25_4;
atl1c_stop_phy_polling(hw);
*phy_data = 0;
/* only l2c_b2 & l1d_2 could use slow clock */
if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&
hw->hibernate)
clk_sel = MDIO_CTRL_CLK_25_128;
if (ext) {
val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
val = MDIO_CTRL_SPRES_PRMBL |
FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
MDIO_CTRL_START |
MDIO_CTRL_MODE_EXT |
MDIO_CTRL_OP_READ;
} else {
val = MDIO_CTRL_SPRES_PRMBL |
FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
FIELDX(MDIO_CTRL_REG, reg) |
MDIO_CTRL_START |
MDIO_CTRL_OP_READ;
}
AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
if (!atl1c_wait_mdio_idle(hw))
return -1;
AT_READ_REG(hw, REG_MDIO_CTRL, &val);
*phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA);
atl1c_start_phy_polling(hw, clk_sel);
return 0;
}
/*
* atl1c_write_phy_core
* core funtion to write to register in PHY via MDIO control regsiter.
* ext: extension register (see IEEE 802.3)
* dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
* reg: reg to write
*/
int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
u16 reg, u16 phy_data)
{
u32 val;
u16 clk_sel = MDIO_CTRL_CLK_25_4;
atl1c_stop_phy_polling(hw);
/* only l2c_b2 & l1d_2 could use slow clock */
if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&
hw->hibernate)
clk_sel = MDIO_CTRL_CLK_25_128;
if (ext) {
val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
val = MDIO_CTRL_SPRES_PRMBL |
FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
FIELDX(MDIO_CTRL_DATA, phy_data) |
MDIO_CTRL_START |
MDIO_CTRL_MODE_EXT;
} else {
val = MDIO_CTRL_SPRES_PRMBL |
FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
FIELDX(MDIO_CTRL_DATA, phy_data) |
FIELDX(MDIO_CTRL_REG, reg) |
MDIO_CTRL_START;
}
AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
if (!atl1c_wait_mdio_idle(hw))
return -1;
atl1c_start_phy_polling(hw, clk_sel);
return 0;
}
/*
* Reads the value from a PHY register
* hw - Struct containing variables accessed by shared code
* reg_addr - address of the PHY register to read
*/
int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
{
return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data);
}
/*
* 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
*/
int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
{
return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data);
}
/* read from PHY extension register */
int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
u16 reg_addr, u16 *phy_data)
{
return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data);
}
/* write to PHY extension register */
int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
u16 reg_addr, u16 phy_data)
{
return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);
}
int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
{
int err;
err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);
if (unlikely(err))
return err;
else
err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data);
return err;
}
int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data)
{
int err;
err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);
if (unlikely(err))
return err;
else
err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
return err;
}
/*
* Configures PHY autoneg and flow control advertisement settings
*
* hw - Struct containing variables accessed by shared code
*/
static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
{
u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL;
u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
~GIGA_CR_1000T_SPEED_MASK;
if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
mii_adv_data |= ADVERTISE_10HALF;
if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
mii_adv_data |= ADVERTISE_10FULL;
if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
mii_adv_data |= ADVERTISE_100HALF;
if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
mii_adv_data |= ADVERTISE_100FULL;
if (hw->autoneg_advertised & ADVERTISED_Autoneg)
mii_adv_data |= ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL;
if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) {
if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
mii_giga_ctrl_data |= ADVERTISE_1000HALF;
if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
mii_giga_ctrl_data |= ADVERTISE_1000FULL;
if (hw->autoneg_advertised & ADVERTISED_Autoneg)
mii_giga_ctrl_data |= ADVERTISE_1000HALF |
ADVERTISE_1000FULL;
}
if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0)
return -1;
return 0;
}
void atl1c_phy_disable(struct atl1c_hw *hw)
{
atl1c_power_saving(hw, 0);
}
int atl1c_phy_reset(struct atl1c_hw *hw)
{
struct atl1c_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
u16 phy_data;
u32 phy_ctrl_data, lpi_ctrl;
int err;
/* reset PHY core */
AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ |
GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS);
phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST;
if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE))
phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);
else
phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);
AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
AT_WRITE_FLUSH(hw);
udelay(10);
AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET);
AT_WRITE_FLUSH(hw);
udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */
/* switch clock */
if (hw->nic_type == athr_l2c_b) {
atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data);
atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD,
phy_data & ~CFGLPSPD_RSTCNT_CLK125SW);
}
/* tx-half amplitude issue fix */
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data);
phy_data |= CABLE1TH_DET_EN;
atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data);
}
/* clear bit3 of dbgport 3B to lower voltage */
if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) {
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
phy_data &= ~VOLT_CTRL_SWLOWEST;
atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
}
/* power saving config */
phy_data =
hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ?
L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF;
atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data);
/* hib */
atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
SYSMODCTRL_IECHOADJ_DEF);
} else {
/* disable pws */
atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data);
atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS,
phy_data & ~LEGCYPS_EN);
/* disable hibernate */
atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data);
atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG,
phy_data & HIBNEG_PSHIB_EN);
}
/* disable AZ(EEE) by default */
if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ||
hw->nic_type == athr_l2c_b2) {
AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl);
AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN);
atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0);
atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3,
L2CB_CLDCTRL3);
}
/* other debug port to set */
atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF);
atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF);
atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF);
/* UNH-IOL test issue, set bit7 */
atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG,
TST100BTCFG_DEF | TST100BTCFG_LITCH_EN);
/* set phy interrupt mask */
phy_data = IER_LINK_UP | IER_LINK_DOWN;
err = atl1c_write_phy_reg(hw, MII_IER, phy_data);
if (err) {
if (netif_msg_hw(adapter))
dev_err(&pdev->dev,
"Error enable PHY linkChange Interrupt\n");
return err;
}
return 0;
}
int atl1c_phy_init(struct atl1c_hw *hw)
{
struct atl1c_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
int ret_val;
u16 mii_bmcr_data = BMCR_RESET;
if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||
(atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {
dev_err(&pdev->dev, "Error get phy ID\n");
return -1;
}
switch (hw->media_type) {
case MEDIA_TYPE_AUTO_SENSOR:
ret_val = atl1c_phy_setup_adv(hw);
if (ret_val) {
if (netif_msg_link(adapter))
dev_err(&pdev->dev,
"Error Setting up Auto-Negotiation\n");
return ret_val;
}
mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
break;
case MEDIA_TYPE_100M_FULL:
mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX;
break;
case MEDIA_TYPE_100M_HALF:
mii_bmcr_data |= BMCR_SPEED100;
break;
case MEDIA_TYPE_10M_FULL:
mii_bmcr_data |= BMCR_FULLDPLX;
break;
case MEDIA_TYPE_10M_HALF:
break;
default:
if (netif_msg_link(adapter))
dev_err(&pdev->dev, "Wrong Media type %d\n",
hw->media_type);
return -1;
}
ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
if (ret_val)
return ret_val;
hw->phy_configured = true;
return 0;
}
/*
* 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
*/
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
{
int err;
u16 phy_data;
/* Read PHY Specific Status Register (17) */
err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
if (err)
return err;
if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
return -1;
switch (phy_data & GIGA_PSSR_SPEED) {
case GIGA_PSSR_1000MBS:
*speed = SPEED_1000;
break;
case GIGA_PSSR_100MBS:
*speed = SPEED_100;
break;
case GIGA_PSSR_10MBS:
*speed = SPEED_10;
break;
default:
return -1;
}
if (phy_data & GIGA_PSSR_DPLX)
*duplex = FULL_DUPLEX;
else
*duplex = HALF_DUPLEX;
return 0;
}
/* select one link mode to get lower power consumption */
int atl1c_phy_to_ps_link(struct atl1c_hw *hw)
{
struct atl1c_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
int ret = 0;
u16 autoneg_advertised = ADVERTISED_10baseT_Half;
u16 save_autoneg_advertised;
u16 phy_data;
u16 mii_lpa_data;
u16 speed = SPEED_0;
u16 duplex = FULL_DUPLEX;
int i;
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
if (phy_data & BMSR_LSTATUS) {
atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
if (mii_lpa_data & LPA_10FULL)
autoneg_advertised = ADVERTISED_10baseT_Full;
else if (mii_lpa_data & LPA_10HALF)
autoneg_advertised = ADVERTISED_10baseT_Half;
else if (mii_lpa_data & LPA_100HALF)
autoneg_advertised = ADVERTISED_100baseT_Half;
else if (mii_lpa_data & LPA_100FULL)
autoneg_advertised = ADVERTISED_100baseT_Full;
save_autoneg_advertised = hw->autoneg_advertised;
hw->phy_configured = false;
hw->autoneg_advertised = autoneg_advertised;
if (atl1c_restart_autoneg(hw) != 0) {
dev_dbg(&pdev->dev, "phy autoneg failed\n");
ret = -1;
}
hw->autoneg_advertised = save_autoneg_advertised;
if (mii_lpa_data) {
for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
mdelay(100);
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
if (phy_data & BMSR_LSTATUS) {
if (atl1c_get_speed_and_duplex(hw, &speed,
&duplex) != 0)
dev_dbg(&pdev->dev,
"get speed and duplex failed\n");
break;
}
}
}
} else {
speed = SPEED_10;
duplex = HALF_DUPLEX;
}
adapter->link_speed = speed;
adapter->link_duplex = duplex;
return ret;
}
int atl1c_restart_autoneg(struct atl1c_hw *hw)
{
int err = 0;
u16 mii_bmcr_data = BMCR_RESET;
err = atl1c_phy_setup_adv(hw);
if (err)
return err;
mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
}
int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc)
{
struct atl1c_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
u32 master_ctrl, mac_ctrl, phy_ctrl;
u32 wol_ctrl, speed;
u16 phy_data;
wol_ctrl = 0;
speed = adapter->link_speed == SPEED_1000 ?
MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100;
AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl);
AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl);
AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl);
master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS;
mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed);
mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN);
if (adapter->link_duplex == FULL_DUPLEX)
mac_ctrl |= MAC_CTRL_DUPLX;
phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
GPHY_CTRL_HIB_EN;
if (!wufc) { /* without WoL */
master_ctrl |= MASTER_CTRL_CLK_SEL_DIS;
phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
hw->phy_configured = false; /* re-init PHY when resume */
return 0;
}
phy_ctrl |= GPHY_CTRL_EXT_RESET;
if (wufc & AT_WUFC_MAG) {
mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN;
wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11)
wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN;
}
if (wufc & AT_WUFC_LNKC) {
wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
dev_dbg(&pdev->dev, "%s: write phy MII_IER failed.\n",
atl1c_driver_name);
}
}
/* clear PHY interrupt */
atl1c_read_phy_reg(hw, MII_ISR, &phy_data);
dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n",
atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl);
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl);
return 0;
}
/* configure phy after Link change Event */
void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed)
{
u16 phy_val;
bool adj_thresh = false;
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ||
hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2)
adj_thresh = true;
if (link_speed != SPEED_0) { /* link up */
/* az with brcm, half-amp */
if (hw->nic_type == athr_l1d_2) {
atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6,
&phy_val);
phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN);
phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ?
AZ_ANADECT_LONG : AZ_ANADECT_DEF;
atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val);
}
/* threshold adjust */
if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) {
atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP);
atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
L1D_SYSMODCTRL_IECHOADJ_DEF);
}
} else { /* link down */
if (adj_thresh && hw->msi_lnkpatch) {
atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
SYSMODCTRL_IECHOADJ_DEF);
atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB,
L1D_MSE16DB_DOWN);
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
obj-$(CONFIG_ATL1E) += atl1e.o
atl1e-objs += atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o

View file

@ -0,0 +1,507 @@
/*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
* Copyright(c) 2007 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.
*/
#ifndef _ATL1E_H_
#define _ATL1E_H_
#include <linux/interrupt.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 <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/tcp.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/workqueue.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
#include "atl1e_hw.h"
#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
#define CMD_IO_SPACE 0x0001
#define CMD_MEMORY_SPACE 0x0002
#define CMD_BUS_MASTER 0x0004
#define BAR_0 0
#define BAR_1 1
#define BAR_5 5
/* 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 */
#define SPEED_0 0xffff
#define HALF_DUPLEX 1
#define FULL_DUPLEX 2
/* Error Codes */
#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 AT_ERR_TIMEOUT 9
#define MAX_JUMBO_FRAME_SIZE 0x2000
#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd) \
_tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\
(((_vlan) >> 9) & 8))
#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan) \
_vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\
(((_tdp) & 0x88) << 5))
#define AT_MAX_RECEIVE_QUEUE 4
#define AT_PAGE_NUM_PER_QUEUE 2
#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL
#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL
#define AT_TX_WATCHDOG (5 * HZ)
#define AT_MAX_INT_WORK 10
#define AT_TWSI_EEPROM_TIMEOUT 100
#define AT_HW_MAX_IDLE_DELAY 10
#define AT_SUSPEND_LINK_TIMEOUT 28
#define AT_REGS_LEN 75
#define AT_EEPROM_LEN 512
#define AT_ADV_MASK (ADVERTISE_10_HALF |\
ADVERTISE_10_FULL |\
ADVERTISE_100_HALF |\
ADVERTISE_100_FULL |\
ADVERTISE_1000_FULL)
/* tpd word 2 */
#define TPD_BUFLEN_MASK 0x3FFF
#define TPD_BUFLEN_SHIFT 0
#define TPD_DMAINT_MASK 0x0001
#define TPD_DMAINT_SHIFT 14
#define TPD_PKTNT_MASK 0x0001
#define TPD_PKTINT_SHIFT 15
#define TPD_VLANTAG_MASK 0xFFFF
#define TPD_VLAN_SHIFT 16
/* tpd word 3 bits 0:4 */
#define TPD_EOP_MASK 0x0001
#define TPD_EOP_SHIFT 0
#define TPD_IP_VERSION_MASK 0x0001
#define TPD_IP_VERSION_SHIFT 1 /* 0 : IPV4, 1 : IPV6 */
#define TPD_INS_VL_TAG_MASK 0x0001
#define TPD_INS_VL_TAG_SHIFT 2
#define TPD_CC_SEGMENT_EN_MASK 0x0001
#define TPD_CC_SEGMENT_EN_SHIFT 3
#define TPD_SEGMENT_EN_MASK 0x0001
#define TPD_SEGMENT_EN_SHIFT 4
/* tdp word 3 bits 5:7 if ip version is 0 */
#define TPD_IP_CSUM_MASK 0x0001
#define TPD_IP_CSUM_SHIFT 5
#define TPD_TCP_CSUM_MASK 0x0001
#define TPD_TCP_CSUM_SHIFT 6
#define TPD_UDP_CSUM_MASK 0x0001
#define TPD_UDP_CSUM_SHIFT 7
/* tdp word 3 bits 5:7 if ip version is 1 */
#define TPD_V6_IPHLLO_MASK 0x0007
#define TPD_V6_IPHLLO_SHIFT 7
/* tpd word 3 bits 8:9 bit */
#define TPD_VL_TAGGED_MASK 0x0001
#define TPD_VL_TAGGED_SHIFT 8
#define TPD_ETHTYPE_MASK 0x0001
#define TPD_ETHTYPE_SHIFT 9
/* tdp word 3 bits 10:13 if ip version is 0 */
#define TDP_V4_IPHL_MASK 0x000F
#define TPD_V4_IPHL_SHIFT 10
/* tdp word 3 bits 10:13 if ip version is 1 */
#define TPD_V6_IPHLHI_MASK 0x000F
#define TPD_V6_IPHLHI_SHIFT 10
/* tpd word 3 bit 14:31 if segment enabled */
#define TPD_TCPHDRLEN_MASK 0x000F
#define TPD_TCPHDRLEN_SHIFT 14
#define TPD_HDRFLAG_MASK 0x0001
#define TPD_HDRFLAG_SHIFT 18
#define TPD_MSS_MASK 0x1FFF
#define TPD_MSS_SHIFT 19
/* tdp word 3 bit 16:31 if custom csum enabled */
#define TPD_PLOADOFFSET_MASK 0x00FF
#define TPD_PLOADOFFSET_SHIFT 16
#define TPD_CCSUMOFFSET_MASK 0x00FF
#define TPD_CCSUMOFFSET_SHIFT 24
struct atl1e_tpd_desc {
__le64 buffer_addr;
__le32 word2;
__le32 word3;
};
/* how about 0x2000 */
#define MAX_TX_BUF_LEN 0x2000
#define MAX_TX_BUF_SHIFT 13
#define MAX_TSO_SEG_SIZE 0x3c00
/* rrs word 1 bit 0:31 */
#define RRS_RX_CSUM_MASK 0xFFFF
#define RRS_RX_CSUM_SHIFT 0
#define RRS_PKT_SIZE_MASK 0x3FFF
#define RRS_PKT_SIZE_SHIFT 16
#define RRS_CPU_NUM_MASK 0x0003
#define RRS_CPU_NUM_SHIFT 30
#define RRS_IS_RSS_IPV4 0x0001
#define RRS_IS_RSS_IPV4_TCP 0x0002
#define RRS_IS_RSS_IPV6 0x0004
#define RRS_IS_RSS_IPV6_TCP 0x0008
#define RRS_IS_IPV6 0x0010
#define RRS_IS_IP_FRAG 0x0020
#define RRS_IS_IP_DF 0x0040
#define RRS_IS_802_3 0x0080
#define RRS_IS_VLAN_TAG 0x0100
#define RRS_IS_ERR_FRAME 0x0200
#define RRS_IS_IPV4 0x0400
#define RRS_IS_UDP 0x0800
#define RRS_IS_TCP 0x1000
#define RRS_IS_BCAST 0x2000
#define RRS_IS_MCAST 0x4000
#define RRS_IS_PAUSE 0x8000
#define RRS_ERR_BAD_CRC 0x0001
#define RRS_ERR_CODE 0x0002
#define RRS_ERR_DRIBBLE 0x0004
#define RRS_ERR_RUNT 0x0008
#define RRS_ERR_RX_OVERFLOW 0x0010
#define RRS_ERR_TRUNC 0x0020
#define RRS_ERR_IP_CSUM 0x0040
#define RRS_ERR_L4_CSUM 0x0080
#define RRS_ERR_LENGTH 0x0100
#define RRS_ERR_DES_ADDR 0x0200
struct atl1e_recv_ret_status {
u16 seq_num;
u16 hash_lo;
__le32 word1;
u16 pkt_flag;
u16 err_flag;
u16 hash_hi;
u16 vtag;
};
enum atl1e_dma_req_block {
atl1e_dma_req_128 = 0,
atl1e_dma_req_256 = 1,
atl1e_dma_req_512 = 2,
atl1e_dma_req_1024 = 3,
atl1e_dma_req_2048 = 4,
atl1e_dma_req_4096 = 5
};
enum atl1e_rrs_type {
atl1e_rrs_disable = 0,
atl1e_rrs_ipv4 = 1,
atl1e_rrs_ipv4_tcp = 2,
atl1e_rrs_ipv6 = 4,
atl1e_rrs_ipv6_tcp = 8
};
enum atl1e_nic_type {
athr_l1e = 0,
athr_l2e_revA = 1,
athr_l2e_revB = 2
};
struct atl1e_hw_stats {
/* rx */
unsigned long rx_ok; /* The number of good packet received. */
unsigned long rx_bcast; /* The number of good broadcast packet received. */
unsigned long rx_mcast; /* The number of good multicast packet received. */
unsigned long rx_pause; /* The number of Pause packet received. */
unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */
unsigned long rx_fcs_err; /* The number of packets with bad FCS. */
unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */
unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */
unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */
unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */
unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */
unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */
unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */
unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */
unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */
unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */
unsigned long rx_align_err; /* Alignment Error */
unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */
/* tx */
unsigned long tx_ok; /* The number of good packet transmitted. */
unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */
unsigned long tx_mcast; /* The number of good multicast packet transmitted. */
unsigned long tx_pause; /* The number of Pause packet transmitted. */
unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */
unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */
unsigned long tx_defer; /* The number of packets transmitted that is deferred. */
unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */
unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */
unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */
unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */
unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */
unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */
unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */
unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */
unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */
};
struct atl1e_hw {
u8 __iomem *hw_addr; /* inner register address */
resource_size_t mem_rang;
struct atl1e_adapter *adapter;
enum atl1e_nic_type nic_type;
u16 device_id;
u16 vendor_id;
u16 subsystem_id;
u16 subsystem_vendor_id;
u8 revision_id;
u16 pci_cmd_word;
u8 mac_addr[ETH_ALEN];
u8 perm_mac_addr[ETH_ALEN];
u8 preamble_len;
u16 max_frame_size;
u16 rx_jumbo_th;
u16 tx_jumbo_th;
u16 media_type;
#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
u16 autoneg_advertised;
#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
u16 mii_autoneg_adv_reg;
u16 mii_1000t_ctrl_reg;
u16 imt; /* Interrupt Moderator timer ( 2us resolution) */
u16 ict; /* Interrupt Clear timer (2us resolution) */
u32 smb_timer;
u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
interrupt request */
u16 tpd_thresh;
u16 rx_count_down; /* 2us resolution */
u16 tx_count_down;
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */
enum atl1e_rrs_type rrs_type;
u32 base_cpu;
u32 indirect_tab;
enum atl1e_dma_req_block dmar_block;
enum atl1e_dma_req_block dmaw_block;
u8 dmaw_dly_cnt;
u8 dmar_dly_cnt;
bool phy_configured;
bool re_autoneg;
bool emi_ca;
};
/*
* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer
*/
struct atl1e_tx_buffer {
struct sk_buff *skb;
u16 flags;
#define ATL1E_TX_PCIMAP_SINGLE 0x0001
#define ATL1E_TX_PCIMAP_PAGE 0x0002
#define ATL1E_TX_PCIMAP_TYPE_MASK 0x0003
u16 length;
dma_addr_t dma;
};
#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do { \
((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK; \
((tx_buff)->flags) |= (type); \
} while (0)
struct atl1e_rx_page {
dma_addr_t dma; /* receive rage DMA address */
u8 *addr; /* receive rage virtual address */
dma_addr_t write_offset_dma; /* the DMA address which contain the
receive data offset in the page */
u32 *write_offset_addr; /* the virtaul address which contain
the receive data offset in the page */
u32 read_offset; /* the offset where we have read */
};
struct atl1e_rx_page_desc {
struct atl1e_rx_page rx_page[AT_PAGE_NUM_PER_QUEUE];
u8 rx_using;
u16 rx_nxseq;
};
/* transmit packet descriptor (tpd) ring */
struct atl1e_tx_ring {
struct atl1e_tpd_desc *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
u16 count; /* the count of transmit rings */
rwlock_t tx_lock;
u16 next_to_use;
atomic_t next_to_clean;
struct atl1e_tx_buffer *tx_buffer;
dma_addr_t cmb_dma;
u32 *cmb;
};
/* receive packet descriptor ring */
struct atl1e_rx_ring {
void *desc;
dma_addr_t dma;
int size;
u32 page_size; /* bytes length of rxf page */
u32 real_page_size; /* real_page_size = page_size + jumbo + aliagn */
struct atl1e_rx_page_desc rx_page_desc[AT_MAX_RECEIVE_QUEUE];
};
/* board specific private data structure */
struct atl1e_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
struct napi_struct napi;
struct mii_if_info mii; /* MII interface info */
struct atl1e_hw hw;
struct atl1e_hw_stats hw_stats;
u32 wol;
u16 link_speed;
u16 link_duplex;
spinlock_t mdio_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;
/* All Descriptor memory */
dma_addr_t ring_dma;
void *ring_vir_addr;
u32 ring_size;
struct atl1e_tx_ring tx_ring;
struct atl1e_rx_ring rx_ring;
int num_rx_queues;
unsigned long flags;
#define __AT_TESTING 0x0001
#define __AT_RESETTING 0x0002
#define __AT_DOWN 0x0003
u32 bd_number; /* board number;*/
u32 pci_state[16];
u32 *config_space;
};
#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)))
extern char atl1e_driver_name[];
extern char atl1e_driver_version[];
void atl1e_check_options(struct atl1e_adapter *adapter);
int atl1e_up(struct atl1e_adapter *adapter);
void atl1e_down(struct atl1e_adapter *adapter);
void atl1e_reinit_locked(struct atl1e_adapter *adapter);
s32 atl1e_reset_hw(struct atl1e_hw *hw);
void atl1e_set_ethtool_ops(struct net_device *netdev);
#endif /* _ATL1_E_H_ */

View file

@ -0,0 +1,392 @@
/*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*
*/
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/slab.h>
#include "atl1e.h"
static int atl1e_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_hw *hw = &adapter->hw;
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP);
if (hw->nic_type == athr_l1e)
ecmd->supported |= SUPPORTED_1000baseT_Full;
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) {
ethtool_cmd_speed_set(ecmd, adapter->link_speed);
if (adapter->link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
} else {
ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
ecmd->duplex = DUPLEX_UNKNOWN;
}
ecmd->autoneg = AUTONEG_ENABLE;
return 0;
}
static int atl1e_set_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_hw *hw = &adapter->hw;
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
if (ecmd->autoneg == AUTONEG_ENABLE) {
u16 adv4, adv9;
if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
if (hw->nic_type == athr_l1e) {
hw->autoneg_advertised =
ecmd->advertising & AT_ADV_MASK;
} else {
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
} else if (ecmd->advertising&ADVERTISE_1000_HALF) {
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
} else {
hw->autoneg_advertised =
ecmd->advertising & AT_ADV_MASK;
}
ecmd->advertising = hw->autoneg_advertised |
ADVERTISED_TP | ADVERTISED_Autoneg;
adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL;
adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK;
if (hw->autoneg_advertised & ADVERTISE_10_HALF)
adv4 |= ADVERTISE_10HALF;
if (hw->autoneg_advertised & ADVERTISE_10_FULL)
adv4 |= ADVERTISE_10FULL;
if (hw->autoneg_advertised & ADVERTISE_100_HALF)
adv4 |= ADVERTISE_100HALF;
if (hw->autoneg_advertised & ADVERTISE_100_FULL)
adv4 |= ADVERTISE_100FULL;
if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
adv9 |= ADVERTISE_1000FULL;
if (adv4 != hw->mii_autoneg_adv_reg ||
adv9 != hw->mii_1000t_ctrl_reg) {
hw->mii_autoneg_adv_reg = adv4;
hw->mii_1000t_ctrl_reg = adv9;
hw->re_autoneg = true;
}
} else {
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
/* reset the link */
if (netif_running(adapter->netdev)) {
atl1e_down(adapter);
atl1e_up(adapter);
} else
atl1e_reset_hw(&adapter->hw);
clear_bit(__AT_RESETTING, &adapter->flags);
return 0;
}
static u32 atl1e_get_msglevel(struct net_device *netdev)
{
#ifdef DBG
return 1;
#else
return 0;
#endif
}
static int atl1e_get_regs_len(struct net_device *netdev)
{
return AT_REGS_LEN * sizeof(u32);
}
static void atl1e_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_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_GPHY_CTRL);
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_TRD_ADDR);
regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN);
regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR);
regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR);
regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN);
regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR);
regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR);
atl1e_read_phy_reg(hw, MII_BMCR, &phy_data);
regs_buff[73] = (u32)phy_data;
atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
regs_buff[74] = (u32)phy_data;
}
static int atl1e_get_eeprom_len(struct net_device *netdev)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
if (!atl1e_check_eeprom_exist(&adapter->hw))
return AT_EEPROM_LEN;
else
return 0;
}
static int atl1e_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_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 (atl1e_check_eeprom_exist(hw)) /* not exist */
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 == NULL)
return -ENOMEM;
for (i = first_dword; i < last_dword; i++) {
if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
kfree(eeprom_buff);
return -EIO;
}
}
memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
eeprom->len);
kfree(eeprom_buff);
return ret_val;
}
static int atl1e_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_hw *hw = &adapter->hw;
u32 *eeprom_buff;
u32 *ptr;
int first_dword, last_dword;
int ret_val = 0;
int i;
if (eeprom->len == 0)
return -EOPNOTSUPP;
if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EINVAL;
first_dword = eeprom->offset >> 2;
last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL);
if (eeprom_buff == NULL)
return -ENOMEM;
ptr = 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 (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) {
ret_val = -EIO;
goto out;
}
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 (!atl1e_read_eeprom(hw, last_dword * 4,
&(eeprom_buff[last_dword - first_dword]))) {
ret_val = -EIO;
goto out;
}
}
/* 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 (!atl1e_write_eeprom(hw, ((first_dword + i) * 4),
eeprom_buff[i])) {
ret_val = -EIO;
goto out;
}
}
out:
kfree(eeprom_buff);
return ret_val;
}
static void atl1e_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
strlcpy(drvinfo->driver, atl1e_driver_name, sizeof(drvinfo->driver));
strlcpy(drvinfo->version, atl1e_driver_version,
sizeof(drvinfo->version));
strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
drvinfo->n_stats = 0;
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = atl1e_get_regs_len(netdev);
drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
}
static void atl1e_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
wol->supported = WAKE_MAGIC | WAKE_PHY;
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;
if (adapter->wol & AT_WUFC_LNKC)
wol->wolopts |= WAKE_PHY;
}
static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
WAKE_UCAST | WAKE_MCAST | WAKE_BCAST))
return -EOPNOTSUPP;
/* these settings will always override what we currently have */
adapter->wol = 0;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= AT_WUFC_MAG;
if (wol->wolopts & WAKE_PHY)
adapter->wol |= AT_WUFC_LNKC;
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
return 0;
}
static int atl1e_nway_reset(struct net_device *netdev)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev))
atl1e_reinit_locked(adapter);
return 0;
}
static const struct ethtool_ops atl1e_ethtool_ops = {
.get_settings = atl1e_get_settings,
.set_settings = atl1e_set_settings,
.get_drvinfo = atl1e_get_drvinfo,
.get_regs_len = atl1e_get_regs_len,
.get_regs = atl1e_get_regs,
.get_wol = atl1e_get_wol,
.set_wol = atl1e_set_wol,
.get_msglevel = atl1e_get_msglevel,
.nway_reset = atl1e_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = atl1e_get_eeprom_len,
.get_eeprom = atl1e_get_eeprom,
.set_eeprom = atl1e_set_eeprom,
};
void atl1e_set_ethtool_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &atl1e_ethtool_ops;
}

View file

@ -0,0 +1,650 @@
/*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*/
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/crc32.h>
#include "atl1e.h"
/*
* check_eeprom_exist
* return 0 if eeprom exist
*/
int atl1e_check_eeprom_exist(struct atl1e_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;
}
void atl1e_hw_set_mac_addr(struct atl1e_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);
}
/*
* atl1e_get_permanent_address
* return 0 if get valid mac address,
*/
static int atl1e_get_permanent_address(struct atl1e_hw *hw)
{
u32 addr[2];
u32 i;
u32 twsi_ctrl_data;
u8 eth_addr[ETH_ALEN];
if (is_valid_ether_addr(hw->perm_mac_addr))
return 0;
/* init */
addr[0] = addr[1] = 0;
if (!atl1e_check_eeprom_exist(hw)) {
/* eeprom exist */
twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
msleep(10);
twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
break;
}
if (i >= AT_TWSI_EEPROM_TIMEOUT)
return AT_ERR_TIMEOUT;
}
/* 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 *) &eth_addr[2] = swab32(addr[0]);
*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
if (is_valid_ether_addr(eth_addr)) {
memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
return 0;
}
return AT_ERR_EEPROM;
}
bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
{
return true;
}
bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
{
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++) {
msleep(2);
control = AT_READ_REG(hw, REG_VPD_CAP);
if (control & VPD_CAP_VPD_FLAG)
break;
}
if (control & VPD_CAP_VPD_FLAG) {
*p_value = AT_READ_REG(hw, REG_VPD_DATA);
return true;
}
return false; /* timeout */
}
void atl1e_force_ps(struct atl1e_hw *hw)
{
AT_WRITE_REGW(hw, REG_GPHY_CTRL,
GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
}
/*
* Reads the adapter's MAC address from the EEPROM
*
* hw - Struct containing variables accessed by shared code
*/
int atl1e_read_mac_addr(struct atl1e_hw *hw)
{
int err = 0;
err = atl1e_get_permanent_address(hw);
if (err)
return AT_ERR_EEPROM;
memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
return 0;
}
/*
* atl1e_hash_mc_addr
* purpose
* set hash value for a multicast address
*/
u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
{
u32 crc32;
u32 value = 0;
int i;
crc32 = ether_crc_le(6, mc_addr);
for (i = 0; i < 32; i++)
value |= (((crc32 >> i) & 1) << (31 - i));
return value;
}
/*
* Sets the bit in the multicast table corresponding to the hash value.
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*/
void atl1e_hash_set(struct atl1e_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);
}
/*
* Reads the value from a PHY register
* hw - Struct containing variables accessed by shared code
* reg_addr - address of the PHY register to read
*/
int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
{
u32 val;
int i;
val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
wmb();
for (i = 0; i < MDIO_WAIT_TIMES; i++) {
udelay(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 0;
}
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
*/
int atl1e_write_phy_reg(struct atl1e_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);
wmb();
for (i = 0; i < MDIO_WAIT_TIMES; i++) {
udelay(2);
val = AT_READ_REG(hw, REG_MDIO_CTRL);
if (!(val & (MDIO_START | MDIO_BUSY)))
break;
wmb();
}
if (!(val & (MDIO_START | MDIO_BUSY)))
return 0;
return AT_ERR_PHY;
}
/*
* atl1e_init_pcie - init PCIE module
*/
static void atl1e_init_pcie(struct atl1e_hw *hw)
{
u32 value;
/* comment 2lines below to save more power when sususpend
value = LTSSM_TEST_MODE_DEF;
AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
*/
/* pcie flow control mode change */
value = AT_READ_REG(hw, 0x1008);
value |= 0x8000;
AT_WRITE_REG(hw, 0x1008, value);
}
/*
* Configures PHY autoneg and flow control advertisement settings
*
* hw - Struct containing variables accessed by shared code
*/
static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
{
s32 ret_val;
u16 mii_autoneg_adv_reg;
u16 mii_1000t_ctrl_reg;
if (0 != hw->mii_autoneg_adv_reg)
return 0;
/* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
mii_1000t_ctrl_reg = MII_AT001_CR_1000T_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 &= ~ADVERTISE_ALL;
mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
/*
* Need to parse MediaType and setup the
* appropriate PHY registers.
*/
switch (hw->media_type) {
case MEDIA_TYPE_AUTO_SENSOR:
mii_autoneg_adv_reg |= ADVERTISE_ALL;
hw->autoneg_advertised = ADVERTISE_ALL;
if (hw->nic_type == athr_l1e) {
mii_1000t_ctrl_reg |= ADVERTISE_1000FULL;
hw->autoneg_advertised |= ADVERTISE_1000_FULL;
}
break;
case MEDIA_TYPE_100M_FULL:
mii_autoneg_adv_reg |= ADVERTISE_100FULL;
hw->autoneg_advertised = ADVERTISE_100_FULL;
break;
case MEDIA_TYPE_100M_HALF:
mii_autoneg_adv_reg |= ADVERTISE_100_HALF;
hw->autoneg_advertised = ADVERTISE_100_HALF;
break;
case MEDIA_TYPE_10M_FULL:
mii_autoneg_adv_reg |= ADVERTISE_10_FULL;
hw->autoneg_advertised = ADVERTISE_10_FULL;
break;
default:
mii_autoneg_adv_reg |= ADVERTISE_10_HALF;
hw->autoneg_advertised = ADVERTISE_10_HALF;
break;
}
/* flow control fixed to enable all */
mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP);
hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
if (ret_val)
return ret_val;
if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000,
mii_1000t_ctrl_reg);
if (ret_val)
return ret_val;
}
return 0;
}
/*
* Resets the PHY and make all config validate
*
* hw - Struct containing variables accessed by shared code
*
* Sets bit 15 and 12 of the MII control regiser (for F001 bug)
*/
int atl1e_phy_commit(struct atl1e_hw *hw)
{
struct atl1e_adapter *adapter = hw->adapter;
int ret_val;
u16 phy_data;
phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART;
ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
if (ret_val) {
u32 val;
int i;
/**************************************
* pcie serdes link may be down !
**************************************/
for (i = 0; i < 25; i++) {
msleep(1);
val = AT_READ_REG(hw, REG_MDIO_CTRL);
if (!(val & (MDIO_START | MDIO_BUSY)))
break;
}
if (0 != (val & (MDIO_START | MDIO_BUSY))) {
netdev_err(adapter->netdev,
"pcie linkdown at least for 25ms\n");
return ret_val;
}
netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i);
}
return 0;
}
int atl1e_phy_init(struct atl1e_hw *hw)
{
struct atl1e_adapter *adapter = hw->adapter;
s32 ret_val;
u16 phy_val;
if (hw->phy_configured) {
if (hw->re_autoneg) {
hw->re_autoneg = false;
return atl1e_restart_autoneg(hw);
}
return 0;
}
/* RESET GPHY Core */
AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
msleep(2);
AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
GPHY_CTRL_EXT_RESET);
msleep(2);
/* patches */
/* p1. eable hibernation mode */
ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
if (ret_val)
return ret_val;
ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
if (ret_val)
return ret_val;
/* p2. set Class A/B for all modes */
ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
if (ret_val)
return ret_val;
phy_val = 0x02ef;
/* remove Class AB */
/* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
if (ret_val)
return ret_val;
/* p3. 10B ??? */
ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
if (ret_val)
return ret_val;
ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
if (ret_val)
return ret_val;
/* p4. 1000T power */
ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
if (ret_val)
return ret_val;
ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
if (ret_val)
return ret_val;
ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
if (ret_val)
return ret_val;
ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
if (ret_val)
return ret_val;
msleep(1);
/*Enable PHY LinkChange Interrupt */
ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
if (ret_val) {
netdev_err(adapter->netdev,
"Error enable PHY linkChange Interrupt\n");
return ret_val;
}
/* setup AutoNeg parameters */
ret_val = atl1e_phy_setup_autoneg_adv(hw);
if (ret_val) {
netdev_err(adapter->netdev,
"Error Setting up Auto-Negotiation\n");
return ret_val;
}
/* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n");
ret_val = atl1e_phy_commit(hw);
if (ret_val) {
netdev_err(adapter->netdev, "Error resetting the phy\n");
return ret_val;
}
hw->phy_configured = true;
return 0;
}
/*
* Reset the transmit and receive units; mask and clear all interrupts.
* hw - Struct containing variables accessed by shared code
* return : 0 or idle status (if error)
*/
int atl1e_reset_hw(struct atl1e_hw *hw)
{
struct atl1e_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
u32 idle_status_data = 0;
u16 pci_cfg_cmd_word = 0;
int timeout = 0;
/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
pci_read_config_word(pdev, 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);
pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
}
/*
* 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_LED_MODE | MASTER_CTRL_SOFT_RST);
wmb();
msleep(1);
/* Wait at least 10ms for All module to be Idle */
for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
if (idle_status_data == 0)
break;
msleep(1);
cpu_relax();
}
if (timeout >= AT_HW_MAX_IDLE_DELAY) {
netdev_err(adapter->netdev,
"MAC state machine can't be idle since disabled for 10ms second\n");
return AT_ERR_TIMEOUT;
}
return 0;
}
/*
* 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.
*/
int atl1e_init_hw(struct atl1e_hw *hw)
{
s32 ret_val = 0;
atl1e_init_pcie(hw);
/* Zero out the Multicast HASH table */
/* 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);
ret_val = atl1e_phy_init(hw);
return ret_val;
}
/*
* Detects the current speed and duplex settings of the hardware.
*
* hw - Struct containing variables accessed by shared code
* speed - Speed of the connection
* duplex - Duplex setting of the connection
*/
int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
{
int err;
u16 phy_data;
/* Read PHY Specific Status Register (17) */
err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
if (err)
return err;
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_1000MBS:
*speed = SPEED_1000;
break;
case MII_AT001_PSSR_100MBS:
*speed = SPEED_100;
break;
case MII_AT001_PSSR_10MBS:
*speed = SPEED_10;
break;
default:
return AT_ERR_PHY_SPEED;
}
if (phy_data & MII_AT001_PSSR_DPLX)
*duplex = FULL_DUPLEX;
else
*duplex = HALF_DUPLEX;
return 0;
}
int atl1e_restart_autoneg(struct atl1e_hw *hw)
{
int err = 0;
err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
if (err)
return err;
if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
err = atl1e_write_phy_reg(hw, MII_CTRL1000,
hw->mii_1000t_ctrl_reg);
if (err)
return err;
}
err = atl1e_write_phy_reg(hw, MII_BMCR,
BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
return err;
}

View file

@ -0,0 +1,690 @@
/*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*/
#ifndef _ATHL1E_HW_H_
#define _ATHL1E_HW_H_
#include <linux/types.h>
#include <linux/mii.h>
struct atl1e_adapter;
struct atl1e_hw;
/* function prototype */
s32 atl1e_reset_hw(struct atl1e_hw *hw);
s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
s32 atl1e_init_hw(struct atl1e_hw *hw);
s32 atl1e_phy_commit(struct atl1e_hw *hw);
s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr);
void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value);
s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value);
bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value);
s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
s32 atl1e_phy_init(struct atl1e_hw *hw);
int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
void atl1e_force_ps(struct atl1e_hw *hw);
s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
/* register definition */
#define REG_PM_CTRLSTAT 0x44
#define REG_PCIE_CAP_LIST 0x58
#define REG_DEVICE_CAP 0x5C
#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0
#define REG_DEVICE_CTRL 0x60
#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7
#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5
#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7
#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12
#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
#define REG_LTSSM_TEST_MODE 0x12FC
#define LTSSM_TEST_MODE_DEF 0xE000
/* 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_ITIMER2_EN 0x20
#define MASTER_CTRL_INT_RDCLR 0x40
#define MASTER_CTRL_LED_MODE 0x200
#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 /* w */
#define REG_IRQ_MODU_TIMER2_INIT 0x140A /* w */
#define REG_GPHY_CTRL 0x140C
#define GPHY_CTRL_EXT_RESET 1
#define GPHY_CTRL_PIPE_MOD 2
#define GPHY_CTRL_TEST_MODE_MASK 3
#define GPHY_CTRL_TEST_MODE_SHIFT 2
#define GPHY_CTRL_BERT_START 0x10
#define GPHY_CTRL_GATE_25M_EN 0x20
#define GPHY_CTRL_LPW_EXIT 0x40
#define GPHY_CTRL_PHY_IDDQ 0x80
#define GPHY_CTRL_PHY_IDDQ_DIS 0x100
#define GPHY_CTRL_PCLK_SEL_DIS 0x200
#define GPHY_CTRL_HIB_EN 0x400
#define GPHY_CTRL_HIB_PULSE 0x800
#define GPHY_CTRL_SEL_ANA_RST 0x1000
#define GPHY_CTRL_PHY_PLL_ON 0x2000
#define GPHY_CTRL_PWDOWN_HW 0x4000
#define GPHY_CTRL_DEFAULT (\
GPHY_CTRL_PHY_PLL_ON |\
GPHY_CTRL_SEL_ANA_RST |\
GPHY_CTRL_HIB_PULSE |\
GPHY_CTRL_HIB_EN)
#define GPHY_CTRL_PW_WOL_DIS (\
GPHY_CTRL_PHY_PLL_ON |\
GPHY_CTRL_SEL_ANA_RST |\
GPHY_CTRL_HIB_PULSE |\
GPHY_CTRL_HIB_EN |\
GPHY_CTRL_PWDOWN_HW |\
GPHY_CTRL_PCLK_SEL_DIS |\
GPHY_CTRL_PHY_IDDQ)
/* 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_RXQ 4 /* 1: RXQ state machine is in non-IDLE state. 0: RXQ is idling */
#define IDLE_STATUS_TXQ 8 /* 1: TXQ state machine is in non-IDLE state. 0: TXQ is idling */
#define IDLE_STATUS_DMAR 0x10 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */
#define IDLE_STATUS_DMAW 0x20 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */
#define IDLE_STATUS_SMB 0x40 /* 1: SMB state machine is in non-IDLE state. 0: SMB is idling */
#define IDLE_STATUS_CMB 0x80 /* 1: CMB state machine is in non-IDLE state. 0: CMB 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_AP_EN 0x10000000
#define MDIO_WAIT_TIMES 10
/* MII PHY Status Register */
#define REG_PHY_STATUS 0x1418
#define PHY_STATUS_100M 0x20000
#define PHY_STATUS_EMI_CA 0x40000
/* BIST Control and Status Register0 (for the Packet Memory) */
#define REG_BIST0_CTRL 0x141c
#define BIST0_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
/* BIST process and reset to zero when BIST is done */
#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
/* decoder failure or more than 1 cell stuck-to-x failure */
#define BIST0_FUSE_FLAG 0x4 /* 1: Indicating one cell has been fixed */
/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
#define REG_BIST1_CTRL 0x1420
#define BIST1_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
/* BIST process and reset to zero when BIST is done */
#define BIST1_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
/* decoder failure or more than 1 cell stuck-to-x failure.*/
#define BIST1_FUSE_FLAG 0x4
/* 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_LENCHK 0x100 /* 1: Instruct MAC to check if length field matches the real packet length */
#define MAC_CTRL_HUGE_EN 0x200 /* 1: receive Jumbo frame enable */
#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length */
#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_TX_PAUSE 0x10000 /* 1: transmit test pause */
#define MAC_CTRL_SCNT 0x20000 /* 1: shortcut slot time counter */
#define MAC_CTRL_SRST_TX 0x40000 /* 1: synchronized reset Transmit MAC module */
#define MAC_CTRL_TX_SIMURST 0x80000 /* 1: transmit simulation reset */
#define MAC_CTRL_SPEED_SHIFT 20 /* 10: gigabit 01:10M/100M */
#define MAC_CTRL_SPEED_MASK 0x300000
#define MAC_CTRL_SPEED_1000 2
#define MAC_CTRL_SPEED_10_100 1
#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 /* 1: transmit maximum backoff (half-duplex test bit) */
#define MAC_CTRL_TX_HUGE 0x800000 /* 1: transmit huge enable */
#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 /* 1: RX checksum enable */
#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_DBG 0x8000000 /* 1: upload all received frame to system (Debug Mode) */
/* 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_CLK_SWITCH_EN 0x00008000
#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_PT5_EN 0x00200000
#define WOL_PT6_EN 0x00400000
/* WOL Length ( 2 DWORD ) */
#define REG_WOL_PATTERN_LEN 0x14a4
#define WOL_PT_LEN_MASK 0x7f
#define WOL_PT0_LEN_SHIFT 0
#define WOL_PT1_LEN_SHIFT 8
#define WOL_PT2_LEN_SHIFT 16
#define WOL_PT3_LEN_SHIFT 24
#define WOL_PT4_LEN_SHIFT 0
#define WOL_PT5_LEN_SHIFT 8
#define WOL_PT6_LEN_SHIFT 16
/* Internal SRAM Partition Register */
#define REG_SRAM_TRD_ADDR 0x1518
#define REG_SRAM_TRD_LEN 0x151C
#define REG_SRAM_RXF_ADDR 0x1520
#define REG_SRAM_RXF_LEN 0x1524
#define REG_SRAM_TXF_ADDR 0x1528
#define REG_SRAM_TXF_LEN 0x152C
#define REG_SRAM_TCPH_ADDR 0x1530
#define REG_SRAM_PKTH_ADDR 0x1532
/* Load Ptr Register */
#define REG_LOAD_PTR 0x1534 /* Software sets this bit after the initialization of the head and tail */
/*
* addresses of all descriptors, as well as the following descriptor
* control register, which triggers each function block to load the head
* pointer to prepare for the operation. This bit is then self-cleared
* after one cycle.
*/
/* Descriptor Control register */
#define REG_RXF3_BASE_ADDR_HI 0x153C
#define REG_DESC_BASE_ADDR_HI 0x1540
#define REG_RXF0_BASE_ADDR_HI 0x1540 /* share with DESC BASE ADDR HI */
#define REG_HOST_RXF0_PAGE0_LO 0x1544
#define REG_HOST_RXF0_PAGE1_LO 0x1548
#define REG_TPD_BASE_ADDR_LO 0x154C
#define REG_RXF1_BASE_ADDR_HI 0x1550
#define REG_RXF2_BASE_ADDR_HI 0x1554
#define REG_HOST_RXFPAGE_SIZE 0x1558
#define REG_TPD_RING_SIZE 0x155C
/* RSS about */
#define REG_RSS_KEY0 0x14B0
#define REG_RSS_KEY1 0x14B4
#define REG_RSS_KEY2 0x14B8
#define REG_RSS_KEY3 0x14BC
#define REG_RSS_KEY4 0x14C0
#define REG_RSS_KEY5 0x14C4
#define REG_RSS_KEY6 0x14C8
#define REG_RSS_KEY7 0x14CC
#define REG_RSS_KEY8 0x14D0
#define REG_RSS_KEY9 0x14D4
#define REG_IDT_TABLE4 0x14E0
#define REG_IDT_TABLE5 0x14E4
#define REG_IDT_TABLE6 0x14E8
#define REG_IDT_TABLE7 0x14EC
#define REG_IDT_TABLE0 0x1560
#define REG_IDT_TABLE1 0x1564
#define REG_IDT_TABLE2 0x1568
#define REG_IDT_TABLE3 0x156C
#define REG_IDT_TABLE REG_IDT_TABLE0
#define REG_RSS_HASH_VALUE 0x1570
#define REG_RSS_HASH_FLAG 0x1574
#define REG_BASE_CPU_NUMBER 0x157C
/* TXQ Control Register */
#define REG_TXQ_CTRL 0x1580
#define TXQ_CTRL_NUM_TPD_BURST_MASK 0xF
#define TXQ_CTRL_NUM_TPD_BURST_SHIFT 0
#define TXQ_CTRL_EN 0x20 /* 1: Enable TXQ */
#define TXQ_CTRL_ENH_MODE 0x40 /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16 /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff
/* Jumbo packet Threshold for task offload */
#define REG_TX_EARLY_TH 0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
#define TX_TX_EARLY_TH_MASK 0x7ff
#define TX_TX_EARLY_TH_SHIFT 0
/* RXQ Control Register */
#define REG_RXQ_CTRL 0x15A0
#define RXQ_CTRL_PBA_ALIGN_32 0 /* rx-packet alignment */
#define RXQ_CTRL_PBA_ALIGN_64 1
#define RXQ_CTRL_PBA_ALIGN_128 2
#define RXQ_CTRL_PBA_ALIGN_256 3
#define RXQ_CTRL_Q1_EN 0x10
#define RXQ_CTRL_Q2_EN 0x20
#define RXQ_CTRL_Q3_EN 0x40
#define RXQ_CTRL_IPV6_XSUM_VERIFY_EN 0x80
#define RXQ_CTRL_HASH_TLEN_SHIFT 8
#define RXQ_CTRL_HASH_TLEN_MASK 0xFF
#define RXQ_CTRL_HASH_TYPE_IPV4 0x10000
#define RXQ_CTRL_HASH_TYPE_IPV4_TCP 0x20000
#define RXQ_CTRL_HASH_TYPE_IPV6 0x40000
#define RXQ_CTRL_HASH_TYPE_IPV6_TCP 0x80000
#define RXQ_CTRL_RSS_MODE_DISABLE 0
#define RXQ_CTRL_RSS_MODE_SQSINT 0x4000000
#define RXQ_CTRL_RSS_MODE_MQUESINT 0x8000000
#define RXQ_CTRL_RSS_MODE_MQUEMINT 0xC000000
#define RXQ_CTRL_NIP_QUEUE_SEL_TBL 0x10000000
#define RXQ_CTRL_HASH_ENABLE 0x20000000
#define RXQ_CTRL_CUT_THRU_EN 0x40000000
#define RXQ_CTRL_EN 0x80000000
/* Rx jumbo packet threshold and rrd retirement timer */
#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
/*
* Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
* When the packet length greater than or equal to this value, RXQ
* shall start cut-through forwarding of the received packet.
*/
#define RXQ_JMBOSZ_TH_MASK 0x7ff
#define RXQ_JMBOSZ_TH_SHIFT 0 /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
#define RXQ_JMBO_LKAH_MASK 0xf
#define RXQ_JMBO_LKAH_SHIFT 11
/* RXF flow control register */
#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0
#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff
#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16
#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff
/* DMA Engine Control Register */
#define REG_DMA_CTRL 0x15C0
#define DMA_CTRL_DMAR_IN_ORDER 0x1
#define DMA_CTRL_DMAR_ENH_ORDER 0x2
#define DMA_CTRL_DMAR_OUT_ORDER 0x4
#define DMA_CTRL_RCB_VALUE 0x8
#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
#define DMA_CTRL_DMAR_REQ_PRI 0x400
#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x1F
#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11
#define DMA_CTRL_DMAW_DLY_CNT_MASK 0xF
#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16
#define DMA_CTRL_TXCMB_EN 0x100000
#define DMA_CTRL_RXCMB_EN 0x200000
/* CMB/SMB Control Register */
#define REG_SMB_STAT_TIMER 0x15C4
#define REG_TRIG_RRD_THRESH 0x15CA
#define REG_TRIG_TPD_THRESH 0x15C8
#define REG_TRIG_TXTIMER 0x15CC
#define REG_TRIG_RXTIMER 0x15CE
/* HOST RXF Page 1,2,3 address */
#define REG_HOST_RXF1_PAGE0_LO 0x15D0
#define REG_HOST_RXF1_PAGE1_LO 0x15D4
#define REG_HOST_RXF2_PAGE0_LO 0x15D8
#define REG_HOST_RXF2_PAGE1_LO 0x15DC
#define REG_HOST_RXF3_PAGE0_LO 0x15E0
#define REG_HOST_RXF3_PAGE1_LO 0x15E4
/* Mail box */
#define REG_MB_RXF1_RADDR 0x15B4
#define REG_MB_RXF2_RADDR 0x15B8
#define REG_MB_RXF3_RADDR 0x15BC
#define REG_MB_TPD_PROD_IDX 0x15F0
/* RXF-Page 0-3 PageNo & Valid bit */
#define REG_HOST_RXF0_PAGE0_VLD 0x15F4
#define HOST_RXF_VALID 1
#define HOST_RXF_PAGENO_SHIFT 1
#define HOST_RXF_PAGENO_MASK 0x7F
#define REG_HOST_RXF0_PAGE1_VLD 0x15F5
#define REG_HOST_RXF1_PAGE0_VLD 0x15F6
#define REG_HOST_RXF1_PAGE1_VLD 0x15F7
#define REG_HOST_RXF2_PAGE0_VLD 0x15F8
#define REG_HOST_RXF2_PAGE1_VLD 0x15F9
#define REG_HOST_RXF3_PAGE0_VLD 0x15FA
#define REG_HOST_RXF3_PAGE1_VLD 0x15FB
/* Interrupt Status Register */
#define REG_ISR 0x1600
#define ISR_SMB 1
#define ISR_TIMER 2 /* Interrupt when Timer is counted down to zero */
/*
* Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
* in Table 51 Selene Master Control Register (Offset 0x1400).
*/
#define ISR_MANUAL 4
#define ISR_HW_RXF_OV 8 /* RXF overflow interrupt */
#define ISR_HOST_RXF0_OV 0x10
#define ISR_HOST_RXF1_OV 0x20
#define ISR_HOST_RXF2_OV 0x40
#define ISR_HOST_RXF3_OV 0x80
#define ISR_TXF_UN 0x100
#define ISR_RX0_PAGE_FULL 0x200
#define ISR_DMAR_TO_RST 0x400
#define ISR_DMAW_TO_RST 0x800
#define ISR_GPHY 0x1000
#define ISR_TX_CREDIT 0x2000
#define ISR_GPHY_LPW 0x4000 /* GPHY low power state interrupt */
#define ISR_RX_PKT 0x10000 /* One packet received, triggered by RFD */
#define ISR_TX_PKT 0x20000 /* One packet transmitted, triggered by TPD */
#define ISR_TX_DMA 0x40000
#define ISR_RX_PKT_1 0x80000
#define ISR_RX_PKT_2 0x100000
#define ISR_RX_PKT_3 0x200000
#define ISR_MAC_RX 0x400000
#define ISR_MAC_TX 0x800000
#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
/* Interrupt Mask Register */
#define REG_IMR 0x1604
#define IMR_NORMAL_MASK (\
ISR_SMB |\
ISR_TXF_UN |\
ISR_HW_RXF_OV |\
ISR_HOST_RXF0_OV|\
ISR_MANUAL |\
ISR_GPHY |\
ISR_GPHY_LPW |\
ISR_DMAR_TO_RST |\
ISR_DMAW_TO_RST |\
ISR_PHY_LINKDOWN|\
ISR_RX_PKT |\
ISR_TX_PKT)
#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
#define REG_MAC_RX_STATUS_BIN 0x1700
#define REG_MAC_RX_STATUS_END 0x175c
#define REG_MAC_TX_STATUS_BIN 0x1760
#define REG_MAC_TX_STATUS_END 0x17c0
/* Hardware Offset Register */
#define REG_HOST_RXF0_PAGEOFF 0x1800
#define REG_TPD_CONS_IDX 0x1804
#define REG_HOST_RXF1_PAGEOFF 0x1808
#define REG_HOST_RXF2_PAGEOFF 0x180C
#define REG_HOST_RXF3_PAGEOFF 0x1810
/* RXF-Page 0-3 Offset DMA Address */
#define REG_HOST_RXF0_MB0_LO 0x1820
#define REG_HOST_RXF0_MB1_LO 0x1824
#define REG_HOST_RXF1_MB0_LO 0x1828
#define REG_HOST_RXF1_MB1_LO 0x182C
#define REG_HOST_RXF2_MB0_LO 0x1830
#define REG_HOST_RXF2_MB1_LO 0x1834
#define REG_HOST_RXF3_MB0_LO 0x1838
#define REG_HOST_RXF3_MB1_LO 0x183C
/* Tpd CMB DMA Address */
#define REG_HOST_TX_CMB_LO 0x1840
#define REG_HOST_SMB_ADDR_LO 0x1844
/* DEBUG ADDR */
#define REG_DEBUG_DATA0 0x1900
#define REG_DEBUG_DATA1 0x1904
/***************************** MII definition ***************************************/
/* PHY Common Register */
#define MII_AT001_PSCR 0x10
#define MII_AT001_PSSR 0x11
#define MII_INT_CTRL 0x12
#define MII_INT_STATUS 0x13
#define MII_SMARTSPEED 0x14
#define MII_LBRERROR 0x18
#define MII_RESV2 0x1a
#define MII_DBG_ADDR 0x1D
#define MII_DBG_DATA 0x1E
/* Autoneg Advertisement Register */
#define MII_AR_DEFAULT_CAP_MASK 0
/* 1000BASE-T Control Register */
#define MII_AT001_CR_1000T_SPEED_MASK \
(ADVERTISE_1000FULL | ADVERTISE_1000HALF)
#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK MII_AT001_CR_1000T_SPEED_MASK
/* 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 */
#endif /*_ATHL1E_HW_H_*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,269 @@
/*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*/
#include <linux/netdevice.h>
#include "atl1e.h"
/* This is the only thing that needs to be changed to adjust the
* maximum number of ports that the driver can manage.
*/
#define ATL1E_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 ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
#define ATL1E_PARAM(x, desc) \
static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
static unsigned int num_##x; \
module_param_array_named(x, x, int, &num_##x, 0); \
MODULE_PARM_DESC(x, desc);
/* Transmit Memory count
*
* Valid Range: 64-2048
*
* Default Value: 128
*/
#define ATL1E_MIN_TX_DESC_CNT 32
#define ATL1E_MAX_TX_DESC_CNT 1020
#define ATL1E_DEFAULT_TX_DESC_CNT 128
ATL1E_PARAM(tx_desc_cnt, "Transmit description count");
/* Receive Memory Block Count
*
* Valid Range: 16-512
*
* Default Value: 128
*/
#define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */
#define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */
#define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */
ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)");
/* User Specified MediaType Override
*
* Valid Range: 0-5
* - 0 - auto-negotiate at all supported speeds
* - 1 - only link at 100Mbps Full Duplex
* - 2 - only link at 100Mbps Half Duplex
* - 3 - only link at 10Mbps Full Duplex
* - 4 - only link at 10Mbps Half Duplex
* Default Value: 0
*/
ATL1E_PARAM(media_type, "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
ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer");
#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 atl1e_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 atl1e_opt_list { int i; char *str; } *p;
} l;
} arg;
};
static int atl1e_validate_option(int *value, struct atl1e_option *opt,
struct atl1e_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
switch (opt->type) {
case enable_option:
switch (*value) {
case OPTION_ENABLED:
netdev_info(adapter->netdev,
"%s Enabled\n", opt->name);
return 0;
case OPTION_DISABLED:
netdev_info(adapter->netdev,
"%s Disabled\n", opt->name);
return 0;
}
break;
case range_option:
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
netdev_info(adapter->netdev, "%s set to %i\n",
opt->name, *value);
return 0;
}
break;
case list_option:{
int i;
struct atl1e_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')
netdev_info(adapter->netdev,
"%s\n", ent->str);
return 0;
}
}
break;
}
default:
BUG();
}
netdev_info(adapter->netdev, "Invalid %s specified (%i) %s\n",
opt->name, *value, opt->err);
*value = opt->def;
return -1;
}
/**
* atl1e_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 atl1e_check_options(struct atl1e_adapter *adapter)
{
int bd = adapter->bd_number;
if (bd >= ATL1E_MAX_NIC) {
netdev_notice(adapter->netdev,
"no configuration for board #%i\n", bd);
netdev_notice(adapter->netdev,
"Using defaults for all values\n");
}
{ /* Transmit Ring Size */
struct atl1e_option opt = {
.type = range_option,
.name = "Transmit Ddescription Count",
.err = "using default of "
__MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT),
.def = ATL1E_DEFAULT_TX_DESC_CNT,
.arg = { .r = { .min = ATL1E_MIN_TX_DESC_CNT,
.max = ATL1E_MAX_TX_DESC_CNT} }
};
int val;
if (num_tx_desc_cnt > bd) {
val = tx_desc_cnt[bd];
atl1e_validate_option(&val, &opt, adapter);
adapter->tx_ring.count = (u16) val & 0xFFFC;
} else
adapter->tx_ring.count = (u16)opt.def;
}
{ /* Receive Memory Block Count */
struct atl1e_option opt = {
.type = range_option,
.name = "Memory size of rx buffer(KB)",
.err = "using default of "
__MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE),
.def = ATL1E_DEFAULT_RX_MEM_SIZE,
.arg = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE,
.max = ATL1E_MAX_RX_MEM_SIZE} }
};
int val;
if (num_rx_mem_size > bd) {
val = rx_mem_size[bd];
atl1e_validate_option(&val, &opt, adapter);
adapter->rx_ring.page_size = (u32)val * 1024;
} else {
adapter->rx_ring.page_size = (u32)opt.def * 1024;
}
}
{ /* Interrupt Moderate Timer */
struct atl1e_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;
if (num_int_mod_timer > bd) {
val = int_mod_timer[bd];
atl1e_validate_option(&val, &opt, adapter);
adapter->hw.imt = (u16) val;
} else
adapter->hw.imt = (u16)(opt.def);
}
{ /* MediaType */
struct atl1e_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;
if (num_media_type > bd) {
val = media_type[bd];
atl1e_validate_option(&val, &opt, adapter);
adapter->hw.media_type = (u16) val;
} else
adapter->hw.media_type = (u16)(opt.def);
}
}

View file

@ -0,0 +1,3 @@
obj-$(CONFIG_ATL1) += atl1.o
obj-$(CONFIG_ATL2) += atl2.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,803 @@
/*
* Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
* Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
* Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
*
* Derived from Intel e1000 driver
* Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ATL1_H
#define ATL1_H
#include <linux/compiler.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/mii.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include "atlx.h"
#define ATLX_DRIVER_NAME "atl1"
MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
#define atlx_adapter atl1_adapter
#define atlx_check_for_link atl1_check_for_link
#define atlx_check_link atl1_check_link
#define atlx_hash_mc_addr atl1_hash_mc_addr
#define atlx_hash_set atl1_hash_set
#define atlx_hw atl1_hw
#define atlx_mii_ioctl atl1_mii_ioctl
#define atlx_read_phy_reg atl1_read_phy_reg
#define atlx_set_mac atl1_set_mac
#define atlx_set_mac_addr atl1_set_mac_addr
struct atl1_adapter;
struct atl1_hw;
/* function prototypes needed by multiple files */
static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
static void atl1_set_mac_addr(struct atl1_hw *hw);
static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
static u32 atl1_check_link(struct atl1_adapter *adapter);
/* hardware definitions specific to L1 */
/* Block IDLE Status Register */
#define IDLE_STATUS_RXMAC 0x1
#define IDLE_STATUS_TXMAC 0x2
#define IDLE_STATUS_RXQ 0x4
#define IDLE_STATUS_TXQ 0x8
#define IDLE_STATUS_DMAR 0x10
#define IDLE_STATUS_DMAW 0x20
#define IDLE_STATUS_SMB 0x40
#define IDLE_STATUS_CMB 0x80
/* MDIO Control Register */
#define MDIO_WAIT_TIMES 30
/* MAC Control Register */
#define MAC_CTRL_TX_PAUSE 0x10000
#define MAC_CTRL_SCNT 0x20000
#define MAC_CTRL_SRST_TX 0x40000
#define MAC_CTRL_TX_SIMURST 0x80000
#define MAC_CTRL_SPEED_SHIFT 20
#define MAC_CTRL_SPEED_MASK 0x300000
#define MAC_CTRL_SPEED_1000 0x2
#define MAC_CTRL_SPEED_10_100 0x1
#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000
#define MAC_CTRL_TX_HUGE 0x800000
#define MAC_CTRL_RX_CHKSUM_EN 0x1000000
#define MAC_CTRL_DBG 0x8000000
/* Wake-On-Lan control register */
#define WOL_CLK_SWITCH_EN 0x8000
#define WOL_PT5_EN 0x200000
#define WOL_PT6_EN 0x400000
#define WOL_PT5_MATCH 0x8000000
#define WOL_PT6_MATCH 0x10000000
/* WOL Length ( 2 DWORD ) */
#define REG_WOL_PATTERN_LEN 0x14A4
#define WOL_PT_LEN_MASK 0x7F
#define WOL_PT0_LEN_SHIFT 0
#define WOL_PT1_LEN_SHIFT 8
#define WOL_PT2_LEN_SHIFT 16
#define WOL_PT3_LEN_SHIFT 24
#define WOL_PT4_LEN_SHIFT 0
#define WOL_PT5_LEN_SHIFT 8
#define WOL_PT6_LEN_SHIFT 16
/* Internal SRAM Partition Registers, low 32 bits */
#define REG_SRAM_RFD_LEN 0x1504
#define REG_SRAM_RRD_ADDR 0x1508
#define REG_SRAM_RRD_LEN 0x150C
#define REG_SRAM_TPD_ADDR 0x1510
#define REG_SRAM_TPD_LEN 0x1514
#define REG_SRAM_TRD_ADDR 0x1518
#define REG_SRAM_TRD_LEN 0x151C
#define REG_SRAM_RXF_ADDR 0x1520
#define REG_SRAM_RXF_LEN 0x1524
#define REG_SRAM_TXF_ADDR 0x1528
#define REG_SRAM_TXF_LEN 0x152C
#define REG_SRAM_TCPH_PATH_ADDR 0x1530
#define SRAM_TCPH_ADDR_MASK 0xFFF
#define SRAM_TCPH_ADDR_SHIFT 0
#define SRAM_PATH_ADDR_MASK 0xFFF
#define SRAM_PATH_ADDR_SHIFT 16
/* Load Ptr Register */
#define REG_LOAD_PTR 0x1534
/* Descriptor Control registers, low 32 bits */
#define REG_DESC_RFD_ADDR_LO 0x1544
#define REG_DESC_RRD_ADDR_LO 0x1548
#define REG_DESC_TPD_ADDR_LO 0x154C
#define REG_DESC_CMB_ADDR_LO 0x1550
#define REG_DESC_SMB_ADDR_LO 0x1554
#define REG_DESC_RFD_RRD_RING_SIZE 0x1558
#define DESC_RFD_RING_SIZE_MASK 0x7FF
#define DESC_RFD_RING_SIZE_SHIFT 0
#define DESC_RRD_RING_SIZE_MASK 0x7FF
#define DESC_RRD_RING_SIZE_SHIFT 16
#define REG_DESC_TPD_RING_SIZE 0x155C
#define DESC_TPD_RING_SIZE_MASK 0x3FF
#define DESC_TPD_RING_SIZE_SHIFT 0
/* TXQ Control Register */
#define REG_TXQ_CTRL 0x1580
#define TXQ_CTRL_TPD_BURST_NUM_SHIFT 0
#define TXQ_CTRL_TPD_BURST_NUM_MASK 0x1F
#define TXQ_CTRL_EN 0x20
#define TXQ_CTRL_ENH_MODE 0x40
#define TXQ_CTRL_TPD_FETCH_TH_SHIFT 8
#define TXQ_CTRL_TPD_FETCH_TH_MASK 0x3F
#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16
#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xFFFF
/* Jumbo packet Threshold for task offload */
#define REG_TX_JUMBO_TASK_TH_TPD_IPG 0x1584
#define TX_JUMBO_TASK_TH_MASK 0x7FF
#define TX_JUMBO_TASK_TH_SHIFT 0
#define TX_TPD_MIN_IPG_MASK 0x1F
#define TX_TPD_MIN_IPG_SHIFT 16
/* RXQ Control Register */
#define REG_RXQ_CTRL 0x15A0
#define RXQ_CTRL_RFD_BURST_NUM_SHIFT 0
#define RXQ_CTRL_RFD_BURST_NUM_MASK 0xFF
#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT 8
#define RXQ_CTRL_RRD_BURST_THRESH_MASK 0xFF
#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT 16
#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK 0x1F
#define RXQ_CTRL_CUT_THRU_EN 0x40000000
#define RXQ_CTRL_EN 0x80000000
/* Rx jumbo packet threshold and rrd retirement timer */
#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
#define RXQ_JMBOSZ_TH_MASK 0x7FF
#define RXQ_JMBOSZ_TH_SHIFT 0
#define RXQ_JMBO_LKAH_MASK 0xF
#define RXQ_JMBO_LKAH_SHIFT 11
#define RXQ_RRD_TIMER_MASK 0xFFFF
#define RXQ_RRD_TIMER_SHIFT 16
/* RFD flow control register */
#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
#define RXQ_RXF_PAUSE_TH_HI_SHIFT 16
#define RXQ_RXF_PAUSE_TH_HI_MASK 0xFFF
#define RXQ_RXF_PAUSE_TH_LO_SHIFT 0
#define RXQ_RXF_PAUSE_TH_LO_MASK 0xFFF
/* RRD flow control register */
#define REG_RXQ_RRD_PAUSE_THRESH 0x15AC
#define RXQ_RRD_PAUSE_TH_HI_SHIFT 0
#define RXQ_RRD_PAUSE_TH_HI_MASK 0xFFF
#define RXQ_RRD_PAUSE_TH_LO_SHIFT 16
#define RXQ_RRD_PAUSE_TH_LO_MASK 0xFFF
/* DMA Engine Control Register */
#define REG_DMA_CTRL 0x15C0
#define DMA_CTRL_DMAR_IN_ORDER 0x1
#define DMA_CTRL_DMAR_ENH_ORDER 0x2
#define DMA_CTRL_DMAR_OUT_ORDER 0x4
#define DMA_CTRL_RCB_VALUE 0x8
#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
#define DMA_CTRL_DMAR_EN 0x400
#define DMA_CTRL_DMAW_EN 0x800
/* CMB/SMB Control Register */
#define REG_CSMB_CTRL 0x15D0
#define CSMB_CTRL_CMB_NOW 1
#define CSMB_CTRL_SMB_NOW 2
#define CSMB_CTRL_CMB_EN 4
#define CSMB_CTRL_SMB_EN 8
/* CMB DMA Write Threshold Register */
#define REG_CMB_WRITE_TH 0x15D4
#define CMB_RRD_TH_SHIFT 0
#define CMB_RRD_TH_MASK 0x7FF
#define CMB_TPD_TH_SHIFT 16
#define CMB_TPD_TH_MASK 0x7FF
/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
#define REG_CMB_WRITE_TIMER 0x15D8
#define CMB_RX_TM_SHIFT 0
#define CMB_RX_TM_MASK 0xFFFF
#define CMB_TX_TM_SHIFT 16
#define CMB_TX_TM_MASK 0xFFFF
/* Number of packet received since last CMB write */
#define REG_CMB_RX_PKT_CNT 0x15DC
/* Number of packet transmitted since last CMB write */
#define REG_CMB_TX_PKT_CNT 0x15E0
/* SMB auto DMA timer register */
#define REG_SMB_TIMER 0x15E4
/* Mailbox Register */
#define REG_MAILBOX 0x15F0
#define MB_RFD_PROD_INDX_SHIFT 0
#define MB_RFD_PROD_INDX_MASK 0x7FF
#define MB_RRD_CONS_INDX_SHIFT 11
#define MB_RRD_CONS_INDX_MASK 0x7FF
#define MB_TPD_PROD_INDX_SHIFT 22
#define MB_TPD_PROD_INDX_MASK 0x3FF
/* Interrupt Status Register */
#define ISR_SMB 0x1
#define ISR_TIMER 0x2
#define ISR_MANUAL 0x4
#define ISR_RXF_OV 0x8
#define ISR_RFD_UNRUN 0x10
#define ISR_RRD_OV 0x20
#define ISR_TXF_UNRUN 0x40
#define ISR_LINK 0x80
#define ISR_HOST_RFD_UNRUN 0x100
#define ISR_HOST_RRD_OV 0x200
#define ISR_DMAR_TO_RST 0x400
#define ISR_DMAW_TO_RST 0x800
#define ISR_GPHY 0x1000
#define ISR_RX_PKT 0x10000
#define ISR_TX_PKT 0x20000
#define ISR_TX_DMA 0x40000
#define ISR_RX_DMA 0x80000
#define ISR_CMB_RX 0x100000
#define ISR_CMB_TX 0x200000
#define ISR_MAC_RX 0x400000
#define ISR_MAC_TX 0x800000
#define ISR_DIS_SMB 0x20000000
#define ISR_DIS_DMA 0x40000000
/* Normal Interrupt mask without RX/TX enabled */
#define IMR_NORXTX_MASK (\
ISR_SMB |\
ISR_GPHY |\
ISR_PHY_LINKDOWN|\
ISR_DMAR_TO_RST |\
ISR_DMAW_TO_RST)
/* Normal Interrupt mask */
#define IMR_NORMAL_MASK (\
IMR_NORXTX_MASK |\
ISR_CMB_TX |\
ISR_CMB_RX)
/* Debug Interrupt Mask (enable all interrupt) */
#define IMR_DEBUG_MASK (\
ISR_SMB |\
ISR_TIMER |\
ISR_MANUAL |\
ISR_RXF_OV |\
ISR_RFD_UNRUN |\
ISR_RRD_OV |\
ISR_TXF_UNRUN |\
ISR_LINK |\
ISR_CMB_TX |\
ISR_CMB_RX |\
ISR_RX_PKT |\
ISR_TX_PKT |\
ISR_MAC_RX |\
ISR_MAC_TX)
#define MEDIA_TYPE_1000M_FULL 1
#define MEDIA_TYPE_100M_FULL 2
#define MEDIA_TYPE_100M_HALF 3
#define MEDIA_TYPE_10M_FULL 4
#define MEDIA_TYPE_10M_HALF 5
#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* All but 1000-Half */
#define MAX_JUMBO_FRAME_SIZE 10240
#define ATL1_EEDUMP_LEN 48
/* Statistics counters collected by the MAC */
struct stats_msg_block {
/* rx */
u32 rx_ok; /* good RX packets */
u32 rx_bcast; /* good RX broadcast packets */
u32 rx_mcast; /* good RX multicast packets */
u32 rx_pause; /* RX pause frames */
u32 rx_ctrl; /* RX control packets other than pause frames */
u32 rx_fcs_err; /* RX packets with bad FCS */
u32 rx_len_err; /* RX packets with length != actual size */
u32 rx_byte_cnt; /* good bytes received. FCS is NOT included */
u32 rx_runt; /* RX packets < 64 bytes with good FCS */
u32 rx_frag; /* RX packets < 64 bytes with bad FCS */
u32 rx_sz_64; /* 64 byte RX packets */
u32 rx_sz_65_127;
u32 rx_sz_128_255;
u32 rx_sz_256_511;
u32 rx_sz_512_1023;
u32 rx_sz_1024_1518;
u32 rx_sz_1519_max; /* 1519 byte to MTU RX packets */
u32 rx_sz_ov; /* truncated RX packets > MTU */
u32 rx_rxf_ov; /* frames dropped due to RX FIFO overflow */
u32 rx_rrd_ov; /* frames dropped due to RRD overflow */
u32 rx_align_err; /* alignment errors */
u32 rx_bcast_byte_cnt; /* RX broadcast bytes, excluding FCS */
u32 rx_mcast_byte_cnt; /* RX multicast bytes, excluding FCS */
u32 rx_err_addr; /* packets dropped due to address filtering */
/* tx */
u32 tx_ok; /* good TX packets */
u32 tx_bcast; /* good TX broadcast packets */
u32 tx_mcast; /* good TX multicast packets */
u32 tx_pause; /* TX pause frames */
u32 tx_exc_defer; /* TX packets deferred excessively */
u32 tx_ctrl; /* TX control frames, excluding pause frames */
u32 tx_defer; /* TX packets deferred */
u32 tx_byte_cnt; /* bytes transmitted, FCS is NOT included */
u32 tx_sz_64; /* 64 byte TX packets */
u32 tx_sz_65_127;
u32 tx_sz_128_255;
u32 tx_sz_256_511;
u32 tx_sz_512_1023;
u32 tx_sz_1024_1518;
u32 tx_sz_1519_max; /* 1519 byte to MTU TX packets */
u32 tx_1_col; /* packets TX after a single collision */
u32 tx_2_col; /* packets TX after multiple collisions */
u32 tx_late_col; /* TX packets with late collisions */
u32 tx_abort_col; /* TX packets aborted w/excessive collisions */
u32 tx_underrun; /* TX packets aborted due to TX FIFO underrun
* or TRD FIFO underrun */
u32 tx_rd_eop; /* reads beyond the EOP into the next frame
* when TRD was not written timely */
u32 tx_len_err; /* TX packets where length != actual size */
u32 tx_trunc; /* TX packets truncated due to size > MTU */
u32 tx_bcast_byte; /* broadcast bytes transmitted, excluding FCS */
u32 tx_mcast_byte; /* multicast bytes transmitted, excluding FCS */
u32 smb_updated; /* 1: SMB Updated. This is used by software to
* indicate the statistics update. Software
* should clear this bit after retrieving the
* statistics information. */
};
/* Coalescing Message Block */
struct coals_msg_block {
u32 int_stats; /* interrupt status */
u16 rrd_prod_idx; /* TRD Producer Index. */
u16 rfd_cons_idx; /* RFD Consumer Index. */
u16 update; /* Selene sets this bit every time it DMAs the
* CMB to host memory. Software should clear
* this bit when CMB info is processed. */
u16 tpd_cons_idx; /* TPD Consumer Index. */
};
/* RRD descriptor */
struct rx_return_desc {
u8 num_buf; /* Number of RFD buffers used by the received packet */
u8 resved;
u16 buf_indx; /* RFD Index of the first buffer */
union {
u32 valid;
struct {
u16 rx_chksum;
u16 pkt_size;
} xsum_sz;
} xsz;
u16 pkt_flg; /* Packet flags */
u16 err_flg; /* Error flags */
u16 resved2;
u16 vlan_tag; /* VLAN TAG */
};
#define PACKET_FLAG_ETH_TYPE 0x0080
#define PACKET_FLAG_VLAN_INS 0x0100
#define PACKET_FLAG_ERR 0x0200
#define PACKET_FLAG_IPV4 0x0400
#define PACKET_FLAG_UDP 0x0800
#define PACKET_FLAG_TCP 0x1000
#define PACKET_FLAG_BCAST 0x2000
#define PACKET_FLAG_MCAST 0x4000
#define PACKET_FLAG_PAUSE 0x8000
#define ERR_FLAG_CRC 0x0001
#define ERR_FLAG_CODE 0x0002
#define ERR_FLAG_DRIBBLE 0x0004
#define ERR_FLAG_RUNT 0x0008
#define ERR_FLAG_OV 0x0010
#define ERR_FLAG_TRUNC 0x0020
#define ERR_FLAG_IP_CHKSUM 0x0040
#define ERR_FLAG_L4_CHKSUM 0x0080
#define ERR_FLAG_LEN 0x0100
#define ERR_FLAG_DES_ADDR 0x0200
/* RFD descriptor */
struct rx_free_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
__le16 buf_len; /* Size of the receive buffer in host memory */
u16 coalese; /* Update consumer index to host after the
* reception of this frame */
/* __packed is required */
} __packed;
/*
* The L1 transmit packet descriptor is comprised of four 32-bit words.
*
* 31 0
* +---------------------------------------+
* | Word 0: Buffer addr lo |
* +---------------------------------------+
* | Word 1: Buffer addr hi |
* +---------------------------------------+
* | Word 2 |
* +---------------------------------------+
* | Word 3 |
* +---------------------------------------+
*
* Words 0 and 1 combine to form a 64-bit buffer address.
*
* Word 2 is self explanatory in the #define block below.
*
* Word 3 has two forms, depending upon the state of bits 3 and 4.
* If bits 3 and 4 are both zero, then bits 14:31 are unused by the
* hardware. Otherwise, if either bit 3 or 4 is set, the definition
* of bits 14:31 vary according to the following depiction.
*
* 0 End of packet 0 End of packet
* 1 Coalesce 1 Coalesce
* 2 Insert VLAN tag 2 Insert VLAN tag
* 3 Custom csum enable = 0 3 Custom csum enable = 1
* 4 Segment enable = 1 4 Segment enable = 0
* 5 Generate IP checksum 5 Generate IP checksum
* 6 Generate TCP checksum 6 Generate TCP checksum
* 7 Generate UDP checksum 7 Generate UDP checksum
* 8 VLAN tagged 8 VLAN tagged
* 9 Ethernet frame type 9 Ethernet frame type
* 10-+ 10-+
* 11 | IP hdr length (10:13) 11 | IP hdr length (10:13)
* 12 | (num 32-bit words) 12 | (num 32-bit words)
* 13-+ 13-+
* 14-+ 14 Unused
* 15 | TCP hdr length (14:17) 15 Unused
* 16 | (num 32-bit words) 16-+
* 17-+ 17 |
* 18 Header TPD flag 18 |
* 19-+ 19 | Payload offset
* 20 | 20 | (16:23)
* 21 | 21 |
* 22 | 22 |
* 23 | 23-+
* 24 | 24-+
* 25 | MSS (19:31) 25 |
* 26 | 26 |
* 27 | 27 | Custom csum offset
* 28 | 28 | (24:31)
* 29 | 29 |
* 30 | 30 |
* 31-+ 31-+
*/
/* tpd word 2 */
#define TPD_BUFLEN_MASK 0x3FFF
#define TPD_BUFLEN_SHIFT 0
#define TPD_DMAINT_MASK 0x0001
#define TPD_DMAINT_SHIFT 14
#define TPD_PKTNT_MASK 0x0001
#define TPD_PKTINT_SHIFT 15
#define TPD_VLANTAG_MASK 0xFFFF
#define TPD_VLANTAG_SHIFT 16
/* tpd word 3 bits 0:13 */
#define TPD_EOP_MASK 0x0001
#define TPD_EOP_SHIFT 0
#define TPD_COALESCE_MASK 0x0001
#define TPD_COALESCE_SHIFT 1
#define TPD_INS_VL_TAG_MASK 0x0001
#define TPD_INS_VL_TAG_SHIFT 2
#define TPD_CUST_CSUM_EN_MASK 0x0001
#define TPD_CUST_CSUM_EN_SHIFT 3
#define TPD_SEGMENT_EN_MASK 0x0001
#define TPD_SEGMENT_EN_SHIFT 4
#define TPD_IP_CSUM_MASK 0x0001
#define TPD_IP_CSUM_SHIFT 5
#define TPD_TCP_CSUM_MASK 0x0001
#define TPD_TCP_CSUM_SHIFT 6
#define TPD_UDP_CSUM_MASK 0x0001
#define TPD_UDP_CSUM_SHIFT 7
#define TPD_VL_TAGGED_MASK 0x0001
#define TPD_VL_TAGGED_SHIFT 8
#define TPD_ETHTYPE_MASK 0x0001
#define TPD_ETHTYPE_SHIFT 9
#define TPD_IPHL_MASK 0x000F
#define TPD_IPHL_SHIFT 10
/* tpd word 3 bits 14:31 if segment enabled */
#define TPD_TCPHDRLEN_MASK 0x000F
#define TPD_TCPHDRLEN_SHIFT 14
#define TPD_HDRFLAG_MASK 0x0001
#define TPD_HDRFLAG_SHIFT 18
#define TPD_MSS_MASK 0x1FFF
#define TPD_MSS_SHIFT 19
/* tpd word 3 bits 16:31 if custom csum enabled */
#define TPD_PLOADOFFSET_MASK 0x00FF
#define TPD_PLOADOFFSET_SHIFT 16
#define TPD_CCSUMOFFSET_MASK 0x00FF
#define TPD_CCSUMOFFSET_SHIFT 24
struct tx_packet_desc {
__le64 buffer_addr;
__le32 word2;
__le32 word3;
};
/* DMA Order Settings */
enum atl1_dma_order {
atl1_dma_ord_in = 1,
atl1_dma_ord_enh = 2,
atl1_dma_ord_out = 4
};
enum atl1_dma_rcb {
atl1_rcb_64 = 0,
atl1_rcb_128 = 1
};
enum atl1_dma_req_block {
atl1_dma_req_128 = 0,
atl1_dma_req_256 = 1,
atl1_dma_req_512 = 2,
atl1_dma_req_1024 = 3,
atl1_dma_req_2048 = 4,
atl1_dma_req_4096 = 5
};
#define ATL1_MAX_INTR 3
#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */
#define ATL1_DEFAULT_TPD 256
#define ATL1_MAX_TPD 1024
#define ATL1_MIN_TPD 64
#define ATL1_DEFAULT_RFD 512
#define ATL1_MIN_RFD 128
#define ATL1_MAX_RFD 2048
#define ATL1_REG_COUNT 1538
#define ATL1_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
#define ATL1_RFD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_free_desc)
#define ATL1_TPD_DESC(R, i) ATL1_GET_DESC(R, i, struct tx_packet_desc)
#define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc)
/*
* atl1_ring_header represents a single, contiguous block of DMA space
* mapped for the three descriptor rings (tpd, rfd, rrd) and the two
* message blocks (cmb, smb) described below
*/
struct atl1_ring_header {
void *desc; /* virtual address */
dma_addr_t dma; /* physical address*/
unsigned int size; /* length in bytes */
};
/*
* atl1_buffer is wrapper around a pointer to a socket buffer
* so a DMA handle can be stored along with the skb
*/
struct atl1_buffer {
struct sk_buff *skb; /* socket buffer */
u16 length; /* rx buffer length */
u16 alloced; /* 1 if skb allocated */
dma_addr_t dma;
};
/* transmit packet descriptor (tpd) ring */
struct atl1_tpd_ring {
void *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
u16 size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
u16 hw_idx; /* hardware index */
atomic_t next_to_clean;
atomic_t next_to_use;
struct atl1_buffer *buffer_info;
};
/* receive free descriptor (rfd) ring */
struct atl1_rfd_ring {
void *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
u16 size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
atomic_t next_to_use;
u16 next_to_clean;
struct atl1_buffer *buffer_info;
};
/* receive return descriptor (rrd) ring */
struct atl1_rrd_ring {
void *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
unsigned int size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
u16 next_to_use;
atomic_t next_to_clean;
};
/* coalescing message block (cmb) */
struct atl1_cmb {
struct coals_msg_block *cmb;
dma_addr_t dma;
};
/* statistics message block (smb) */
struct atl1_smb {
struct stats_msg_block *smb;
dma_addr_t dma;
};
/* Statistics counters */
struct atl1_sft_stats {
u64 rx_packets;
u64 tx_packets;
u64 rx_bytes;
u64 tx_bytes;
u64 multicast;
u64 collisions;
u64 rx_errors;
u64 rx_length_errors;
u64 rx_crc_errors;
u64 rx_dropped;
u64 rx_frame_errors;
u64 rx_fifo_errors;
u64 rx_missed_errors;
u64 tx_errors;
u64 tx_fifo_errors;
u64 tx_aborted_errors;
u64 tx_window_errors;
u64 tx_carrier_errors;
u64 tx_pause; /* TX pause frames */
u64 excecol; /* TX packets w/ excessive collisions */
u64 deffer; /* TX packets deferred */
u64 scc; /* packets TX after a single collision */
u64 mcc; /* packets TX after multiple collisions */
u64 latecol; /* TX packets w/ late collisions */
u64 tx_underun; /* TX packets aborted due to TX FIFO underrun
* or TRD FIFO underrun */
u64 tx_trunc; /* TX packets truncated due to size > MTU */
u64 rx_pause; /* num Pause packets received. */
u64 rx_rrd_ov;
u64 rx_trunc;
};
/* hardware structure */
struct atl1_hw {
u8 __iomem *hw_addr;
struct atl1_adapter *back;
enum atl1_dma_order dma_ord;
enum atl1_dma_rcb rcb_value;
enum atl1_dma_req_block dmar_block;
enum atl1_dma_req_block dmaw_block;
u8 preamble_len;
u8 max_retry;
u8 jam_ipg; /* IPG to start JAM for collision based flow
* control in half-duplex mode. In units 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
* receive frames. Frame gap below such IFP
* is dropped */
u8 ipgr1; /* 64bit Carrier-Sense window */
u8 ipgr2; /* 96-bit IPG window */
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned
* burst. Each TPD is 16 bytes long */
u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned
* burst. Each RFD is 12 bytes long */
u8 rfd_fetch_gap;
u8 rrd_burst; /* Threshold number of RRDs that can be retired
* in a burst. Each RRD is 16 bytes long */
u8 tpd_fetch_th;
u8 tpd_fetch_gap;
u16 tx_jumbo_task_th;
u16 txf_burst; /* Number of data bytes to read in a cache-
* aligned burst. Each SRAM entry is 8 bytes */
u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN
* packets should add 4 bytes */
u16 rx_jumbo_lkah;
u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after
* every 512ns passes. */
u16 lcol; /* Collision Window */
u16 cmb_tpd;
u16 cmb_rrd;
u16 cmb_rx_timer;
u16 cmb_tx_timer;
u32 smb_timer;
u16 media_type;
u16 autoneg_advertised;
u16 mii_autoneg_adv_reg;
u16 mii_1000t_ctrl_reg;
u32 max_frame_size;
u32 min_frame_size;
u16 dev_rev;
/* spi flash */
u8 flash_vendor;
u8 mac_addr[ETH_ALEN];
u8 perm_mac_addr[ETH_ALEN];
bool phy_configured;
};
struct atl1_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
struct atl1_sft_stats soft_stats;
u32 rx_buffer_len;
u32 wol;
u16 link_speed;
u16 link_duplex;
spinlock_t lock;
struct napi_struct napi;
struct work_struct reset_dev_task;
struct work_struct link_chg_task;
struct timer_list phy_config_timer;
bool phy_timer_pending;
/* all descriptor rings' memory */
struct atl1_ring_header ring_header;
/* TX */
struct atl1_tpd_ring tpd_ring;
spinlock_t mb_lock;
/* RX */
struct atl1_rfd_ring rfd_ring;
struct atl1_rrd_ring rrd_ring;
u64 hw_csum_err;
u64 hw_csum_good;
u32 msg_enable;
u16 imt; /* interrupt moderator timer (2us resolution) */
u16 ict; /* interrupt clear timer (2us resolution */
struct mii_if_info mii; /* MII interface info */
/*
* Use this value to check is napi handler allowed to
* enable ints or not
*/
bool int_enabled;
u32 bd_number; /* board number */
bool pci_using_64;
struct atl1_hw hw;
struct atl1_smb smb;
struct atl1_cmb cmb;
};
#endif /* ATL1_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,524 @@
/* atl2.h -- atl2 driver definitions
*
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
* Copyright(c) 2006 xiong huang <xiong.huang@atheros.com>
* Copyright(c) 2007 Chris Snook <csnook@redhat.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.
*/
#ifndef _ATL2_H_
#define _ATL2_H_
#include <linux/atomic.h>
#include <linux/netdevice.h>
#ifndef _ATL2_HW_H_
#define _ATL2_HW_H_
#ifndef _ATL2_OSDEP_H_
#define _ATL2_OSDEP_H_
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include "atlx.h"
#ifdef ETHTOOL_OPS_COMPAT
int ethtool_ioctl(struct ifreq *ifr);
#endif
#define PCI_COMMAND_REGISTER PCI_COMMAND
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
#define ATL2_WRITE_REG(a, reg, value) (iowrite32((value), \
((a)->hw_addr + (reg))))
#define ATL2_WRITE_FLUSH(a) (ioread32((a)->hw_addr))
#define ATL2_READ_REG(a, reg) (ioread32((a)->hw_addr + (reg)))
#define ATL2_WRITE_REGB(a, reg, value) (iowrite8((value), \
((a)->hw_addr + (reg))))
#define ATL2_READ_REGB(a, reg) (ioread8((a)->hw_addr + (reg)))
#define ATL2_WRITE_REGW(a, reg, value) (iowrite16((value), \
((a)->hw_addr + (reg))))
#define ATL2_READ_REGW(a, reg) (ioread16((a)->hw_addr + (reg)))
#define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \
(iowrite32((value), (((a)->hw_addr + (reg)) + ((offset) << 2))))
#define ATL2_READ_REG_ARRAY(a, reg, offset) \
(ioread32(((a)->hw_addr + (reg)) + ((offset) << 2)))
#endif /* _ATL2_OSDEP_H_ */
struct atl2_adapter;
struct atl2_hw;
/* function prototype */
static s32 atl2_reset_hw(struct atl2_hw *hw);
static s32 atl2_read_mac_addr(struct atl2_hw *hw);
static s32 atl2_init_hw(struct atl2_hw *hw);
static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,
u16 *duplex);
static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr);
static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value);
static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data);
static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data);
static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);
static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);
static void atl2_set_mac_addr(struct atl2_hw *hw);
static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue);
static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value);
static s32 atl2_phy_init(struct atl2_hw *hw);
static int atl2_check_eeprom_exist(struct atl2_hw *hw);
static void atl2_force_ps(struct atl2_hw *hw);
/* register definition */
/* Block IDLE Status Register */
#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC is non-IDLE */
#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC is non-IDLE */
#define IDLE_STATUS_DMAR 8 /* 1: DMAR is non-IDLE */
#define IDLE_STATUS_DMAW 4 /* 1: DMAW is non-IDLE */
/* MDIO Control Register */
#define MDIO_WAIT_TIMES 10
/* MAC Control Register */
#define MAC_CTRL_DBG_TX_BKPRESURE 0x100000 /* 1: TX max backoff */
#define MAC_CTRL_MACLP_CLK_PHY 0x8000000 /* 1: 25MHz from phy */
#define MAC_CTRL_HALF_LEFT_BUF_SHIFT 28
#define MAC_CTRL_HALF_LEFT_BUF_MASK 0xF /* MAC retry buf x32B */
/* 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 */
/* Descriptor Control register */
#define REG_TXD_BASE_ADDR_LO 0x1544 /* The base address of the Transmit
* Data Mem 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 */
#define REG_PAUSE_OFF_TH 0x15AA /* RXD lower watermark of overflow
* threshold configuration register */
/* 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 ISR_TIMER 1 /* Interrupt when Timer counts 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 full
* 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_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_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)
#define IMR_NORMAL_MASK (\
/*ISR_LINK_CHG |*/\
ISR_MANUAL |\
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 /* Num pause packets received */
#define REG_STS_RXD_OV 0x1704 /* Num frames dropped due to RX
* FIFO overflow */
#define REG_STS_RXS_OV 0x1708 /* Num frames dropped due to RX
* Status Buffer Overflow */
#define REG_STS_RX_FILTER 0x170C /* Num packets dropped due to
* address filtering */
/* MII definitions */
/* PHY Common Register */
#define MII_SMARTSPEED 0x14
#define MII_DBG_ADDR 0x1D
#define MII_DBG_DATA 0x1E
/* PCI Command Register Bit Definitions */
#define PCI_REG_COMMAND 0x04
#define CMD_IO_SPACE 0x0001
#define CMD_MEMORY_SPACE 0x0002
#define CMD_BUS_MASTER 0x0004
#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 AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */
/* 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
struct tx_pkt_header {
unsigned pkt_size:11;
unsigned:4; /* reserved */
unsigned ins_vlan:1; /* txmac should insert vlan */
unsigned short vlan; /* vlan tag */
};
/* FIXME: replace above bitfields with MASK/SHIFT defines below */
#define TX_PKT_HEADER_SIZE_MASK 0x7FF
#define TX_PKT_HEADER_SIZE_SHIFT 0
#define TX_PKT_HEADER_INS_VLAN_MASK 0x1
#define TX_PKT_HEADER_INS_VLAN_SHIFT 15
#define TX_PKT_HEADER_VLAN_TAG_MASK 0xFFFF
#define TX_PKT_HEADER_VLAN_TAG_SHIFT 16
struct tx_pkt_status {
unsigned pkt_size:11;
unsigned:5; /* reserved */
unsigned ok:1; /* current packet transmitted without error */
unsigned bcast:1; /* broadcast packet */
unsigned mcast:1; /* multicast packet */
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 aborted
* due to txram underrun */
unsigned:3; /* reserved */
unsigned update:1; /* always 1'b1 in tx_status_buf */
};
/* FIXME: replace above bitfields with MASK/SHIFT defines below */
#define TX_PKT_STATUS_SIZE_MASK 0x7FF
#define TX_PKT_STATUS_SIZE_SHIFT 0
#define TX_PKT_STATUS_OK_MASK 0x1
#define TX_PKT_STATUS_OK_SHIFT 16
#define TX_PKT_STATUS_BCAST_MASK 0x1
#define TX_PKT_STATUS_BCAST_SHIFT 17
#define TX_PKT_STATUS_MCAST_MASK 0x1
#define TX_PKT_STATUS_MCAST_SHIFT 18
#define TX_PKT_STATUS_PAUSE_MASK 0x1
#define TX_PKT_STATUS_PAUSE_SHIFT 19
#define TX_PKT_STATUS_CTRL_MASK 0x1
#define TX_PKT_STATUS_CTRL_SHIFT 20
#define TX_PKT_STATUS_DEFER_MASK 0x1
#define TX_PKT_STATUS_DEFER_SHIFT 21
#define TX_PKT_STATUS_EXC_DEFER_MASK 0x1
#define TX_PKT_STATUS_EXC_DEFER_SHIFT 22
#define TX_PKT_STATUS_SINGLE_COL_MASK 0x1
#define TX_PKT_STATUS_SINGLE_COL_SHIFT 23
#define TX_PKT_STATUS_MULTI_COL_MASK 0x1
#define TX_PKT_STATUS_MULTI_COL_SHIFT 24
#define TX_PKT_STATUS_LATE_COL_MASK 0x1
#define TX_PKT_STATUS_LATE_COL_SHIFT 25
#define TX_PKT_STATUS_ABORT_COL_MASK 0x1
#define TX_PKT_STATUS_ABORT_COL_SHIFT 26
#define TX_PKT_STATUS_UNDERRUN_MASK 0x1
#define TX_PKT_STATUS_UNDERRUN_SHIFT 27
#define TX_PKT_STATUS_UPDATE_MASK 0x1
#define TX_PKT_STATUS_UPDATE_SHIFT 31
struct rx_pkt_status {
unsigned pkt_size:11; /* packet size, max 2047 bytes */
unsigned:5; /* reserved */
unsigned ok:1; /* current packet 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 64 bytes
* with good crc */
unsigned frag:1; /* received a packet less than 64 bytes
* with bad crc */
unsigned trunc:1; /* current frame truncated 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;
};
/* FIXME: replace above bitfields with MASK/SHIFT defines below */
#define RX_PKT_STATUS_SIZE_MASK 0x7FF
#define RX_PKT_STATUS_SIZE_SHIFT 0
#define RX_PKT_STATUS_OK_MASK 0x1
#define RX_PKT_STATUS_OK_SHIFT 16
#define RX_PKT_STATUS_BCAST_MASK 0x1
#define RX_PKT_STATUS_BCAST_SHIFT 17
#define RX_PKT_STATUS_MCAST_MASK 0x1
#define RX_PKT_STATUS_MCAST_SHIFT 18
#define RX_PKT_STATUS_PAUSE_MASK 0x1
#define RX_PKT_STATUS_PAUSE_SHIFT 19
#define RX_PKT_STATUS_CTRL_MASK 0x1
#define RX_PKT_STATUS_CTRL_SHIFT 20
#define RX_PKT_STATUS_CRC_MASK 0x1
#define RX_PKT_STATUS_CRC_SHIFT 21
#define RX_PKT_STATUS_CODE_MASK 0x1
#define RX_PKT_STATUS_CODE_SHIFT 22
#define RX_PKT_STATUS_RUNT_MASK 0x1
#define RX_PKT_STATUS_RUNT_SHIFT 23
#define RX_PKT_STATUS_FRAG_MASK 0x1
#define RX_PKT_STATUS_FRAG_SHIFT 24
#define RX_PKT_STATUS_TRUNK_MASK 0x1
#define RX_PKT_STATUS_TRUNK_SHIFT 25
#define RX_PKT_STATUS_ALIGN_MASK 0x1
#define RX_PKT_STATUS_ALIGN_SHIFT 26
#define RX_PKT_STATUS_VLAN_MASK 0x1
#define RX_PKT_STATUS_VLAN_SHIFT 27
#define RX_PKT_STATUS_UPDATE_MASK 0x1
#define RX_PKT_STATUS_UPDATE_SHIFT 31
#define RX_PKT_STATUS_VLAN_TAG_MASK 0xFFFF
#define RX_PKT_STATUS_VLAN_TAG_SHIFT 32
struct rx_desc {
struct rx_pkt_status status;
unsigned char packet[1536-sizeof(struct rx_pkt_status)];
};
enum atl2_speed_duplex {
atl2_10_half = 0,
atl2_10_full = 1,
atl2_100_half = 2,
atl2_100_full = 3
};
struct atl2_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;
};
/* Structure containing variables used by the shared code (atl2_hw.c) */
struct atl2_hw {
u8 __iomem *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[ETH_ALEN];
u8 perm_mac_addr[ETH_ALEN];
/* FIXME */
/* bool phy_preamble_sup; */
bool phy_configured;
};
#endif /* _ATL2_HW_H_ */
struct atl2_ring_header {
/* pointer to the descriptor ring memory */
void *desc;
/* physical address of the descriptor ring */
dma_addr_t dma;
/* length of descriptor ring in bytes */
unsigned int size;
};
/* board specific private data structure */
struct atl2_adapter {
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
u32 wol;
u16 link_speed;
u16 link_duplex;
spinlock_t stats_lock;
struct work_struct reset_task;
struct work_struct link_chg_task;
struct timer_list watchdog_timer;
struct timer_list phy_config_timer;
unsigned long cfg_phy;
bool mac_disabled;
/* All Descriptor memory */
dma_addr_t ring_dma;
void *ring_vir_addr;
int ring_size;
struct tx_pkt_header *txd_ring;
dma_addr_t txd_dma;
struct tx_pkt_status *txs_ring;
dma_addr_t txs_dma;
struct rx_desc *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; /* 1536 bytes 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 atl2_hw.h */
u32 bd_number; /* board number */
bool pci_using_64;
bool have_msi;
struct atl2_hw hw;
u32 usr_cmd;
/* FIXME */
/* u32 regs_buff[ATL2_REGS_LEN]; */
u32 pci_state[16];
u32 *config_space;
};
enum atl2_state_t {
__ATL2_TESTING,
__ATL2_RESETTING,
__ATL2_DOWN
};
#endif /* _ATL2_H_ */

View file

@ -0,0 +1,279 @@
/* atlx.c -- common functions for Attansic network drivers
*
* Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
* Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
* Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*/
/* Including this file like a header is a temporary hack, I promise. -- CHS */
#ifndef ATLX_C
#define ATLX_C
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include "atlx.h"
static s32 atlx_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
static u32 atlx_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
static void atlx_set_mac_addr(struct atl1_hw *hw);
static struct atlx_spi_flash_dev flash_table[] = {
/* MFR_NAME WRSR READ PRGM WREN WRDI RDSR RDID SEC_ERS CHIP_ERS */
{"Atmel", 0x00, 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},
};
static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
switch (cmd) {
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
return atlx_mii_ioctl(netdev, ifr, cmd);
default:
return -EOPNOTSUPP;
}
}
/**
* atlx_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 atlx_set_mac(struct net_device *netdev, void *p)
{
struct atlx_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
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);
atlx_set_mac_addr(&adapter->hw);
return 0;
}
static void atlx_check_for_link(struct atlx_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
u16 phy_data = 0;
spin_lock(&adapter->lock);
adapter->phy_timer_pending = false;
atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
spin_unlock(&adapter->lock);
/* notify upper layer link down ASAP */
if (!(phy_data & BMSR_LSTATUS)) {
/* Link Down */
if (netif_carrier_ok(netdev)) {
/* old link state: Up */
dev_info(&adapter->pdev->dev, "%s link is down\n",
netdev->name);
adapter->link_speed = SPEED_0;
netif_carrier_off(netdev);
}
}
schedule_work(&adapter->link_chg_task);
}
/**
* atlx_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 atlx_set_multi(struct net_device *netdev)
{
struct atlx_adapter *adapter = netdev_priv(netdev);
struct atlx_hw *hw = &adapter->hw;
struct netdev_hw_addr *ha;
u32 rctl;
u32 hash_value;
/* Check for Promiscuous and All Multicast modes */
rctl = ioread32(hw->hw_addr + 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);
iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
/* clear the old settings from the multicast hash table */
iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
/* compute mc addresses' hash value ,and put it into hash table */
netdev_for_each_mc_addr(ha, netdev) {
hash_value = atlx_hash_mc_addr(hw, ha->addr);
atlx_hash_set(hw, hash_value);
}
}
static inline void atlx_imr_set(struct atlx_adapter *adapter,
unsigned int imr)
{
iowrite32(imr, adapter->hw.hw_addr + REG_IMR);
ioread32(adapter->hw.hw_addr + REG_IMR);
}
/**
* atlx_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
*/
static void atlx_irq_enable(struct atlx_adapter *adapter)
{
atlx_imr_set(adapter, IMR_NORMAL_MASK);
adapter->int_enabled = true;
}
/**
* atlx_irq_disable - Mask off interrupt generation on the NIC
* @adapter: board private structure
*/
static void atlx_irq_disable(struct atlx_adapter *adapter)
{
adapter->int_enabled = false;
atlx_imr_set(adapter, 0);
synchronize_irq(adapter->pdev->irq);
}
static void atlx_clear_phy_int(struct atlx_adapter *adapter)
{
u16 phy_data;
unsigned long flags;
spin_lock_irqsave(&adapter->lock, flags);
atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
spin_unlock_irqrestore(&adapter->lock, flags);
}
/**
* atlx_tx_timeout - Respond to a Tx Hang
* @netdev: network interface device structure
*/
static void atlx_tx_timeout(struct net_device *netdev)
{
struct atlx_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
schedule_work(&adapter->reset_dev_task);
}
/*
* atlx_link_chg_task - deal with link change event Out of interrupt context
*/
static void atlx_link_chg_task(struct work_struct *work)
{
struct atlx_adapter *adapter;
unsigned long flags;
adapter = container_of(work, struct atlx_adapter, link_chg_task);
spin_lock_irqsave(&adapter->lock, flags);
atlx_check_link(adapter);
spin_unlock_irqrestore(&adapter->lock, flags);
}
static void __atlx_vlan_mode(netdev_features_t features, u32 *ctrl)
{
if (features & NETIF_F_HW_VLAN_CTAG_RX) {
/* enable VLAN tag insert/strip */
*ctrl |= MAC_CTRL_RMV_VLAN;
} else {
/* disable VLAN tag insert/strip */
*ctrl &= ~MAC_CTRL_RMV_VLAN;
}
}
static void atlx_vlan_mode(struct net_device *netdev,
netdev_features_t features)
{
struct atlx_adapter *adapter = netdev_priv(netdev);
unsigned long flags;
u32 ctrl;
spin_lock_irqsave(&adapter->lock, flags);
/* atlx_irq_disable(adapter); FIXME: confirm/remove */
ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
__atlx_vlan_mode(features, &ctrl);
iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
/* atlx_irq_enable(adapter); FIXME */
spin_unlock_irqrestore(&adapter->lock, flags);
}
static void atlx_restore_vlan(struct atlx_adapter *adapter)
{
atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
}
static netdev_features_t atlx_fix_features(struct net_device *netdev,
netdev_features_t features)
{
/*
* Since there is no support for separate rx/tx vlan accel
* enable/disable make sure tx flag is always in same state as rx.
*/
if (features & NETIF_F_HW_VLAN_CTAG_RX)
features |= NETIF_F_HW_VLAN_CTAG_TX;
else
features &= ~NETIF_F_HW_VLAN_CTAG_TX;
return features;
}
static int atlx_set_features(struct net_device *netdev,
netdev_features_t features)
{
netdev_features_t changed = netdev->features ^ features;
if (changed & NETIF_F_HW_VLAN_CTAG_RX)
atlx_vlan_mode(netdev, features);
return 0;
}
#endif /* ATLX_C */

View file

@ -0,0 +1,502 @@
/* atlx_hw.h -- common hardware definitions for Attansic network drivers
*
* Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
* Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
* Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
* Copyright(c) 2007 Atheros Corporation. All rights reserved.
*
* 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.
*/
#ifndef ATLX_H
#define ATLX_H
#include <linux/module.h>
#include <linux/types.h>
#define ATLX_ERR_PHY 2
#define ATLX_ERR_PHY_SPEED 7
#define ATLX_ERR_PHY_RES 8
#define SPEED_0 0xffff
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define HALF_DUPLEX 1
#define FULL_DUPLEX 2
#define MEDIA_TYPE_AUTO_SENSOR 0
/* register definitions */
#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 0x7F
#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 /* FIXME: define or remove */
#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
#define REG_PCIE_DLL_TX_CTRL1 0x1104
#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK 0x400
#define PCIE_DLL_TX_CTRL1_DEF 0x568
#define REG_LTSSM_TEST_MODE 0x12FC
#define LTSSM_TEST_MODE_DEF 0x6500
/* 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 Moderator Timer Initial Value Register */
#define REG_IRQ_MODU_TIMER_INIT 0x1408
#define REG_PHY_ENABLE 0x140C
/* IRQ Anti-Lost Timer Initial Value Register */
#define REG_CMBDISDMA_TIMER 0x140E
/* Block IDLE Status Register */
#define REG_IDLE_STATUS 0x1410
/* MDIO Control Register */
#define REG_MDIO_CTRL 0x1414
#define MDIO_DATA_MASK 0xFFFF
#define MDIO_DATA_SHIFT 0
#define MDIO_REG_ADDR_MASK 0x1F
#define MDIO_REG_ADDR_SHIFT 16
#define MDIO_RW 0x200000
#define MDIO_SUP_PREAMBLE 0x400000
#define MDIO_START 0x800000
#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
/* MII PHY Status Register */
#define REG_PHY_STATUS 0x1418
/* BIST Control and Status Register0 (for the Packet Memory) */
#define REG_BIST0_CTRL 0x141C
#define BIST0_NOW 0x1
#define BIST0_SRAM_FAIL 0x2
#define BIST0_FUSE_FLAG 0x4
#define REG_BIST1_CTRL 0x1420
#define BIST1_NOW 0x1
#define BIST1_SRAM_FAIL 0x2
#define BIST1_FUSE_FLAG 0x4
/* SerDes Lock Detect Control and Status Register */
#define REG_SERDES_LOCK 0x1424
#define SERDES_LOCK_DETECT 1
#define SERDES_LOCK_DETECT_EN 2
/* MAC Control Register */
#define REG_MAC_CTRL 0x1480
#define MAC_CTRL_TX_EN 1
#define MAC_CTRL_RX_EN 2
#define MAC_CTRL_TX_FLOW 4
#define MAC_CTRL_RX_FLOW 8
#define MAC_CTRL_LOOPBACK 0x10
#define MAC_CTRL_DUPLX 0x20
#define MAC_CTRL_ADD_CRC 0x40
#define MAC_CTRL_PAD 0x80
#define MAC_CTRL_LENCHK 0x100
#define MAC_CTRL_HUGE_EN 0x200
#define MAC_CTRL_PRMLEN_SHIFT 10
#define MAC_CTRL_PRMLEN_MASK 0xF
#define MAC_CTRL_RMV_VLAN 0x4000
#define MAC_CTRL_PROMIS_EN 0x8000
#define MAC_CTRL_MC_ALL_EN 0x2000000
#define MAC_CTRL_BC_EN 0x4000000
/* MAC IPG/IFG Control Register */
#define REG_MAC_IPG_IFG 0x1484
#define MAC_IPG_IFG_IPGT_SHIFT 0
#define MAC_IPG_IFG_IPGT_MASK 0x7F
#define MAC_IPG_IFG_MIFG_SHIFT 8
#define MAC_IPG_IFG_MIFG_MASK 0xFF
#define MAC_IPG_IFG_IPGR1_SHIFT 16
#define MAC_IPG_IFG_IPGR1_MASK 0x7F
#define MAC_IPG_IFG_IPGR2_SHIFT 24
#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
#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3FF
#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xF
#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000
#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000
#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000
#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000
#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20
#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xF
#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24
#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xF
/* Maximum Frame Length Control Register */
#define REG_MTU 0x149C
/* Wake-On-Lan control register */
#define REG_WOL_CTRL 0x14A0
#define WOL_PATTERN_EN 0x1
#define WOL_PATTERN_PME_EN 0x2
#define WOL_MAGIC_EN 0x4
#define WOL_MAGIC_PME_EN 0x8
#define WOL_LINK_CHG_EN 0x10
#define WOL_LINK_CHG_PME_EN 0x20
#define WOL_PATTERN_ST 0x100
#define WOL_MAGIC_ST 0x200
#define WOL_LINKCHG_ST 0x400
#define WOL_PT0_EN 0x10000
#define WOL_PT1_EN 0x20000
#define WOL_PT2_EN 0x40000
#define WOL_PT3_EN 0x80000
#define WOL_PT4_EN 0x100000
#define WOL_PT0_MATCH 0x1000000
#define WOL_PT1_MATCH 0x2000000
#define WOL_PT2_MATCH 0x4000000
#define WOL_PT3_MATCH 0x8000000
#define WOL_PT4_MATCH 0x10000000
/* Internal SRAM Partition Register, high 32 bits */
#define REG_SRAM_RFD_ADDR 0x1500
/* Descriptor Control register, high 32 bits */
#define REG_DESC_BASE_ADDR_HI 0x1540
/* Interrupt Status Register */
#define REG_ISR 0x1600
#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
/* Interrupt Mask Register */
#define REG_IMR 0x1604
#define REG_RFD_RRD_IDX 0x1800
#define REG_TPD_IDX 0x1804
/* MII definitions */
/* PHY Common Register */
#define MII_ATLX_CR 0x09
#define MII_ATLX_SR 0x0A
#define MII_ATLX_ESR 0x0F
#define MII_ATLX_PSCR 0x10
#define MII_ATLX_PSSR 0x11
/* 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 /* Ext 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 stat 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 /* 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 Dir bit */
#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability support */
#define MII_AR_SPEED_MASK 0x01E0
#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
/* 1000BASE-T Control Register */
#define MII_ATLX_CR_1000T_HD_CAPS 0x0100 /* Adv 1000T HD cap */
#define MII_ATLX_CR_1000T_FD_CAPS 0x0200 /* Adv 1000T FD cap */
#define MII_ATLX_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device,
* 0=DTE device */
#define MII_ATLX_CR_1000T_MS_VALUE 0x0800 /* 1=Config PHY as Master,
* 0=Configure PHY as Slave */
#define MII_ATLX_CR_1000T_MS_ENABLE 0x1000 /* 1=Man Master/Slave config,
* 0=Auto Master/Slave config
*/
#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
#define MII_ATLX_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
#define MII_ATLX_CR_1000T_TEST_MODE_2 0x4000 /* Master Xmit Jitter test */
#define MII_ATLX_CR_1000T_TEST_MODE_3 0x6000 /* Slave Xmit Jitter test */
#define MII_ATLX_CR_1000T_TEST_MODE_4 0x8000 /* Xmitter Distortion test */
#define MII_ATLX_CR_1000T_SPEED_MASK 0x0300
#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK 0x0300
/* 1000BASE-T Status Register */
#define MII_ATLX_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
#define MII_ATLX_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
#define MII_ATLX_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master
* 0=Slave
*/
#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config
* fault */
#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
/* Extended Status Register */
#define MII_ATLX_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
#define MII_ATLX_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
#define MII_ATLX_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
#define MII_ATLX_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
/* ATLX PHY Specific Control Register */
#define MII_ATLX_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Func disabled */
#define MII_ATLX_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enbld */
#define MII_ATLX_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
#define MII_ATLX_PSCR_MAC_POWERDOWN 0x0008
#define MII_ATLX_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low
* 0=CLK125 toggling
*/
#define MII_ATLX_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5,
* Manual MDI configuration
*/
#define MII_ATLX_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
#define MII_ATLX_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover
* 100BASE-TX/10BASE-T: MDI
* Mode */
#define MII_ATLX_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
* all speeds.
*/
#define MII_ATLX_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_ATLX_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in
* 100BASE-TX
* 0=MII interface in
* 100BASE-TX
*/
#define MII_ATLX_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler dsbl */
#define MII_ATLX_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT 1
#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT 5
#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
/* ATLX PHY Specific Status Register */
#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
#define MII_ATLX_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
#define MII_ATLX_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
#define MII_ATLX_PSSR_10MBS 0x0000 /* 00=10Mbs */
#define MII_ATLX_PSSR_100MBS 0x4000 /* 01=100Mbs */
#define MII_ATLX_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
#define MII_DBG_ADDR 0x1D
#define MII_DBG_DATA 0x1E
/* 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 ATLX_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
#define ATLX_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
#define ATLX_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
#define ATLX_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
#define ATLX_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
#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
#define ADVERTISE_1000_FULL 0x0020
#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
#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
struct atlx_spi_flash_dev {
const char *manu_name; /* manufacturer id */
/* op-code */
u8 cmd_wrsr;
u8 cmd_read;
u8 cmd_program;
u8 cmd_wren;
u8 cmd_wrdi;
u8 cmd_rdsr;
u8 cmd_rdid;
u8 cmd_sector_erase;
u8 cmd_chip_erase;
};
#endif /* ATLX_H */