*
* Copyright 2008 JMicron Technology Corporation
* http://www.jmicron.com/
+ * Copyright (c) 2009 - 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
*
* Author: Guo-Fu Tseng <cooldavid@cooldavid.org>
*
*/
#ifndef __JME_H_INCLUDED__
-#define __JME_H_INCLUDEE__
+#define __JME_H_INCLUDED__
+#include <linux/interrupt.h>
#define DRV_NAME "jme"
-#define DRV_VERSION "1.0"
+#define DRV_VERSION "1.0.8.2-jmmod"
#define PFX DRV_NAME ": "
#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
NETIF_MSG_TX_ERR | \
NETIF_MSG_HW)
-#define jeprintk(pdev, fmt, args...) \
- printk(KERN_ERR PFX fmt, ## args)
+#ifndef pr_err
+#define pr_err(fmt, arg...) \
+ printk(KERN_ERR fmt, ##arg)
+#endif
+#ifndef netdev_err
+#define netdev_err(netdev, fmt, arg...) \
+ pr_err(fmt, ##arg)
+#endif
#ifdef TX_DEBUG
-#define tx_dbg(priv, fmt, args...) \
- printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ## args)
+#define tx_dbg(priv, fmt, args...) \
+ printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args)
#else
-#define tx_dbg(priv, fmt, args...)
+#define tx_dbg(priv, fmt, args...) \
+do { \
+ if (0) \
+ printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args); \
+} while (0)
#endif
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33)
#define jme_msg(msglvl, type, priv, fmt, args...) \
if (netif_msg_##type(priv)) \
printk(msglvl "%s: " fmt, (priv)->dev->name, ## args)
#define msg_hw(priv, fmt, args...) \
jme_msg(KERN_ERR, hw, priv, fmt, ## args)
+#ifndef netif_info
+#define netif_info(priv, type, dev, fmt, args...) \
+ msg_ ## type(priv, fmt, ## args)
+#endif
+#ifndef netif_err
+#define netif_err(priv, type, dev, fmt, args...) \
+ msg_ ## type(priv, fmt, ## args)
+#endif
+#endif
+
+#ifndef NETIF_F_TSO6
+#define NETIF_F_TSO6 0
+#endif
+#ifndef NETIF_F_IPV6_CSUM
+#define NETIF_F_IPV6_CSUM 0
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
+#define __USE_NDO_FIX_FEATURES__
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
+#define __UNIFY_VLAN_RX_PATH__
+#endif
+
/*
* Extra PCI Configuration space interface
*/
#define HALF_US 500 /* 500 ns */
#define JMESPIIOCTL SIOCDEVPRIVATE
+#define PCI_PRIV_PE1 0xE4
+
+enum pci_priv_pe1_bit_masks {
+ PE1_ASPMSUPRT = 0x00000003, /*
+ * RW:
+ * Aspm_support[1:0]
+ * (R/W Port of 5C[11:10])
+ */
+ PE1_MULTIFUN = 0x00000004, /* RW: Multi_fun_bit */
+ PE1_RDYDMA = 0x00000008, /* RO: ~link.rdy_for_dma */
+ PE1_ASPMOPTL = 0x00000030, /* RW: link.rx10s_option[1:0] */
+ PE1_ASPMOPTH = 0x000000C0, /* RW: 10_req=[3]?HW:[2] */
+ PE1_GPREG0 = 0x0000FF00, /*
+ * SRW:
+ * Cfg_gp_reg0
+ * [7:6] phy_giga BG control
+ * [5] CREQ_N as CREQ_N1 (CPPE# as CREQ#)
+ * [4:0] Reserved
+ */
+ PE1_GPREG0_PBG = 0x0000C000, /* phy_giga BG control */
+ PE1_GPREG1 = 0x00FF0000, /* RW: Cfg_gp_reg1 */
+ PE1_REVID = 0xFF000000, /* RO: Rev ID */
+};
+
+enum pci_priv_pe1_values {
+ PE1_GPREG0_ENBG = 0x00000000, /* en BG */
+ PE1_GPREG0_PDD3COLD = 0x00004000, /* giga_PD + d3cold */
+ PE1_GPREG0_PDPCIESD = 0x00008000, /* giga_PD + pcie_shutdown */
+ PE1_GPREG0_PDPCIEIDDQ = 0x0000C000, /* giga_PD + pcie_iddq */
+};
+
/*
* Dynamic(adaptive)/Static PCC values
*/
};
#define TXDESC_MSS_SHIFT 2
-enum jme_rxdescwb_flags_bits {
+enum jme_txwbdesc_flags_bits {
TXWBFLAG_OWN = 0x80,
TXWBFLAG_INT = 0x40,
TXWBFLAG_TMOUT = 0x20,
/*
* The structure holding buffer information and ring descriptors all together.
*/
-#define MAX_RING_DESC_NR 1024
struct jme_ring {
void *alloc; /* pointer to allocated memory */
void *desc; /* pointer to ring memory */
dma_addr_t dma; /* phys address for ring dma */
/* Buffer information corresponding to each descriptor */
- struct jme_buffer_info bufinf[MAX_RING_DESC_NR];
+ struct jme_buffer_info *bufinf;
int next_to_use;
atomic_t next_to_clean;
atomic_t nr_free;
};
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
+#define false 0
+#define true 0
+#define netdev_alloc_skb(dev, len) dev_alloc_skb(len)
+#define PCI_VENDOR_ID_JMICRON 0x197B
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,19)
+#define PCI_VDEVICE(vendor, device) \
+ PCI_VENDOR_ID_##vendor, (device), \
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
+#define NET_STAT(priv) priv->stats
+#define NETDEV_GET_STATS(netdev, fun_ptr) \
+ netdev->get_stats = fun_ptr
+#define DECLARE_NET_DEVICE_STATS struct net_device_stats stats;
+/*
+ * CentOS 5.2 have *_hdr helpers back-ported
+ */
+#ifdef RHEL_RELEASE_CODE
+#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2)
+#define __DEFINE_IPHDR_HELPERS__
+#endif
+#else
+#define __DEFINE_IPHDR_HELPERS__
+#endif
+#else
#define NET_STAT(priv) (priv->dev->stats)
#define NETDEV_GET_STATS(netdev, fun_ptr)
#define DECLARE_NET_DEVICE_STATS
+#endif
+
+#ifdef __DEFINE_IPHDR_HELPERS__
+static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
+{
+ return skb->nh.iph;
+}
+
+static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
+{
+ return skb->nh.ipv6h;
+}
+
+static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb)
+{
+ return skb->h.th;
+}
+#endif
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
+#define DECLARE_NAPI_STRUCT
+#define NETIF_NAPI_SET(dev, napis, pollfn, q) \
+ dev->poll = pollfn; \
+ dev->weight = q;
+#define JME_NAPI_HOLDER(holder) struct net_device *holder
+#define JME_NAPI_WEIGHT(w) int *w
+#define JME_NAPI_WEIGHT_VAL(w) *w
+#define JME_NAPI_WEIGHT_SET(w, r) *w = r
+#define DECLARE_NETDEV struct net_device *netdev = jme->dev;
+#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev)
+#define JME_NAPI_ENABLE(priv) netif_poll_enable(priv->dev);
+#define JME_NAPI_DISABLE(priv) netif_poll_disable(priv->dev);
+#define JME_RX_SCHEDULE_PREP(priv) \
+ netif_rx_schedule_prep(priv->dev)
+#define JME_RX_SCHEDULE(priv) \
+ __netif_rx_schedule(priv->dev);
+#else
#define DECLARE_NAPI_STRUCT struct napi_struct napi;
#define NETIF_NAPI_SET(dev, napis, pollfn, q) \
netif_napi_add(dev, napis, pollfn, q);
#define JME_NAPI_WEIGHT(w) int w
#define JME_NAPI_WEIGHT_VAL(w) w
#define JME_NAPI_WEIGHT_SET(w, r)
-#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev, napis)
+#define DECLARE_NETDEV
+#define JME_RX_COMPLETE(dev, napis) napi_complete(napis)
#define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi);
#define JME_NAPI_DISABLE(priv) \
if (!napi_disable_pending(&priv->napi)) \
napi_disable(&priv->napi);
#define JME_RX_SCHEDULE_PREP(priv) \
- netif_rx_schedule_prep(priv->dev, &priv->napi)
+ napi_schedule_prep(&priv->napi)
#define JME_RX_SCHEDULE(priv) \
- __netif_rx_schedule(priv->dev, &priv->napi);
+ __napi_schedule(&priv->napi);
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)
+#define JME_NEW_PM_API
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,26)
+static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
+{
+ return ep->speed;
+}
+#endif
/*
* Jmac Adapter Private data
*/
-#define SHADOW_REG_NR 8
struct jme_adapter {
struct pci_dev *pdev;
struct net_device *dev;
void __iomem *regs;
- dma_addr_t shadow_dma;
- u32 *shadow_regs;
struct mii_if_info mii_if;
struct jme_ring rxring[RX_RING_NR];
struct jme_ring txring[TX_RING_NR];
u32 reg_rxmcs;
u32 reg_ghc;
u32 reg_pmcs;
+ u32 reg_gpreg1;
u32 phylink;
u32 tx_ring_size;
u32 tx_ring_mask;
u32 rx_ring_mask;
u8 mrrs;
unsigned int fpgaver;
- unsigned int chipver;
- u8 rev;
+ u8 chiprev;
+ u8 chip_main_rev;
+ u8 chip_sub_rev;
+ u8 pcirev;
u32 msg_enable;
struct ethtool_cmd old_ecmd;
unsigned int old_mtu;
+#ifndef __UNIFY_VLAN_RX_PATH__
struct vlan_group *vlgrp;
+#endif
struct dynpcc_info dpi;
atomic_t intr_sem;
atomic_t link_changing;
atomic_t rx_cleaning;
atomic_t rx_empty;
int (*jme_rx)(struct sk_buff *skb);
+#ifndef __UNIFY_VLAN_RX_PATH__
int (*jme_vlan_rx)(struct sk_buff *skb,
struct vlan_group *grp,
unsigned short vlan_tag);
+#endif
DECLARE_NAPI_STRUCT
DECLARE_NET_DEVICE_STATS
};
-enum shadow_reg_val {
- SHADOW_IEVE = 0,
-};
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
+static struct net_device_stats *
+jme_get_stats(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ return &jme->stats;
+}
+#endif
enum jme_flags_bits {
JME_FLAG_MSI = 1,
JME_FLAG_SSET = 2,
+#ifndef __USE_NDO_FIX_FEATURES__
JME_FLAG_TXCSUM = 3,
JME_FLAG_TSO = 4,
+#endif
JME_FLAG_POLL = 5,
JME_FLAG_SHUTDOWN = 6,
};
#define JME_REG_LEN 0x500
#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9216
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
+static inline struct jme_adapter*
+jme_napi_priv(struct net_device *holder)
+{
+ struct jme_adapter *jme;
+ jme = netdev_priv(holder);
+ return jme;
+}
+#else
static inline struct jme_adapter*
jme_napi_priv(struct napi_struct *napi)
{
jme = container_of(napi, struct jme_adapter, napi);
return jme;
}
+#endif
/*
* MMaped I/O Resters
JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */
+ JME_PHY_PWR = JME_PHY | 0x24, /* New PHY Power Ctrl Register */
JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */
JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */
JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */
TXTRHD_TXRL_SHIFT = 0,
};
+enum jme_txtrhd_values {
+ TXTRHD_FULLDUPLEX = 0x00000000,
+ TXTRHD_HALFDUPLEX = TXTRHD_TXPEN |
+ ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
+ TXTRHD_TXREN |
+ ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL),
+};
+
/*
* RX Control/Status Bits
*/
* Global Host Control
*/
enum jme_ghc_bit_mask {
- GHC_SWRST = 0x40000000,
- GHC_DPX = 0x00000040,
- GHC_SPEED = 0x00000030,
- GHC_LINK_POLL = 0x00000001,
+ GHC_SWRST = 0x40000000,
+ GHC_TO_CLK_SRC = 0x00C00000,
+ GHC_TXMAC_CLK_SRC = 0x00300000,
+ GHC_DPX = 0x00000040,
+ GHC_SPEED = 0x00000030,
+ GHC_LINK_POLL = 0x00000001,
};
enum jme_ghc_speed_val {
- GHC_SPEED_10M = 0x00000010,
- GHC_SPEED_100M = 0x00000020,
- GHC_SPEED_1000M = 0x00000030,
+ GHC_SPEED_10M = 0x00000010,
+ GHC_SPEED_100M = 0x00000020,
+ GHC_SPEED_1000M = 0x00000030,
+};
+
+enum jme_ghc_to_clk {
+ GHC_TO_CLK_OFF = 0x00000000,
+ GHC_TO_CLK_GPHY = 0x00400000,
+ GHC_TO_CLK_PCIE = 0x00800000,
+ GHC_TO_CLK_INVALID = 0x00C00000,
+};
+
+enum jme_ghc_txmac_clk {
+ GHC_TXMAC_CLK_OFF = 0x00000000,
+ GHC_TXMAC_CLK_GPHY = 0x00100000,
+ GHC_TXMAC_CLK_PCIE = 0x00200000,
+ GHC_TXMAC_CLK_INVALID = 0x00300000,
};
/*
* Power management control and status register
*/
enum jme_pmcs_bit_masks {
+ PMCS_STMASK = 0xFFFF0000,
PMCS_WF7DET = 0x80000000,
PMCS_WF6DET = 0x40000000,
PMCS_WF5DET = 0x20000000,
PMCS_LFDET = 0x00040000,
PMCS_LRDET = 0x00020000,
PMCS_MFDET = 0x00010000,
+ PMCS_ENMASK = 0x0000FFFF,
PMCS_WF7EN = 0x00008000,
PMCS_WF6EN = 0x00004000,
PMCS_WF5EN = 0x00002000,
PMCS_MFEN = 0x00000001,
};
+/*
+ * New PHY Power Control Register
+ */
+enum jme_phy_pwr_bit_masks {
+ PHY_PWR_DWN1SEL = 0x01000000, /* Phy_giga.p_PWR_DOWN1_SEL */
+ PHY_PWR_DWN1SW = 0x02000000, /* Phy_giga.p_PWR_DOWN1_SW */
+ PHY_PWR_DWN2 = 0x04000000, /* Phy_giga.p_PWR_DOWN2 */
+ PHY_PWR_CLKSEL = 0x08000000, /*
+ * XTL_OUT Clock select
+ * (an internal free-running clock)
+ * 0: xtl_out = phy_giga.A_XTL25_O
+ * 1: xtl_out = phy_giga.PD_OSC
+ */
+};
+
/*
* Giga PHY Status Registers
*/
GPREG0_PHYADDR_1,
};
+/*
+ * General Purpose REG-1
+ */
+enum jme_gpreg1_bit_masks {
+ GPREG1_RXCLKOFF = 0x04000000,
+ GPREG1_PCREQN = 0x00020000,
+ GPREG1_HALFMODEPATCH = 0x00000040, /* For Chip revision 0x11 only */
+ GPREG1_RSSPATCH = 0x00000020, /* For Chip revision 0x11 only */
+ GPREG1_INTRDELAYUNIT = 0x00000018,
+ GPREG1_INTRDELAYENABLE = 0x00000007,
+};
+
+enum jme_gpreg1_vals {
+ GPREG1_INTDLYUNIT_16NS = 0x00000000,
+ GPREG1_INTDLYUNIT_256NS = 0x00000008,
+ GPREG1_INTDLYUNIT_1US = 0x00000010,
+ GPREG1_INTDLYUNIT_16US = 0x00000018,
+
+ GPREG1_INTDLYEN_1U = 0x00000001,
+ GPREG1_INTDLYEN_2U = 0x00000002,
+ GPREG1_INTDLYEN_3U = 0x00000003,
+ GPREG1_INTDLYEN_4U = 0x00000004,
+ GPREG1_INTDLYEN_5U = 0x00000005,
+ GPREG1_INTDLYEN_6U = 0x00000006,
+ GPREG1_INTDLYEN_7U = 0x00000007,
+
+ GPREG1_DEFAULT = GPREG1_PCREQN,
+};
+
/*
* Interrupt Status Bits
*/
*/
enum jme_chipmode_bit_masks {
CM_FPGAVER_MASK = 0xFFFF0000,
- CM_CHIPVER_MASK = 0x0000FF00,
+ CM_CHIPREV_MASK = 0x0000FF00,
CM_CHIPMODE_MASK = 0x0000000F,
};
enum jme_chipmode_shifts {
CM_FPGAVER_SHIFT = 16,
- CM_CHIPVER_SHIFT = 8,
-};
-
-/*
- * Shadow base address register bits
- */
-enum jme_shadow_base_address_bits {
- SHBA_POSTEN = 0x1,
+ CM_CHIPREV_SHIFT = 8,
};
/*
"JME_RXMCHT_LO", "JME_RXMCHT_HI", "JME_WFODP", "JME_WFOI",
"JME_SMI", "JME_GHC", "UNKNOWN", "UNKNOWN",
"JME_PMCS"};
+
static char *PE_REG_NAME[] = {
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
"UNKNOWN", "UNKNOWN", "JME_PHY_CS", "UNKNOWN",
"JME_PHY_LINK", "UNKNOWN", "UNKNOWN", "UNKNOWN",
"JME_SMBCSR", "JME_SMBINTF"};
+
static char *MISC_REG_NAME[] = {
"JME_TMCSR", "JME_GPIO", "JME_GPREG0", "JME_GPREG1",
"JME_IEVE", "JME_IREQ", "JME_IENS", "JME_IENC",
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
"JME_TIMER1", "JME_TIMER2", "UNKNOWN", "JME_APMC",
"JME_PCCSRX0"};
+
static inline void reg_dbg(const struct jme_adapter *jme,
const char *msg, u32 val, u32 reg)
{
const char *regname;
- switch(reg & 0xF00) {
+ switch (reg & 0xF00) {
case 0x000:
regname = MAC_REG_NAME[(reg & 0xFF) >> 2];
break;
regname = PE_REG_NAME[(reg & 0xFF) >> 2];
break;
case 0x800:
- regname = MISC_REG_NAME[(reg & 0xFF) >>2];
+ regname = MISC_REG_NAME[(reg & 0xFF) >> 2];
break;
default:
regname = PE_REG_NAME[0];
#define BMSR_ANCOMP 0x0020
+/*
+ * Workaround
+ */
+static inline int is_buggy250(unsigned short device, u8 chiprev)
+{
+ return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
+}
+
+static inline int new_phy_power_ctrl(u8 chip_main_rev)
+{
+ return chip_main_rev >= 5;
+}
+
/*
* Function prototypes
*/
static int jme_set_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd);
+static void jme_set_unicastaddr(struct net_device *netdev);
static void jme_set_multi(struct net_device *netdev);
#endif
+