summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2009-08-21 17:49:31 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2009-08-21 17:49:31 +0000
commita17bc421735489d6935c486814332ae1b4e4b84e (patch)
treeb6929be47db1bf3ed9feae13a122e14ea9479d6b /c
parent2009-08-21 Xi Yang <hiyangxi@gmail.com> (diff)
downloadrtems-a17bc421735489d6935c486814332ae1b4e4b84e.tar.bz2
2009-08-21 Xi Yang <hiyangxi@gmail.com>
* Makefile.am: Add fb/fb.c add rtl8019 Ethernet card support * preinstall.am: Install skyeye_fb.h, Install wd80x3 * fb/fb.c, fb/skyeye_fb.h: Framebuffer support for skyeye simulator * rtl8019/wd80x3, rtl8019/rtl8019.c: rtl8019 support * startup/memmap.c: Change the size of Map I/O to 1216M * bsp/bsp.h: Add rtl8019 related infomation
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/arm/gumstix/ChangeLog9
-rwxr-xr-xc/src/lib/libbsp/arm/gumstix/Makefile.am15
-rwxr-xr-xc/src/lib/libbsp/arm/gumstix/configure.ac1
-rw-r--r--c/src/lib/libbsp/arm/gumstix/fb/fb.c174
-rwxr-xr-xc/src/lib/libbsp/arm/gumstix/include/bsp.h19
-rwxr-xr-xc/src/lib/libbsp/arm/gumstix/preinstall.am2
-rw-r--r--c/src/lib/libbsp/arm/gumstix/rtl8019/rtl8019.c1259
-rw-r--r--c/src/lib/libbsp/arm/gumstix/rtl8019/wd80x3.h133
-rwxr-xr-xc/src/lib/libbsp/arm/gumstix/startup/memmap.c2
9 files changed, 1613 insertions, 1 deletions
diff --git a/c/src/lib/libbsp/arm/gumstix/ChangeLog b/c/src/lib/libbsp/arm/gumstix/ChangeLog
index 06e5db0467..5b1b4d4313 100644
--- a/c/src/lib/libbsp/arm/gumstix/ChangeLog
+++ b/c/src/lib/libbsp/arm/gumstix/ChangeLog
@@ -1,3 +1,12 @@
+2009-08-21 Xi Yang <hiyangxi@gmail.com>
+
+ * Makefile.am: Add fb/fb.c add rtl8019 Ethernet card support
+ * preinstall.am: Install skyeye_fb.h, Install wd80x3
+ * fb/fb.c, fb/skyeye_fb.h: Framebuffer support for skyeye simulator
+ * rtl8019/wd80x3, rtl8019/rtl8019.c: rtl8019 support
+ * startup/memmap.c: Change the size of Map I/O to 1216M
+ * bsp/bsp.h: Add rtl8019 related infomation
+
2009-07-16 Joel Sherrill <joel.sherrill@oarcorp.com>
* configure.ac: Rename BSP_BOOTCARD_OPTIONS to
diff --git a/c/src/lib/libbsp/arm/gumstix/Makefile.am b/c/src/lib/libbsp/arm/gumstix/Makefile.am
index 89d71abfa9..9943917c8b 100755
--- a/c/src/lib/libbsp/arm/gumstix/Makefile.am
+++ b/c/src/lib/libbsp/arm/gumstix/Makefile.am
@@ -40,6 +40,17 @@ libbsp_a_SOURCES += ../../shared/bsplibc.c ../../shared/bsppost.c \
libbsp_a_SOURCES += console/uarts.c ../../shared/console.c
#abort
libbsp_a_SOURCES += ../shared/abort/abort.c
+#framebuffer
+if ON_SKYEYE
+libbsp_a_SOURCES += fb/fb.c
+if HAS_NETWORKING
+rtl8019_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
+noinst_PROGRAMS += rtl8019.rel
+rtl8019_rel_SOURCES = rtl8019/rtl8019.c rtl8019/wd80x3.h
+rtl8019_rel_CPPFLAGS = $(AM_CPPFLAGS) $(rtl8019_CPPFLAGS)
+rtl8019_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+endif
+endif
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/shared/arm920.rel \
../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/clock.rel \
@@ -48,5 +59,9 @@ libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/shared/arm920.rel \
../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/irq.rel \
../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/pmc.rel
+if HAS_NETWORKING
+libbsp_a_LIBADD += rtl8019.rel
+endif
+
include $(srcdir)/preinstall.am
include $(top_srcdir)/../../../../automake/local.am
diff --git a/c/src/lib/libbsp/arm/gumstix/configure.ac b/c/src/lib/libbsp/arm/gumstix/configure.ac
index a229a3a7b5..0014b30779 100755
--- a/c/src/lib/libbsp/arm/gumstix/configure.ac
+++ b/c/src/lib/libbsp/arm/gumstix/configure.ac
@@ -21,6 +21,7 @@ RTEMS_BSPOPTS_HELP([ON_SKYEYE],
simulator. Speed up the clock ticks while the idle task is running so
time spent in the idle task is minimized. This significantly reduces
the wall time required to execute the RTEMS test suites.])
+AM_CONDITIONAL(ON_SKYEYE,test "$ON_SKYEYE" = "1")
RTEMS_CHECK_NETWORKING
AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
diff --git a/c/src/lib/libbsp/arm/gumstix/fb/fb.c b/c/src/lib/libbsp/arm/gumstix/fb/fb.c
new file mode 100644
index 0000000000..49b3d1873f
--- /dev/null
+++ b/c/src/lib/libbsp/arm/gumstix/fb/fb.c
@@ -0,0 +1,174 @@
+ /*
+ * By Yang Xi <hiyangxi@gmail.com>.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <pxa255.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+
+#include <rtems/fb.h>
+#include <rtems/framebuffer.h>
+#include <rtems.h>
+
+#define SCREEN_WIDTH 480
+#define SCREEN_HEIGHT 272
+#define BPP 16
+#define LCD_DMA_POINTER (0xa0000000 + 62*(1<<20) + 0x1000)
+#define LCD_BUFFER_SIZE (SCREEN_WIDTH*SCREEN_HEIGHT*2)
+
+
+static struct fb_var_screeninfo fb_var =
+ {
+ .xres = SCREEN_WIDTH,
+ .yres = SCREEN_HEIGHT,
+ .bits_per_pixel = BPP
+ };
+
+static struct fb_fix_screeninfo fb_fix =
+ {
+ .smem_start = (volatile char *)LCD_DMA_POINTER,
+ .smem_len = LCD_BUFFER_SIZE,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .line_length = 80
+ };
+
+static void enable_fbskyeye(void)
+{
+ LCCR1 &= ~LCCR1_PPL;
+ LCCR1 |= (SCREEN_WIDTH -1 ) & LCCR1_PPL;
+ LCCR2 &= ~LCCR2_LPP;
+ LCCR2 |= (SCREEN_HEIGHT/2 -1) & LCCR2_LPP;
+ LCCR3 &= ~LCCR3_BPP;
+ LCCR3 |= 4<<24;
+ FDADR0 = LCD_DMA_POINTER - 0x1000;
+ LCCR0 |= LCCR0_ENB;
+}
+
+
+static void disable_fbskyeye(void)
+{
+ LCCR0 &= ~LCCR0_ENB;
+}
+
+static int get_fix_screen_info( struct fb_fix_screeninfo *info )
+{
+ *info = fb_fix;
+ return 0;
+}
+
+static int get_var_screen_info( struct fb_var_screeninfo *info )
+{
+ *info = fb_var;
+ return 0;
+}
+
+rtems_device_driver
+frame_buffer_initialize(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code status;
+
+ printk( "FBSKYEYE -- driver initializing..\n" );
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name ("/dev/fb", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ printk("Error registering FBSKYEYE device!\n");
+ rtems_fatal_error_occurred( status );
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+
+rtems_device_driver
+frame_buffer_open( rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ /* rtems_status_code status; */
+ printk( "FBSKYEYE open called.\n" );
+ enable_fbskyeye();
+ return RTEMS_SUCCESSFUL;
+}
+
+
+rtems_device_driver
+frame_buffer_close(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ printk( "fbskyeye close called.\n" );
+ disable_fbskyeye();
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver
+frame_buffer_read( rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+ printk( "FBSKYEYE read called.\n" );
+ rw_args->bytes_moved = 0;
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver
+frame_buffer_write( rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+ printk( "FBSKYEY write called.\n" );
+ rw_args->bytes_moved = 0;
+ return RTEMS_SUCCESSFUL;
+}
+
+
+rtems_device_driver
+frame_buffer_control( rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+ )
+{
+ rtems_libio_ioctl_args_t *args = arg;
+ printk( "FBSKYEYE ioctl called, cmd=%x\n", args->command );
+ switch( args->command )
+ {
+ case FBIOGET_FSCREENINFO:
+ args->ioctl_return = get_fix_screen_info( args->buffer );
+ break;
+ case FBIOGET_VSCREENINFO:
+ args->ioctl_return = get_var_screen_info( args->buffer );
+ break;
+ case FBIOPUT_VSCREENINFO:
+ /* not implemented yet*/
+ break;
+ case FBIOGETCMAP:
+ args->ioctl_return = 0;
+ break;
+ case FBIOPUTCMAP:
+ args->ioctl_return = 0;
+ break;
+ default:
+ args->ioctl_return = 0;
+ break;
+
+ }
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/arm/gumstix/include/bsp.h b/c/src/lib/libbsp/arm/gumstix/include/bsp.h
index 326f87f722..83af58ed78 100755
--- a/c/src/lib/libbsp/arm/gumstix/include/bsp.h
+++ b/c/src/lib/libbsp/arm/gumstix/include/bsp.h
@@ -22,6 +22,7 @@ extern "C" {
#include <rtems/clockdrv.h>
#include <libchip/serial.h>
+
/* What is the input clock freq in hertz */
#define BSP_MAIN_FREQ 3686400 /* 3.6864 MHz */
#define BSP_SLCK_FREQ 32768 /* 32.768 KHz */
@@ -42,6 +43,24 @@ extern rtems_configuration_table Configuration;
#define ST_PIMR_PIV 33 /* 33 ticks of the 32.768Khz clock ~= 1msec */
+#define outport_byte(port,val) *((unsigned char volatile*)(port)) = (val)
+#define inport_byte(port,val) (val) = *((unsigned char volatile*)(port))
+#define outport_word(port,val) *((unsigned short volatile*)(port)) = (val)
+#define inport_word(port,val) (val) = *((unsigned short volatile*)(port))
+
+struct rtems_bsdnet_ifconfig;
+extern int rtems_ne_driver_attach(struct rtems_bsdnet_ifconfig *, int);
+#define BSP_NE2000_NETWORK_DRIVER_NAME "ne1"
+#define BSP_NE2000_NETWORK_DRIVER_ATTACH rtems_ne_driver_attach
+
+#ifndef RTEMS_BSP_NETWORK_DRIVER_NAME
+#define RTEMS_BSP_NETWORK_DRIVER_NAME BSP_NE2000_NETWORK_DRIVER_NAME
+#endif
+
+#ifndef RTEMS_BSP_NETWORK_DRIVER_ATTACH
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH BSP_NE2000_NETWORK_DRIVER_ATTACH
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/c/src/lib/libbsp/arm/gumstix/preinstall.am b/c/src/lib/libbsp/arm/gumstix/preinstall.am
index 73323b55bf..6c8531e024 100755
--- a/c/src/lib/libbsp/arm/gumstix/preinstall.am
+++ b/c/src/lib/libbsp/arm/gumstix/preinstall.am
@@ -65,3 +65,5 @@ $(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds
PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds
+if ON_SKYEYE
+endif
diff --git a/c/src/lib/libbsp/arm/gumstix/rtl8019/rtl8019.c b/c/src/lib/libbsp/arm/gumstix/rtl8019/rtl8019.c
new file mode 100644
index 0000000000..3a2cf6b5b4
--- /dev/null
+++ b/c/src/lib/libbsp/arm/gumstix/rtl8019/rtl8019.c
@@ -0,0 +1,1259 @@
+/*
+ *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.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <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 (int irno);
+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
+
+/* Find the NE2000 device which is attached at a particular interrupt
+ vector. */
+
+static struct ne_softc *
+ne_device_for_irno (int irno)
+{
+ int i;
+
+ for (i = 0; i < NNEDRIVER; ++i)
+ {
+ if (ne_softc[i].irno == irno
+ && ne_softc[i].arpcom.ac_if.if_softc != NULL)
+ return &ne_softc[i];
+ }
+
+ return NULL;
+}
+
+/* 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_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_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 (uint32_t cdata)
+{
+ rtems_vector_number v = (rtems_vector_number) cdata;
+ struct ne_softc *sc;
+
+ sc = ne_device_for_irno (v);
+ 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 (const rtems_irq_connect_data *irq)
+{
+ struct ne_softc *sc;
+
+#ifdef DEBUG_NE
+ printk ("ne_interrupt_on()\n");
+#endif
+ sc = ne_device_for_irno (irq->name);
+ if (sc != NULL)
+ outport_byte (sc->port + IMR, NE_INTERRUPTS);
+}
+
+/* Turn NE2000 interrupts off. See ne_interrupt_on. */
+
+static void
+ne_interrupt_off (const rtems_irq_connect_data *irq)
+{
+ struct ne_softc *sc;
+
+#ifdef DEBUG_NE
+ printk ("ne_interrupt_off()\n");
+#endif
+ sc = ne_device_for_irno (irq->name);
+ if (sc != NULL)
+ outport_byte (sc->port + IMR, 0);
+}
+
+/*
+ *Return whether NE2000 interrupts are on.
+ *If it is eanbled, return 1
+*/
+static int
+ne_interrupt_is_on (const rtems_irq_connect_data *irq)
+{
+ struct ne_softc *sc;
+ unsigned char imr;
+#ifdef DEBUG_NE
+ printk("ne_interrupt_is_on()\n");
+#endif
+ sc = ne_device_for_irno(irq->name);
+ if(sc != NULL){
+ /*Read IMR in Page2*/
+ outport_byte (sc->port + CMDR, MSK_PG2 | MSK_RD2 | MSK_STP);
+ inport_byte(sc->port + IMR, imr);
+ /*Back Page 0*/
+ outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+ if(imr == NE_INTERRUPTS)
+ return 1;
+ }
+ return 0;
+}
+
+/* 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(int irno)
+{
+ rtems_irq_connect_data irq;
+
+#ifdef DEBUG_NE
+ printk("ne_init_irq_handler(%d)\n", irno);
+#endif
+ irq.name = irno;
+ irq.hdl = ne_interrupt_handler;
+ irq.on = ne_interrupt_on;
+ irq.off = ne_interrupt_off;
+ irq.isOn = ne_interrupt_is_on;
+
+ if (!BSP_install_rtems_irq_handler (&irq))
+ rtems_panic ("Can't attach NE interrupt handler for irq %d\n", irno);
+}
+
+/* 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, stat, 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;
+ }
+
+ stat = hdr.rsr;
+
+ /* 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_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->irno);
+ }
+
+ 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;
+}
diff --git a/c/src/lib/libbsp/arm/gumstix/rtl8019/wd80x3.h b/c/src/lib/libbsp/arm/gumstix/rtl8019/wd80x3.h
new file mode 100644
index 0000000000..5f7a1fa970
--- /dev/null
+++ b/c/src/lib/libbsp/arm/gumstix/rtl8019/wd80x3.h
@@ -0,0 +1,133 @@
+/*
+ * Information about the DP8390 Ethernet controller.
+ *
+ * $Id$
+ */
+
+#ifndef __BSP_WD80x3_h
+#define __BSP_WD80x3_h
+
+/* Register descriptions */
+/* Controller DP8390. */
+
+#define DATAPORT 0x10 /* Port Window. */
+#define RESET 0x1f /* Issue a read for reset */
+#define W83CREG 0x00 /* I/O port definition */
+#define ADDROM 0x08
+
+/* page 0 read or read/write registers */
+
+#define CMDR 0x00+RO
+#define CLDA0 0x01+RO /* current local dma addr 0 for read */
+#define CLDA1 0x02+RO /* current local dma addr 1 for read */
+#define BNRY 0x03+RO /* boundary reg for rd and wr */
+#define TSR 0x04+RO /* tx status reg for rd */
+#define NCR 0x05+RO /* number of collision reg for rd */
+#define FIFO 0x06+RO /* FIFO for rd */
+#define ISR 0x07+RO /* interrupt status reg for rd and wr */
+#define CRDA0 0x08+RO /* current remote dma address 0 for rd */
+#define CRDA1 0x09+RO /* current remote dma address 1 for rd */
+#define RSR 0x0C+RO /* rx status reg for rd */
+#define CNTR0 0x0D+RO /* tally cnt 0 for frm alg err for rd */
+#define CNTR1 RO+0x0E /* tally cnt 1 for crc err for rd */
+#define CNTR2 0x0F+RO /* tally cnt 2 for missed pkt for rd */
+
+/* page 0 write registers */
+
+#define PSTART 0x01+RO /* page start register */
+#define PSTOP 0x02+RO /* page stop register */
+#define TPSR 0x04+RO /* tx start page start reg */
+#define TBCR0 0x05+RO /* tx byte count 0 reg */
+#define TBCR1 0x06+RO /* tx byte count 1 reg */
+#define RSAR0 0x08+RO /* remote start address reg 0 */
+#define RSAR1 0x09+RO /* remote start address reg 1 */
+#define RBCR0 0x0A+RO /* remote byte count reg 0 */
+#define RBCR1 0x0B+RO /* remote byte count reg 1 */
+#define RCR 0x0C+RO /* rx configuration reg */
+#define TCR 0x0D+RO /* tx configuration reg */
+#define DCR RO+0x0E /* data configuration reg */
+#define IMR 0x0F+RO /* interrupt mask reg */
+
+/* page 1 registers */
+
+#define PAR 0x01+RO /* physical addr reg base for rd and wr */
+#define CURR 0x07+RO /* current page reg for rd and wr */
+#define MAR 0x08+RO /* multicast addr reg base fro rd and WR */
+#define MARsize 8 /* size of multicast addr space */
+
+/*-----W83CREG command bits-----*/
+#define MSK_RESET 0x80 /* W83CREG masks */
+#define MSK_ENASH 0x40
+#define MSK_DECOD 0x3F /* memory decode bits, corresponding */
+ /* to SA 18-13. SA 19 assumed to be 1 */
+
+/*-----CMDR command bits-----*/
+#define MSK_STP 0x01 /* stop the chip */
+#define MSK_STA 0x02 /* start the chip */
+#define MSK_TXP 0x04 /* initial txing of a frm */
+#define MSK_RRE 0x08 /* remote read */
+#define MSK_RWR 0x10 /* remote write */
+#define MSK_RD2 0x20 /* no DMA used */
+#define MSK_PG0 0x00 /* select register page 0 */
+#define MSK_PG1 0x40 /* select register page 1 */
+#define MSK_PG2 0x80 /* select register page 2 */
+
+/*-----ISR and TSR status bits-----*/
+#define MSK_PRX 0x01 /* rx with no error */
+#define MSK_PTX 0x02 /* tx with no error */
+#define MSK_RXE 0x04 /* rx with error */
+#define MSK_TXE 0x08 /* tx with error */
+#define MSK_OVW 0x10 /* overwrite warning */
+#define MSK_CNT 0x20 /* MSB of one of the tally counters is set */
+#define MSK_RDC 0x40 /* remote dma completed */
+#define MSK_RST 0x80 /* reset state indicator */
+
+/*-----DCR command bits-----*/
+#define MSK_WTS 0x01 /* word transfer mode selection */
+#define MSK_BOS 0x02 /* byte order selection */
+#define MSK_LAS 0x04 /* long addr selection */
+#define MSK_BMS 0x08 /* burst mode selection */
+#define MSK_ARM 0x10 /* autoinitialize remote */
+#define MSK_FT00 0x00 /* burst lrngth selection */
+#define MSK_FT01 0x20 /* burst lrngth selection */
+#define MSK_FT10 0x40 /* burst lrngth selection */
+#define MSK_FT11 0x60 /* burst lrngth selection */
+
+/*-----RCR command bits-----*/
+#define MSK_SEP 0x01 /* save error pkts */
+#define MSK_AR 0x02 /* accept runt pkt */
+#define MSK_AB 0x04 /* 8390 RCR */
+#define MSK_AM 0x08 /* accept multicast */
+#define MSK_PRO 0x10 /* accept all pkt with physical adr */
+#define MSK_MON 0x20 /* monitor mode */
+
+/*-----TCR command bits-----*/
+#define MSK_CRC 0x01 /* inhibit CRC, do not append crc */
+#define MSK_LOOP 0x02 /* set loopback mode */
+#define MSK_BCST 0x04 /* Accept broadcasts */
+#define MSK_LB01 0x06 /* encoded loopback control */
+#define MSK_ATD 0x08 /* auto tx disable */
+#define MSK_OFST 0x10 /* collision offset enable */
+
+/*-----receive status bits-----*/
+#define SMK_PRX 0x01 /* rx without error */
+#define SMK_CRC 0x02 /* CRC error */
+#define SMK_FAE 0x04 /* frame alignment error */
+#define SMK_FO 0x08 /* FIFO overrun */
+#define SMK_MPA 0x10 /* missed pkt */
+#define SMK_PHY 0x20 /* physical/multicase address */
+#define SMK_DIS 0x40 /* receiver disable. set in monitor mode */
+#define SMK_DEF 0x80 /* deferring */
+
+/*-----transmit status bits-----*/
+#define SMK_PTX 0x01 /* tx without error */
+#define SMK_DFR 0x02 /* non deferred tx */
+#define SMK_COL 0x04 /* tx collided */
+#define SMK_ABT 0x08 /* tx abort because of excessive collisions */
+#define SMK_CRS 0x10 /* carrier sense lost */
+#define SMK_FU 0x20 /* FIFO underrun */
+#define SMK_CDH 0x40 /* collision detect heartbeat */
+#define SMK_OWC 0x80 /* out of window collision */
+
+#endif
+/* end of include */
diff --git a/c/src/lib/libbsp/arm/gumstix/startup/memmap.c b/c/src/lib/libbsp/arm/gumstix/startup/memmap.c
index cf1921d753..f30518735b 100755
--- a/c/src/lib/libbsp/arm/gumstix/startup/memmap.c
+++ b/c/src/lib/libbsp/arm/gumstix/startup/memmap.c
@@ -12,7 +12,7 @@
mmu_sect_map_t mem_map[] = {
/* <phys addr> <virt addr> <size> <flags> */
- {0x40000000, 0x40000000, 20, MMU_CACHE_NONE}, /*Map I/O*/
+ {0x40000000, 0x40000000, 1216, MMU_CACHE_NONE}, /*Map I/O*/
{0xA0000000, 0x00000000, 1, MMU_CACHE_NONE}, /*sram*/
{0xA0000000, 0xA0000000, 64, MMU_CACHE_WBACK}, /* SDRAM */
{0x00000000, 0x00000000, 0, 0} /* The end */