summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-18 21:06:17 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-18 21:06:17 +0000
commit1094cf0dc51e8df18b90074c8925c36170f9f13d (patch)
tree387051e6f8284104583cd06913a027893a4cce0d /c
parentAdded comments. (diff)
downloadrtems-1094cf0dc51e8df18b90074c8925c36170f9f13d.tar.bz2
Patch from Emmanuel RAGUET <raguet@crf.canon.fr> to add files
that were accidentally not committed earlier. The DECNet driver is being added as its own directory to avoid forcing the driver to have to pull in the complete set of network drivers.
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/i386/pc386/dec21140/Makefile.in57
-rw-r--r--c/src/lib/libbsp/i386/pc386/dec21140/dec21140.c876
-rw-r--r--c/src/lib/libbsp/i386/pc386/network/Makefile.in2
-rw-r--r--c/src/lib/libbsp/i386/pc386/network/network.c13
-rw-r--r--c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in2
5 files changed, 942 insertions, 8 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/dec21140/Makefile.in b/c/src/lib/libbsp/i386/pc386/dec21140/Makefile.in
new file mode 100644
index 0000000000..f72b830cad
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/dec21140/Makefile.in
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+INSTALL = @INSTALL@
+
+PGM=${ARCH}/dec21140.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=dec21140
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \
+ -DDIAGNOSTIC -DBOOTP_COMPAT
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/i386/pc386/dec21140/dec21140.c b/c/src/lib/libbsp/i386/pc386/dec21140/dec21140.c
new file mode 100644
index 0000000000..13bd268ef4
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/dec21140/dec21140.c
@@ -0,0 +1,876 @@
+/*
+ * RTEMS driver for TULIP based Ethernet Controller
+ *
+ * $Header$
+ */
+
+#include <bsp.h>
+#include <pcibios.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <libcpu/cpu.h>
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <irq.h>
+
+#ifdef malloc
+#undef malloc
+#endif
+#ifdef free
+#undef free
+#endif
+
+#define PCI_VENDOR_ID_DEC 0x1011
+#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009
+
+#define IO_MASK 0x3
+#define MEM_MASK 0xF
+
+/* command and status registers, 32-bit access, only if IO-ACCESS */
+#define ioCSR0 0x00 /* bus mode register */
+#define ioCSR1 0x08 /* transmit poll demand */
+#define ioCSR2 0x10 /* receive poll demand */
+#define ioCSR3 0x18 /* receive list base address */
+#define ioCSR4 0x20 /* transmit list base address */
+#define ioCSR5 0x28 /* status register */
+#define ioCSR6 0x30 /* operation mode register */
+#define ioCSR7 0x38 /* interrupt mask register */
+#define ioCSR8 0x40 /* missed frame counter */
+#define ioCSR9 0x48 /* Ethernet ROM register */
+#define ioCSR10 0x50 /* reserved */
+#define ioCSR11 0x58 /* full-duplex register */
+#define ioCSR12 0x60 /* SIA status register */
+#define ioCSR13 0x68
+#define ioCSR14 0x70
+#define ioCSR15 0x78 /* SIA general register */
+
+/* command and status registers, 32-bit access, only if MEMORY-ACCESS */
+#define memCSR0 0x00 /* bus mode register */
+#define memCSR1 0x02 /* transmit poll demand */
+#define memCSR2 0x04 /* receive poll demand */
+#define memCSR3 0x06 /* receive list base address */
+#define memCSR4 0x08 /* transmit list base address */
+#define memCSR5 0x0A /* status register */
+#define memCSR6 0x0C /* operation mode register */
+#define memCSR7 0x0E /* interrupt mask register */
+#define memCSR8 0x10 /* missed frame counter */
+#define memCSR9 0x12 /* Ethernet ROM register */
+#define memCSR10 0x14 /* reserved */
+#define memCSR11 0x16 /* full-duplex register */
+#define memCSR12 0x18 /* SIA status register */
+#define memCSR13 0x1A
+#define memCSR14 0x1C
+#define memCSR15 0x1E /* SIA general register */
+
+#define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */
+
+#define RESET_CHIP 0x00000001
+#define CSR0_MODE 0x01a08000 /* 01a08000 */
+#define ROM_ADDRESS 0x00004800
+#define CSR6_INIT 0x020c0000 /* 020c0000 */
+#define CSR6_TX 0x00002000
+#define CSR6_TXRX 0x00002002
+#define IT_SETUP 0x00010040 /* 0001ebef */
+#define CLEAR_IT 0xFFFFFFFF
+#define NO_IT 0x00000000
+
+#define NRXBUFS 7 /* number of receive buffers */
+#define NTXBUFS 1 /* number of transmit buffers */
+
+/* message descriptor entry */
+struct MD {
+ volatile unsigned long status;
+ volatile unsigned long counts;
+ unsigned long buf1, buf2;
+};
+
+/*
+ * Number of WDs supported by this driver
+ */
+#define NDECDRIVER 1
+
+/*
+ * Receive buffer size -- Allow for a full ethernet packet including CRC
+ */
+#define RBUF_SIZE 1520
+
+#define ET_MINLEN 60 /* minimum message length */
+
+/*
+ * RTEMS event used by interrupt handler to signal driver tasks.
+ * This must not be any of the events used by the network task synchronization.
+ */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+
+/*
+ * RTEMS event used to start transmit daemon.
+ * This must not be the same as INTERRUPT_EVENT.
+ */
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+
+#if (MCLBYTES < RBUF_SIZE)
+# error "Driver must have MCLBYTES > RBUF_SIZE"
+#endif
+
+/*
+ * Per-device data
+ */
+ struct dec21140_softc {
+ struct arpcom arpcom;
+ rtems_irq_connect_data irqInfo;
+ struct MD *MDbase;
+ char *bufferBase;
+ int acceptBroadcast;
+ int rxBdCount;
+ int txBdCount;
+ rtems_id rxDaemonTid;
+ rtems_id txDaemonTid;
+
+ unsigned int port;
+ unsigned int *base;
+ unsigned long bpar;
+
+ /*
+ * Statistics
+ */
+ unsigned long rxInterrupts;
+ unsigned long rxNotFirst;
+ unsigned long rxNotLast;
+ unsigned long rxGiant;
+ unsigned long rxNonOctet;
+ unsigned long rxRunt;
+ unsigned long rxBadCRC;
+ unsigned long rxOverrun;
+ unsigned long rxCollision;
+
+ unsigned long txInterrupts;
+ unsigned long txDeferred;
+ unsigned long txHeartbeat;
+ unsigned long txLateCollision;
+ unsigned long txRetryLimit;
+ unsigned long txUnderrun;
+ unsigned long txLostCarrier;
+ unsigned long txRawWait;
+};
+
+static struct dec21140_softc dec21140_softc[NDECDRIVER];
+
+/*
+ * DEC21140 interrupt handler
+ */
+static rtems_isr
+dec21140Enet_interrupt_handler (rtems_vector_number v)
+{
+ unsigned int *tbase;
+ unsigned long status;
+
+ unsigned int sc;
+
+ tbase = dec21140_softc[0].base ;
+
+ /*
+ * Read status
+ */
+ *(tbase+memCSR7) = NO_IT;
+ status = *(tbase+memCSR5);
+ *(tbase+memCSR5) = CLEAR_IT;
+
+ /*
+ * Frame received?
+ */
+ if (status & 0x00000040){
+ dec21140_softc[0].rxInterrupts++;
+ sc = rtems_event_send (dec21140_softc[0].rxDaemonTid, INTERRUPT_EVENT);
+ }
+}
+
+static void nopOn(const rtems_irq_connect_data* notUsed)
+{
+ /*
+ * code should be moved from dec21140Enet_initialize_hardware
+ * to this location
+ */
+}
+
+static int dec21140IsOn(const rtems_irq_connect_data* irq)
+{
+ return BSP_irq_enabled_at_i8259s (irq->name);
+}
+
+/*
+ * Read and write the MII registers using software-generated serial
+ * MDIO protocol.
+ */
+#define MDIO_SHIFT_CLK 0x10000
+#define MDIO_DATA_WRITE0 0x00000
+#define MDIO_DATA_WRITE1 0x20000
+#define MDIO_ENB 0x00000
+#define MDIO_ENB_IN 0x40000
+#define MDIO_DATA_READ 0x80000
+
+static int mdio_read(unsigned int *ioaddr, int phy_id, int location)
+{
+ int i, i3;
+ int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ unsigned short retval = 0;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ *ioaddr = MDIO_ENB | MDIO_DATA_WRITE1;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ }
+ /* Shift the read command bits out. */
+ for (i = 17; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ *ioaddr = dataval;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = dataval | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = dataval;
+ for(i3=0; i3<1000; i3++);
+ }
+ *ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = MDIO_ENB_IN;
+
+ for (i = 16; i > 0; i--) {
+ *ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ retval = (retval << 1) | ((*ioaddr & MDIO_DATA_READ) ? 1 : 0);
+ *ioaddr = MDIO_ENB_IN;
+ for(i3=0; i3<1000; i3++);
+ }
+ /* Clear out extra bits. */
+ for (i = 16; i > 0; i--) {
+ *ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = MDIO_ENB_IN;
+ for(i3=0; i3<1000; i3++);
+ }
+ return retval;
+}
+
+static int mdio_write(unsigned int *ioaddr, int phy_id, int location, int value)
+{
+ int i, i3;
+ int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ *ioaddr = MDIO_ENB | MDIO_DATA_WRITE1;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ }
+ /* Shift the read command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ *ioaddr = dataval;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = dataval | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ }
+
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ *ioaddr = MDIO_ENB_IN;
+ for(i3=0; i3<1000; i3++);
+ *ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
+ for(i3=0; i3<1000; i3++);
+ }
+ return 0;
+
+
+}
+
+/*
+ * This routine reads a word (16 bits) from the serial EEPROM.
+ */
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
+#define EE_CS 0x01 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x05
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_ENB (0x4800 | EE_CS)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << 6)
+#define EE_READ_CMD (6 << 6)
+#define EE_ERASE_CMD (7 << 6)
+
+static int eeget16(unsigned int *ioaddr, int location)
+{
+ int i, i3;
+ unsigned short retval = 0;
+ int read_cmd = location | EE_READ_CMD;
+
+ *ioaddr = EE_ENB & ~EE_CS;
+ *ioaddr = EE_ENB;
+
+ /* Shift the read command bits out. */
+ for (i = 10; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ *ioaddr = EE_ENB | dataval;
+ for (i3=0; i3<1000; i3++) ;
+ *ioaddr = EE_ENB | dataval | EE_SHIFT_CLK;
+ for (i3=0; i3<1000; i3++) ;
+ *ioaddr = EE_ENB | dataval; /* Finish EEPROM a clock tick. */
+ for (i3=0; i3<1000; i3++) ;
+ }
+ *ioaddr = EE_ENB;
+
+ for (i = 16; i > 0; i--) {
+ *ioaddr = EE_ENB | EE_SHIFT_CLK;
+ for (i3=0; i3<1000; i3++) ;
+ retval = (retval << 1) | ((*ioaddr & EE_DATA_READ) ? 1 : 0);
+ *ioaddr = EE_ENB;
+ for (i3=0; i3<1000; i3++) ;
+ }
+
+ /* Terminate the EEPROM access. */
+ *ioaddr = EE_ENB & ~EE_CS;
+ return retval;
+}
+
+/*
+ * Initialize the ethernet hardware
+ */
+static void
+dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
+{
+ rtems_status_code st;
+ unsigned int *tbase;
+ union {char c[64]; unsigned short s[32];} rombuf;
+ int i, i2, i3;
+ char *cp, direction, *setup_frm, *eaddrs;
+ unsigned long csr12_val, mii_reg0;
+ unsigned char *buffer;
+ struct MD *rmd;
+
+
+ tbase = sc->base;
+
+ /*
+ * WARNING : First write in CSR6
+ * Then Reset the chip ( 1 in CSR0)
+ */
+
+ *(tbase+memCSR6) = CSR6_INIT;
+ *(tbase+memCSR0) = RESET_CHIP;
+ for(i3=0; i3<1000; i3++);
+
+ /*
+ * Init CSR0
+ */
+ *(tbase+memCSR0) = CSR0_MODE;
+
+ csr12_val = *(tbase+memCSR8);
+
+ for (i=0; i<32; i++)
+ rombuf.s[i] = eeget16(tbase+memCSR9, i);
+ memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN);
+
+
+ mii_reg0 = mdio_read(tbase+memCSR9, 0, 0);
+ mdio_write(tbase+memCSR9, 0, 0, mii_reg0 | 0x1000);
+
+#ifdef DEC_DEBUG
+ printk("DC21140 %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n",
+ sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
+ sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
+ sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5],
+ sc->irqInfo.name, sc->port, sc->base);
+#endif
+
+ /*
+ * Init RX ring
+ */
+ sc->rxBdCount = 0;
+
+ cp = (char *)malloc((NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE) + PG_SIZE);
+ sc->bufferBase = cp;
+ cp += (PG_SIZE - (int)cp) & MASK_OFFSET ;
+ if (_CPU_is_paging_enabled())
+ _CPU_change_memory_mapping_attribute
+ (NULL, cp,
+ (NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE),
+ PTE_CACHE_DISABLE | PTE_WRITABLE);
+ rmd = (struct MD*)cp;
+ sc->MDbase = rmd;
+ buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD));
+
+ *(tbase+memCSR3) = (long)(sc->MDbase);
+ for (i=0 ; i<NRXBUFS; i++){
+ rmd->buf2 = 0;
+ rmd->buf1 = (unsigned long)(buffer + (i*RBUF_SIZE));
+ if (i == NRXBUFS-1)
+ rmd->counts = 0xfec00000 | (RBUF_SIZE);
+ else
+ rmd->counts = 0xfcc00000 | (RBUF_SIZE);
+ rmd->status = 0x80000000;
+ rmd++;
+ }
+
+ /*
+ * Init TX ring
+ */
+ sc->txBdCount = 0;
+ *(tbase+memCSR4) = (long)(rmd);
+ rmd->buf2 = 0;
+ rmd->buf1 = (unsigned long)(buffer + (NRXBUFS*RBUF_SIZE));
+ rmd->counts = 0x62000000;
+ rmd->status = 0x0;
+
+ /*
+ * Set up interrupts
+ */
+ *(tbase+memCSR5) = IT_SETUP;
+ *(tbase+memCSR7) = IT_SETUP;
+
+ sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
+ sc->irqInfo.on = nopOn;
+ sc->irqInfo.off = nopOn;
+ sc->irqInfo.isOn = dec21140IsOn;
+ st = BSP_install_rtems_irq_handler (&sc->irqInfo);
+ if (!st)
+ rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
+ sc->irqInfo.name);
+
+ /*
+ * Start TX for setup frame
+ */
+ *(tbase+memCSR6) = CSR6_INIT | CSR6_TX;
+
+ /*
+ * Build setup frame
+ */
+ setup_frm = (char *)(rmd->buf1);
+ eaddrs = (char *)(sc->arpcom.ac_enaddr);
+ /* Fill the buffer with our physical address. */
+ for (i = 1; i < 16; i++) {
+ *setup_frm++ = eaddrs[0];
+ *setup_frm++ = eaddrs[1];
+ setup_frm += 2;
+ *setup_frm++ = eaddrs[2];
+ *setup_frm++ = eaddrs[3];
+ setup_frm += 2;
+ *setup_frm++ = eaddrs[4];
+ *setup_frm++ = eaddrs[5];
+ setup_frm += 2;
+ }
+ /* Add the broadcast address when doing perfect filtering */
+ memset(setup_frm, 0xff, 12);
+ rmd->counts = 0x0a000000 | 192 ;
+ rmd->status = 0x80000000;
+ *(tbase+memCSR1) = 1;
+ while (rmd->status != 0x7fffffff);
+
+ /*
+ * Enable RX and TX
+ */
+ *(tbase+memCSR6) = CSR6_INIT | CSR6_TXRX;
+
+ /*
+ * Set up PHY
+ */
+
+ i = rombuf.c[27];
+ i+=2;
+ direction = rombuf.c[i];
+ i +=4;
+ *(tbase+memCSR12) = direction | 0x100;
+ for (i2 = 0; i2 < rombuf.c[(i+2) + rombuf.c[i+1]]; i2++){
+ *(tbase + memCSR12) = rombuf.c[(i+3) + rombuf.c[i+1] + i2];
+ }
+ for (i2 = 0; i2 < rombuf.c[i+1]; i2++){
+ *(tbase + memCSR12) = rombuf.c[(i+2) + i2];
+ }
+}
+
+static void
+dec21140_rxDaemon (void *arg)
+{
+ unsigned int *tbase;
+ struct ether_header *eh;
+ struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0];
+ struct ifnet *ifp = &dp->arpcom.ac_if;
+ struct mbuf *m;
+ struct MD *rmd;
+ unsigned int len;
+ char *temp;
+ rtems_event_set events;
+ int nbMD;
+
+ tbase = dec21140_softc[0].base ;
+
+ for (;;){
+
+ rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+ rmd = dec21140_softc[0].MDbase;
+ nbMD = 0;
+
+ while (nbMD < NRXBUFS){
+ if ( (rmd->status & 0x80000000) == 0){
+ len = (rmd->status >> 16) & 0x7ff;
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+ temp = m->m_data;
+ m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
+ memcpy(temp, (char *)rmd->buf1, len);
+ rmd->status = 0x80000000;
+ eh = mtod (m, struct ether_header *);
+ m->m_data += sizeof(struct ether_header);
+ ether_input (ifp, eh, m);
+ }
+ rmd++;
+ nbMD++;
+ }
+ *(tbase+memCSR7) = IT_SETUP;
+ }
+}
+
+static void
+sendpacket (struct ifnet *ifp, struct mbuf *m)
+{
+ struct dec21140_softc *dp = ifp->if_softc;
+ volatile struct MD *tmd;
+ unsigned char *temp;
+ struct mbuf *n;
+ unsigned int len;
+ unsigned int *tbase;
+
+ tbase = dp->base;
+
+ /*
+ * Waiting for Transmitter ready
+ */
+ tmd = dec21140_softc[0].MDbase + NRXBUFS;
+ while ( (tmd->status & 0x80000000) != 0 );
+ len = 0;
+ n = m;
+ temp = (char *)(tmd->buf1);
+
+ for (;;){
+ len += m->m_len;
+ memcpy(temp, (char *)m->m_data, m->m_len);
+ temp += m->m_len ;
+ if ((m = m->m_next) == NULL)
+ break;
+ }
+
+ if (len < ET_MINLEN) len = ET_MINLEN;
+ tmd->counts = 0xe2000000 | len;
+ tmd->status = 0x80000000;
+
+ *(tbase+memCSR1) = 0x1;
+
+ m_freem(n);
+}
+
+/*
+ * Driver transmit daemon
+ */
+void
+dec21140_txDaemon (void *arg)
+{
+ struct dec21140_softc *sc = (struct dec21140_softc *)arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ rtems_event_set events;
+
+ for (;;) {
+ /*
+ * Wait for packet
+ */
+
+ rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
+
+ /*
+ * Send packets till queue is empty
+ */
+ for (;;) {
+ /*
+ * Get the next mbuf chain to transmit.
+ */
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (!m)
+ break;
+ sendpacket (ifp, m);
+ }
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+}
+
+
+static void
+dec21140_start (struct ifnet *ifp)
+{
+ struct dec21140_softc *sc = ifp->if_softc;
+
+ rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
+ ifp->if_flags |= IFF_OACTIVE;
+}
+
+/*
+ * Initialize and start the device
+ */
+static void
+dec21140_init (void *arg)
+{
+ struct dec21140_softc *sc = arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ if (sc->txDaemonTid == 0) {
+
+ /*
+ * Set up DEC21140 hardware
+ */
+ dec21140Enet_initialize_hardware (sc);
+
+ /*
+ * Start driver tasks
+ */
+ sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096,
+ dec21140_rxDaemon, sc);
+ sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096,
+ dec21140_txDaemon, sc);
+ }
+
+ /*
+ * Tell the world that we're running.
+ */
+ ifp->if_flags |= IFF_RUNNING;
+
+}
+
+/*
+ * Stop the device
+ */
+static void
+dec21140_stop (struct dec21140_softc *sc)
+{
+ unsigned int *tbase;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ ifp->if_flags &= ~IFF_RUNNING;
+
+ /*
+ * Stop the transmitter
+ */
+ tbase=dec21140_softc[0].base ;
+ *(tbase+memCSR7) = NO_IT;
+ *(tbase+memCSR6) = CSR6_INIT;
+ free(sc->bufferBase);
+}
+
+
+/*
+ * Show interface statistics
+ */
+static void
+dec21140_stats (struct dec21140_softc *sc)
+{
+ printf (" Rx Interrupts:%-8lu", sc->rxInterrupts);
+ printf (" Not First:%-8lu", sc->rxNotFirst);
+ printf (" Not Last:%-8lu\n", sc->rxNotLast);
+ printf (" Giant:%-8lu", sc->rxGiant);
+ printf (" Runt:%-8lu", sc->rxRunt);
+ printf (" Non-octet:%-8lu\n", sc->rxNonOctet);
+ printf (" Bad CRC:%-8lu", sc->rxBadCRC);
+ printf (" Overrun:%-8lu", sc->rxOverrun);
+ printf (" Collision:%-8lu\n", sc->rxCollision);
+
+ printf (" Tx Interrupts:%-8lu", sc->txInterrupts);
+ printf (" Deferred:%-8lu", sc->txDeferred);
+ printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
+ printf (" No Carrier:%-8lu", sc->txLostCarrier);
+ printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
+ printf (" Late Collision:%-8lu\n", sc->txLateCollision);
+ printf (" Underrun:%-8lu", sc->txUnderrun);
+ printf (" Raw output wait:%-8lu\n", sc->txRawWait);
+}
+
+/*
+ * Driver ioctl handler
+ */
+static int
+dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data)
+{
+ struct dec21140_softc *sc = ifp->if_softc;
+ int error = 0;
+
+ switch (command) {
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ ether_ioctl (ifp, command, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+ case IFF_RUNNING:
+ dec21140_stop (sc);
+ break;
+
+ case IFF_UP:
+ dec21140_init (sc);
+ break;
+
+ case IFF_UP | IFF_RUNNING:
+ dec21140_stop (sc);
+ dec21140_init (sc);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case SIO_RTEMS_SHOW_STATS:
+ dec21140_stats (sc);
+ break;
+
+ /*
+ * FIXME: All sorts of multicast commands need to be added here!
+ */
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+/*
+ * Attach an DEC21140 driver to the system
+ */
+int
+rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
+{
+ struct dec21140_softc *sc;
+ struct ifnet *ifp;
+ int mtu;
+ int i;
+ int signature;
+ int value;
+ char interrupt;
+ int diag;
+
+ /*
+ * Initialise PCI module
+ */
+ if (pcib_init() == PCIB_ERR_NOTPRESENT)
+ rtems_panic("PCI BIOS not found !!");
+
+ /*
+ * First, find a DEC board
+ */
+ if ((diag = pcib_find_by_devid(PCI_VENDOR_ID_DEC,
+ PCI_DEVICE_ID_DEC_TULIP_FAST,
+ 0,
+ &signature)) != PCIB_ERR_SUCCESS)
+ rtems_panic("DEC PCI board not found !! (%d)\n", diag);
+ else {
+ printk("DEC PCI Device found\n");
+ }
+
+ /*
+ * Find a free driver
+ */
+ for (i = 0 ; i < NDECDRIVER ; i++) {
+ sc = &dec21140_softc[i];
+ ifp = &sc->arpcom.ac_if;
+ if (ifp->if_softc == NULL)
+ break;
+ }
+ if (i >= NDECDRIVER) {
+ printk ("Too many DEC drivers.\n");
+ return 0;
+ }
+
+ /*
+ * Process options
+ */
+
+ pcib_conf_read32(signature, 16, &value);
+ sc->port = value & ~IO_MASK;
+
+ pcib_conf_read32(signature, 20, &value);
+ if (_CPU_is_paging_enabled())
+ _CPU_map_phys_address(&(sc->base),
+ (void *)(value & ~MEM_MASK),
+ DEC_REGISTER_SIZE ,
+ PTE_CACHE_DISABLE | PTE_WRITABLE);
+ else
+ sc->base = (unsigned int *)(value & ~MEM_MASK);
+
+ pcib_conf_read8(signature, 60, &interrupt);
+ sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt;
+
+ if (config->hardware_address) {
+ memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
+ ETHER_ADDR_LEN);
+ }
+ else {
+ memset (sc->arpcom.ac_enaddr, 0x08,ETHER_ADDR_LEN);
+ }
+ if (config->mtu)
+ mtu = config->mtu;
+ else
+ mtu = ETHERMTU;
+
+ sc->acceptBroadcast = !config->ignore_broadcast;
+
+ /*
+ * Set up network interface values
+ */
+ ifp->if_softc = sc;
+ ifp->if_unit = i + 1;
+ ifp->if_name = "dc";
+ ifp->if_mtu = mtu;
+ ifp->if_init = dec21140_init;
+ ifp->if_ioctl = dec21140_ioctl;
+ ifp->if_start = dec21140_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);
+
+ return 1;
+};
+
+
+
+
+
+
+
+
+
+
+
diff --git a/c/src/lib/libbsp/i386/pc386/network/Makefile.in b/c/src/lib/libbsp/i386/pc386/network/Makefile.in
index 19d46e143f..b3e294aae8 100644
--- a/c/src/lib/libbsp/i386/pc386/network/Makefile.in
+++ b/c/src/lib/libbsp/i386/pc386/network/Makefile.in
@@ -13,7 +13,7 @@ INSTALL = @INSTALL@
PGM=${ARCH}/network.rel
# C source names, if any, go here -- minus the .c
-C_PIECES=network dec21140
+C_PIECES=network
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
diff --git a/c/src/lib/libbsp/i386/pc386/network/network.c b/c/src/lib/libbsp/i386/pc386/network/network.c
index c7923136a5..e897435f7a 100644
--- a/c/src/lib/libbsp/i386/pc386/network/network.c
+++ b/c/src/lib/libbsp/i386/pc386/network/network.c
@@ -1,11 +1,12 @@
/*
- * RTEMS driver for M68360 WD1 Ethernet
+ * RTEMS driver for WD800x
*
- * W. Eric Norum
- * Saskatchewan Accelerator Laboratory
- * University of Saskatchewan
- * Saskatoon, Saskatchewan, CANADA
- * eric@skatter.usask.ca
+ * Based on the 68360 Network Driver by:
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
*
* $Id$
*/
diff --git a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in
index 1c4148cdeb..87b2cfbeb9 100644
--- a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in
+++ b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in
@@ -11,7 +11,7 @@ PROJECT_ROOT = @PROJECT_ROOT@
INSTALL = @INSTALL@
# We only build the Network library if HAS_NETWORKING was defined
-NETWORK_yes_V = network ne2000
+NETWORK_yes_V = dec21140 network ne2000
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES=startup clock console timer $(NETWORK)