Commit 40346461 authored by Marc Zyngier's avatar Marc Zyngier Committed by Jeff Garzik

More znet net driver updates. Driver now survives plug/unplug of cable.

parent 8ad09275
...@@ -72,7 +72,10 @@ ...@@ -72,7 +72,10 @@
- Use proper resources management. - Use proper resources management.
- Use wireless/i82593.h as much as possible (structure, constants) - Use wireless/i82593.h as much as possible (structure, constants)
- Compiles as module or build-in. - Compiles as module or build-in.
- Now survives unplugging/replugging cable.
Some code was taken from wavelan_cs.
Tested on a vintage Zenith Z-Note 433Lnp+. Probably broken on Tested on a vintage Zenith Z-Note 433Lnp+. Probably broken on
anything else. Testers (and detailed bug reports) are welcome :-). anything else. Testers (and detailed bug reports) are welcome :-).
...@@ -105,7 +108,7 @@ ...@@ -105,7 +108,7 @@
/* This include could be elsewhere, since it is not wireless specific */ /* This include could be elsewhere, since it is not wireless specific */
#include "wireless/i82593.h" #include "wireless/i82593.h"
static const char version[] __initdata = "znet.c:v1.02 9/23/94 becker@cesdis.gsfc.nasa.gov\n"; static const char version[] __initdata = "znet.c:v1.02 9/23/94 becker@scyld.com\n";
#ifndef ZNET_DEBUG #ifndef ZNET_DEBUG
#define ZNET_DEBUG 1 #define ZNET_DEBUG 1
...@@ -299,7 +302,7 @@ static void znet_set_multicast_list (struct net_device *dev) ...@@ -299,7 +302,7 @@ static void znet_set_multicast_list (struct net_device *dev)
cfblk->cd_filter = 0; /* CD is recognized immediately */ cfblk->cd_filter = 0; /* CD is recognized immediately */
/* Byte 9 */ /* Byte 9 */
cfblk->min_fr_len = 64 >> 2; /* Minimum frame length 64 bytes */ cfblk->min_fr_len = ETH_ZLEN >> 2; /* Minimum frame length */
/* Byte A */ /* Byte A */
cfblk->lng_typ = 1; /* Type/length checks OFF */ cfblk->lng_typ = 1; /* Type/length checks OFF */
...@@ -544,10 +547,14 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -544,10 +547,14 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Check that the part hasn't reset itself, probably from suspend. */ /* Check that the part hasn't reset itself, probably from suspend. */
outb(CR0_STATUS_0, ioaddr); outb(CR0_STATUS_0, ioaddr);
if (inw(ioaddr) == 0x0010 if (inw(ioaddr) == 0x0010 &&
&& inw(ioaddr) == 0x0000 inw(ioaddr) == 0x0000 &&
&& inw(ioaddr) == 0x0010) inw(ioaddr) == 0x0010) {
hardware_init(dev); if (znet_debug > 1)
printk (KERN_WARNING "%s : waking up\n", dev->name);
hardware_init(dev);
znet_transceiver_power (dev, 1);
}
if (1) { if (1) {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
...@@ -624,7 +631,9 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -624,7 +631,9 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if ((status & SR0_INTERRUPT) == 0) if ((status & SR0_INTERRUPT) == 0)
break; break;
if ((status & 0x0F) == SR0_TRANSMIT_DONE) { if ((status & SR0_EVENT_MASK) == SR0_TRANSMIT_DONE ||
(status & SR0_EVENT_MASK) == SR0_RETRANSMIT_DONE ||
(status & SR0_EVENT_MASK) == SR0_TRANSMIT_NO_CRC_DONE) {
int tx_status; int tx_status;
outb(CR0_STATUS_1, ioaddr); outb(CR0_STATUS_1, ioaddr);
tx_status = inw(ioaddr); tx_status = inw(ioaddr);
...@@ -644,6 +653,15 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -644,6 +653,15 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* ...and the catch-all. */ /* ...and the catch-all. */
if ((tx_status | (TX_LOST_CRS | TX_LOST_CTS | TX_UND_RUN | TX_HRT_BEAT | TX_MAX_COL)) != (TX_LOST_CRS | TX_LOST_CTS | TX_UND_RUN | TX_HRT_BEAT | TX_MAX_COL)) if ((tx_status | (TX_LOST_CRS | TX_LOST_CTS | TX_UND_RUN | TX_HRT_BEAT | TX_MAX_COL)) != (TX_LOST_CRS | TX_LOST_CTS | TX_UND_RUN | TX_HRT_BEAT | TX_MAX_COL))
znet->stats.tx_errors++; znet->stats.tx_errors++;
/* Transceiver may be stuck if cable
* was removed while emiting a
* packet. Flip it off, then on to
* reset it. This is very empirical,
* but it seems to work. */
znet_transceiver_power (dev, 0);
znet_transceiver_power (dev, 1);
} }
netif_wake_queue (dev); netif_wake_queue (dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment