Index: bsps/arm/gumstix/net/rtl8019.c
===================================================================
--- bsps/arm/gumstix/net/rtl8019.c	(revision 031df3914990db0336a0d386fb53558b05de467e)
+++ bsps/arm/gumstix/net/rtl8019.c	(revision 031df3914990db0336a0d386fb53558b05de467e)
@@ -0,0 +1,1196 @@
+/*
+ *By Yang Xi <hiyangxi@gmail.com>.
+ *RTL8019 ethernet driver for Gumstix on SKYEYE simulator
+ *Based on NE2000 driver for pc386 bsp
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#define __INSIDE_RTEMS_BSD_TCPIP_STACK__
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include "wd80x3.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+
+/* Define this to force byte-wide data transfers with the NIC. This
+   is needed for boards like the TS-1325 386EX PC, which support only
+   an 8-bit PC/104 bus.  Undefine this on a normal PC.*/
+
+#define NE2000_BYTE_TRANSFERS
+
+/* Define this to print debugging messages with printk.  */
+
+/*#define DEBUG_NE2000
+  #define DEBUG_NE*/
+
+/* We expect to be able to read a complete packet into an mbuf.  */
+
+#if (MCLBYTES < 1520)
+# error "Driver must have MCLBYTES >= 1520"
+#endif
+
+/* The 8390 macro definitions in wd80x3.h expect RO to be defined.  */
+#define RO 0
+
+/* Minimum size of Ethernet packet.  */
+#define ET_MINLEN 60
+
+/* The number of NE2000 devices supported by this driver.  */
+
+#define NNEDRIVER 1
+
+/* RTEMS event number used by the interrupt handler to signal the
+   driver task.  This must not be any of the events used by the
+   network task synchronization.  */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+
+/* RTEMS event number used to start the transmit daemon.  This must
+   not be the same as INTERRUPT_EVENT.  */
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+
+/* Interrupts we want to handle from the device.  */
+
+#define NE_INTERRUPTS \
+  (MSK_PRX | MSK_PTX | MSK_RXE | MSK_TXE | MSK_OVW | MSK_CNT)
+
+/* The size of a page in device memory.  */
+
+#define NE_PAGE_SIZE (256)
+
+/* The first page address in device memory.  */
+
+#define NE_START_PAGE (0x40)
+
+/* The last page address, plus 1.  */
+
+#define NE_STOP_PAGE (0x80)
+
+/* The number of pages used for a single transmit buffer.  This is
+   1536 bytes, enough for a full size packet.  */
+
+#define NE_TX_PAGES (6)
+
+/* The number of transmit buffers.  We use two, so we can load one
+   packet while the other is being sent.  */
+
+#define NE_TX_BUFS (2)
+
+/* We use the first pages in memory as transmit buffers, and the
+   remaining ones as receive buffers.  */
+
+#define NE_FIRST_TX_PAGE (NE_START_PAGE)
+
+#define NE_FIRST_RX_PAGE (NE_FIRST_TX_PAGE + NE_TX_PAGES * NE_TX_BUFS)
+
+/* Data we store for each NE2000 device.  */
+
+struct ne_softc {
+  /* The bsdnet information structure.  */
+  struct arpcom arpcom;
+
+  /* The interrupt request number.  */
+  unsigned int irno;
+  /* The base IO port number.  */
+  unsigned int port;
+
+  /* Whether we accept broadcasts.  */
+  int accept_broadcasts;
+
+  /* The thread ID of the transmit task.   */
+  rtems_id tx_daemon_tid;
+  /* The thread ID of the receive task.  */
+  rtems_id rx_daemon_tid;
+
+  /* Whether we use byte-transfers with the device. */
+  bool byte_transfers;
+
+  /* The number of memory buffers which the transmit daemon has loaded
+     with data to be sent, but which have not yet been completely
+     sent.  */
+  int inuse;
+  /* The index of the next available transmit memory buffer.  */
+  int nextavail;
+  /* The index of the next transmit buffer to send.  */
+  int nextsend;
+  /* Nonzero if the device is currently transmitting a packet.  */
+  int transmitting;
+  /* The length of the data stored in each transmit buffer.  */
+  int sendlen[NE_TX_BUFS];
+
+  /* Set if we have a packet overrun while receiving.  */
+  int overrun;
+  /* Set if we should resend after an overrun.  */
+  int resend;
+
+  /* Statistics.  */
+  struct {
+    /* Number of packets received.  */
+    unsigned long rx_packets;
+    /* Number of packets sent.  */
+    unsigned long tx_packets;
+    /* Number of interrupts.  */
+    unsigned long interrupts;
+    /* Number of receive acknowledgements.  */
+    unsigned long rx_acks;
+    /* Number of transmit acknowledgements.  */
+    unsigned long tx_acks;
+    /* Number of packet overruns.  */
+    unsigned long overruns;
+    /* Number of frame errors.  */
+    unsigned long rx_frame_errors;
+    /* Number of CRC errors.  */
+    unsigned long rx_crc_errors;
+    /* Number of missed packets.  */
+    unsigned long rx_missed_errors;
+  } stats;
+};
+
+/* The list of NE2000 devices on this system.  */
+
+static struct ne_softc ne_softc[NNEDRIVER];
+
+/*
+ * receive ring descriptor
+ *
+ * The National Semiconductor DS8390 Network interface controller uses
+ * the following receive ring headers.  The way this works is that the
+ * memory on the interface card is chopped up into 256 bytes blocks.
+ * A contiguous portion of those blocks are marked for receive packets
+ * by setting start and end block #'s in the NIC.  For each packet that
+ * is put into the receive ring, one of these headers (4 bytes each) is
+ * tacked onto the front. The first byte is a copy of the receiver status
+ * register at the time the packet was received.
+ */
+struct ne_ring
+{
+	unsigned char rsr;    /* receiver status */
+	unsigned char next;   /* pointer to next packet	*/
+	unsigned short count; /* bytes in packet (length + 4)	*/
+};
+
+/* Forward declarations to avoid warnings */
+
+static void ne_init_irq_handler (struct ne_softc *sc);
+static void ne_stop (struct ne_softc *sc);
+static void ne_stop_hardware (struct ne_softc *sc);
+static void ne_init (void *arg);
+static void ne_init_hardware (struct ne_softc *sc);
+
+static void ne_reset(struct ne_softc *sc);
+#ifdef DEBUG_NE
+static void ne_dump(struct ne_softc *sc);
+#endif
+
+/* Read data from an NE2000 device.  Read LEN bytes at ADDR, storing
+   them into P.  */
+
+static void
+ne_read_data (struct ne_softc *sc, int addr, int len, unsigned char *p)
+{
+  unsigned int port = sc->port;
+  unsigned int dport = port + DATAPORT;
+  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
+  outport_byte (port + RBCR0, len);
+  outport_byte (port + RBCR1, len >> 8);
+  outport_byte (port + RSAR0, addr);
+  outport_byte (port + RSAR1, addr >> 8);
+  outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA);
+
+  if (sc->byte_transfers)
+  {
+    unsigned char d;
+    while (len > 0)
+    {
+      inport_byte(dport, d);
+      *p++ = d;
+      len--;
+    }
+  }
+  else  /* word transfers */
+  {
+    unsigned short d;
+    while (len > 1)
+    {
+      inport_word(dport, d);
+      *p++ = d;
+      *p++ = d >> 8;
+      len -= 2;
+    }
+    if (len)
+    {
+      inport_word(dport, d);
+      *p++ = d;
+    }
+  }
+
+  outport_byte (port + ISR, MSK_RDC);
+}
+
+/* Handle the current NE2000 status.  This is called when the device
+   signals an interrupt.  It is also called at other times while
+   NE2000 interrupts have been disabled.  */
+
+static void
+ne_check_status (struct ne_softc *sc, int from_irq_handler)
+{
+  struct ifnet *ifp = &sc->arpcom.ac_if;
+  unsigned int port = sc->port;
+  unsigned char status;
+
+  /* It seems that we need to use a loop here, because if the NE2000
+     signals an interrupt because packet transmission is complete, and
+     then receives a packet while interrupts are disabled, it seems to
+     sometimes fail to signal the interrupt for the received packet
+     when interrupts are reenabled.  (Based on the behaviour of the
+     Realtek 8019AS chip).  */
+
+  /* int count = 0; */
+  while (1)
+  {
+    inport_byte (port + ISR, status);
+#ifdef DEBUG_NE2000
+    printk ("NE2000 status 0x%x\n", status);
+#endif
+    if (status == 0)
+      break;
+
+    /* ack */
+    outport_byte (port + ISR, status);
+
+    /* Check for incoming packet overwrite.  */
+    if (status & MSK_OVW)
+    {
+      ifp->if_timer = 0;
+#ifdef DEBUG_NE
+      printk("^\n");
+#endif
+      ++sc->stats.overruns;
+      ne_reset(sc);
+      /* Reenable device interrupts.  */
+      if (from_irq_handler)
+        outport_byte(port + IMR, NE_INTERRUPTS);
+      return;
+    }
+
+    /* Check for transmitted packet.  The transmit daemon may now be
+       able to send another packet to the device.  */
+    if ((status & (MSK_PTX | MSK_TXE)) != 0)
+    {
+      ifp->if_timer = 0;
+      ++sc->stats.tx_acks;
+      --sc->inuse;
+      sc->transmitting = 0;
+      if (sc->inuse > 0 || (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) != 0)
+        rtems_bsdnet_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
+    }
+
+    /* Check for received packet.  */
+    if ((status & (MSK_PRX | MSK_RXE)) != 0)
+    {
+      ++sc->stats.rx_acks;
+      rtems_bsdnet_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);
+    }
+
+    /* Check for counter change.  */
+    if ((status & MSK_CNT) != 0)
+    {
+      unsigned char add;
+      inport_byte (port + CNTR0, add);
+      sc->stats.rx_frame_errors += add;
+      inport_byte (port + CNTR1, add);
+      sc->stats.rx_crc_errors += add;
+      inport_byte (port + CNTR2, add);
+      sc->stats.rx_missed_errors += add;
+    }
+
+    break;
+  }
+
+  outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
+
+}
+
+/* Handle an NE2000 interrupt.  */
+
+static void
+ne_interrupt_handler (void *arg)
+{
+  struct ne_softc *sc = arg;
+
+  if (sc == NULL)
+    return;
+
+  ++sc->stats.interrupts;
+
+#ifdef DEBUG_NE
+  printk("!");
+#endif
+  ne_check_status(sc, 1);
+}
+
+/* Turn NE2000 interrupts on.  */
+
+static void
+ne_interrupt_on (struct ne_softc *sc)
+{
+#ifdef DEBUG_NE
+  printk ("ne_interrupt_on()\n");
+#endif
+  if (sc != NULL)
+    outport_byte (sc->port + IMR, NE_INTERRUPTS);
+}
+
+/* Initialize the NE2000 hardware.  */
+
+static void
+ne_init_hardware (struct ne_softc *sc)
+{
+  unsigned int port = sc->port;
+  int i;
+
+#ifdef DEBUG_NE2000
+  printk ("ne_init_hardware()\n");
+#endif
+
+  /* Initialize registers.  */
+
+  /* Set interface for page 0, Remote DMA complete, Stopped */
+  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+  /* Set FIFO threshold to 8, No auto-init Remote DMA, byte order=80x86 */
+  /* byte-wide DMA xfers */
+  if (sc->byte_transfers)
+    outport_byte (port + DCR, MSK_FT10 | MSK_BMS);
+  /* word-wide DMA xfers */
+  else
+    outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
+
+  /* Clear Remote Byte Count Registers */
+  outport_byte (port + RBCR0, 0);
+  outport_byte (port + RBCR1, 0);
+
+  /* For the moment, don't store incoming packets in memory. */
+  outport_byte (port + RCR, MSK_MON);
+
+  /* Place NIC in internal loopback mode */
+  outport_byte (port + TCR, MSK_LOOP);
+
+  /* Initialize transmit/receive (ring-buffer) Page Start */
+  outport_byte (port + TPSR, NE_FIRST_TX_PAGE);
+  outport_byte (port + PSTART, NE_FIRST_RX_PAGE);
+
+  /* Initialize Receiver (ring-buffer) Page Stop and Boundary */
+  outport_byte (port + PSTOP, NE_STOP_PAGE);
+  outport_byte (port + BNRY, NE_STOP_PAGE - 1);
+
+  /* Clear all interrupts */
+  outport_byte (port + ISR, 0xff);
+  /* Disable all interrupts */
+  outport_byte (port + IMR, 0);
+
+  /* Program Command Register for page 1 */
+  outport_byte (port + CMDR, MSK_PG1 | MSK_RD2 | MSK_STP);
+
+  /* Set the Ethernet hardware address.  */
+  for (i = 0; i < ETHER_ADDR_LEN; ++i)
+    outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]);
+
+  /* Set Current Page pointer to next_packet */
+  outport_byte (port + CURR, NE_FIRST_RX_PAGE);
+
+  /* Clear the multicast address.  */
+  for (i = 0; i < MARsize; ++i)
+    outport_byte (port + MAR + i, 0);
+
+  /* Set page 0 registers */
+  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+  /* accept broadcast */
+  outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0));
+
+  /* Start interface */
+  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
+
+  /* Take interface out of loopback */
+  outport_byte (port + TCR, 0);
+}
+
+/* Set up interrupts.
+*/
+static void
+ne_init_irq_handler(struct ne_softc *sc)
+{
+  rtems_status_code status = RTEMS_SUCCESSFUL;
+
+#ifdef DEBUG_NE
+  printk("ne_init_irq_handler(%d)\n", sc->irno);
+#endif
+
+  status = rtems_interrupt_handler_install(
+    sc->irno,
+    "RTL8019",
+    RTEMS_INTERRUPT_UNIQUE,
+    ne_interrupt_handler,
+    sc
+  );
+  assert(status == RTEMS_SUCCESSFUL);
+  ne_interrupt_on(sc);
+}
+
+/* The NE2000 packet receive daemon.  This task is started when the
+   NE2000 driver is initialized.  */
+
+#ifdef DEBUG_NE
+static int ccc = 0; /* experinent! */
+#endif
+
+static void
+ne_rx_daemon (void *arg)
+{
+  struct ne_softc *sc = (struct ne_softc *) arg;
+  struct ifnet *ifp = &sc->arpcom.ac_if;
+  unsigned int port = sc->port;
+
+  while (1)
+  {
+    rtems_event_set events;
+
+    /* Wait for the interrupt handler to tell us that there is a
+       packet ready to receive.  */
+    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+                                RTEMS_WAIT | RTEMS_EVENT_ANY,
+                                RTEMS_NO_TIMEOUT,
+                                &events);
+
+    /* Don't let the device interrupt us now.  */
+    outport_byte (port + IMR, 0);
+
+    while (1)
+    {
+      unsigned char startpage, currpage;
+      unsigned short len;
+      unsigned char next, cnt1, cnt2;
+      struct mbuf *m = NULL;
+      unsigned char *p;
+      int startaddr;
+      int toend;
+      struct ether_header *eh;
+      struct ne_ring hdr; /* ring buffer header */
+      int reset;
+
+      inport_byte (port + BNRY, startpage);
+
+      outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
+      inport_byte (port + CURR, currpage);
+      outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
+
+      ++startpage;
+      if (startpage >= NE_STOP_PAGE)
+        startpage = NE_FIRST_RX_PAGE;
+
+      if (startpage == currpage)
+        break;
+
+#ifdef DEBUG_NE2000
+      printk ("ne_rx_daemon: start page %x; current page %x\n",
+              startpage, currpage);
+#endif
+
+      reset = 0;
+
+      /* Read the buffer header */
+      startaddr = startpage * NE_PAGE_SIZE;
+      ne_read_data(sc, startaddr, sizeof(hdr), (unsigned char *)&hdr);
+      next = hdr.next;
+
+      if (next >= NE_STOP_PAGE)
+        next = NE_FIRST_RX_PAGE;
+
+      /* check packet length */
+      len = hdr.count;
+      if (currpage < startpage)
+        cnt1 = currpage + (NE_STOP_PAGE - NE_FIRST_RX_PAGE) - startpage;
+      else
+        cnt1 = currpage - startpage;
+      cnt2 = len / NE_PAGE_SIZE;
+      if (len % NE_PAGE_SIZE)
+        cnt2++;
+      if (cnt1 < cnt2)
+      {
+#ifdef DEBUG_NE
+        printk("(%x<%x:%x)\n", cnt1, cnt2, len);
+/*
+        printk("start page 0x%x; current page 0x%x\n",
+                startpage, currpage);
+        printk("cnt1 < cnt2 (0x%x, 0x%x); len 0x%x\n",
+                cnt1, cnt2, len);
+*/
+#endif
+        reset = 1;
+      }
+      if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) ||
+          len < (ETHER_MIN_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) ||
+          len > MCLBYTES)
+      {
+#ifdef DEBUG_NE
+        printk("(%x)", len);
+
+        printk("start page 0x%x; current page 0x%x\n",
+                startpage, currpage);
+        printk("len out of range: 0x%x\n", len);
+        printk("stat: 0x%x, next: 0x%x\n", hdr.rsr, hdr.next);
+#endif
+        reset = 1;
+      }
+#ifdef DEBUG_NE
+      if (++ccc == 100)
+      { ccc = 0; reset = 1;
+        printk("T");
+      }
+#endif
+
+      /* reset interface */
+      if (reset)
+      {
+	printk("Reset in RX\n");
+        ne_reset(sc);
+        goto Next;
+      }
+
+      /* The first four bytes of the length are the buffer header
+       * Just decrease them by 2 since in ARM, we have to make sure
+       * 4bytes memory access align on 4bytes
+       */
+      len -= 2;
+      startaddr += 2;
+
+      MGETHDR (m, M_WAIT, MT_DATA);
+      MCLGET (m, M_WAIT);
+
+      if (m == NULL)
+	panic ("ne_rx_daemon");
+
+      m->m_pkthdr.rcvif = ifp;
+      m->m_nextpkt = 0;
+
+      p = mtod (m, unsigned char *);
+      m->m_len = m->m_pkthdr.len = len - (sizeof(struct ether_header) + 2);
+
+      toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr;
+      if (toend < len)
+	{
+	  ne_read_data (sc, startaddr, toend, p);
+	  p += toend;
+	  len -= toend;
+	  startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE;
+	}
+
+      if (len > 0)
+        ne_read_data (sc, startaddr, len, p);
+
+      m->m_data +=2;
+      eh = mtod(m, struct ether_header *);
+      m->m_data += sizeof (struct ether_header);
+
+#ifdef DEBUG_NE
+      /*printk("[r%d]", hdr.count - sizeof(hdr));*/
+      printk("<\n");
+#endif
+      ether_input (ifp, eh, m);
+      ++sc->stats.rx_packets;
+      outport_byte (port + BNRY, next - 1);
+    }
+
+    if (sc->overrun) {
+      outport_byte (port + ISR, MSK_OVW);
+      outport_byte (port + TCR, 0);
+      if (sc->resend)
+        outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
+      sc->resend = 0;
+      sc->overrun = 0;
+    }
+
+  Next:
+    /* Reenable device interrupts.  */
+    outport_byte (port + IMR, NE_INTERRUPTS);
+  }
+}
+
+/* Load an NE2000 packet onto the device.  */
+
+static void
+ne_loadpacket (struct ne_softc *sc, struct mbuf *m)
+{
+  unsigned int port = sc->port;
+  unsigned int dport = port + DATAPORT;
+  struct mbuf *mhold = m;
+  int leftover;
+  unsigned char leftover_data;
+  int timeout;
+  int send_cnt = 0;
+
+#ifdef DEBUG_NE2000
+  printk ("Uploading NE2000 packet\n");
+#endif
+
+  /* Reset remote DMA complete flag.  */
+  outport_byte (port + ISR, MSK_RDC);
+
+  /* Write out the count.  */
+  outport_byte (port + RBCR0, m->m_pkthdr.len);
+  outport_byte (port + RBCR1, m->m_pkthdr.len >> 8);
+
+  sc->sendlen[sc->nextavail] = m->m_pkthdr.len;
+
+  /* Tell the device which address we want to write to.  */
+  outport_byte (port + RSAR0, 0);
+  outport_byte (port + RSAR1,
+                NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES));
+
+  /* Set up the write.  */
+  outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA);
+
+  /* Transfer the mbuf chain to device memory.  NE2000 devices require
+     that the data be transferred as words, so we need to handle odd
+     length mbufs.  Never occurs if we force byte transfers. */
+
+  leftover = 0;
+  leftover_data = '\0';
+
+  for (; m != NULL; m = m->m_next) {
+    int len;
+    unsigned char *data;
+
+    len = m->m_len;
+    if (len == 0)
+      continue;
+
+    data = mtod (m, unsigned char *);
+
+    if (leftover) {
+      unsigned char next;
+
+      /* Data left over from previous mbuf in chain.  */
+      next = *data++;
+      --len;
+      outport_word (dport, leftover_data | (next << 8));
+      send_cnt += 2;
+      leftover = 0;
+    }
+
+    /* If using byte transfers, len always ends up as zero so
+       there are no leftovers. */
+
+    if (sc->byte_transfers)
+      while (len > 0) {
+        outport_byte (dport, *data++);
+        len--;
+      }
+    else
+      while (len > 1) {
+        outport_word (dport, data[0] | (data[1] << 8));
+        data += 2;
+        len -= 2;
+        send_cnt += 2;
+      }
+
+    if (len > 0)
+      {
+        leftover = 1;
+        leftover_data = *data++;
+      }
+  }
+
+  if (leftover)
+  {
+    outport_word (dport, leftover_data);
+    send_cnt += 2;
+  }
+
+#ifdef DEBUG_NE
+  /* printk("{l%d|%d}", send_cnt, sc->nextavail); */
+  printk("v");
+#endif
+  m_freem (mhold);
+
+  /* Wait for the device to complete accepting the data, with a
+     limiting counter so that we don't wait too long.  */
+  for (timeout = 0; timeout < 1000; ++timeout)
+    {
+      unsigned char status;
+
+      inport_byte (port + ISR, status);
+
+#ifdef DEBUG_NE2000
+      if ((status &~ MSK_RDC) != 0)
+        printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n",
+                status);
+#endif
+
+      if ((status & MSK_RDC) != 0) {
+        outport_byte (port + ISR, MSK_RDC);
+        break;
+      }
+    }
+
+  if (timeout >= 1000)
+    printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n");
+
+  ++sc->nextavail;
+  if (sc->nextavail == NE_TX_BUFS)
+    sc->nextavail = 0;
+}
+
+/* Tell the NE2000 to transmit a buffer whose contents we have already
+   loaded onto the device.  */
+
+static void
+ne_transmit (struct ne_softc *sc)
+{
+  struct ifnet *ifp = &sc->arpcom.ac_if;
+  unsigned int port = sc->port;
+  int len;
+
+#ifdef DEBUG_NE2000
+  printk ("Transmitting NE2000 packet\n");
+#endif
+
+  len = sc->sendlen[sc->nextsend];
+  if (len < ET_MINLEN)
+    len = ET_MINLEN;
+  outport_byte (port + TBCR0, len);
+  outport_byte (port + TBCR1, len >> 8);
+
+  outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES));
+
+  outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
+
+#ifdef DEBUG_NE
+  /* printk("{s%d|%d}", len, sc->nextsend); */
+  printk(">");
+#endif
+  ++sc->nextsend;
+  if (sc->nextsend == NE_TX_BUFS)
+    sc->nextsend = 0;
+
+  ++sc->stats.tx_packets;
+
+  /* set watchdog timer */
+  ifp->if_timer = 2;
+}
+
+/* The NE2000 packet transmit daemon.  This task is started when the
+   NE2000 driver is initialized.  */
+
+static void
+ne_tx_daemon (void *arg)
+{
+  struct ne_softc *sc = (struct ne_softc *) arg;
+  unsigned int port = sc->port;
+  struct ifnet *ifp = &sc->arpcom.ac_if;
+
+  while (1) {
+    rtems_event_set events;
+
+    /* Wait for a packet to be ready for sending, or for there to be
+       room for another packet in the device memory.  */
+    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
+                                RTEMS_EVENT_ANY | RTEMS_WAIT,
+                                RTEMS_NO_TIMEOUT,
+                                &events);
+
+#ifdef DEBUG_NE2000
+    printk ("ne_tx_daemon\n");
+#endif
+
+    /* This daemon handles both uploading data onto the device and
+       telling the device to transmit data which has been uploaded.
+       These are separate tasks, because while the device is
+       transmitting one buffer we will upload another.  */
+
+    /* Don't let the device interrupt us now.  */
+    outport_byte (port + IMR, 0);
+
+    while (1) {
+      struct mbuf *m;
+
+      /* If the device is not transmitting a packet, and we have
+         uploaded a packet, tell the device to transmit it.  */
+      if (! sc->transmitting && sc->inuse > 0) {
+        sc->transmitting = 1;
+        ne_transmit (sc);
+      }
+
+      /* If we don't have any more buffers to send, quit now.  */
+      if (ifp->if_snd.ifq_head == NULL) {
+        ifp->if_flags &= ~IFF_OACTIVE;
+        break;
+      }
+
+      /* Allocate a buffer to load data into.  If there are none
+         available, quit until a buffer has been transmitted.  */
+      if (sc->inuse >= NE_TX_BUFS)
+        break;
+
+      ++sc->inuse;
+
+      IF_DEQUEUE (&ifp->if_snd, m);
+      if (m == NULL)
+        panic ("ne_tx_daemon");
+
+      ne_loadpacket (sc, m);
+
+      /* Check the device status.  It may have finished transmitting
+         the last packet.  */
+      ne_check_status(sc, 0);
+    }
+
+    /* Reenable device interrupts.  */
+    outport_byte (port + IMR, NE_INTERRUPTS);
+  }
+}
+
+/* Start sending an NE2000 packet.  */
+
+static void
+ne_start (struct ifnet *ifp)
+{
+  struct ne_softc *sc = ifp->if_softc;
+
+#ifdef DEBUG_NE
+  printk("S");
+#endif
+  /* Tell the transmit daemon to wake up and send a packet.  */
+  rtems_bsdnet_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
+  ifp->if_flags |= IFF_OACTIVE;
+}
+
+/* Initialize and start and NE2000.  */
+
+static void
+ne_init (void *arg)
+{
+  struct ne_softc *sc = (struct ne_softc *) arg;
+  struct ifnet *ifp = &sc->arpcom.ac_if;
+
+#ifdef DEBUG_NE
+  printk("ne_init()\n");
+  ne_dump(sc);
+#endif
+
+  /* only once... */
+  if (sc->tx_daemon_tid == 0)
+  {
+    sc->inuse = 0;
+    sc->nextavail = 0;
+    sc->nextsend = 0;
+    sc->transmitting = 0;
+
+    ne_init_hardware (sc);
+
+    sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc);
+    sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc);
+
+    /* install rtems irq handler */
+    ne_init_irq_handler(sc);
+  }
+
+  ifp->if_flags |= IFF_RUNNING;
+}
+
+/* Stop an NE2000.  */
+
+static void
+ne_stop (struct ne_softc *sc)
+{
+  sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+
+  ne_stop_hardware(sc);
+
+  sc->inuse = 0;
+  sc->nextavail = 0;
+  sc->nextsend = 0;
+  sc->transmitting = 0;
+  sc->overrun = 0;
+  sc->resend = 0;
+}
+
+static void
+ne_stop_hardware (struct ne_softc *sc)
+{
+  unsigned int port = sc->port;
+  int i;
+
+  /* Stop everything.  */
+  outport_byte (port + CMDR, MSK_STP | MSK_RD2);
+
+  /* Wait for the interface to stop, using I as a time limit.  */
+  for (i = 0; i < 5000; ++i)
+    {
+      unsigned char status;
+
+      inport_byte (port + ISR, status);
+      if ((status & MSK_RST) != 0)
+        break;
+    }
+}
+
+/* reinitializing interface
+*/
+static void
+ne_reset(struct ne_softc *sc)
+{
+  ne_stop(sc);
+  ne_init_hardware(sc);
+  sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
+  sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+#ifdef DEBUG_NE
+  printk("*");
+#endif
+}
+
+#ifdef DEBUG_NE
+/* show anything about ne
+*/
+static void
+ne_dump(struct ne_softc *sc)
+{
+  int i;
+  printk("\nne configuration:\n");
+  printk("ethernet addr:");
+  for (i=0; i<ETHER_ADDR_LEN; i++)
+    printk(" %x", sc->arpcom.ac_enaddr[i]);
+  printk("\n");
+  printk("irq = %d\n", sc->irno);
+  printk("port = 0x%x\n", sc->port);
+  printk("accept_broadcasts = %d\n", sc->accept_broadcasts);
+  printk("byte_transfers = %d\n", sc->byte_transfers);
+}
+#endif
+
+/* Show NE2000 interface statistics.  */
+
+static void
+ne_stats (struct ne_softc *sc)
+{
+  printf ("    Received packets: %-8lu", sc->stats.rx_packets);
+  printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets);
+  printf ("        Receive acks: %-8lu", sc->stats.rx_acks);
+  printf ("       Transmit acks: %-8lu\n", sc->stats.tx_acks);
+  printf ("     Packet overruns: %-8lu", sc->stats.overruns);
+  printf ("        Frame errors: %-8lu\n", sc->stats.rx_frame_errors);
+  printf ("          CRC errors: %-8lu", sc->stats.rx_crc_errors);
+  printf ("      Missed packets: %-8lu\n", sc->stats.rx_missed_errors);
+  printf ("          Interrupts: %-8lu\n", sc->stats.interrupts);
+}
+
+/* NE2000 driver ioctl handler.  */
+
+static int
+ne_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
+{
+  struct ne_softc *sc = ifp->if_softc;
+  int error = 0;
+
+  switch (command) {
+  case SIOCGIFADDR:
+  case SIOCSIFADDR:
+    error = ether_ioctl (ifp, command, data);
+    break;
+
+  case SIOCSIFFLAGS:
+    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+    case IFF_RUNNING:
+      ne_stop (sc);
+      break;
+
+    case IFF_UP:
+      printk("IFF_UP\n");
+      ne_init (sc);
+      break;
+
+    case IFF_UP | IFF_RUNNING:
+      ne_stop (sc);
+      ne_init (sc);
+      break;
+
+    default:
+      break;
+    }
+    break;
+
+  case SIO_RTEMS_SHOW_STATS:
+    ne_stats (sc);
+    break;
+
+    /* FIXME: Multicast commands must be added here.  */
+
+  default:
+    error = EINVAL;
+    break;
+  }
+
+  return error;
+}
+
+/*
+ * Device timeout/watchdog routine. Entered if the device neglects to
+ *	generate an interrupt after a transmit has been started on it.
+ */
+static void
+ne_watchdog(struct ifnet *ifp)
+{
+  struct ne_softc *sc = ifp->if_softc;
+
+  printk("ne2000: device timeout\n");
+    ifp->if_oerrors++;
+
+  ne_reset(sc);
+}
+
+static void
+print_byte(unsigned char b)
+{
+  printk("%x%x", b >> 4, b & 0x0f);
+}
+
+/* Attach an NE2000 driver to the system.  */
+
+int
+rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach)
+{
+  int i;
+  struct ne_softc *sc;
+  struct ifnet *ifp;
+  int mtu;
+
+  /* dettach ... */
+  if (!attach)
+    return 0;
+
+  /* Find a free driver.  */
+  sc = NULL;
+  for (i = 0; i < NNEDRIVER; ++i) {
+    sc = &ne_softc[i];
+    ifp = &sc->arpcom.ac_if;
+    if (ifp->if_softc == NULL)
+      break;
+  }
+
+  if (sc == NULL) {
+    printf ("Too many NE2000 drivers.\n");
+    return 0;
+  }
+
+  memset (sc, 0, sizeof *sc);
+
+  /* Check whether we do byte-wide or word-wide transfers.  */
+
+#ifdef NE2000_BYTE_TRANSFERS
+  sc->byte_transfers = true;
+#else
+  sc->byte_transfers = false;
+#endif
+
+  /* Handle the options passed in by the caller.  */
+
+  if (config->mtu != 0)
+    mtu = config->mtu;
+  else
+    mtu = ETHERMTU;
+
+    /* We use 16 as the default IRQ.  */
+  sc->irno = XSCALE_IRQ_NETWORK;
+
+
+
+  /*IO prts are mapped to 0X40000600 */
+  sc->port = 0x40000600;
+
+  sc->accept_broadcasts = ! config->ignore_broadcast;
+
+  if (config->hardware_address != NULL)
+    memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
+            ETHER_ADDR_LEN);
+  else
+    {
+      unsigned char prom[16];
+      int ia;
+
+      /* Read the PROM to get the Ethernet hardware address.  */
+
+      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+      if (sc->byte_transfers) {
+        outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS);
+      }
+      else {
+        outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
+      }
+
+      outport_byte (sc->port + RBCR0, 0);
+      outport_byte (sc->port + RBCR1, 0);
+      outport_byte (sc->port + RCR, MSK_MON);
+      outport_byte (sc->port + TCR, MSK_LOOP);
+      outport_byte (sc->port + IMR, 0);
+      outport_byte (sc->port + ISR, 0xff);
+
+      ne_read_data (sc, 0, sizeof prom, prom);
+
+      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+      for (ia = 0; ia < ETHER_ADDR_LEN; ++ia)
+        sc->arpcom.ac_enaddr[ia] = prom[ia * 2];
+    }
+
+  /* Set up the network interface.  */
+
+  ifp->if_softc = sc;
+  ifp->if_unit = i + 1;
+  ifp->if_name = "ne";
+  ifp->if_mtu = mtu;
+  ifp->if_init = ne_init;
+  ifp->if_ioctl = ne_ioctl;
+  ifp->if_watchdog = ne_watchdog;
+  ifp->if_start = ne_start;
+  ifp->if_output = ether_output;
+  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
+  if (ifp->if_snd.ifq_maxlen == 0)
+    ifp->if_snd.ifq_maxlen = ifqmaxlen;
+
+  /* Attach the interface.  */
+
+  if_attach (ifp);
+  ether_ifattach (ifp);
+
+  printk("network device '%s' <", config->name);
+  print_byte(sc->arpcom.ac_enaddr[0]);
+  for (i=1; i<ETHER_ADDR_LEN; i++)
+  { printk(":");
+    print_byte(sc->arpcom.ac_enaddr[i]);
+  }
+  printk("> initialized on port 0x%x, irq %d\n", sc->port, sc->irno);
+
+  return 1;
+}
Index: bsps/arm/gumstix/net/wd80x3.h
===================================================================
--- bsps/arm/gumstix/net/wd80x3.h	(revision 031df3914990db0336a0d386fb53558b05de467e)
+++ bsps/arm/gumstix/net/wd80x3.h	(revision 031df3914990db0336a0d386fb53558b05de467e)
@@ -0,0 +1,303 @@
+/**
+ * @file
+ * @ingroup gumstix_dp8390
+ * @brief DP8390 Ethernet Controller Support
+ */
+
+/*
+ *  Information about the DP8390 Ethernet controller.
+ */
+
+#ifndef __BSP_WD80x3_h
+#define __BSP_WD80x3_h
+
+/* Register descriptions */
+
+/**
+ * @defgroup gumstix_dp8390 DP8390 Support
+ * @ingroup arm_gumstix
+ * @brief DP8390 Ethernet Controller Support
+ * @{
+ */
+
+/**
+ * @name Controller DP8390.
+ * @{
+ */
+
+/** @brief Port Window. */
+#define DATAPORT	0x10
+/** @brief Issue a read for reset */
+#define RESET		0x1f
+/** @brief I/O port definition */
+#define W83CREG		0x00
+#define	ADDROM		0x08
+
+/** @} */
+
+/**
+ * @name page 0 read or read/write registers
+ * @{
+ */
+
+#define	CMDR		0x00+RO
+/** @brief current local dma addr 0 for read */
+#define CLDA0  		0x01+RO
+/** @brief current local dma addr 1 for read */
+#define CLDA1  		0x02+RO
+/** @brief boundary reg for rd and wr */
+#define BNRY   		0x03+RO
+/** @brief tx status reg for rd */
+#define TSR    		0x04+RO
+/** @brief number of collision reg for rd */
+#define NCR    		0x05+RO
+/** @breif FIFO for rd */
+#define FIFO   		0x06+RO
+/** @brief interrupt status reg for rd and wr */
+#define ISR    		0x07+RO
+/** @brief current remote dma address 0 for rd */
+#define CRDA0  		0x08+RO
+/** @brief current remote dma address 1 for rd */
+#define CRDA1  		0x09+RO
+/** @brief rx status reg for rd */
+#define RSR    		0x0C+RO
+/** @brief tally cnt 0 for frm alg err for rd */
+#define CNTR0  		0x0D+RO
+/** @brief tally cnt 1 for crc err for rd */
+#define CNTR1  		RO+0x0E
+/** @brief tally cnt 2 for missed pkt for rd */
+#define CNTR2  		0x0F+RO
+
+/** @} */
+
+/**
+ * @name page 0 write registers
+ * @{
+ */
+
+/** @brief page start register */
+#define PSTART 		0x01+RO
+/** @brief page stop register */
+#define PSTOP  		0x02+RO
+/** @breif tx start page start reg */
+#define TPSR   		0x04+RO
+/** @brief tx byte count 0 reg */
+#define TBCR0  		0x05+RO
+/** @brief tx byte count 1 reg */
+#define TBCR1  		0x06+RO
+/** @brief remote start address reg 0  */
+#define RSAR0  		0x08+RO
+/** @brief remote start address reg 1 */
+#define RSAR1  		0x09+RO
+/** @brief remote byte count reg 0 */
+#define RBCR0  		0x0A+RO
+/** @brief remote byte count reg 1 */
+#define RBCR1  		0x0B+RO
+/** @brief rx configuration reg */
+#define RCR    		0x0C+RO
+/** @brief tx configuration reg */
+#define TCR    		0x0D+RO
+/** @brief data configuration reg */
+#define DCR    		RO+0x0E
+/** @brief interrupt mask reg */
+#define IMR    		0x0F+RO
+
+/** @} */
+
+/**
+ * @name page 1 registers
+ * @{
+ */
+
+/** @brief physical addr reg base for rd and wr */
+#define PAR   		0x01+RO
+/** @brief current page reg for rd and wr */
+#define CURR   		0x07+RO
+/** @brief multicast addr reg base fro rd and WR */
+#define MAR   		0x08+RO
+/** @brief size of multicast addr space */
+#define MARsize	8
+
+/** @} */
+
+/**
+ * @name W83CREG command bits
+ * @{
+ */
+
+/** @brief W83CREG masks */
+#define MSK_RESET  0x80
+#define MSK_ENASH  0x40
+/** @brief memory decode bits, corresponding */
+#define MSK_DECOD  0x3F
+
+/** @} */
+
+/**
+ * @name CMDR command bits
+ * @{
+ */
+
+/** @brief stop the chip */
+#define MSK_STP		0x01
+/** @brief start the chip */
+#define MSK_STA		0x02
+/** @brief initial txing of a frm */
+#define MSK_TXP	       	0x04
+/** @brief remote read */
+#define MSK_RRE		0x08
+/** @brief remote write */
+#define MSK_RWR		0x10
+/** @brief no DMA used */
+#define MSK_RD2		0x20
+/** @brief select register page 0 */
+#define MSK_PG0	       	0x00
+/** @brief select register page 1 */
+#define MSK_PG1	       	0x40
+/** @brief select register page 2 */
+#define MSK_PG2	       	0x80
+
+/** @} */
+
+/**
+ * @name ISR and TSR status bits
+ * @{
+ */
+
+/* @brief rx with no error */
+#define MSK_PRX 	0x01
+/* @brief tx with no error */
+#define MSK_PTX 	0x02
+/* @brief rx with error */
+#define MSK_RXE 	0x04
+/* @brief tx with error */
+#define MSK_TXE 	0x08
+/* @brief overwrite warning */
+#define MSK_OVW 	0x10
+/* @brief MSB of one of the tally counters is set */
+#define MSK_CNT 	0x20
+/* @brief remote dma completed */
+#define MSK_RDC 	0x40
+/* @brief reset state indicator */
+#define MSK_RST		0x80
+
+/** @} */
+
+/**
+ * @name DCR command bits
+ * @{
+ */
+
+/** @brief word transfer mode selection */
+#define MSK_WTS		0x01
+/** @brief byte order selection */
+#define MSK_BOS		0x02
+/** @brief long addr selection */
+#define MSK_LAS		0x04
+/** @brief burst mode selection */
+#define MSK_BMS		0x08
+/** @brief autoinitialize remote */
+#define MSK_ARM		0x10
+/** @brief burst lrngth selection */
+#define MSK_FT00	0x00
+/** @brief burst lrngth selection */
+#define MSK_FT01	0x20
+/** @brief burst lrngth selection */
+#define MSK_FT10	0x40
+/** @brief burst lrngth selection */
+#define MSK_FT11	0x60
+
+/** @} */
+
+/**
+ * @name RCR command bits
+ * @{
+ */
+
+/** @brief save error pkts */
+#define MSK_SEP		0x01
+/** @brief accept runt pkt */
+#define MSK_AR	 	0x02
+/** @brief 8390 RCR */
+#define MSK_AB		0x04
+/** @brief accept multicast  */
+#define MSK_AM	 	0x08
+/** @brief accept all pkt with physical adr */
+#define MSK_PRO		0x10
+/** @brief monitor mode */
+#define MSK_MON		0x20
+
+/** @} */
+
+/**
+ * @name TCR command bits
+ * @{
+ */
+
+/** @brief inhibit CRC, do not append crc */
+#define MSK_CRC		0x01
+/** @brief set loopback mode */
+#define MSK_LOOP	0x02
+/** @brief Accept broadcasts */
+#define MSK_BCST	0x04
+/** @brief encoded loopback control */
+#define MSK_LB01	0x06
+/** @brief auto tx disable */
+#define MSK_ATD		0x08
+/** @brief collision offset enable  */
+#define MSK_OFST	0x10
+
+/** @} */
+
+/**
+ * @name receive status bits
+ * @{
+ */
+
+/** @brief rx without error */
+#define SMK_PRX   0x01
+/** @brief CRC error */
+#define SMK_CRC   0x02
+/** @brief frame alignment error */
+#define SMK_FAE   0x04
+/** @brief FIFO overrun */
+#define SMK_FO    0x08
+/** @brief missed pkt */
+#define SMK_MPA   0x10
+/** @brief physical/multicase address */
+#define SMK_PHY   0x20
+/** @brief receiver disable. set in monitor mode */
+#define SMK_DIS   0x40
+/** @brief deferring */
+#define SMK_DEF	  0x80
+
+/** @} */
+
+/**
+ * @name transmit status bits
+ * @{
+ */
+
+/** @brief tx without error */
+#define SMK_PTX   0x01
+/** @brief non deferred tx */
+#define SMK_DFR   0x02
+/** @brief tx collided */
+#define SMK_COL   0x04
+/** @brief tx abort because of excessive collisions */
+#define SMK_ABT   0x08
+/** @brief carrier sense lost */
+#define SMK_CRS   0x10
+/** @brief FIFO underrun */
+#define SMK_FU    0x20
+/** @brief collision detect heartbeat */
+#define SMK_CDH   0x40
+/** @brief out of window collision */
+#define SMK_OWC	  0x80
+
+/** @} */
+
+/** @} */
+
+#endif
+/* end of include */
