Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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/interrupt.h>
 17#include <linux/kernel.h>
 18#include <linux/jiffies.h>
 19#include "tulip.h"
 20
 21
 22void pnic_do_nway(struct net_device *dev)
 23{
 24	struct tulip_private *tp = netdev_priv(dev);
 25	void __iomem *ioaddr = tp->base_addr;
 26	u32 phy_reg = ioread32(ioaddr + 0xB8);
 27	u32 new_csr6 = tp->csr6 & ~0x40C40200;
 28
 29	if (phy_reg & 0x78000000) { /* Ignore baseT4 */
 30		if (phy_reg & 0x20000000)		dev->if_port = 5;
 31		else if (phy_reg & 0x40000000)	dev->if_port = 3;
 32		else if (phy_reg & 0x10000000)	dev->if_port = 4;
 33		else if (phy_reg & 0x08000000)	dev->if_port = 0;
 34		tp->nwayset = 1;
 35		new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000;
 36		iowrite32(0x32 | (dev->if_port & 1), ioaddr + CSR12);
 37		if (dev->if_port & 1)
 38			iowrite32(0x1F868, ioaddr + 0xB8);
 39		if (phy_reg & 0x30000000) {
 40			tp->full_duplex = 1;
 41			new_csr6 |= 0x00000200;
 42		}
 43		if (tulip_debug > 1)
 44			netdev_dbg(dev, "PNIC autonegotiated status %08x, %s\n",
 45				   phy_reg, medianame[dev->if_port]);
 46		if (tp->csr6 != new_csr6) {
 47			tp->csr6 = new_csr6;
 48			/* Restart Tx */
 49			tulip_restart_rxtx(tp);
 50			dev->trans_start = jiffies;
 51		}
 52	}
 53}
 54
 55void pnic_lnk_change(struct net_device *dev, int csr5)
 56{
 57	struct tulip_private *tp = netdev_priv(dev);
 58	void __iomem *ioaddr = tp->base_addr;
 59	int phy_reg = ioread32(ioaddr + 0xB8);
 60
 61	if (tulip_debug > 1)
 62		netdev_dbg(dev, "PNIC link changed state %08x, CSR5 %08x\n",
 63			   phy_reg, csr5);
 64	if (ioread32(ioaddr + CSR5) & TPLnkFail) {
 65		iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
 66		/* If we use an external MII, then we mustn't use the
 67		 * internal negotiation.
 68		 */
 69		if (tulip_media_cap[dev->if_port] & MediaIsMII)
 70			return;
 71		if (! tp->nwayset || time_after(jiffies, dev_trans_start(dev) + 1*HZ)) {
 72			tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
 73			iowrite32(tp->csr6, ioaddr + CSR6);
 74			iowrite32(0x30, ioaddr + CSR12);
 75			iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
 76			dev->trans_start = jiffies;
 77		}
 78	} else if (ioread32(ioaddr + CSR5) & TPLnkPass) {
 79		if (tulip_media_cap[dev->if_port] & MediaIsMII) {
 80			spin_lock(&tp->lock);
 81			tulip_check_duplex(dev);
 82			spin_unlock(&tp->lock);
 83		} else {
 84			pnic_do_nway(dev);
 85		}
 86		iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
 87	}
 88}
 89
 90void pnic_timer(unsigned long data)
 91{
 92	struct net_device *dev = (struct net_device *)data;
 93	struct tulip_private *tp = netdev_priv(dev);
 94	void __iomem *ioaddr = tp->base_addr;
 95	int next_tick = 60*HZ;
 96
 97	if(!ioread32(ioaddr + CSR7)) {
 98		/* the timer was called due to a work overflow
 99		 * in the interrupt handler. Skip the connection
100		 * checks, the nic is definitively speaking with
101		 * his link partner.
102		 */
103		goto too_good_connection;
104	}
105
106	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
107		spin_lock_irq(&tp->lock);
108		if (tulip_check_duplex(dev) > 0)
109			next_tick = 3*HZ;
110		spin_unlock_irq(&tp->lock);
111	} else {
112		int csr12 = ioread32(ioaddr + CSR12);
113		int new_csr6 = tp->csr6 & ~0x40C40200;
114		int phy_reg = ioread32(ioaddr + 0xB8);
115		int csr5 = ioread32(ioaddr + CSR5);
116
117		if (tulip_debug > 1)
118			netdev_dbg(dev, "PNIC timer PHY status %08x, %s CSR5 %08x\n",
119				   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				netdev_dbg(dev, "%s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n",
130					   medianame[dev->if_port],
131					   csr12,
132					   ioread32(ioaddr + CSR5),
133					   ioread32(ioaddr + 0xB8));
134			next_tick = 3*HZ;
135			if (tp->medialock) {
136			} else if (tp->nwayset  &&  (dev->if_port & 1)) {
137				next_tick = 1*HZ;
138			} else if (dev->if_port == 0) {
139				dev->if_port = 3;
140				iowrite32(0x33, ioaddr + CSR12);
141				new_csr6 = 0x01860000;
142				iowrite32(0x1F868, ioaddr + 0xB8);
143			} else {
144				dev->if_port = 0;
145				iowrite32(0x32, ioaddr + CSR12);
146				new_csr6 = 0x00420000;
147				iowrite32(0x1F078, ioaddr + 0xB8);
148			}
149			if (tp->csr6 != new_csr6) {
150				tp->csr6 = new_csr6;
151				/* Restart Tx */
152				tulip_restart_rxtx(tp);
153				dev->trans_start = jiffies;
154				if (tulip_debug > 1)
155					dev_info(&dev->dev,
156						 "Changing PNIC configuration to %s %s-duplex, CSR6 %08x\n",
157						 medianame[dev->if_port],
158						 tp->full_duplex ? "full" : "half",
159						 new_csr6);
160			}
161		}
162	}
163too_good_connection:
164	mod_timer(&tp->timer, RUN_AT(next_tick));
165	if(!ioread32(ioaddr + CSR7)) {
166		if (tulip_debug > 1)
167			dev_info(&dev->dev, "sw timer wakeup\n");
168		disable_irq(dev->irq);
169		tulip_refill_rx(dev);
170		enable_irq(dev->irq);
171		iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
172	}
173}