[U-Boot] NE2000 driver issues and extensions
Rutger Hofman
uboot at rutgerhofman.nl
Thu Dec 3 17:22:10 CET 2009
On our new, custom BlackFin board (see http://www.rfidguardian.org) we
have an Asix AX88796B Ethernet chip. This chip is NE2000-compatible
according to the manufacturer.
When porting this driver to our board, and extending it for extra
commands (DP_RESET in software and then some, attempt to read the MAC
address from an EEPROM), I met a few issues with the ne2000 controller:
bug 1) when a corrupted packet arrives, the driver attempts to detect
this by doing a sanity check on the packet length in
uboot_push_packet_len(). If the length check fails, this function
returns and the caller continues as if nothing happened, reading
rcv_hdr[1] as the location for the next packet. But this header will
probably also be corrupt, so the management of receive pages becomes
nonsensical.
Proposed fix:
a) check rcv_hdr[0], the receive status byte; if != 0x01, then the
packet is corrupt;
b) check the length; if it exceeds PKTSIZE_ALIGN, the packet is corrupt;
c) if the packet is corrupt, advance the next-packet-pointer to the
following location, irrespective of the pointer in the header. This will
discard the corrupt packet and keep the received pages consistent
bug 2) dp83902a_RxEvent() caches a pointer to the next-page-to-be read,
then calls uboot_push_packet_len(), which calls upper layers via
NetReceive(). If the upper layers want, they can call dp83902a_start()
-- which happens e.g. when a tftp-ed file doesn't exist.
dp83902a_start() resets the receive page pointers to the initial state.
But when NetReceive() returns, the modified pointers into the receive
pages are ignored. The BNDRY pointer is set to the cached next pointer,
which has no relation to the current state.
Proposed fix:
a) dp83902a_start() sets a bit in the driver state. This bit cleared
before the driver upcalls to NetReceive(); if the bit is set after
NetReceive() returned, the driver knows that the receive page pointers
are reset. In that case, it doesn't touch the receive page pointers any
more.
Another issue:
Extension 1) our chip has an x16 bus. I extended the driver to support
16-bit data read/writes, following the implementation in eCos (where the
ne2000 driver originates). Issue: the endianness in the eCos driver
appears wrong to me -- NE2000 is little-endian itself, so the driver
must convert between NE2000's little-endianness and the endianness of
the host. The eCos driver appears to assume a big-endian host in all cases.
I plan to also report this on the eCos mailing lists.
Rutger
More information about the U-Boot
mailing list