patch-2.4.3 linux/drivers/net/tulip/pnic.c
Next file: linux/drivers/net/tulip/tulip.h
Previous file: linux/drivers/net/tulip/media.c
Back to the patch index
Back to the overall index
- Lines: 135
- Date:
Fri Mar 2 11:02:14 2001
- Orig file:
v2.4.2/linux/drivers/net/tulip/pnic.c
- Orig date:
Wed Feb 21 18:20:29 2001
diff -u --recursive --new-file v2.4.2/linux/drivers/net/tulip/pnic.c linux/drivers/net/tulip/pnic.c
@@ -50,6 +50,61 @@
}
}
+/* Modified version of tulip_check_duplex:
+ * Always update the 100mbps bit, even if the
+ * full duplex bit didn't change.
+ * Manfred Spraul <manfred@colorfullife.com>
+ */
+int pnic_check_duplex(struct net_device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ int mii_reg1, mii_reg5, negotiated, duplex;
+ int new_csr6;
+
+ mii_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
+ mii_reg5 = tulip_mdio_read(dev, tp->phys[0], 5);
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
+ "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
+ if (mii_reg1 == 0xffff)
+ return -2;
+ if ((mii_reg1 & 0x0004) == 0) {
+ int new_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
+ if ((new_reg1 & 0x0004) == 0) {
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: No link beat on the MII interface,"
+ " status %4.4x.\n", dev->name, new_reg1);
+ return -1;
+ }
+ }
+ negotiated = mii_reg5 & tp->advertising[0];
+ /* 100baseTx-FD or 10T-FD, but not 100-HD */
+ duplex = ((negotiated & 0x0300) == 0x0100
+ || (negotiated & 0x00C0) == 0x0040) ||
+ tp->full_duplex_lock;
+
+ new_csr6 = tp->csr6;
+ if (negotiated & 0x0380) /* 100mbps. */
+ new_csr6 &= ~0x00400000;
+ else
+ new_csr6 |= 0x00400000;
+ if (duplex)
+ new_csr6 |= 0x0200;
+ else
+ new_csr6 &= ~0x0200;
+ if (new_csr6 != tp->csr6) {
+ tp->full_duplex = duplex;
+ tp->csr6 = new_csr6;
+ if (tulip_debug > 0)
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII"
+ "#%d link partner capability of %4.4x.\n",
+ dev->name, tp->full_duplex ? "full" : "half",
+ tp->phys[0], mii_reg5);
+ tulip_restart_rxtx(tp, tp->csr6);
+ return 1;
+ }
+ return 0;
+}
void pnic_lnk_change(struct net_device *dev, int csr5)
{
@@ -62,6 +117,11 @@
dev->name, phy_reg, csr5);
if (inl(ioaddr + CSR5) & TPLnkFail) {
outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
+ /* If we use an external MII, then we mustn't use the
+ * internal negotiation.
+ */
+ if (tulip_media_cap[dev->if_port] & MediaIsMII)
+ return;
if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) {
tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
tulip_outl_csr(tp, tp->csr6, CSR6);
@@ -70,11 +130,18 @@
dev->trans_start = jiffies;
}
} else if (inl(ioaddr + CSR5) & TPLnkPass) {
- pnic_do_nway(dev);
+ if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+ spin_lock(&tp->lock);
+ pnic_check_duplex(dev);
+ spin_unlock(&tp->lock);
+ } else {
+ pnic_do_nway(dev);
+ }
outl((inl(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
}
}
+int tulip_refill_rx(struct net_device *dev);
void pnic_timer(unsigned long data)
{
@@ -82,10 +149,21 @@
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
int next_tick = 60*HZ;
+
+ if(!inl(ioaddr + CSR7)) {
+ /* the timer was called due to a work overflow
+ * in the interrupt handler. Skip the connection
+ * checks, the nic is definitively speaking with
+ * his link partner.
+ */
+ goto too_good_connection;
+ }
if (tulip_media_cap[dev->if_port] & MediaIsMII) {
- if (tulip_check_duplex(dev) > 0)
+ spin_lock_irq(&tp->lock);
+ if (pnic_check_duplex(dev) > 0)
next_tick = 3*HZ;
+ spin_unlock_irq(&tp->lock);
} else {
int csr12 = inl(ioaddr + CSR12);
int new_csr6 = tp->csr6 & ~0x40C40200;
@@ -137,7 +215,14 @@
}
}
}
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+too_good_connection:
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ if(!inl(ioaddr + CSR7)) {
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: sw timer wakeup.\n", dev->name);
+ disable_irq(dev->irq);
+ tulip_refill_rx(dev);
+ enable_irq(dev->irq);
+ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+ }
}
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)