Re: all input packets cause RX-ERRs on ne2000 clones (2.0.0 kernel)

Mike (ford@omnicron.com)
Tue, 14 Jan 97 11:52:57 -0500


A while back, I wrote on linux-net about my two very different x86
boxes, both with very differnet NE2000 clone 10baseT adapters, both of
which didn't work under Linux 2.0.0. I have some more information to
report, and I'm CCing linux-laptop since my only remaining problem is
with a Socket EA PCMCIA card.

> The symptom is that the Ethernet adapter is recognized by the
> kernel (ifconfig -a shows eth0 with the right hardware address and other
> parameters) but any received packet just increments the RX-ERR count and
> is not processed.
[ ... ]
> I would suspect a hardware problem if it weren't for the fact that
> I get exactly the same behavior on these two very different machines.

Well, after some poking around on the system with the PCI Ethernet
adapter, I found out that this adapter has its station identifier ROM
arranged as if it were an 8-bit card, but it can only be accessed as a
16-bit card. This confuses the 2.0.0 NEx000 driver. I added a hack to
the driver so that it will consider any card with an I/O address above
0xF000 (where the PCI bus is addressed on many systems) to be a 16-bit
card, regardless of its SA_prom arrangement. Now the PCI card works
fine. The patch I made to ne.c is enclosed below. I am told that newer
kernels have a different fix for this problem, but from what I heard,
that fix wouldn't work for my situation where the driver is a loaded
module.

However, my other system, with its Socket EA NE2000-compatible PCMCIA
card has a different problem. I added debugging code to 8390.c and
confirmed that the errors are being detected in the "bogosity" code. I
tried to clean up this code a bit, making its sanity check somewhat more
precise but that turned out to be unrelated.

It seems that this is what is happening: When the driver tries to read
a word of data from the card's buffer, it always gets 0x4310: The 8390
header always looks like it got a 0x4310-byte frame, and the next frame
is 0x43 and the status is 0x10. Here is the dmesg log, and the patch to
8390.c which includes the printk is also below. Every single received
packet causes one of the error messages below.

Any ideas? Thanks for any help,
-=] Ford [=-

loading device 'eth0'...
eth0: Socket EA, port 0x300, irq 5, 10baseT port, 00 C0 1B 00 06 A5
eth0: bogosity: rx_frame.count=17168, rx_frame.next=67, rx_frame.status=0x10,
this_frame=13, next_frame=81, num_rx_pages=242
eth0: bogosity: rx_frame.count=17168, rx_frame.next=67, rx_frame.status=0x10,
this_frame=14, next_frame=82, num_rx_pages=242
eth0: bogosity: rx_frame.count=17168, rx_frame.next=67, rx_frame.status=0x10,
this_frame=15, next_frame=83, num_rx_pages=242
eth0: bogosity: rx_frame.count=17168, rx_frame.next=67, rx_frame.status=0x10,
this_frame=16, next_frame=84, num_rx_pages=242

*** ne.c.~1~ Tue May 28 00:39:18 1996
--- ne.c Tue Dec 31 07:23:07 1996
***************
*** 300,312 ****
}

if (wordlength == 2) {
/* We must set the 8390 for word mode. */
outb_p(0x49, ioaddr + EN0_DCFG);
/* We used to reset the ethercard here, but it doesn't seem
to be necessary. */
- /* Un-double the SA_prom values. */
- for (i = 0; i < 16; i++)
- SA_prom[i] = SA_prom[i+i];
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
} else {
--- 300,318 ----
}

if (wordlength == 2) {
+ /* Un-double the SA_prom values. */
+ for (i = 0; i < 16; i++)
+ SA_prom[i] = SA_prom[i+i];
+ }
+
+ if (ioaddr > 0xF000)
+ wordlength = 2;
+
+ if (wordlength == 2) {
/* We must set the 8390 for word mode. */
outb_p(0x49, ioaddr + EN0_DCFG);
/* We used to reset the ethercard here, but it doesn't seem
to be necessary. */
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
} else {

*** 8390.c.~1~ Sat May 18 04:15:09 1996
--- 8390.c Tue Dec 31 08:13:21 1996
***************
*** 522,538 ****

pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);

! next_frame = this_frame + 1 + ((pkt_len+4)>>8);

/* Check for bogosity warned by 3c503 book: the status byte is never
written. This happened a lot during testing! This code should be
cleaned up someday. */
! if (rx_frame.next != next_frame
! && rx_frame.next != next_frame + 1
! && rx_frame.next != next_frame - num_rx_pages
! && rx_frame.next != next_frame + 1 - num_rx_pages) {
ei_local->current_page = rxing_page;
outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
ei_local->stat.rx_errors++;
continue;
}
--- 522,542 ----

pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);

! next_frame = this_frame + ((rx_frame.count+4+255)>>8);
! if (next_frame >= ei_local->stop_page)
! next_frame -= num_rx_pages;

/* Check for bogosity warned by 3c503 book: the status byte is never
written. This happened a lot during testing! This code should be
cleaned up someday. */
! if (rx_frame.next != next_frame) {
ei_local->current_page = rxing_page;
outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
+ printk("%s: bogosity: rx_frame.count=%d, rx_frame.next=%d, "
+ "rx_frame.status=%#2x,\n"
+ " this_frame=%d, next_frame=%d, num_rx_pages=%d\n",
+ dev->name, rx_frame.count, rx_frame.next, rx_frame.status,
+ this_frame, next_frame, num_rx_pages);
ei_local->stat.rx_errors++;
continue;
}