patch-2.1.29 linux/drivers/net/sunhme.c
Next file: linux/drivers/net/sunhme.h
Previous file: linux/drivers/net/myri_sbus.c
Back to the patch index
Back to the overall index
- Lines: 198
- Date:
Wed Mar 5 17:04:32 1997
- Orig file:
v2.1.28/linux/drivers/net/sunhme.c
- Orig date:
Sun Feb 2 05:18:42 1997
diff -u --recursive --new-file v2.1.28/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
@@ -6,7 +6,7 @@
*/
static char *version =
- "sunhme.c:v1.1 10/Oct/96 David S. Miller (davem@caipfs.rutgers.edu)\n";
+ "sunhme.c:v1.2 10/Oct/96 David S. Miller (davem@caipfs.rutgers.edu)\n";
#include <linux/module.h>
@@ -279,17 +279,9 @@
{
hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
- /* Downgrade duplex if full. */
- if(hp->sw_bmcr & BMCR_FULLDPLX) {
- hp->sw_bmcr &= ~(BMCR_FULLDPLX);
- happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
- return 0;
- }
-
/* Downgrade from 100 to 10. */
if(hp->sw_bmcr & BMCR_SPEED100) {
hp->sw_bmcr &= ~(BMCR_SPEED100);
- hp->sw_bmcr |= (BMCR_FULLDPLX);
happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
return 0;
}
@@ -346,14 +338,20 @@
/* All we care about is making sure the bigmac tx_cfg has a
* proper duplex setting.
*/
- if(hp->timer_state == lupwait) {
+ if(hp->timer_state == arbwait) {
hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA);
- if((hp->sw_lpa & LPA_100FULL) ||
- (!(hp->sw_lpa & LPA_100HALF) && (hp->sw_lpa & LPA_10FULL)))
+ if(!(hp->sw_lpa & (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL)))
+ goto no_response;
+ if(hp->sw_lpa & LPA_100FULL)
+ full = 1;
+ else if(hp->sw_lpa & LPA_100HALF)
+ full = 0;
+ else if(hp->sw_lpa & LPA_10FULL)
full = 1;
else
full = 0;
} else {
+ /* Forcing a link mode. */
hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
if(hp->sw_bmcr & BMCR_FULLDPLX)
full = 1;
@@ -370,6 +368,8 @@
hp->bigmacregs->tx_cfg &= ~(BIGMAC_TXCFG_FULLDPLX);
return 0;
+no_response:
+ return 1;
}
static int happy_meal_init(struct happy_meal *hp, int from_irq);
@@ -390,11 +390,19 @@
/* Enter force mode. */
do_force_mode:
hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
- printk("%s: Auto-Negotiation timeout, trying force link "
- "mode BMCR=0x%04x.\n", hp->dev->name, hp->sw_bmcr);
- hp->sw_bmcr &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
- hp->sw_bmcr |= (BMCR_FULLDPLX | BMCR_ANENABLE);
+ printk("%s: Auto-Negotiation unsuccessful, trying force link mode\n",
+ hp->dev->name);
+ hp->sw_bmcr = BMCR_SPEED100;
happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
+
+ /* OK, seems we need do disable the transceiver for the first
+ * tick to make sure we get an accurate link state at the
+ * second tick.
+ */
+ hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
+ hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
+ happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+
hp->timer_state = ltrywait;
hp->timer_ticks = 0;
restart_timer = 1;
@@ -409,6 +417,9 @@
if(ret) {
/* Ooops, something bad happened, go to force
* mode.
+ *
+ * XXX Broken hubs which don't support 802.3u
+ * XXX auto-negotiation make this happen as well.
*/
goto do_force_mode;
}
@@ -455,6 +466,21 @@
* error recovery code for the most part.
*/
hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
+ hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
+ if(hp->timer_ticks == 1) {
+ /* Re-enable transceiver, we'll re-enable the transceiver next
+ * tick, then check link state on the following tick. */
+ hp->sw_csconfig |= CSCONFIG_TCVDISAB;
+ happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+ restart_timer = 1;
+ break;
+ }
+ if(hp->timer_ticks == 2) {
+ hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
+ happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+ restart_timer = 1;
+ break;
+ }
if(hp->sw_bmsr & BMSR_LSTATUS) {
/* Force mode selection success. */
display_forced_link_mode(hp, tregs);
@@ -462,7 +488,7 @@
hp->timer_state = asleep;
restart_timer = 0;
} else {
- if(hp->timer_ticks >= 3) { /* 6 seconds or so... */
+ if(hp->timer_ticks >= 4) { /* 6 seconds or so... */
int ret;
ret = try_next_permutation(hp, tregs);
@@ -483,6 +509,9 @@
}
return;
}
+ hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
+ hp->sw_csconfig |= CSCONFIG_TCVDISAB;
+ happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
hp->timer_ticks = 0;
restart_timer = 1;
} else {
@@ -1033,9 +1062,19 @@
* XXX Should probably reset the DP83840 first
* XXX as this is a gross fatal error...
*/
- hp->sw_bmcr &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
- hp->sw_bmcr |= (BMCR_FULLDPLX | BMCR_SPEED100);
+ hp->sw_bmcr = BMCR_SPEED100;
happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
+
+ /* OK, seems we need do disable the transceiver for the first
+ * tick to make sure we get an accurate link state at the
+ * second tick.
+ */
+ hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
+ printk("%s: CSCONFIG [%04x], disabling transceiver\n", hp->dev->name,
+ hp->sw_csconfig);
+ hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
+ happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+
hp->timer_state = ltrywait;
} else {
hp->timer_state = arbwait;
@@ -1379,9 +1418,11 @@
/* Defer-timer expired. Probably means the happy meal needed
* to back off too much before it could transmit one frame.
*/
+#if 0 /* XXX This isn't worth reporting and is in fact a normal condition. */
printk("%s: Transmit defer timer expired, subnet congested?\n",
hp->dev->name);
reset = 1;
+#endif
}
if(status & GREG_STAT_NORXD) {
@@ -2050,7 +2091,8 @@
return ENODEV;
}
- prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers);
+ prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
+ sdev->num_registers, sdev);
hp->gregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
sizeof(struct hmeal_gregs),
"Happy Meal Global Regs",
@@ -2196,10 +2238,16 @@
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_happy_dev) {
+ struct happy_meal *hp = root_happy_dev;
sunshine = root_happy_dev->next_module;
- unregister_netdev(root_happy_dev->dev);
- kfree(root_happy_dev->dev);
+ sparc_free_io(hp->gregs, sizeof(struct hmeal_gregs));
+ sparc_free_io(hp->etxregs, sizeof(struct hmeal_etxregs));
+ sparc_free_io(hp->erxregs, sizeof(struct hmeal_erxregs));
+ sparc_free_io(hp->bigmacregs, sizeof(struct hmeal_bigmacregs));
+ sparc_free_io(hp->tcvregs, sizeof(struct hmeal_tcvregs));
+ unregister_netdev(hp->dev);
+ kfree(hp->dev);
root_happy_dev = sunshine;
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov