Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.28 171 lines 5.3 kB view raw
1/* 2 drivers/net/tulip/pnic.c 3 4 Copyright 2000,2001 The Linux Kernel Team 5 Written/copyright 1994-2001 by Donald Becker. 6 7 This software may be used and distributed according to the terms 8 of the GNU General Public License, incorporated herein by reference. 9 10 Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} 11 for more information on this driver. 12 13 Please submit bugs to http://bugzilla.kernel.org/ . 14*/ 15 16#include <linux/kernel.h> 17#include <linux/jiffies.h> 18#include "tulip.h" 19 20 21void pnic_do_nway(struct net_device *dev) 22{ 23 struct tulip_private *tp = netdev_priv(dev); 24 void __iomem *ioaddr = tp->base_addr; 25 u32 phy_reg = ioread32(ioaddr + 0xB8); 26 u32 new_csr6 = tp->csr6 & ~0x40C40200; 27 28 if (phy_reg & 0x78000000) { /* Ignore baseT4 */ 29 if (phy_reg & 0x20000000) dev->if_port = 5; 30 else if (phy_reg & 0x40000000) dev->if_port = 3; 31 else if (phy_reg & 0x10000000) dev->if_port = 4; 32 else if (phy_reg & 0x08000000) dev->if_port = 0; 33 tp->nwayset = 1; 34 new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000; 35 iowrite32(0x32 | (dev->if_port & 1), ioaddr + CSR12); 36 if (dev->if_port & 1) 37 iowrite32(0x1F868, ioaddr + 0xB8); 38 if (phy_reg & 0x30000000) { 39 tp->full_duplex = 1; 40 new_csr6 |= 0x00000200; 41 } 42 if (tulip_debug > 1) 43 printk(KERN_DEBUG "%s: PNIC autonegotiated status %8.8x, %s.\n", 44 dev->name, phy_reg, medianame[dev->if_port]); 45 if (tp->csr6 != new_csr6) { 46 tp->csr6 = new_csr6; 47 /* Restart Tx */ 48 tulip_restart_rxtx(tp); 49 dev->trans_start = jiffies; 50 } 51 } 52} 53 54void pnic_lnk_change(struct net_device *dev, int csr5) 55{ 56 struct tulip_private *tp = netdev_priv(dev); 57 void __iomem *ioaddr = tp->base_addr; 58 int phy_reg = ioread32(ioaddr + 0xB8); 59 60 if (tulip_debug > 1) 61 printk(KERN_DEBUG "%s: PNIC link changed state %8.8x, CSR5 %8.8x.\n", 62 dev->name, phy_reg, csr5); 63 if (ioread32(ioaddr + CSR5) & TPLnkFail) { 64 iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); 65 /* If we use an external MII, then we mustn't use the 66 * internal negotiation. 67 */ 68 if (tulip_media_cap[dev->if_port] & MediaIsMII) 69 return; 70 if (! tp->nwayset || time_after(jiffies, dev->trans_start + 1*HZ)) { 71 tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); 72 iowrite32(tp->csr6, ioaddr + CSR6); 73 iowrite32(0x30, ioaddr + CSR12); 74 iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ 75 dev->trans_start = jiffies; 76 } 77 } else if (ioread32(ioaddr + CSR5) & TPLnkPass) { 78 if (tulip_media_cap[dev->if_port] & MediaIsMII) { 79 spin_lock(&tp->lock); 80 tulip_check_duplex(dev); 81 spin_unlock(&tp->lock); 82 } else { 83 pnic_do_nway(dev); 84 } 85 iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7); 86 } 87} 88 89void pnic_timer(unsigned long data) 90{ 91 struct net_device *dev = (struct net_device *)data; 92 struct tulip_private *tp = netdev_priv(dev); 93 void __iomem *ioaddr = tp->base_addr; 94 int next_tick = 60*HZ; 95 96 if(!ioread32(ioaddr + CSR7)) { 97 /* the timer was called due to a work overflow 98 * in the interrupt handler. Skip the connection 99 * checks, the nic is definitively speaking with 100 * his link partner. 101 */ 102 goto too_good_connection; 103 } 104 105 if (tulip_media_cap[dev->if_port] & MediaIsMII) { 106 spin_lock_irq(&tp->lock); 107 if (tulip_check_duplex(dev) > 0) 108 next_tick = 3*HZ; 109 spin_unlock_irq(&tp->lock); 110 } else { 111 int csr12 = ioread32(ioaddr + CSR12); 112 int new_csr6 = tp->csr6 & ~0x40C40200; 113 int phy_reg = ioread32(ioaddr + 0xB8); 114 int csr5 = ioread32(ioaddr + CSR5); 115 116 if (tulip_debug > 1) 117 printk(KERN_DEBUG "%s: PNIC timer PHY status %8.8x, %s " 118 "CSR5 %8.8x.\n", 119 dev->name, phy_reg, medianame[dev->if_port], csr5); 120 if (phy_reg & 0x04000000) { /* Remote link fault */ 121 iowrite32(0x0201F078, ioaddr + 0xB8); 122 next_tick = 1*HZ; 123 tp->nwayset = 0; 124 } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */ 125 pnic_do_nway(dev); 126 next_tick = 60*HZ; 127 } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */ 128 if (tulip_debug > 1) 129 printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " 130 "CSR5 %8.8x, PHY %3.3x.\n", 131 dev->name, medianame[dev->if_port], csr12, 132 ioread32(ioaddr + CSR5), ioread32(ioaddr + 0xB8)); 133 next_tick = 3*HZ; 134 if (tp->medialock) { 135 } else if (tp->nwayset && (dev->if_port & 1)) { 136 next_tick = 1*HZ; 137 } else if (dev->if_port == 0) { 138 dev->if_port = 3; 139 iowrite32(0x33, ioaddr + CSR12); 140 new_csr6 = 0x01860000; 141 iowrite32(0x1F868, ioaddr + 0xB8); 142 } else { 143 dev->if_port = 0; 144 iowrite32(0x32, ioaddr + CSR12); 145 new_csr6 = 0x00420000; 146 iowrite32(0x1F078, ioaddr + 0xB8); 147 } 148 if (tp->csr6 != new_csr6) { 149 tp->csr6 = new_csr6; 150 /* Restart Tx */ 151 tulip_restart_rxtx(tp); 152 dev->trans_start = jiffies; 153 if (tulip_debug > 1) 154 printk(KERN_INFO "%s: Changing PNIC configuration to %s " 155 "%s-duplex, CSR6 %8.8x.\n", 156 dev->name, medianame[dev->if_port], 157 tp->full_duplex ? "full" : "half", new_csr6); 158 } 159 } 160 } 161too_good_connection: 162 mod_timer(&tp->timer, RUN_AT(next_tick)); 163 if(!ioread32(ioaddr + CSR7)) { 164 if (tulip_debug > 1) 165 printk(KERN_INFO "%s: sw timer wakeup.\n", dev->name); 166 disable_irq(dev->irq); 167 tulip_refill_rx(dev); 168 enable_irq(dev->irq); 169 iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); 170 } 171}