From c0438adde978a8b66e82ce9509e338dc1d714ccc Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 18 Feb 1999 21:09:25 +0000 Subject: Renamed network to wd8003. --- c/src/lib/libbsp/i386/pc386/Makefile.in | 2 +- c/src/lib/libbsp/i386/pc386/network/Makefile.in | 57 -- c/src/lib/libbsp/i386/pc386/network/network.c | 657 ------------------------ c/src/lib/libbsp/i386/pc386/wd8003/Makefile.in | 57 ++ c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c | 657 ++++++++++++++++++++++++ c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in | 2 +- 6 files changed, 716 insertions(+), 716 deletions(-) delete mode 100644 c/src/lib/libbsp/i386/pc386/network/Makefile.in delete mode 100644 c/src/lib/libbsp/i386/pc386/network/network.c create mode 100644 c/src/lib/libbsp/i386/pc386/wd8003/Makefile.in create mode 100644 c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c (limited to 'c') diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.in b/c/src/lib/libbsp/i386/pc386/Makefile.in index d10dbee0e9..165a921429 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/Makefile.in @@ -14,7 +14,7 @@ include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg include $(RTEMS_ROOT)/make/directory.cfg # We only build the Network library if HAS_NETWORKING was defined -NETWORK_yes_V = network ne2000 +NETWORK_yes_V = dec21140 ne2000 wd8003 NETWORK = $(NETWORK_$(HAS_NETWORKING)_V) # wrapup is the one that actually builds and installs the library diff --git a/c/src/lib/libbsp/i386/pc386/network/Makefile.in b/c/src/lib/libbsp/i386/pc386/network/Makefile.in deleted file mode 100644 index b3e294aae8..0000000000 --- a/c/src/lib/libbsp/i386/pc386/network/Makefile.in +++ /dev/null @@ -1,57 +0,0 @@ -# -# $Id$ -# - -@SET_MAKE@ -srcdir = @srcdir@ -VPATH = @srcdir@ -RTEMS_ROOT = @top_srcdir@ -PROJECT_ROOT = @PROJECT_ROOT@ - -INSTALL = @INSTALL@ - -PGM=${ARCH}/network.rel - -# C source names, if any, go here -- minus the .c -C_PIECES=network -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/network/network.c b/c/src/lib/libbsp/i386/pc386/network/network.c deleted file mode 100644 index e897435f7a..0000000000 --- a/c/src/lib/libbsp/i386/pc386/network/network.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * RTEMS driver for WD800x - * - * Based on the 68360 Network Driver by: - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - * - * $Id$ - */ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#define ET_MINLEN 60 /* minimum message length */ - -/* - * Number of WDs supported by this driver - */ -#define NWDDRIVER 1 - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses four or more buffer descriptors. - */ -#define RX_BUF_COUNT 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 - -/* - * 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 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1520 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct wd_softc { - struct arpcom arpcom; - rtems_irq_connect_data irqInfo; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - unsigned int port; - unsigned char *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; -}; - -#define RO 0x10 - -#define SHATOT (8*1024) /* size of shared memory */ -#define SHAPAGE 256 /* shared memory information */ -#define MAXSIZ 1536 /*(MAXBUF - MESSH_SZ)*/ -#define OUTPAGE ((SHATOT-(MAXSIZ+SHAPAGE-1))/SHAPAGE) - -static volatile unsigned long overrun; -static volatile unsigned long resend; -static struct wd_softc wd_softc[NWDDRIVER]; - -/* - * WD interrupt handler - */ -static rtems_isr -wd8003Enet_interrupt_handler (rtems_vector_number v) -{ - unsigned int tport; - unsigned char status, status2; - - tport = wd_softc[0].port ; - - /* - * Read status - */ - inport_byte(tport+ISR, status); - outport_byte(tport+IMR, 0x00); - - /* - * Ring overwrite - */ - - if (status & MSK_OVW){ - outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */ - Wait_X_ms(2); - outport_byte(tport+RBCR0, 0); /* clear byte count */ - outport_byte(tport+RBCR1, 0); - inport_byte(tport+ISR, status2); - status |= (status2 & (MSK_PTX+MSK_TXE)) ; /* TX status */ - outport_byte(tport+TCR, MSK_LOOP); /* loopback mode */ - outport_byte(tport+CMDR, MSK_STA + MSK_RD2); /* start */ - overrun = 1 ; - if ((status & (MSK_PTX+MSK_TXE)) == 0) - resend = 1; - } - - /* - * Frame received? - */ - if (status & (MSK_PRX+MSK_RXE)) { - outport_byte(tport+ISR, status & (MSK_PRX+MSK_RXE)); - wd_softc[0].rxInterrupts++; - rtems_event_send (wd_softc[0].rxDaemonTid, INTERRUPT_EVENT); - } - -} - -static void nopOn(const rtems_irq_connect_data* notUsed) -{ - /* - * code should be moved from wd8003Enet_initialize_hardware - * to this location - */ -} - -static int wdIsOn(const rtems_irq_connect_data* irq) -{ - return BSP_irq_enabled_at_i8259s (irq->name); -} - -/* - * Initialize the ethernet hardware - */ -static void -wd8003Enet_initialize_hardware (struct wd_softc *sc) -{ - int i1, ultra; - char cc1, cc2; - unsigned char temp; - rtems_status_code st; - unsigned int tport; - unsigned char *hwaddr; - - tport = sc->port; - - /* address from board ROM */ - inport_byte(tport+0x04, temp); - outport_byte(tport+0x04, temp & 0x7f); - - hwaddr = sc->arpcom.ac_enaddr; - for (i1=cc2=0; i1<8; i1++) { - inport_byte(tport + ADDROM + i1, cc1); - cc2 += cc1; - if (i1 < 6) - hwaddr[i1] = cc1; - } - - inport_byte(tport+0x04, temp); - outport_byte(tport+0x04, temp | 0x80); /* alternate registers */ - outport_byte(tport+W83CREG, MSK_RESET); /* reset board, set buffer */ - outport_byte(tport+W83CREG, 0); - outport_byte(tport+W83CREG, MSK_ENASH + (int)((sc->bpar>>13)&0x3f)); - - outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); - cc1 = MSK_BMS + MSK_FT10; /* configure 8 or 16 bits */ - - inport_byte(tport+0x07, temp) ; - - ultra = ((temp & 0xf0) == 0x20 || (temp & 0xf0) == 0x40); - if (ultra) - cc1 = MSK_WTS + MSK_BMS + MSK_FT10; - outport_byte(tport+DCR, cc1); - outport_byte(tport+RBCR0, 0); - outport_byte(tport+RBCR1, 0); - outport_byte(tport+RCR, MSK_MON); /* disable the rxer */ - outport_byte(tport+TCR, 0); /* normal operation */ - outport_byte(tport+PSTOP, OUTPAGE); /* init PSTOP */ - outport_byte(tport+PSTART, 0); /* init PSTART */ - outport_byte(tport+BNRY, -1); /* init BNRY */ - outport_byte(tport+ISR, -1); /* clear IR's */ - outport_byte(tport+IMR, 0x15); /* enable interrupt */ - - outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); - - for (i1=0; i1<6; i1++) /* initial physical addr */ - outport_byte(tport+PAR+i1, hwaddr[i1]); - - for (i1=0; i1irqInfo.hdl = wd8003Enet_interrupt_handler; - sc->irqInfo.on = nopOn; - sc->irqInfo.off = nopOn; - sc->irqInfo.isOn = wdIsOn; - - st = BSP_install_rtems_irq_handler (&sc->irqInfo); - if (!st) - rtems_panic ("Can't attach WD interrupt handler for irq %d\n", - sc->irqInfo.name); -} - -static void -wd_rxDaemon (void *arg) -{ - unsigned int tport; - struct ether_header *eh; - struct wd_softc *dp = (struct wd_softc *)&wd_softc[0]; - struct ifnet *ifp = &dp->arpcom.ac_if; - struct mbuf *m; - unsigned int i2; - unsigned int len; - volatile unsigned char start, next, current; - char *shp, *temp; - rtems_event_set events; - - tport = wd_softc[0].port ; - - for (;;){ - - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - for (;;){ - inport_byte(tport+BNRY, start); - - outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); - inport_byte(tport+CURR, current); - outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); - - start += 1; - if (start >= OUTPAGE){ - start = 0; - } - - if (current == start) - break; - - shp = dp->base + 1 + (SHAPAGE * start); - next = *shp++; - len = *((short *)shp)++ - 4; - - if (next >= OUTPAGE){ - next = 0; - } - - 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); - - if ((i2 = (OUTPAGE - start) * SHAPAGE - 4) < len){ - memcpy(temp, shp, i2); - len -= i2; - temp += i2; - shp = dp->base; - } - memcpy(temp, shp, len); - - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input (ifp, eh, m); - - outport_byte(tport+BNRY, next-1); - } - - /* - * Ring overwrite - */ - if (overrun){ - outport_byte(tport+ISR, MSK_OVW); /* reset IR */ - outport_byte(tport+TCR, 0); /* out of loopback */ - if (resend == 1) - outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); /* resend */ - resend = 0; - overrun = 0; - } - - outport_byte(tport+IMR, 0x15); /* re-enable IT rx */ - } -} - -static void -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct wd_softc *dp = ifp->if_softc; - struct mbuf *n; - unsigned int len, tport; - char *shp, txReady; - - tport = dp->port; - - /* - * Waiting for Transmitter ready - */ - inport_byte(tport+CMDR, txReady); - while(txReady & MSK_TXP) - inport_byte(tport+CMDR, txReady); - - len = 0; - shp = dp->base + (SHAPAGE * OUTPAGE); - - n = m; - - for (;;){ - len += m->m_len; - memcpy(shp, (char *)m->m_data, m->m_len); - shp += m->m_len ; - if ((m = m->m_next) == NULL) - break; - } - - m_freem(n); - - if (len < ET_MINLEN) len = ET_MINLEN; - outport_byte(tport+TBCR0, len); - outport_byte(tport+TBCR1, (len >> 8) ); - outport_byte(tport+TPSR, OUTPAGE); - outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); -} - -/* - * Driver transmit daemon - */ -void -wd_txDaemon (void *arg) -{ - struct wd_softc *sc = (struct wd_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; - } -} - -/* - * Send packet (caller provides header). - */ -static void -wd_start (struct ifnet *ifp) -{ - struct wd_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 -wd_init (void *arg) -{ - struct wd_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Set up WD hardware - */ - wd8003Enet_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, wd_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, wd_rxDaemon, sc); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - -} - -/* - * Stop the device - */ -static void -wd_stop (struct wd_softc *sc) -{ - unsigned int tport; - unsigned char temp; - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Stop the transmitter - */ - tport=wd_softc[0].port ; - inport_byte(tport+0x04,temp); - outport_byte(tport+0x04, temp & 0x7f); - outport_byte(tport + CMDR, MSK_STP + MSK_RD2); - -} - - -/* - * Show interface statistics - */ -static void -wd_stats (struct wd_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 -wd_ioctl (struct ifnet *ifp, int command, caddr_t data) -{ - struct wd_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: - wd_stop (sc); - break; - - case IFF_UP: - wd_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - wd_stop (sc); - wd_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - wd_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Attach an WD driver to the system - */ -int -rtems_wd_driver_attach (struct rtems_bsdnet_ifconfig *config) -{ - struct wd_softc *sc; - struct ifnet *ifp; - int mtu; - int i; - - /* - * Find a free driver - */ - for (i = 0 ; i < NWDDRIVER ; i++) { - sc = &wd_softc[i]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc == NULL) - break; - } - if (i >= NWDDRIVER) { - printf ("Too many WD drivers.\n"); - return 0; - } - - /* - * Process options - */ - 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; - - - if (config->irno) - sc->irqInfo.name = config->irno; - else - sc->irqInfo.name = 5; - - if (config->port) - sc->port = config->port; - else - sc->port = 0x240; - - if (config->bpar) { - sc->bpar = config->bpar; - sc->base = (unsigned char*) config->bpar; - } - else { - sc->bpar = 0xD0000; - sc->base = (unsigned char*) 0xD0000; - } - - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = i + 1; - ifp->if_name = "wd"; - ifp->if_mtu = mtu; - ifp->if_init = wd_init; - ifp->if_ioctl = wd_ioctl; - ifp->if_start = wd_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; - - /* - * init some variables - */ - overrun = 0; - resend = 0; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -}; diff --git a/c/src/lib/libbsp/i386/pc386/wd8003/Makefile.in b/c/src/lib/libbsp/i386/pc386/wd8003/Makefile.in new file mode 100644 index 0000000000..b02e724894 --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/wd8003/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}/wd8003.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=wd8003 +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/wd8003/wd8003.c b/c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c new file mode 100644 index 0000000000..e897435f7a --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c @@ -0,0 +1,657 @@ +/* + * RTEMS driver for WD800x + * + * Based on the 68360 Network Driver by: + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * $Id$ + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#define ET_MINLEN 60 /* minimum message length */ + +/* + * Number of WDs supported by this driver + */ +#define NWDDRIVER 1 + +/* + * Default number of buffer descriptors set aside for this driver. + * The number of transmit buffer descriptors has to be quite large + * since a single frame often uses four or more buffer descriptors. + */ +#define RX_BUF_COUNT 15 +#define TX_BUF_COUNT 4 +#define TX_BD_PER_BUF 4 + +/* + * 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 + +/* + * Receive buffer size -- Allow for a full ethernet packet including CRC + */ +#define RBUF_SIZE 1520 + +#if (MCLBYTES < RBUF_SIZE) +# error "Driver must have MCLBYTES > RBUF_SIZE" +#endif + +/* + * Per-device data + */ +struct wd_softc { + struct arpcom arpcom; + rtems_irq_connect_data irqInfo; + struct mbuf **rxMbuf; + struct mbuf **txMbuf; + int acceptBroadcast; + int rxBdCount; + int txBdCount; + int txBdHead; + int txBdTail; + int txBdActiveCount; + rtems_id rxDaemonTid; + rtems_id txDaemonTid; + + unsigned int port; + unsigned char *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; +}; + +#define RO 0x10 + +#define SHATOT (8*1024) /* size of shared memory */ +#define SHAPAGE 256 /* shared memory information */ +#define MAXSIZ 1536 /*(MAXBUF - MESSH_SZ)*/ +#define OUTPAGE ((SHATOT-(MAXSIZ+SHAPAGE-1))/SHAPAGE) + +static volatile unsigned long overrun; +static volatile unsigned long resend; +static struct wd_softc wd_softc[NWDDRIVER]; + +/* + * WD interrupt handler + */ +static rtems_isr +wd8003Enet_interrupt_handler (rtems_vector_number v) +{ + unsigned int tport; + unsigned char status, status2; + + tport = wd_softc[0].port ; + + /* + * Read status + */ + inport_byte(tport+ISR, status); + outport_byte(tport+IMR, 0x00); + + /* + * Ring overwrite + */ + + if (status & MSK_OVW){ + outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */ + Wait_X_ms(2); + outport_byte(tport+RBCR0, 0); /* clear byte count */ + outport_byte(tport+RBCR1, 0); + inport_byte(tport+ISR, status2); + status |= (status2 & (MSK_PTX+MSK_TXE)) ; /* TX status */ + outport_byte(tport+TCR, MSK_LOOP); /* loopback mode */ + outport_byte(tport+CMDR, MSK_STA + MSK_RD2); /* start */ + overrun = 1 ; + if ((status & (MSK_PTX+MSK_TXE)) == 0) + resend = 1; + } + + /* + * Frame received? + */ + if (status & (MSK_PRX+MSK_RXE)) { + outport_byte(tport+ISR, status & (MSK_PRX+MSK_RXE)); + wd_softc[0].rxInterrupts++; + rtems_event_send (wd_softc[0].rxDaemonTid, INTERRUPT_EVENT); + } + +} + +static void nopOn(const rtems_irq_connect_data* notUsed) +{ + /* + * code should be moved from wd8003Enet_initialize_hardware + * to this location + */ +} + +static int wdIsOn(const rtems_irq_connect_data* irq) +{ + return BSP_irq_enabled_at_i8259s (irq->name); +} + +/* + * Initialize the ethernet hardware + */ +static void +wd8003Enet_initialize_hardware (struct wd_softc *sc) +{ + int i1, ultra; + char cc1, cc2; + unsigned char temp; + rtems_status_code st; + unsigned int tport; + unsigned char *hwaddr; + + tport = sc->port; + + /* address from board ROM */ + inport_byte(tport+0x04, temp); + outport_byte(tport+0x04, temp & 0x7f); + + hwaddr = sc->arpcom.ac_enaddr; + for (i1=cc2=0; i1<8; i1++) { + inport_byte(tport + ADDROM + i1, cc1); + cc2 += cc1; + if (i1 < 6) + hwaddr[i1] = cc1; + } + + inport_byte(tport+0x04, temp); + outport_byte(tport+0x04, temp | 0x80); /* alternate registers */ + outport_byte(tport+W83CREG, MSK_RESET); /* reset board, set buffer */ + outport_byte(tport+W83CREG, 0); + outport_byte(tport+W83CREG, MSK_ENASH + (int)((sc->bpar>>13)&0x3f)); + + outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); + cc1 = MSK_BMS + MSK_FT10; /* configure 8 or 16 bits */ + + inport_byte(tport+0x07, temp) ; + + ultra = ((temp & 0xf0) == 0x20 || (temp & 0xf0) == 0x40); + if (ultra) + cc1 = MSK_WTS + MSK_BMS + MSK_FT10; + outport_byte(tport+DCR, cc1); + outport_byte(tport+RBCR0, 0); + outport_byte(tport+RBCR1, 0); + outport_byte(tport+RCR, MSK_MON); /* disable the rxer */ + outport_byte(tport+TCR, 0); /* normal operation */ + outport_byte(tport+PSTOP, OUTPAGE); /* init PSTOP */ + outport_byte(tport+PSTART, 0); /* init PSTART */ + outport_byte(tport+BNRY, -1); /* init BNRY */ + outport_byte(tport+ISR, -1); /* clear IR's */ + outport_byte(tport+IMR, 0x15); /* enable interrupt */ + + outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); + + for (i1=0; i1<6; i1++) /* initial physical addr */ + outport_byte(tport+PAR+i1, hwaddr[i1]); + + for (i1=0; i1irqInfo.hdl = wd8003Enet_interrupt_handler; + sc->irqInfo.on = nopOn; + sc->irqInfo.off = nopOn; + sc->irqInfo.isOn = wdIsOn; + + st = BSP_install_rtems_irq_handler (&sc->irqInfo); + if (!st) + rtems_panic ("Can't attach WD interrupt handler for irq %d\n", + sc->irqInfo.name); +} + +static void +wd_rxDaemon (void *arg) +{ + unsigned int tport; + struct ether_header *eh; + struct wd_softc *dp = (struct wd_softc *)&wd_softc[0]; + struct ifnet *ifp = &dp->arpcom.ac_if; + struct mbuf *m; + unsigned int i2; + unsigned int len; + volatile unsigned char start, next, current; + char *shp, *temp; + rtems_event_set events; + + tport = wd_softc[0].port ; + + for (;;){ + + + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + + for (;;){ + inport_byte(tport+BNRY, start); + + outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); + inport_byte(tport+CURR, current); + outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); + + start += 1; + if (start >= OUTPAGE){ + start = 0; + } + + if (current == start) + break; + + shp = dp->base + 1 + (SHAPAGE * start); + next = *shp++; + len = *((short *)shp)++ - 4; + + if (next >= OUTPAGE){ + next = 0; + } + + 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); + + if ((i2 = (OUTPAGE - start) * SHAPAGE - 4) < len){ + memcpy(temp, shp, i2); + len -= i2; + temp += i2; + shp = dp->base; + } + memcpy(temp, shp, len); + + eh = mtod (m, struct ether_header *); + m->m_data += sizeof(struct ether_header); + ether_input (ifp, eh, m); + + outport_byte(tport+BNRY, next-1); + } + + /* + * Ring overwrite + */ + if (overrun){ + outport_byte(tport+ISR, MSK_OVW); /* reset IR */ + outport_byte(tport+TCR, 0); /* out of loopback */ + if (resend == 1) + outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); /* resend */ + resend = 0; + overrun = 0; + } + + outport_byte(tport+IMR, 0x15); /* re-enable IT rx */ + } +} + +static void +sendpacket (struct ifnet *ifp, struct mbuf *m) +{ + struct wd_softc *dp = ifp->if_softc; + struct mbuf *n; + unsigned int len, tport; + char *shp, txReady; + + tport = dp->port; + + /* + * Waiting for Transmitter ready + */ + inport_byte(tport+CMDR, txReady); + while(txReady & MSK_TXP) + inport_byte(tport+CMDR, txReady); + + len = 0; + shp = dp->base + (SHAPAGE * OUTPAGE); + + n = m; + + for (;;){ + len += m->m_len; + memcpy(shp, (char *)m->m_data, m->m_len); + shp += m->m_len ; + if ((m = m->m_next) == NULL) + break; + } + + m_freem(n); + + if (len < ET_MINLEN) len = ET_MINLEN; + outport_byte(tport+TBCR0, len); + outport_byte(tport+TBCR1, (len >> 8) ); + outport_byte(tport+TPSR, OUTPAGE); + outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); +} + +/* + * Driver transmit daemon + */ +void +wd_txDaemon (void *arg) +{ + struct wd_softc *sc = (struct wd_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; + } +} + +/* + * Send packet (caller provides header). + */ +static void +wd_start (struct ifnet *ifp) +{ + struct wd_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 +wd_init (void *arg) +{ + struct wd_softc *sc = arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + + if (sc->txDaemonTid == 0) { + + /* + * Set up WD hardware + */ + wd8003Enet_initialize_hardware (sc); + + /* + * Start driver tasks + */ + sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, wd_txDaemon, sc); + sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, wd_rxDaemon, sc); + } + + /* + * Tell the world that we're running. + */ + ifp->if_flags |= IFF_RUNNING; + +} + +/* + * Stop the device + */ +static void +wd_stop (struct wd_softc *sc) +{ + unsigned int tport; + unsigned char temp; + struct ifnet *ifp = &sc->arpcom.ac_if; + + ifp->if_flags &= ~IFF_RUNNING; + + /* + * Stop the transmitter + */ + tport=wd_softc[0].port ; + inport_byte(tport+0x04,temp); + outport_byte(tport+0x04, temp & 0x7f); + outport_byte(tport + CMDR, MSK_STP + MSK_RD2); + +} + + +/* + * Show interface statistics + */ +static void +wd_stats (struct wd_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 +wd_ioctl (struct ifnet *ifp, int command, caddr_t data) +{ + struct wd_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: + wd_stop (sc); + break; + + case IFF_UP: + wd_init (sc); + break; + + case IFF_UP | IFF_RUNNING: + wd_stop (sc); + wd_init (sc); + break; + + default: + break; + } + break; + + case SIO_RTEMS_SHOW_STATS: + wd_stats (sc); + break; + + /* + * FIXME: All sorts of multicast commands need to be added here! + */ + default: + error = EINVAL; + break; + } + return error; +} + +/* + * Attach an WD driver to the system + */ +int +rtems_wd_driver_attach (struct rtems_bsdnet_ifconfig *config) +{ + struct wd_softc *sc; + struct ifnet *ifp; + int mtu; + int i; + + /* + * Find a free driver + */ + for (i = 0 ; i < NWDDRIVER ; i++) { + sc = &wd_softc[i]; + ifp = &sc->arpcom.ac_if; + if (ifp->if_softc == NULL) + break; + } + if (i >= NWDDRIVER) { + printf ("Too many WD drivers.\n"); + return 0; + } + + /* + * Process options + */ + 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; + + + if (config->irno) + sc->irqInfo.name = config->irno; + else + sc->irqInfo.name = 5; + + if (config->port) + sc->port = config->port; + else + sc->port = 0x240; + + if (config->bpar) { + sc->bpar = config->bpar; + sc->base = (unsigned char*) config->bpar; + } + else { + sc->bpar = 0xD0000; + sc->base = (unsigned char*) 0xD0000; + } + + sc->acceptBroadcast = !config->ignore_broadcast; + + /* + * Set up network interface values + */ + ifp->if_softc = sc; + ifp->if_unit = i + 1; + ifp->if_name = "wd"; + ifp->if_mtu = mtu; + ifp->if_init = wd_init; + ifp->if_ioctl = wd_ioctl; + ifp->if_start = wd_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; + + /* + * init some variables + */ + overrun = 0; + resend = 0; + + /* + * Attach the interface + */ + if_attach (ifp); + ether_ifattach (ifp); + return 1; +}; diff --git a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in index 87b2cfbeb9..331ca7f1f7 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 = dec21140 network ne2000 +NETWORK_yes_V = dec21140 ne2000 wd8003 NETWORK = $(NETWORK_$(HAS_NETWORKING)_V) BSP_PIECES=startup clock console timer $(NETWORK) -- cgit v1.2.3