+static int
+jme_get_regs_len(struct net_device *netdev)
+{
+ return 0x400;
+}
+
+static void
+mmapio_memcpy(struct jme_adapter *jme, __u32 *p, __u32 reg, int len)
+{
+ int i;
+
+ for(i = 0 ; i < len ; i += 4)
+ p[i >> 2] = jread32(jme, reg + i);
+
+}
+
+static void
+jme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ __u32 *p32 = (__u32*)p;
+
+ memset(p, 0, 0x400);
+
+ regs->version = 1;
+ mmapio_memcpy(jme, p32, JME_MAC, JME_MAC_LEN);
+
+ p32 += 0x100 >> 2;
+ mmapio_memcpy(jme, p32, JME_PHY, JME_PHY_LEN);
+
+ p32 += 0x100 >> 2;
+ mmapio_memcpy(jme, p32, JME_MISC, JME_MISC_LEN);
+
+ p32 += 0x100 >> 2;
+ mmapio_memcpy(jme, p32, JME_RSS, JME_RSS_LEN);
+
+}
+
+static int
+jme_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ if(jme->flags & JME_FLAG_POLL)
+ ecmd->use_adaptive_rx_coalesce = false;
+ else
+ ecmd->use_adaptive_rx_coalesce = true;
+
+ ecmd->tx_coalesce_usecs = PCC_TX_TO;
+ ecmd->tx_max_coalesced_frames = PCC_TX_CNT;
+
+ switch(jme->dpi.cur) {
+ case PCC_P1:
+ ecmd->rx_coalesce_usecs = PCC_P1_TO;
+ ecmd->rx_max_coalesced_frames = PCC_P1_CNT;
+ break;
+ case PCC_P2:
+ ecmd->rx_coalesce_usecs = PCC_P2_TO;
+ ecmd->rx_max_coalesced_frames = PCC_P2_CNT;
+ break;
+ case PCC_P3:
+ ecmd->rx_coalesce_usecs = PCC_P3_TO;
+ ecmd->rx_max_coalesced_frames = PCC_P3_CNT;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int
+jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ struct dynpcc_info *dpi = &(jme->dpi);
+
+ if(ecmd->use_adaptive_rx_coalesce
+ && (jme->flags & JME_FLAG_POLL)) {
+ jme->flags &= ~JME_FLAG_POLL;
+ napi_disable(&jme->napi);
+ dpi->cur = PCC_P1;
+ dpi->attempt = PCC_P1;
+ dpi->cnt = 0;
+ jme_set_rx_pcc(jme, PCC_P1);
+ jme_interrupt_mode(jme);
+ }
+ else if(!(ecmd->use_adaptive_rx_coalesce)
+ && !(jme->flags & JME_FLAG_POLL)) {
+ jme->flags |= JME_FLAG_POLL;
+ napi_enable(&jme->napi);
+ jme_interrupt_mode(jme);
+ }
+
+ return 0;
+}
+
+static void
+jme_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ unsigned long flags;
+ __u32 val;
+
+ ecmd->tx_pause = (jme->reg_txpfc & TXPFC_PF_EN) != 0;
+ ecmd->rx_pause = (jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0;
+
+ spin_lock_irqsave(&jme->phy_lock, flags);
+ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ spin_unlock_irqrestore(&jme->phy_lock, flags);
+
+ ecmd->autoneg =
+ (val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0;
+}
+
+static int
+jme_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ unsigned long flags;
+ __u32 val;
+
+ if( ((jme->reg_txpfc & TXPFC_PF_EN) != 0) !=
+ (ecmd->tx_pause != 0)) {
+
+ if(ecmd->tx_pause)
+ jme->reg_txpfc |= TXPFC_PF_EN;
+ else
+ jme->reg_txpfc &= ~TXPFC_PF_EN;
+
+ jwrite32(jme, JME_TXPFC, jme->reg_txpfc);
+ }
+
+ spin_lock_irqsave(&jme->rxmcs_lock, flags);
+ if( ((jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0) !=
+ (ecmd->rx_pause != 0)) {
+
+ if(ecmd->rx_pause)
+ jme->reg_rxmcs |= RXMCS_FLOWCTRL;
+ else
+ jme->reg_rxmcs &= ~RXMCS_FLOWCTRL;
+
+ jwrite32(jme, JME_RXMCS, jme->reg_rxmcs);
+ }
+ spin_unlock_irqrestore(&jme->rxmcs_lock, flags);
+
+ spin_lock_irqsave(&jme->phy_lock, flags);
+ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ if( ((val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0) !=
+ (ecmd->autoneg != 0)) {
+
+ if(ecmd->autoneg)
+ val |= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+ else
+ val &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id,
+ MII_ADVERTISE, val);
+ }
+ spin_unlock_irqrestore(&jme->phy_lock, flags);
+
+ return 0;
+}
+
+static void
+jme_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ wol->supported = WAKE_MAGIC | WAKE_PHY;
+
+ wol->wolopts = 0;
+
+ if(jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
+ wol->wolopts |= WAKE_PHY;
+
+ if(jme->reg_pmcs & PMCS_MFEN)
+ wol->wolopts |= WAKE_MAGIC;
+
+}
+
+static int
+jme_set_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ if(wol->wolopts & (WAKE_MAGICSECURE |
+ WAKE_UCAST |
+ WAKE_MCAST |
+ WAKE_BCAST |
+ WAKE_ARP))
+ return -EOPNOTSUPP;
+
+ jme->reg_pmcs = 0;
+
+ if(wol->wolopts & WAKE_PHY)
+ jme->reg_pmcs |= PMCS_LFEN | PMCS_LREN;
+
+ if(wol->wolopts & WAKE_MAGIC)
+ jme->reg_pmcs |= PMCS_MFEN;
+
+
+ return 0;
+}
+
+static int
+jme_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)