X-Git-Url: http://bbs.cooldavid.org/git/?p=jme.git;a=blobdiff_plain;f=jme.c;h=6020ecf7a5895c58bbeae5921df6e0d2c18473cb;hp=b07d889573c9334b0278de46bbbf5d56135c490f;hb=refs%2Fheads%2Fphyextest;hpb=e523cd894480dcd73a149f1333cff99510712629 diff --git a/jme.c b/jme.c index b07d889..6020ecf 100644 --- a/jme.c +++ b/jme.c @@ -111,6 +111,36 @@ jme_mdio_write(struct net_device *netdev, pr_err("phy(%d) write timeout : %d\n", phy, reg); } +static int +jme_phyext_read(struct jme_adapter *jme, int reg) +{ + jme_mdio_write(jme->dev, jme->mii_if.phy_id, + JME_PHY_SPEC_ADDR_REG, + JME_PHY_SPEC_REG_READ | (reg & 0x3FFF)); + return jme_mdio_read(jme->dev, jme->mii_if.phy_id, + JME_PHY_SPEC_DATA_REG); +} + +static void +jme_phyext_write(struct jme_adapter *jme, int reg, int val) +{ + jme_mdio_write(jme->dev, jme->mii_if.phy_id, + JME_PHY_SPEC_DATA_REG, val); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, + JME_PHY_SPEC_ADDR_REG, + JME_PHY_SPEC_REG_WRITE | (reg & 0x3FFF)); +} + +static void +jme_phyext_memcpy(struct jme_adapter *jme, u32 *p, int reg_nr) +{ + int i; + u16 *p16 = (u16 *)p; + + for (i = 0; i < reg_nr; ++i) + p16[i] = jme_phyext_read(jme, i); +} + static inline void jme_reset_phy_processor(struct jme_adapter *jme) { @@ -962,8 +992,34 @@ jme_disable_rx_engine(struct jme_adapter *jme) jme_mac_rxclk_off(jme); } +static u16 +jme_udpsum(struct sk_buff *skb) +{ + u16 csum = 0xFFFFu; + + if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) + return csum; + if (skb->protocol != htons(ETH_P_IP)) + return csum; + skb_set_network_header(skb, ETH_HLEN); + if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || + (skb->len < (ETH_HLEN + + (ip_hdr(skb)->ihl << 2) + + sizeof(struct udphdr)))) { + skb_reset_network_header(skb); + return csum; + } + skb_set_transport_header(skb, + ETH_HLEN + (ip_hdr(skb)->ihl << 2)); + csum = udp_hdr(skb)->check; + skb_reset_transport_header(skb); + skb_reset_network_header(skb); + + return csum; +} + static int -jme_rxsum_ok(struct jme_adapter *jme, u16 flags) +jme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb) { if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) return false; @@ -976,7 +1032,7 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags) } if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) - == RXWBFLAG_UDPON)) { + == RXWBFLAG_UDPON) && jme_udpsum(skb)) { if (flags & RXWBFLAG_IPV4) netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n"); return false; @@ -1024,7 +1080,7 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) skb_put(skb, framesize); skb->protocol = eth_type_trans(skb, jme->dev); - if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags))) + if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) skb->ip_summed = CHECKSUM_UNNECESSARY; else #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) @@ -1716,17 +1772,73 @@ jme_new_phy_off(struct jme_adapter *jme) pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg); } +static inline void +jme_recal_phy(struct jme_adapter *jme) +{ + u32 miictl1000, comm2; + + miictl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + miictl1000 &= ~JME_PHY_GCTRL_TESTMASK; + miictl1000 |= JME_PHY_GCTRL_TESTMODE1; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, miictl1000); + + comm2 = jme_phyext_read(jme, JME_PHYEXT_COMM2); + comm2 &= ~(0x0001u); + comm2 |= 0x0011u; + jme_phyext_write(jme, JME_PHYEXT_COMM2, comm2); + + mdelay(20); + + comm2 = jme_phyext_read(jme, JME_PHYEXT_COMM2); + comm2 &= ~(0x0013u); + jme_phyext_write(jme, JME_PHYEXT_COMM2, comm2); + + miictl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + miictl1000 &= ~JME_PHY_GCTRL_TESTMASK; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, miictl1000); +} + +static inline void +jme_refill_phyparm(struct jme_adapter *jme) +{ + if (jme->chip_main_rev >= 6 || + (jme->chip_main_rev == 5 && + (jme->chip_sub_rev == 0 || + jme->chip_sub_rev == 1 || + jme->chip_sub_rev == 3))) { + jme_phyext_write(jme, JME_PHYEXT_COMM0, 0x008Au); + jme_phyext_write(jme, JME_PHYEXT_COMM1, 0x4109u); + } else if (jme->chip_main_rev == 3 && + (jme->chip_sub_rev == 1 || + jme->chip_sub_rev == 2)) { + jme_phyext_write(jme, JME_PHYEXT_COMM0, 0xE088u); +// jme_phyext_write(jme, JME_PHYEXT_COMM1, 0x4108u); + } else if (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260 && + jme->chip_main_rev == 2) { + if (jme->chip_sub_rev == 0) { + jme_phyext_write(jme, JME_PHYEXT_COMM0, 0x608Au); +// jme_phyext_write(jme, JME_PHYEXT_COMM1, 0x4108u); + } else if (jme->chip_sub_rev == 2) { + jme_phyext_write(jme, JME_PHYEXT_COMM0, 0x408Au); +// jme_phyext_write(jme, JME_PHYEXT_COMM1, 0x4108u); + } + } +} + static inline void jme_phy_on(struct jme_adapter *jme) { u32 bmcr; + if (new_phy_power_ctrl(jme->chip_main_rev)) + jme_new_phy_on(jme); + bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); bmcr &= ~BMCR_PDOWN; jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); - if (new_phy_power_ctrl(jme->chip_main_rev)) - jme_new_phy_on(jme); + jme_recal_phy(jme); + jme_refill_phyparm(jme); } static inline void @@ -2427,6 +2539,9 @@ jme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) p32 += 0x100 >> 2; mdio_memcpy(jme, p32, JME_PHY_REG_NR); + + p32 += 0x100 >> 2; + jme_phyext_memcpy(jme, p32, JME_PHY_SPEC_REG_NR); } static int