Back to home page

OSCL-LXR

 
 

    


0001 /*
0002     drivers/net/ethernet/dec/tulip/pnic.c
0003 
0004     Copyright 2000,2001  The Linux Kernel Team
0005     Written/copyright 1994-2001 by Donald Becker.
0006 
0007     This software may be used and distributed according to the terms
0008     of the GNU General Public License, incorporated herein by reference.
0009 
0010     Please submit bugs to http://bugzilla.kernel.org/ .
0011 */
0012 
0013 #include <linux/interrupt.h>
0014 #include <linux/kernel.h>
0015 #include <linux/jiffies.h>
0016 #include "tulip.h"
0017 
0018 
0019 void pnic_do_nway(struct net_device *dev)
0020 {
0021     struct tulip_private *tp = netdev_priv(dev);
0022     void __iomem *ioaddr = tp->base_addr;
0023     u32 phy_reg = ioread32(ioaddr + 0xB8);
0024     u32 new_csr6;
0025 
0026     if (phy_reg & 0x78000000) { /* Ignore baseT4 */
0027         if (phy_reg & 0x20000000)       dev->if_port = 5;
0028         else if (phy_reg & 0x40000000)  dev->if_port = 3;
0029         else if (phy_reg & 0x10000000)  dev->if_port = 4;
0030         else if (phy_reg & 0x08000000)  dev->if_port = 0;
0031         tp->nwayset = 1;
0032         new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000;
0033         iowrite32(0x32 | (dev->if_port & 1), ioaddr + CSR12);
0034         if (dev->if_port & 1)
0035             iowrite32(0x1F868, ioaddr + 0xB8);
0036         if (phy_reg & 0x30000000) {
0037             tp->full_duplex = 1;
0038             new_csr6 |= 0x00000200;
0039         }
0040         if (tulip_debug > 1)
0041             netdev_dbg(dev, "PNIC autonegotiated status %08x, %s\n",
0042                    phy_reg, medianame[dev->if_port]);
0043         if (tp->csr6 != new_csr6) {
0044             tp->csr6 = new_csr6;
0045             /* Restart Tx */
0046             tulip_restart_rxtx(tp);
0047             netif_trans_update(dev);
0048         }
0049     }
0050 }
0051 
0052 void pnic_lnk_change(struct net_device *dev, int csr5)
0053 {
0054     struct tulip_private *tp = netdev_priv(dev);
0055     void __iomem *ioaddr = tp->base_addr;
0056     int phy_reg = ioread32(ioaddr + 0xB8);
0057 
0058     if (tulip_debug > 1)
0059         netdev_dbg(dev, "PNIC link changed state %08x, CSR5 %08x\n",
0060                phy_reg, csr5);
0061     if (ioread32(ioaddr + CSR5) & TPLnkFail) {
0062         iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
0063         /* If we use an external MII, then we mustn't use the
0064          * internal negotiation.
0065          */
0066         if (tulip_media_cap[dev->if_port] & MediaIsMII)
0067             return;
0068         if (! tp->nwayset || time_after(jiffies, dev_trans_start(dev) + 1*HZ)) {
0069             tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
0070             iowrite32(tp->csr6, ioaddr + CSR6);
0071             iowrite32(0x30, ioaddr + CSR12);
0072             iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
0073             netif_trans_update(dev);
0074         }
0075     } else if (ioread32(ioaddr + CSR5) & TPLnkPass) {
0076         if (tulip_media_cap[dev->if_port] & MediaIsMII) {
0077             spin_lock(&tp->lock);
0078             tulip_check_duplex(dev);
0079             spin_unlock(&tp->lock);
0080         } else {
0081             pnic_do_nway(dev);
0082         }
0083         iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
0084     }
0085 }
0086 
0087 void pnic_timer(struct timer_list *t)
0088 {
0089     struct tulip_private *tp = from_timer(tp, t, timer);
0090     struct net_device *dev = tp->dev;
0091     void __iomem *ioaddr = tp->base_addr;
0092     int next_tick = 60*HZ;
0093 
0094     if(!ioread32(ioaddr + CSR7)) {
0095         /* the timer was called due to a work overflow
0096          * in the interrupt handler. Skip the connection
0097          * checks, the nic is definitively speaking with
0098          * his link partner.
0099          */
0100         goto too_good_connection;
0101     }
0102 
0103     if (tulip_media_cap[dev->if_port] & MediaIsMII) {
0104         spin_lock_irq(&tp->lock);
0105         if (tulip_check_duplex(dev) > 0)
0106             next_tick = 3*HZ;
0107         spin_unlock_irq(&tp->lock);
0108     } else {
0109         int csr12 = ioread32(ioaddr + CSR12);
0110         int new_csr6 = tp->csr6 & ~0x40C40200;
0111         int phy_reg = ioread32(ioaddr + 0xB8);
0112         int csr5 = ioread32(ioaddr + CSR5);
0113 
0114         if (tulip_debug > 1)
0115             netdev_dbg(dev, "PNIC timer PHY status %08x, %s CSR5 %08x\n",
0116                    phy_reg, medianame[dev->if_port], csr5);
0117         if (phy_reg & 0x04000000) { /* Remote link fault */
0118             iowrite32(0x0201F078, ioaddr + 0xB8);
0119             next_tick = 1*HZ;
0120             tp->nwayset = 0;
0121         } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */
0122             pnic_do_nway(dev);
0123             next_tick = 60*HZ;
0124         } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */
0125             if (tulip_debug > 1)
0126                 netdev_dbg(dev, "%s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n",
0127                        medianame[dev->if_port],
0128                        csr12,
0129                        ioread32(ioaddr + CSR5),
0130                        ioread32(ioaddr + 0xB8));
0131             next_tick = 3*HZ;
0132             if (tp->medialock) {
0133             } else if (tp->nwayset  &&  (dev->if_port & 1)) {
0134                 next_tick = 1*HZ;
0135             } else if (dev->if_port == 0) {
0136                 dev->if_port = 3;
0137                 iowrite32(0x33, ioaddr + CSR12);
0138                 new_csr6 = 0x01860000;
0139                 iowrite32(0x1F868, ioaddr + 0xB8);
0140             } else {
0141                 dev->if_port = 0;
0142                 iowrite32(0x32, ioaddr + CSR12);
0143                 new_csr6 = 0x00420000;
0144                 iowrite32(0x1F078, ioaddr + 0xB8);
0145             }
0146             if (tp->csr6 != new_csr6) {
0147                 tp->csr6 = new_csr6;
0148                 /* Restart Tx */
0149                 tulip_restart_rxtx(tp);
0150                 netif_trans_update(dev);
0151                 if (tulip_debug > 1)
0152                     dev_info(&dev->dev,
0153                          "Changing PNIC configuration to %s %s-duplex, CSR6 %08x\n",
0154                          medianame[dev->if_port],
0155                          tp->full_duplex ? "full" : "half",
0156                          new_csr6);
0157             }
0158         }
0159     }
0160 too_good_connection:
0161     mod_timer(&tp->timer, RUN_AT(next_tick));
0162     if(!ioread32(ioaddr + CSR7)) {
0163         if (tulip_debug > 1)
0164             dev_info(&dev->dev, "sw timer wakeup\n");
0165         disable_irq(dev->irq);
0166         tulip_refill_rx(dev);
0167         enable_irq(dev->irq);
0168         iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
0169     }
0170 }