RFC patch to 89K for 21143 w/QS6611 no MII
B. James Phillippe
bryan@terran.org
Tue Aug 11 21:11:48 1998
Hello,
(Let me draw in a deep breath here....)
I have several generic 21143 ethernet controllers using the Quality
Semiconductor QS6611 PHY chip with no MII tranceiver. For the last few
days I have been poring over the QS6611 data sheets, the 21143 HRM and any
other scraps of info I could find (the SROM v405 ref, etc). I've even been
on the phone with Digital and QSI engineers. All of this research has
pointed me towards one conclusion; without a MII tranceiver this combo
cannot do NWay between 10 and 100Mbp/s; only 10, on the 10BASET port. I
have only a 10BASET and SYM port using RJ45. I have also learned that if I
were able to decode the type 2 and 4 infoblocks of the EEPROM, that I might
be able to deduce what the connected media was (though I don't see how this
is possible from the SROM reference).
Now for an explanation. When using the tulip.c driver, I was
suffering from some media-detection problems. These problems were not
present when using davies de4x5.c Linux driver and the stock Windows98
driver on the same equipment. The tulip.c problems were:
o When ifconfig up a disconnected interface, the driver quickly
reports "negotiation failure" and then tries 100base-Tx. This
also happens after momentarily disconnecting an active 10bT
line.
o Once 100base-Tx has been tried, there is no going back to 10.
The davies driver and Win98 did not suffer from these limitations. I can
sort of deduce that the davies driver works by forever iterating over the
EEPROM contents, so this must be how it does media detection? I have no
idea what Win98 does.
Now for the ugly hack I implemented to work around this problem in tulip.c.
Note that this stuff is probably only necessary for poor saps like me with
sucky ethernet equipment; the newer QS6612 apparently does not have this
limitation. Therefore, this is probably not something that belongs in the
general driver. However, I would *really* like to get back some commens
from the experts (hopefully Mr. Ethernet, himself ;) as to why this works
and whether or not I'm digging a deep grave with this. This is a patch
against 89k:
--- tulip.c-orig Fri Aug 7 23:19:36 1998
+++ tulip.c Tue Aug 11 17:38:17 1998
@@ -1754,7 +1754,7 @@
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
int csr12 = inl(ioaddr + CSR12);
- int next_tick = 60*HZ;
+ int next_tick = 5*HZ;
int new_csr6 = 0;
if (tulip_debug > 1)
@@ -1798,6 +1798,10 @@
}
next_tick = 60*HZ;
}
+ } else if ((csr12 & 0xf3c6) == 0x20c6) {
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: 21143 no connection detected.\n",
+ dev->name);
} else if (dev->if_port == 3) {
if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */
new_csr6 = 0x82420200;
@@ -1878,8 +1882,20 @@
if (!(csr12 & 2))
printk(KERN_INFO"%s: 21143 100baseTx link beat good.\n",
dev->name);
- else
+ else {
+ printk(KERN_INFO"%s: 21143 falling back to 10baseT.\n",
+ dev->name);
dev->if_port = 0;
+ outl(0, ioaddr + CSR13);
+ tp->csr6 = 0x82420200;
+ outl(0x3ffff, ioaddr + CSR14);
+ outl(0x8, ioaddr + CSR15);
+ outl(0x1, ioaddr + CSR13);
+ outl(0x1301, ioaddr + CSR12);
+ outl(tp->csr6, ioaddr + CSR6);
+ outl(tp->csr6|0x2000, ioaddr + CSR6);
+ outl(tp->csr6|0x2002, ioaddr + CSR6);
+ }
} else if (dev->if_port == 0) {
if (!(csr12 & 4))
printk(KERN_INFO"%s: 21143 10baseT link beat good.\n",
@@ -1898,6 +1914,9 @@
outl(tp->csr6 | 0x0002, ioaddr + CSR6);
outl(tp->csr6 | 0x2002, ioaddr + CSR6);
}
+
+ /* Clear port activity bits */
+ outl(inl(ioaddr + CSR12)|0x301, ioaddr + CSR12);
}
static void mxic_timer(unsigned long data)
@@ -2479,6 +2498,7 @@
dev->if_port = tp->saved_if_port;
+#ifdef way_too_many_messages
{
int i;
printk(" Rx ring %8.8x: ", (int)tp->rx_ring);
@@ -2489,6 +2509,7 @@
printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
printk("\n");
}
+#endif
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
thanks,
-bp
--
B. James Phillippe <bryan@terran.org>
Linux Software Engineer, WGT Inc.
http://earth.terran.org/~bryan