summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/dmv177/sonic
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-05-30 10:09:14 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-05-30 10:09:14 +0000
commitc932d85019761fbafef02fc72119e4bcd4e50978 (patch)
tree20d32f1b768006bfee2385a9cf03a4411373e502 /c/src/lib/libbsp/powerpc/dmv177/sonic
parentchanged version to 980527 (diff)
downloadrtems-c932d85019761fbafef02fc72119e4bcd4e50978.tar.bz2
New files -- from rtems-LM-980406 which was based on an RTEMS from 12/97.
This was called the dmv170 BSP in that source tree but since the DMV171 is now obsolete, we have transitioned to the DMV177 and have no intention of checking compatibility with any other models.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/dmv177/sonic')
-rw-r--r--c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in62
-rw-r--r--c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c1176
-rw-r--r--c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h364
3 files changed, 1602 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in
new file mode 100644
index 0000000000..dcab232876
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in
@@ -0,0 +1,62 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @RTEMS_ROOT@
+PROJECT_ROOT = @PROJECT_ROOT@
+RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+
+PGM=${ARCH}/sonic.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=sonic
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+# Assembly source names, if any, go here -- minus the .s
+S_PIECES=
+S_FILES=$(S_PIECES:%=%.s)
+S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o)
+
+SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+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/powerpc/dmv177/sonic/sonic.c b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c
new file mode 100644
index 0000000000..cd748d59b7
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c
@@ -0,0 +1,1176 @@
+/*
+ *******************************************************************
+ *******************************************************************
+ ** **
+ ** RTEMS/KA9Q DRIVER FOR NATIONAL DP83932 `SONIC' **
+ ** SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER **
+ ** **
+ *******************************************************************
+ *******************************************************************
+ */
+
+/*
+ * $Revision$ $Date$ $Author$
+ * $State$
+ */
+
+/*
+ * References:
+ * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface
+ * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor,
+ * 1995.
+ *
+ * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM),
+ * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140,
+ * RRD-B30M75, National Semiconductor, March, 1991.
+ *
+ * 3) SVME/DMV-171 Single Board Computer Documentation Package, #805905,
+ * DY 4 Systems Inc., Kanata, Ontario, September, 1996.
+ */
+#include "sonic.h"
+
+#include <rtems/error.h>
+#include <ka9q/rtems_ka9q.h>
+#include <ka9q/global.h>
+#include <ka9q/domain.h>
+#include <ka9q/enet.h>
+#include <ka9q/iface.h>
+#include <ka9q/netuser.h>
+#include <ka9q/trace.h>
+#include <ka9q/commands.h>
+
+/*
+ * Number of devices supported by this driver
+ */
+#ifndef NSONIC
+# define NSONIC 1
+#endif
+
+/*
+ * Default location of device registers
+ */
+#ifndef SONIC_BASE_ADDRESS
+# define SONIC_BASE_ADDRESS 0xF3000000
+# warning "Using default SONIC_BASE_ADDRESS."
+#endif
+
+/*
+ * Default interrupt vector
+ */
+#ifndef SONIC_VECTOR
+# define SONIC_VECTOR 1
+# warning "Using default SONIC_VECTOR."
+#endif
+
+/*
+ * Default device configuration register values
+ * Conservative, generic values.
+ * DCR:
+ * No extended bus mode
+ * Unlatched bus retry
+ * Programmable outputs unused
+ * Asynchronous bus mode
+ * User definable pins unused
+ * No wait states (access time controlled by DTACK*)
+ * 32-bit DMA
+ * Empty/Fill DMA mode
+ * Maximum Transmit/Receive FIFO
+ * DC2:
+ * Extended programmable outputs unused
+ * Normal HOLD request
+ * Packet compress output unused
+ * No reject on CAM match
+ */
+#ifndef SONIC_DCR
+# define SONIC_DCR (DCR_DW | DCR_TFT1 | DCR_TFT0)
+#endif
+#ifndef SONIC_DC2
+# define SONIC_DC2 (0)
+#endif
+
+/*
+ * Default sizes of transmit and receive descriptor areas
+ */
+#define RDA_COUNT 20
+#define TDA_COUNT 10
+
+/*
+ *
+ * As suggested by National Application Note 746, make the
+ * receive resource area bigger than the receive descriptor area.
+ */
+#define RRA_EXTRA_COUNT 3
+
+/*
+ * RTEMS event used by interrupt handler to signal daemons.
+ */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+
+/*
+ * Largest Ethernet frame.
+ */
+#define MAXIMUM_FRAME_SIZE 1518
+
+/*
+ * Receive buffer size.
+ * Allow for a pointer, plus a full ethernet frame (including Frame
+ * Check Sequence) rounded up to a 4-byte boundary.
+ */
+#define RBUF_SIZE ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3)
+#define RBUF_WC ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2)
+
+/*
+ * Macros for manipulating 32-bit pointers as 16-bit fragments
+ */
+#define LSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p)))
+#define MSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16))
+#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l)))
+
+/*
+ * Hardware-specific storage
+ */
+struct sonic {
+ /*
+ * Connection to KA9Q
+ */
+ struct iface *iface;
+
+ /*
+ * Default location of device registers
+ * ===CACHE===
+ * This area must be non-cacheable, guarded.
+ */
+ volatile struct SonicRegisters *sonic;
+
+ /*
+ * Interrupt vector
+ */
+ rtems_vector_number vector;
+
+ /*
+ * Task waiting for transmit resources
+ */
+ rtems_id txWaitTid;
+
+ /*
+ * Receive resource area
+ */
+ int rdaCount;
+ ReceiveResourcePointer_t rsa;
+
+ /*
+ * Transmit descriptors
+ */
+ int tdaCount;
+ TransmitDescriptorPointer_t tdaHead; /* Last filled */
+ TransmitDescriptorPointer_t tdaTail; /* Next to retire */
+ int tdaActiveCount;
+
+ /*
+ * Statistics
+ */
+ unsigned long rxInterrupts;
+ unsigned long rxMissed;
+ unsigned long rxGiant;
+ unsigned long rxNonOctet;
+ unsigned long rxBadCRC;
+ unsigned long rxCollision;
+
+ unsigned long txInterrupts;
+ unsigned long txSingleCollision;
+ unsigned long txMultipleCollision;
+ unsigned long txCollision;
+ unsigned long txDeferred;
+ unsigned long txUnderrun;
+ unsigned long txLateCollision;
+ unsigned long txExcessiveCollision;
+ unsigned long txExcessiveDeferral;
+ unsigned long txLostCarrier;
+ unsigned long txRawWait;
+};
+static struct sonic sonic[NSONIC];
+
+/*
+ ******************************************************************
+ * *
+ * Support Routines *
+ * *
+ ******************************************************************
+ */
+
+/*
+ * Allocate non-cacheable memory on a single 64k page.
+ * Very simple minded -- just keeps trying till the memory is on a single page.
+ */
+static void *
+sonic_allocate (unsigned int nbytes)
+{
+ void *p;
+ unsigned long a1, a2;
+
+ for (;;) {
+ /*
+ * ===CACHE===
+ * Change malloc to malloc_noncacheable_guarded.
+ */
+ p = malloc (nbytes);
+ if (p == NULL)
+ rtems_panic ("No memory!");
+ a1 = (unsigned long)p;
+ a2 = a1 + nbytes - 1;
+ if ((a1 >> 16) == (a2 >> 16))
+ break;
+ }
+ return p;
+}
+
+/*
+ * Shut down the interface.
+ * This is a pretty simple-minded routine. It doesn't worry
+ * about cleaning up mbufs, shutting down daemons, etc.
+ */
+static int
+sonic_stop (struct iface *iface)
+{
+ int i;
+ struct sonic *dp = &sonic[iface->dev];
+ volatile struct SonicRegisters *rp = dp->sonic;
+
+ /*
+ * Stop the transmitter and receiver.
+ */
+ rp->cr = CR_HTX | CR_RXDIS;
+
+ /*
+ * Wait for things to stop.
+ * For safety's sake, there is an alternate exit.
+ */
+ i = 0;
+ while (rp->cr & (CR_RXEN | CR_TXP)) {
+ if (++i == 10000)
+ break;
+ }
+
+ /*
+ * Reset the device
+ */
+ rp->cr = CR_RST;
+ rp->imr = 0;
+ return 0;
+}
+
+/*
+ * Show interface statistics
+ */
+static void
+sonic_show (struct iface *iface)
+{
+ struct sonic *dp = &sonic[iface->dev];
+
+ printf (" Rx Interrupts:%-8lu", dp->rxInterrupts);
+ printf (" Giant:%-8lu", dp->rxGiant);
+ printf (" Non-octet:%-8lu\n", dp->rxNonOctet);
+ printf (" Bad CRC:%-8lu", dp->rxBadCRC);
+ printf (" Collision:%-8lu", dp->rxCollision);
+ printf (" Missed:%-8lu\n", dp->rxMissed);
+
+ printf ( " Tx Interrupts:%-8lu", dp->txInterrupts);
+ printf ( " Deferred:%-8lu", dp->txDeferred);
+ printf (" Lost Carrier:%-8lu\n", dp->txLostCarrier);
+ printf ( "Single Collisions:%-8lu", dp->txSingleCollision);
+ printf ( "Multiple Collisions:%-8lu", dp->txMultipleCollision);
+ printf ("Excessive Collisions:%-8lu\n", dp->txExcessiveCollision);
+ printf ( " Total Collisions:%-8lu", dp->txCollision);
+ printf ( " Late Collision:%-8lu", dp->txLateCollision);
+ printf (" Underrun:%-8lu\n", dp->txUnderrun);
+ printf ( " Raw output wait:%-8lu\n", dp->txRawWait);
+}
+
+/*
+ ******************************************************************
+ * *
+ * Interrupt Handler *
+ * *
+ ******************************************************************
+ */
+static rtems_isr
+sonic_interrupt_handler (rtems_vector_number v)
+{
+ struct sonic *dp = sonic;
+ volatile struct SonicRegisters *rp;
+
+#if (NSONIC > 1)
+ /*
+ * Find the device which requires service
+ */
+ for (;;) {
+ if (dp->vector == v)
+ break;
+ if (++dp == &sonic[NSONIC])
+ return; /* Spurious interrupt? */
+ }
+#endif /* NSONIC > 1 */
+
+ /*
+ * Get pointer to SONIC registers
+ */
+ rp = dp->sonic;
+
+ /*
+ * Packet received or receive buffer area exceeded?
+ */
+ if ((rp->imr & (IMR_PRXEN | IMR_RBAEEN))
+ && (rp->isr & (ISR_PKTRX | ISR_RBAE))) {
+ rp->imr &= ~(IMR_PRXEN | IMR_RBAEEN);
+ dp->rxInterrupts++;
+ rtems_event_send (dp->iface->rxproc, INTERRUPT_EVENT);
+ }
+
+ /*
+ * Packet started, transmitter done or transmitter error?
+ */
+ if ((rp->imr & (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN))
+ && (rp->isr & (ISR_PINT | ISR_TXDN | ISR_TXER))) {
+ rp->imr &= ~(IMR_PINTEN | IMR_PTXEN | IMR_TXEREN);
+ dp->txInterrupts++;
+ rtems_event_send (dp->txWaitTid, INTERRUPT_EVENT);
+ }
+}
+
+/*
+ ******************************************************************
+ * *
+ * Transmitter Routines *
+ * *
+ ******************************************************************
+ */
+
+/*
+ * Soak up transmit descriptors that have been sent.
+ */
+static void
+sonic_retire_tda (struct sonic *dp)
+{
+ rtems_unsigned16 status;
+ unsigned int collisions;
+
+ /*
+ * Repeat for all completed transmit descriptors.
+ */
+ while ((dp->tdaActiveCount != 0)
+ && ((status = dp->tdaTail->status) != 0)) {
+ /*
+ * Check for errors which stop the transmitter.
+ */
+ if (status & (TDA_STATUS_EXD |
+ TDA_STATUS_EXC |
+ TDA_STATUS_FU |
+ TDA_STATUS_BCM)) {
+ /*
+ * Restart the transmitter if there are
+ * packets waiting to go.
+ */
+ rtems_unsigned16 link;
+ link = *(dp->tdaTail->linkp);
+
+ if ((link & TDA_LINK_EOL) == 0) {
+ volatile struct SonicRegisters *rp = dp->sonic;
+
+ rp->ctda = link;
+ rp->cr = CR_TXP;
+ }
+ }
+
+ /*
+ * Update network statistics
+ */
+ collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT;
+ if (collisions) {
+ if (collisions == 1)
+ dp->txSingleCollision++;
+ else
+ dp->txMultipleCollision++;
+ dp->txCollision += collisions;
+ }
+ if (status & TDA_STATUS_EXC)
+ dp->txExcessiveCollision++;
+ if (status & TDA_STATUS_OWC)
+ dp->txLateCollision++;
+ if (status & TDA_STATUS_EXD)
+ dp->txExcessiveDeferral++;
+ if (status & TDA_STATUS_DEF)
+ dp->txDeferred++;
+ if (status & TDA_STATUS_FU)
+ dp->txUnderrun++;
+ if (status & TDA_STATUS_CRSL)
+ dp->txLostCarrier++;
+
+ /*
+ * Free the packet
+ */
+ dp->tdaActiveCount--;
+ free_p ((struct mbuf **)&dp->tdaTail->mbufp);
+
+ /*
+ * Move to the next transmit descriptor
+ */
+ dp->tdaTail = dp->tdaTail->next;
+ }
+}
+
+/*
+ * Send raw packet (caller provides header).
+ * This code runs in the context of the interface transmit
+ * task (most packets) or in the context of the network
+ * task (for ARP requests).
+ */
+static int
+sonic_raw (struct iface *iface, struct mbuf **bpp)
+{
+ struct sonic *dp = &sonic[iface->dev];
+ volatile struct SonicRegisters *rp = dp->sonic;
+ struct mbuf *bp;
+ TransmitDescriptorPointer_t tdp;
+ volatile struct TransmitDescriptorFragLink *fp;
+ unsigned int packetSize;
+ int i;
+ static char padBuf[64];
+
+ /*
+ * Update the log.
+ */
+ iface->rawsndcnt++;
+ iface->lastsent = secclock ();
+ dump (iface, IF_TRACE_OUT, *bpp);
+
+ /*
+ * It would not do to have two tasks active in the transmit
+ * loop at the same time.
+ * The blocking is simple-minded since the odds of two tasks
+ * simultaneously attempting to use this code are low. The only
+ * way that two tasks can try to run here is:
+ * 1) Task A enters this code and ends up having to
+ * wait for a transmit buffer descriptor.
+ * 2) Task B gains control and tries to transmit a packet.
+ * The RTEMS/KA9Q scheduling semaphore ensures that there
+ * are no race conditions associated with manipulating the
+ * txWaitTid variable.
+ */
+ if (dp->txWaitTid) {
+ dp->txRawWait++;
+ while (dp->txWaitTid)
+ rtems_ka9q_ppause (10);
+ }
+
+ /*
+ * Free up transmit descriptors.
+ */
+ sonic_retire_tda (dp);
+
+ /*
+ * Wait for transmit descriptor to become available.
+ */
+ if (dp->tdaActiveCount == dp->tdaCount) {
+ /*
+ * Find out who we are
+ */
+ if (dp->txWaitTid == 0)
+ rtems_task_ident (RTEMS_SELF, 0, &dp->txWaitTid);
+
+ /*
+ * Clear old events.
+ */
+ rp->isr = ISR_PINT | ISR_TXDN | ISR_TXER;
+
+ /*
+ * Wait for transmit descriptor to become available.
+ * Note that the transmit descriptors are checked
+ * *before* * entering the wait loop -- this catches
+ * the possibility that a transmit descriptor became
+ * available between the `if' the started this block,
+ * and the clearing of the interrupt status register.
+ */
+ sonic_retire_tda (dp);
+ while (dp->tdaActiveCount == dp->tdaCount) {
+ /*
+ * Enable transmitter interrupts.
+ */
+ rp->imr |= (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN);
+
+ /*
+ * Wait for interrupt
+ */
+ rtems_ka9q_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT);
+ rp->isr = ISR_PINT | ISR_TXDN | ISR_TXER;
+ sonic_retire_tda (dp);
+ }
+ }
+
+ /*
+ * Get the head of the packet mbuf chain.
+ */
+ bp = *bpp;
+
+ /*
+ * Fill in the transmit descriptor fragment descriptors.
+ * ===CACHE===
+ * If data cache is operating in write-back mode, flush cached
+ * data to memory.
+ */
+ tdp = dp->tdaHead->next;
+ tdp->mbufp = bp;
+ packetSize = 0;
+ fp = tdp->frag;
+ for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) {
+ fp->frag_lsw = LSW(bp->data);
+ fp->frag_msw = MSW(bp->data);
+ fp->frag_size = bp->cnt;
+ packetSize += bp->cnt;
+
+ /*
+ * Break out of the loop if this mbuf is the last in the frame.
+ */
+ if ((bp = bp->next) == NULL)
+ break;
+ }
+
+ /*
+ * Pad short packets.
+ */
+ if ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {
+ int padSize = 64 - packetSize;
+ fp->frag_lsw = LSW(padBuf);
+ fp->frag_msw = MSW(padBuf);
+ fp->frag_size = padSize;
+ packetSize += padSize;
+ i++;
+ fp++;
+ }
+
+ /*
+ * Fill Transmit Descriptor
+ */
+ tdp->pkt_size = packetSize;
+ tdp->frag_count = i;
+ tdp->status = 0;
+
+ /*
+ * Chain onto list and start transmission.
+ */
+ tdp->linkp = &fp->frag_link;
+ *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;
+ *dp->tdaHead->linkp &= ~TDA_LINK_EOL;
+ rp->cr = CR_TXP;
+ dp->tdaActiveCount++;
+ dp->tdaHead = tdp;
+
+ /*
+ * Let KA9Q know the packet is on the way.
+ */
+ dp->txWaitTid = 0;
+ *bpp = NULL;
+ return 0;
+}
+
+/*
+ ******************************************************************
+ * *
+ * Receiver Routines *
+ * *
+ ******************************************************************
+ */
+
+/*
+ * Wait for SONIC to hand over a Receive Descriptor.
+ */
+static void
+sonic_rda_wait (struct sonic *dp, ReceiveDescriptorPointer_t rdp)
+{
+ int i;
+ volatile struct SonicRegisters *rp = dp->sonic;
+
+ /*
+ * Wait for Receive Descriptor.
+ * The order of the tests is very important.
+ * The RDA is checked after RBAE is detected. This ensures that
+ * the driver processes all RDA entries before reusing the RRA
+ * entry holding the giant packet.
+ * The event wait is done after the RDA and RBAE checks. This
+ * catches the possibility that a Receive Descriptor became ready
+ * between the call to this function and the clearing of the
+ * interrupt status register bit.
+ */
+ for (;;) {
+ /*
+ * Has a giant packet arrived?
+ * The National DP83932C data sheet is very vague on what
+ * happens under this condition. The description of the
+ * Interrupt Status Register (Section 4.3.6) states,
+ * ``Reception is aborted and the SONIC fetches the next
+ * available resource descriptors in the RRA. The buffer
+ * space is not re-used and an RDA is not setup for the
+ * truncated packet.''
+ * I take ``Reception is aborted'' to mean that the RXEN
+ * bit in the Command Register is cleared and must be set
+ * by the driver to begin reception again.
+ * Unfortunately, an alternative interpretation could be
+ * that only reception of the current packet is aborted.
+ * This would be more difficult to recover from....
+ */
+ if (rp->isr & ISR_RBAE) {
+ /*
+ * One more check to soak up any Receive Descriptors
+ * that may already have been handed back to the driver.
+ */
+ if (rdp->in_use == 0)
+ break;
+
+ /*
+ * Check my interpretation of the SONIC manual.
+ */
+ if (rp->cr & CR_RXEN)
+ rtems_panic ("SONIC RBAE/RXEN");
+
+ /*
+ * Update statistics
+ */
+ dp->rxGiant++;
+
+ /*
+ * Reuse receive buffer.
+ * Again, the manual is subject to interpretation. The
+ * RRP register is described as, `the lower address of
+ * the next descriptor the SONIC will read.''
+ * Since, acording to the ISR/RBAE notes, the SONIC has
+ * ``fetched the next available resource descriptor in
+ * the RRA'', I interpret this to mean that that the
+ * driver has to move the RRP back *two* entries to
+ * reuse the receive buffer holding the giant packet.
+ */
+ for (i = 0 ; i < 2 ; i++) {
+ if (rp->rrp == rp->rsa)
+ rp->rrp = rp->rea;
+ rp->rrp -= sizeof (ReceiveResource_t);
+ }
+
+ /*
+ * Restart reception
+ */
+ rp->isr = ISR_RBAE;
+ rp->cr = CR_RXEN;
+ }
+
+ /*
+ * Clear old packet-received events.
+ */
+ rp->isr = ISR_PKTRX;
+
+ /*
+ * Has Receive Descriptor become available?
+ */
+ if (rdp->in_use == 0)
+ break;
+
+ /*
+ * Enable interrupts.
+ */
+ rp->imr |= IMR_PRXEN | IMR_RBAEEN;
+
+ /*
+ * Wait for interrupt.
+ */
+ rtems_ka9q_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT);
+ }
+}
+
+/*
+ * SCC reader task
+ */
+static void
+sonic_rx (int dev, void *p1, void *p2)
+{
+ struct iface *iface = (struct iface *)p1;
+ struct sonic *dp = (struct sonic *)p2;
+ volatile struct SonicRegisters *rp = dp->sonic;
+ struct mbuf *bp;
+ rtems_unsigned16 status;
+ ReceiveDescriptor_t *rda;
+ ReceiveDescriptorPointer_t ordp, rdp;
+ ReceiveResourcePointer_t rwp, rea;
+ rtems_unsigned16 newMissedTally, oldMissedTally;
+ int i;
+ int continuousCount;
+
+ /*
+ * Set up list in Receive Resource Area.
+ * Allocate space for incoming packets.
+ */
+ rwp = dp->rsa;
+ for (i = 0 ; i < (dp->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) {
+ struct mbuf **mbp;
+
+ /*
+ * Allocate memory for buffer.
+ * Place a pointer to the mbuf at the beginning of the buffer
+ * so we can find the mbuf when the SONIC returns the buffer
+ * to the driver.
+ */
+ bp = ambufw (RBUF_SIZE);
+ mbp = (struct mbuf **)bp->data;
+ bp->data += sizeof *mbp;
+ *mbp = bp;
+
+ /*
+ * Set up RRA entry
+ */
+ rwp->buff_ptr_lsw = LSW(bp->data);
+ rwp->buff_ptr_msw = MSW(bp->data);
+ rwp->buff_wc_lsw = RBUF_WC;
+ rwp->buff_wc_msw = 0;
+ }
+ rea = rwp;
+
+ /*
+ * Set up remaining Receive Resource Area pointers
+ */
+ rp->rsa = LSW(dp->rsa);
+ rp->rrp = LSW(dp->rsa);
+ rp->rea = LSW(rea);
+ rp->rwp = LSW(rea);
+
+ /*
+ * Set End Of Buffer Count register to the value recommended
+ * in Note 1 of Section 3.4.4.4 of the SONIC data sheet.
+ */
+ rp->eobc = RBUF_WC - 2;
+
+ /*
+ * Set up circular linked list in Receive Descriptor Area.
+ * Leaves ordp pointing at the `end' of the list and
+ * rdp pointing at the `beginning' of the list.
+ */
+ rda = sonic_allocate (dp->rdaCount * sizeof *rda);
+ ordp = rdp = rda;
+ for (i = 0 ; i < dp->rdaCount ; i++) {
+ /*
+ * Set up RDA entry
+ */
+ if (i == (dp->rdaCount - 1))
+ rdp->next = rda;
+ else
+ rdp->next = (ReceiveDescriptor_t *)(rdp + 1);
+ rdp->in_use = 1;
+ ordp = rdp;
+ rdp = rdp->next;
+ ordp->link = LSW(rdp);
+ }
+ ordp->link |= RDA_LINK_EOL;
+ rp->urda = MSW(rdp);
+ rp->crda = LSW(rdp);
+
+ /*
+ * Start the receiver
+ */
+ oldMissedTally = rp->mpt;
+ rp->cr = CR_RRRA;
+ rp->cr = CR_RXEN;
+
+ /*
+ * Input packet handling loop
+ */
+ continuousCount = 0;
+ for (;;) {
+ /*
+ * Wait till SONIC supplies a Receive Descriptor.
+ */
+ if (rdp->in_use) {
+ continuousCount = 0;
+ sonic_rda_wait (dp, rdp);
+ }
+
+ /*
+ * Check that packet is valid
+ */
+ status = rdp->status;
+ if (status & RDA_STATUS_PRX) {
+ struct mbuf **mbp;
+ void *p;
+
+ /*
+ * Get the mbuf pointer
+ */
+ p = PTR(rdp->pkt_msw, rdp->pkt_lsw);
+ mbp = (struct mbuf **)p - 1;
+ bp = *mbp;
+
+ /*
+ * Pass the packet up the chain.
+ * The mbuf count is reduced to remove
+ * the frame check sequence at the end
+ * of the packet.
+ * ===CACHE===
+ * Invalidate cache entries for this memory.
+ */
+ bp->cnt = rdp->byte_count - sizeof (uint32);
+ net_route (iface, &bp);
+
+ /*
+ * Give the network code a chance to digest the
+ * packet. This guards against a flurry of
+ * incoming packets (usually an ARP storm) from
+ * using up all the available memory.
+ */
+ if (++continuousCount >= dp->rdaCount)
+ kwait_null ();
+
+ /*
+ * Sanity check that Receive Resource Area is
+ * still in sync with Receive Descriptor Area
+ * The buffer reported in the Receive Descriptor
+ * should be the same as the buffer in the Receive
+ * Resource we are about to reuse.
+ */
+ if ((LSW(p) != rwp->buff_ptr_lsw)
+ || (MSW(p) != rwp->buff_ptr_msw))
+ rtems_panic ("SONIC RDA/RRA");
+
+ /*
+ * Allocate a new mbuf.
+ */
+ bp = ambufw (RBUF_SIZE);
+ mbp = (struct mbuf **)bp->data;
+ bp->data += sizeof *mbp;
+ *mbp = bp;
+
+ /*
+ * Reuse Receive Resource.
+ */
+ rwp->buff_ptr_lsw = LSW(bp->data);
+ rwp->buff_ptr_msw = MSW(bp->data);
+ rwp++;
+ if (rwp == rea)
+ rwp = dp->rsa;
+ rp->rwp = LSW(rwp);
+
+ /*
+ * Tell the SONIC to reread the RRA.
+ */
+ if (rp->isr & ISR_RBE)
+ rp->isr = ISR_RBE;
+ }
+ else {
+ if (status & RDA_STATUS_COL)
+ dp->rxCollision++;
+ if (status & RDA_STATUS_FAER)
+ dp->rxNonOctet++;
+ else if (status & RDA_STATUS_CRCR)
+ dp->rxBadCRC++;
+ }
+
+ /*
+ * Count missed packets
+ */
+ newMissedTally = rp->mpt;
+ if (newMissedTally != oldMissedTally) {
+ dp->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF;
+ newMissedTally = oldMissedTally;
+ }
+
+ /*
+ * Move to next receive descriptor
+ */
+ rdp->link |= RDA_LINK_EOL;
+ rdp->in_use = 1;
+ ordp->link &= ~RDA_LINK_EOL;
+ ordp = rdp;
+ rdp = rdp->next;
+ }
+}
+
+/*
+ ******************************************************************
+ * *
+ * Initialization Routines *
+ * *
+ ******************************************************************
+ */
+
+/*
+ * Initialize the SONIC hardware
+ */
+static void
+sonic_initialize_hardware (struct sonic *dp, int broadcastFlag)
+{
+ volatile struct SonicRegisters *rp = dp->sonic;
+ int i;
+ unsigned char *hwaddr;
+ rtems_status_code sc;
+ rtems_isr_entry old_handler;
+ TransmitDescriptorPointer_t otdp, tdp;
+ struct CamDescriptor{
+ rtems_unsigned32 cep;
+ rtems_unsigned32 cap0;
+ rtems_unsigned32 cap1;
+ rtems_unsigned32 cap2;
+ rtems_unsigned32 ce;
+ };
+ volatile struct CamDescriptor *cdp;
+
+ /*
+ * Issue a software reset if necessary.
+ */
+ if ((rp->cr & CR_RST) == 0)
+ rp->cr = CR_RST;
+
+ /*
+ * Set up data configuration registers.
+ */
+ rp->dcr = SONIC_DCR;
+ rp->dcr2 = SONIC_DC2;
+
+ /*
+ * Remove device reset
+ */
+ rp->cr = 0;
+
+ /*
+ * Clear outstanding interrupts.
+ */
+ rp->isr = 0x7FFF;
+
+ /*
+ * Allocate the receive resource area.
+ * In accordance with National Application Note 746, make the
+ * receive resource area bigger than the receive descriptor area.
+ * This has the useful side effect of making the receive resource
+ * area big enough to hold the CAM descriptor area.
+ */
+ dp->rsa = sonic_allocate ((dp->rdaCount + RRA_EXTRA_COUNT) * sizeof *dp->rsa);
+ rp->urra = MSW(dp->rsa);
+
+ /*
+ * Set up the SONIC CAM with our hardware address.
+ * Use the Receive Resource Area to hold the CAM Descriptor Area.
+ */
+ hwaddr = dp->iface->hwaddr;
+ cdp = (struct CamDescriptor *)dp->rsa;
+ cdp->cep = 0; /* Fill first entry in CAM */
+ cdp->cap2 = hwaddr[0] << 8 | hwaddr[1];
+ cdp->cap1 = hwaddr[2] << 8 | hwaddr[3];
+ cdp->cap0 = hwaddr[4] << 8 | hwaddr[5];
+ cdp->ce = 0x0001; /* Enable first entry in CAM */
+ rp->cdc = 1; /* One entry in CDA */
+ rp->cdp = LSW(cdp);
+ rp->cr = CR_LCAM; /* Load the CAM */
+ while (rp->cr & CR_LCAM)
+ continue;
+
+ /*
+ * Verify that CAM was properly loaded.
+ */
+ rp->cep = 0; /* Select first entry in CAM */
+ if ((rp->cap2 != cdp->cap2)
+ || (rp->cap1 != cdp->cap1)
+ || (rp->cap0 != cdp->cap0)
+ || (rp->ce != cdp->ce)) {
+ printf ("Failed to load Ethernet address into SONIC CAM.\n"
+ " Wrote %04x%04x%04x - %#x\n"
+ " Read %04x%04x%04x - %#x\n",
+ cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
+ rp->cap2, rp->cap1, rp->cap0, rp->ce);
+ rtems_panic ("SONIC LCAM");
+ }
+
+ /*
+ * Set up circular linked list in Transmit Descriptor Area.
+ * Use the PINT bit in the transmit configuration field to
+ * request an interrupt on every other transmitted packet.
+ */
+ dp->tdaActiveCount = 0;
+ dp->tdaTail = sonic_allocate (dp->tdaCount * sizeof *tdp);
+ otdp = tdp = dp->tdaTail;
+ for (i = 0 ; i < dp->tdaCount ; i++) {
+ if (i & 1)
+ tdp->pkt_config = TDA_CONFIG_PINT;
+ else
+ tdp->pkt_config = 0;
+ if (i == (dp->tdaCount - 1))
+ tdp->next = (TransmitDescriptor_t *)dp->tdaTail;
+ else
+ tdp->next = (TransmitDescriptor_t *)(tdp + 1);
+ otdp = tdp;
+ tdp = tdp->next;
+ }
+ dp->tdaHead = otdp;
+ dp->tdaHead->linkp = &dp->tdaHead->frag[0].frag_link;
+ rp->utda = MSW(dp->tdaTail);
+ rp->ctda = LSW(dp->tdaTail);
+
+ /*
+ * Enable/disable reception of broadcast packets
+ */
+ if (broadcastFlag)
+ rp->rcr = RCR_BRD;
+ else
+ rp->rcr = 0;
+
+ /*
+ * Attach SONIC interrupt handler
+ */
+ rp->imr = 0;
+ sc = rtems_interrupt_catch (sonic_interrupt_handler, dp->vector, &old_handler);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_panic ("Can't attach SONIC interrupt handler: %s\n",
+ rtems_status_text (sc));
+
+ /*
+ * Remainder of hardware initialization is
+ * done by the receive and transmit daemons.
+ */
+}
+
+/*
+ * Attach an SONIC driver to the system
+ * This is the only `extern' function in the driver.
+ *
+ * argv[0]: interface label, e.g. "rtems"
+ * The remainder of the arguments are optional key/value pairs:
+ * mtu ## -- maximum transmission unit, default 1500
+ * broadcast y/n -- accept or ignore broadcast packets, default yes
+ * rbuf ## -- Set number of receive descriptor entries
+ * tbuf ## -- Set number of transmit descriptor entries
+ * ip ###.###.###.### -- IP address
+ * ether ##:##:##:##:##:## -- Ethernet address
+ * reg ###### -- Address of SONIC device registers
+ * vector ### -- SONIC interrupt vector
+ */
+int
+rtems_ka9q_driver_attach (int argc, char *argv[], void *p)
+{
+ struct sonic *dp;
+ struct iface *iface;
+ char *cp;
+ int argIndex;
+ int broadcastFlag;
+ char cbuf[30];
+
+ /*
+ * Find an unused entry
+ */
+ dp = sonic;
+ for (;;) {
+ if (dp == &sonic[NSONIC]) {
+ printf ("No more SONIC devices.\n");
+ return -1;
+ }
+ if (dp->iface == NULL)
+ break;
+ dp++;
+ }
+ if (if_lookup (argv[0]) != NULL) {
+ printf ("Interface %s already exists\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Create an inteface descriptor
+ */
+ iface = callocw (1, sizeof *iface);
+ iface->name = strdup (argv[0]);
+ iface->dev = dp - sonic;;
+
+ /*
+ * Set default values
+ */
+ broadcastFlag = 1;
+ dp->txWaitTid = 0;
+ dp->rdaCount = RDA_COUNT;
+ dp->tdaCount = TDA_COUNT;
+ iface->mtu = 1500;
+ iface->addr = Ip_addr;
+ iface->hwaddr = mallocw (EADDR_LEN);
+ memset (iface->hwaddr, 0x08, EADDR_LEN);
+ dp->sonic = (struct SonicRegisters *)SONIC_BASE_ADDRESS;
+ dp->vector = SONIC_VECTOR;
+
+ /*
+ * Parse remaining arguments
+ */
+ for (argIndex = 1 ; argIndex < (argc - 1) ; argIndex++) {
+ if (strcmp ("mtu", argv[argIndex]) == 0) {
+ iface->mtu = strtoul (argv[++argIndex], NULL, 0);
+ }
+ else if (strcmp ("broadcast", argv[argIndex]) == 0) {
+ if (*argv[++argIndex] == 'n')
+ broadcastFlag = 0;
+ }
+ else if (strcmp ("rbuf", argv[argIndex]) == 0) {
+ /*
+ * The minimum RDA count is 2. A single-entry RDA
+ * would be difficult to use since the SONIC does
+ * not release (in_use = 0) the RDA that has the
+ * EOL bit set.
+ */
+ dp->rdaCount = strtoul (argv[++argIndex], NULL, 0);
+ if ((dp->rdaCount <= 1) || (dp->rdaCount > 200)) {
+ printf ("RDA option (%d) is invalid.\n", dp->rdaCount);
+ return -1;
+ }
+ }
+ else if (strcmp ("tbuf", argv[argIndex]) == 0) {
+ dp->tdaCount = strtoul (argv[++argIndex], NULL, 0);
+ if ((dp->tdaCount <= 1) || (dp->tdaCount > 200)) {
+ printf ("TDA option (%d) is invalid.\n", dp->tdaCount);
+ return -1;
+ }
+ }
+ else if (strcmp ("ip", argv[argIndex]) == 0) {
+ iface->addr = resolve (argv[++argIndex]);
+ }
+ else if (strcmp ("ether", argv[argIndex]) == 0) {
+ gether (iface->hwaddr, argv[++argIndex]);
+ }
+ else if (strcmp ("reg", argv[argIndex]) == 0) {
+ dp->sonic = (struct SonicRegisters *)strtoul (argv[++argIndex], NULL, 0);
+ }
+ else if (strcmp ("vector", argv[argIndex]) == 0) {
+ dp->vector = strtoul (argv[++argIndex], NULL, 0);
+ }
+ else {
+ printf ("Argument %d (%s) is invalid.\n", argIndex, argv[argIndex]);
+ return -1;
+ }
+ }
+ printf ("Ethernet address: %s\n", pether (cbuf, iface->hwaddr));
+ iface->raw = sonic_raw;
+ iface->stop = sonic_stop;
+ iface->show = sonic_show;
+ dp->iface = iface;
+ setencap (iface, "Ethernet");
+
+ /*
+ * Set up SONIC hardware
+ */
+ sonic_initialize_hardware (dp, broadcastFlag);
+
+ /*
+ * Chain onto list of interfaces
+ */
+ iface->next = Ifaces;
+ Ifaces = iface;
+
+ /*
+ * Start I/O daemons
+ */
+ cp = if_name (iface, " tx");
+ iface->txproc = newproc (cp, 2048, if_tx, iface->dev, iface, NULL, 0);
+ free (cp);
+ cp = if_name (iface, " rx");
+ iface->rxproc = newproc (cp, 2048, sonic_rx, iface->dev, iface, dp, 0);
+ free (cp);
+ return 0;
+}
diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h
new file mode 100644
index 0000000000..2607e2a170
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h
@@ -0,0 +1,364 @@
+/*
+ *******************************************************************
+ *******************************************************************
+ ** **
+ ** DECLARATIONS FOR NATIONAL DP83932 `SONIC' **
+ ** SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER **
+ ** **
+ *******************************************************************
+ *******************************************************************
+ */
+
+/*
+ * $Revision$ $Date$ $Author$
+ * $State$
+ */
+
+#ifndef _SONIC_DP83932_
+#define _SONIC_DP83932_
+
+#include <bsp.h>
+
+/*
+ ******************************************************************
+ * *
+ * Device Registers *
+ * *
+ ******************************************************************
+ */
+struct SonicRegisters {
+ /*
+ * Command and status registers
+ */
+ rtems_unsigned32 cr; /* Command */
+ rtems_unsigned32 dcr; /* Data configuration */
+ rtems_unsigned32 rcr; /* Receive control */
+ rtems_unsigned32 tcr; /* Transmit control */
+ rtems_unsigned32 imr; /* Interrupt mask */
+ rtems_unsigned32 isr; /* Interrupt status */
+
+ /*
+ * Transmit registers
+ */
+ rtems_unsigned32 utda; /* Upper transmit descriptor address */
+ rtems_unsigned32 ctda; /* Current transmit descriptor address */
+
+ /*
+ * Receive registers
+ */
+ rtems_unsigned32 pad0[5];
+ rtems_unsigned32 urda; /* Upper receive descriptor address */
+ rtems_unsigned32 crda; /* Current receive descriptor address */
+ rtems_unsigned32 pad1[4];
+ rtems_unsigned32 eobc; /* End of buffer word count */
+ rtems_unsigned32 urra; /* Upper receive resource */
+ rtems_unsigned32 rsa; /* Resource start address */
+ rtems_unsigned32 rea; /* Resource end address */
+ rtems_unsigned32 rrp; /* Resouce read pointer */
+ rtems_unsigned32 rwp; /* Resouce read pointer */
+
+ /*
+ * Content-addressable memory registers
+ */
+ rtems_unsigned32 pad2[8];
+ rtems_unsigned32 cep; /* CAM entry pointer */
+ rtems_unsigned32 cap2; /* CAM address port 2 */
+ rtems_unsigned32 cap1; /* CAM address port 1 */
+ rtems_unsigned32 cap0; /* CAM address port 0 */
+ rtems_unsigned32 ce; /* CAM enable */
+ rtems_unsigned32 cdp; /* CAM descriptor pointer */
+ rtems_unsigned32 cdc; /* CAM descriptor count */
+
+ /*
+ * Silicon revision
+ */
+ rtems_unsigned32 sr; /* Silicon revision */
+
+ /*
+ * Watchdog counters
+ */
+ rtems_unsigned32 wt0; /* Watchdog timer 0 */
+ rtems_unsigned32 wt1; /* Watchdog timer 1 */
+
+ /*
+ * Another receive register
+ */
+ rtems_unsigned32 rsc; /* Receive sequence counter */
+
+ /*
+ * Tally counters
+ */
+ rtems_unsigned32 crct; /* CRC error tally */
+ rtems_unsigned32 faet; /* FAE tally */
+ rtems_unsigned32 mpt; /* Missed packet tally */
+
+ /*
+ * Another command and status register
+ */
+ rtems_unsigned32 pad3[16];
+ rtems_unsigned32 dcr2; /* Data configuration 2 */
+};
+
+/*
+ * Command register
+ */
+#define CR_LCAM 0x0200
+#define CR_RRRA 0x0100
+#define CR_RST 0x0080
+#define CR_ST 0x0020
+#define CR_STP 0x0010
+#define CR_RXEN 0x0008
+#define CR_RXDIS 0x0004
+#define CR_TXP 0x0002
+#define CR_HTX 0x0001
+
+/*
+ * Data configuration register
+ */
+#define DCR_EXBUS 0x8000
+#define DCR_LBR 0x2000
+#define DCR_PO1 0x1000
+#define DCR_PO0 0x0800
+#define DCR_SBUS 0x0400
+#define DCR_USR1 0x0200
+#define DCR_USR0 0x0100
+#define DCR_WC1 0x0080
+#define DCR_WC0 0x0040
+#define DCR_DW 0x0020
+#define DCR_BMS 0x0010
+#define DCR_RFT1 0x0008
+#define DCR_RFT0 0x0004
+#define DCR_TFT1 0x0002
+#define DCR_TFT0 0x0001
+
+/*
+ * Receive control register
+ */
+#define RCR_ERR 0x8000
+#define RCR_RNT 0x4000
+#define RCR_BRD 0x2000
+#define RCR_PRO 0x1000
+#define RCR_AMC 0x0800
+#define RCR_LB1 0x0400
+#define RCR_LB0 0x0200
+#define RCR_MC 0x0100
+#define RCR_BC 0x0080
+#define RCR_LPKT 0x0040
+#define RCR_CRS 0x0020
+#define RCR_COL 0x0010
+#define RCR_CRCR 0x0008
+#define RCR_FAER 0x0004
+#define RCR_LBK 0x0002
+#define RCR_PRX 0x0001
+
+/*
+ * Transmit control register
+ */
+#define TCR_PINT 0x8000
+#define TCR_POWC 0x4000
+#define TCR_CRCI 0x2000
+#define TCR_EXDIS 0x1000
+#define TCR_EXD 0x0400
+#define TCR_DEF 0x0200
+#define TCR_NCRS 0x0100
+#define TCR_CRSL 0x0080
+#define TCR_EXC 0x0040
+#define TCR_OWC 0x0020
+#define TCR_PMB 0x0008
+#define TCR_FU 0x0004
+#define TCR_BCM 0x0002
+#define TCR_PTX 0x0001
+
+/*
+ * Interrupt mask register
+ */
+#define IMR_BREN 0x4000
+#define IMR_HBLEN 0x2000
+#define IMR_LCDEN 0x1000
+#define IMR_PINTEN 0x0800
+#define IMR_PRXEN 0x0400
+#define IMR_PTXEN 0x0200
+#define IMR_TXEREN 0x0100
+#define IMR_TCEN 0x0080
+#define IMR_RDEEN 0x0040
+#define IMR_RBEEN 0x0020
+#define IMR_RBAEEN 0x0010
+#define IMR_CRCEN 0x0008
+#define IMR_FAEEN 0x0004
+#define IMR_MPEN 0x0002
+#define IMR_RFOEN 0x0001
+
+/*
+ * Interrupt status register
+ */
+#define ISR_BR 0x4000
+#define ISR_HBL 0x2000
+#define ISR_LCD 0x1000
+#define ISR_PINT 0x0800
+#define ISR_PKTRX 0x0400
+#define ISR_TXDN 0x0200
+#define ISR_TXER 0x0100
+#define ISR_TC 0x0080
+#define ISR_RDE 0x0040
+#define ISR_RBE 0x0020
+#define ISR_RBAE 0x0010
+#define ISR_CRC 0x0008
+#define ISR_FAE 0x0004
+#define ISR_MP 0x0002
+#define ISR_RFO 0x0001
+
+/*
+ * Data configuration register 2
+ */
+#define DCR2_EXPO3 0x8000
+#define DCR2_EXPO2 0x4000
+#define DCR2_EXPO1 0x2000
+#define DCR2_EXPO0 0x1000
+#define DCR2_PH 0x0010
+#define DCR2_PCM 0x0004
+#define DCR2_PCNM 0x0002
+#define DCR2_RJCM 0x0001
+
+/*
+ ******************************************************************
+ * *
+ * Transmit Buffer Management *
+ * *
+ ******************************************************************
+ */
+
+/*
+ * Transmit descriptor area entry.
+ * There is one transmit descriptor for each packet to be transmitted.
+ * Statically reserve space for up to MAXIMUM_FRAGS_PER_PACKET fragments
+ * per descriptor.
+ */
+#define MAXIMUM_FRAGS_PER_DESCRIPTOR 6
+struct TransmitDescriptor {
+ rtems_unsigned32 status;
+ rtems_unsigned32 pkt_config;
+ rtems_unsigned32 pkt_size;
+ rtems_unsigned32 frag_count;
+
+ /*
+ * Packet fragment pointers
+ */
+ struct TransmitDescriptorFragLink {
+ rtems_unsigned32 frag_lsw; /* LSW of fragment address */
+#define frag_link frag_lsw
+ rtems_unsigned32 frag_msw; /* MSW of fragment address */
+ rtems_unsigned32 frag_size;
+ } frag[MAXIMUM_FRAGS_PER_DESCRIPTOR];
+
+ /*
+ * Space for link if all fragment pointers are used.
+ */
+ rtems_unsigned32 link_pad;
+
+ /*
+ * Extra RTEMS/KA9Q stuff
+ */
+ struct TransmitDescriptor *next; /* Circularly-linked list */
+ struct mbuf *mbufp; /* First mbuf in packet */
+ volatile rtems_unsigned32 *linkp; /* Pointer to un[xxx].link */
+};
+typedef struct TransmitDescriptor TransmitDescriptor_t;
+typedef volatile TransmitDescriptor_t *TransmitDescriptorPointer_t;
+
+/*
+ * Transmit Configuration.
+ * For standard Ethernet transmission, all bits in the transmit
+ * configuration field are set to 0.
+ */
+#define TDA_CONFIG_PINT 0x8000
+#define TDA_CONFIG_POWC 0x4000
+#define TDA_CONFIG_CRCI 0x2000
+#define TDA_CONFIG_EXDIS 0x1000
+
+/*
+ * Transmit status
+ */
+#define TDA_STATUS_COLLISION_MASK 0xF800
+#define TDA_STATUS_COLLISION_SHIFT 11
+#define TDA_STATUS_EXD 0x0400
+#define TDA_STATUS_DEF 0x0200
+#define TDA_STATUS_NCRS 0x0100
+#define TDA_STATUS_CRSL 0x0080
+#define TDA_STATUS_EXC 0x0040
+#define TDA_STATUS_OWC 0x0020
+#define TDA_STATUS_PMB 0x0008
+#define TDA_STATUS_FU 0x0004
+#define TDA_STATUS_BCM 0x0002
+#define TDA_STATUS_PTX 0x0001
+
+#define TDA_LINK_EOL 0x1
+
+
+
+/*
+ ******************************************************************
+ * *
+ * Receive Buffer Management *
+ * *
+ ******************************************************************
+ */
+
+/*
+ * Receive resource area entry.
+ * There is one receive resource entry for each receive buffer area (RBA).
+ * This driver allows only one packet per receive buffer area, so one
+ * receive resource entry corresponds to one correctly-received packet.
+ */
+struct ReceiveResource {
+ rtems_unsigned32 buff_ptr_lsw; /* LSW of RBA address */
+ rtems_unsigned32 buff_ptr_msw; /* MSW of RBA address */
+ rtems_unsigned32 buff_wc_lsw; /* LSW of RBA size (16-bit words) */
+ rtems_unsigned32 buff_wc_msw; /* MSW of RBA size (16-bit words) */
+};
+typedef struct ReceiveResource ReceiveResource_t;
+typedef volatile ReceiveResource_t *ReceiveResourcePointer_t;
+
+/*
+ * Receive descriptor area entry.
+ * There is one receive descriptor for each packet received.
+ */
+struct ReceiveDescriptor {
+ rtems_unsigned32 status;
+ rtems_unsigned32 byte_count;
+ rtems_unsigned32 pkt_lsw; /* LSW of packet address */
+ rtems_unsigned32 pkt_msw; /* MSW of packet address */
+ rtems_unsigned32 seq_no;
+ rtems_unsigned32 link;
+ rtems_unsigned32 in_use;
+
+ /*
+ * Extra RTEMS/KA9Q stuff
+ */
+ struct ReceiveDescriptor *next; /* Circularly-linked list */
+};
+typedef struct ReceiveDescriptor ReceiveDescriptor_t;
+typedef volatile ReceiveDescriptor_t *ReceiveDescriptorPointer_t;
+
+/*
+ * Receive status
+ */
+#define RDA_STATUS_ERR 0x8800
+#define RDA_STATUS_RNT 0x4000
+#define RDA_STATUS_BRD 0x2000
+#define RDA_STATUS_PRO 0x1000
+#define RDA_STATUS_AMC 0x0800
+#define RDA_STATUS_LB1 0x0400
+#define RDA_STATUS_LB0 0x0200
+#define RDA_STATUS_MC 0x0100
+#define RDA_STATUS_BC 0x0080
+#define RDA_STATUS_LPKT 0x0040
+#define RDA_STATUS_CRS 0x0020
+#define RDA_STATUS_COL 0x0010
+#define RDA_STATUS_CRCR 0x0008
+#define RDA_STATUS_FAER 0x0004
+#define RDA_STATUS_LBK 0x0002
+#define RDA_STATUS_PRX 0x0001
+
+#define RDA_LINK_EOL 0x1
+
+#endif /* _SONIC_DP83932_ */