summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/ppcn_60x/network
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-18 16:48:14 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-18 16:48:14 +0000
commit0c04c377bc8ac177d28bd0e0096d7c6940d33cd4 (patch)
treeba3062eb819e89de2eee14397ffe61b202ad10de /c/src/lib/libbsp/powerpc/ppcn_60x/network
parent./clock/Makefile.in,v (diff)
downloadrtems-0c04c377bc8ac177d28bd0e0096d7c6940d33cd4.tar.bz2
./clock/Makefile.in,v
./clock/clock.c,v ./console/Makefile.in,v ./console/config.c,v ./console/console.c,v ./console/console.h,v ./console/debugio.c,v ./console/i8042.c,v ./console/i8042_p.h,v ./console/i8042vga.c,v ./console/i8042vga.h,v ./console/ns16550.c,v ./console/ns16550.h,v ./console/ns16550_p.h,v ./console/ns16550cfg.c,v ./console/ns16550cfg.h,v ./console/vga.c,v ./console/vga_p.h,v ./console/z85c30.c,v ./console/z85c30.h,v ./console/z85c30_p.h,v ./console/z85c30cfg.c,v ./console/z85c30cfg.h,v ./include/Makefile.in,v ./include/bsp.h,v ./include/chain.h,v ./include/coverhd.h,v ./include/extisrdrv.h,v ./include/nvram.h,v ./include/pci.h,v ./include/tod.h,v ./network/Makefile.in,v ./network/amd79c970.c,v ./network/amd79c970.h,v ./nvram/Makefile.in,v ./nvram/ds1385.h,v ./nvram/mk48t18.h,v ./nvram/nvram.c,v ./nvram/prepnvr.h,v ./nvram/stk11c68.h,v ./pci/Makefile.in,v ./pci/pci.c,v ./start/Makefile.in,v ./start/start.s,v ./startup/Makefile.in,v ./startup/bspclean.c,v ./startup/bspstart.c,v ./startup/bsptrap.s,v ./startup/device-tree,v ./startup/genpvec.c,v ./startup/linkcmds,v ./startup/rtems-ctor.cc,v ./startup/sbrk.c,v ./startup/setvec.c,v ./startup/spurious.c,v ./startup/swap.c,v ./timer/Makefile.in,v ./timer/timer.c,v ./tod/Makefile.in,v ./tod/cmos.h,v ./tod/tod.c,v ./universe/Makefile.in,v ./universe/universe.c,v ./vectors/Makefile.in,v ./vectors/README,v ./vectors/align_h.s,v ./vectors/vectors.s,v ./wrapup/Makefile.in,v ./Makefile.in,v ./README,v ./STATUS,v ./bsp_specs,v
Diffstat (limited to 'c/src/lib/libbsp/powerpc/ppcn_60x/network')
-rw-r--r--c/src/lib/libbsp/powerpc/ppcn_60x/network/Makefile.in54
-rw-r--r--c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.c1010
-rw-r--r--c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.h426
3 files changed, 1490 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/network/Makefile.in b/c/src/lib/libbsp/powerpc/ppcn_60x/network/Makefile.in
new file mode 100644
index 0000000000..cef35eb353
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/ppcn_60x/network/Makefile.in
@@ -0,0 +1,54 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/network.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=amd79c970
+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 +=
+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/ppcn_60x/network/amd79c970.c b/c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.c
new file mode 100644
index 0000000000..ba3849df9a
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.c
@@ -0,0 +1,1010 @@
+/*
+ * COPYRIGHT (c) 1998 by Radstone Technology
+ *
+ *
+ * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
+ * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
+ *
+ * You are hereby granted permission to use, copy, modify, and distribute
+ * this file, provided that this notice, plus the above copyright notice
+ * and disclaimer, appears in all copies. Radstone Technology will provide
+ * no support for this code.
+ *
+ */
+/*
+ * RTEMS/KA9Q driver for PC-NET
+ */
+#include <bsp.h>
+#include <rtems/error.h>
+#include <ka9q/rtems_ka9q.h>
+#include <ka9q/global.h>
+#include <ka9q/enet.h>
+#include <ka9q/iface.h>
+#include <ka9q/netuser.h>
+#include <ka9q/trace.h>
+#include <ka9q/commands.h>
+
+#include <pci.h>
+#include "amd79c970.h"
+
+/*
+ * Number of PC-NETs supported by this driver
+ */
+#define NPCNETDRIVER 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.
+ *
+ * Set the number of Tx and Rx buffers, using Log_2(# buffers).
+ */
+#define LANCE_LOG2_TX_BUFFERS 4
+#define LANCE_LOG2_RX_BUFFERS 4
+#define TX_RING_SIZE (1 << (LANCE_LOG2_TX_BUFFERS))
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS ((LANCE_LOG2_TX_BUFFERS) << 4)
+#define RX_RING_SIZE (1 << (LANCE_LOG2_RX_BUFFERS))
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS ((LANCE_LOG2_RX_BUFFERS) << 4)
+
+/*
+ * RTEMS event used by interrupt handler to signal daemons.
+ * This must *not* be the same event used by the KA9Q task synchronization.
+ */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+
+/*
+ * Receive buffer size -- Allow for a full ethernet packet plus a pointer
+ */
+#define ETHPKT_SIZE 1520
+#define RBUF_SIZE (ETHPKT_SIZE + sizeof (struct iface *))
+
+/*
+ * LANCE Register Access Macros
+ */
+#define PCNET_IO_RD32(dp, reg, value) \
+ inport_32(&dp->pPCNet->u.dwio.##reg, value)
+#define PCNET_IO_WR32(dp, reg, value) \
+ outport_32(&dp->pPCNet->u.dwio.##reg, value)
+
+/*
+ * LANCE Register Access Macros
+ */
+#define RD_CSR32(dp, index, value) \
+ PCNET_IO_WR32(dp, rap, index); \
+ PCNET_IO_RD32(dp, rdp, value)
+
+#define WR_CSR32(dp, index, value) \
+ PCNET_IO_WR32(dp, rap, index); \
+ PCNET_IO_WR32(dp, rdp, value)
+
+#define RD_BCR32(dp, index, value) \
+ PCNET_IO_WR32(dp, rap, index); \
+ PCNET_IO_RD32(dp, bdp, value)
+
+#define WR_BCR32(dp, index, value) \
+ PCNET_IO_WR32(dp, rap, index); \
+ PCNET_IO_WR32(dp, bdp, value)
+
+/*
+ * Hardware-specific storage
+ *
+ * Note that the enetInitBlk field must be aligned to a 16 byte
+ * boundary
+ */
+typedef struct amd79c970Context {
+ rmde_t rxBdBase[RX_RING_SIZE];
+ tmde_t txBdBase[TX_RING_SIZE];
+ initblk_t initBlk;
+ pc_net_t *pPCNet;
+ unsigned32 ulIntVector;
+ struct mbuf **rxMbuf;
+ struct mbuf **txMbuf;
+ int rxBdCount;
+ int txBdCount;
+ int txBdHead;
+ int txBdTail;
+ int txBdActiveCount;
+ struct iface *iface;
+ rtems_id txWaitTid;
+
+ /*
+ * 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 rxDiscarded;
+
+ unsigned long txInterrupts;
+ unsigned long txDeferred;
+ unsigned long txHeartbeat;
+ unsigned long txLateCollision;
+ unsigned long txRetryLimit;
+ unsigned long txUnderrun;
+ unsigned long txLostCarrier;
+ unsigned long txRawWait;
+} amd79c970Context_t;
+static amd79c970Context_t *pAmd79c970Context[NPCNETDRIVER];
+
+/*
+ * PC-NET interrupt handler
+ */
+static rtems_isr
+amd79c970_isr (rtems_vector_number v)
+{
+ unsigned32 ulCSR0, ulCSR4, ulCSR5;
+ amd79c970Context_t *dp;
+ int i;
+
+ for(i=0; i<NPCNETDRIVER; i++)
+ {
+ dp=pAmd79c970Context[i];
+ if(dp->ulIntVector==v)
+ {
+ RD_CSR32(dp, CSR0, ulCSR0);
+ if(ulCSR0 & CSR0_RINT)
+ {
+ /*
+ * We have recieve data
+ */
+ dp->rxInterrupts++;
+ rtems_event_send(
+ dp->iface->rxproc,
+ INTERRUPT_EVENT);
+ }
+
+ if(ulCSR0 & CSR0_TINT)
+ {
+ /*
+ * Data tranmitted or error
+ */
+ dp->txInterrupts++;
+ if(dp->txWaitTid)
+ {
+ rtems_event_send(
+ dp->txWaitTid,
+ INTERRUPT_EVENT);
+ }
+ }
+
+ if((ulCSR0 & CSR0_INTR) &&
+ !(ulCSR0 & (CSR0_RINT | CSR0_TINT)))
+ {
+ /*
+ * Many possible sources
+ */
+ RD_CSR32(dp, CSR4, ulCSR4);
+ RD_CSR32(dp, CSR5, ulCSR5);
+ DEBUG_puts("CSR0=");
+ DEBUG_puth(ulCSR0);
+ DEBUG_puts(", CSR4=");
+ DEBUG_puth(ulCSR4);
+ DEBUG_puts(", CSR5=");
+ DEBUG_puth(ulCSR5);
+ DEBUG_puts("\n\r");
+ /*
+ * Clear it
+ */
+ WR_CSR32(dp, CSR4, ulCSR4);
+ WR_CSR32(dp, CSR5, ulCSR5);
+ }
+
+ /*
+ * Clear interrupts
+ */
+ ulCSR0&=CSR0_BABL | CSR0_CERR | CSR0_MISS |
+ CSR0_MERR | CSR0_RINT | CSR0_TINT | CSR0_IENA;
+ WR_CSR32(dp, CSR0, ulCSR0);
+
+ RD_CSR32(dp, CSR0, ulCSR0);
+ }
+ }
+}
+
+/*
+ * Initialize the ethernet hardware
+ */
+static boolean
+amd79c970_initialize_hardware (int instance, int broadcastFlag)
+{
+ amd79c970Context_t *dp;
+ struct mbuf *bp;
+ int i;
+ unsigned8 ucPCIBusCount;
+ unsigned8 ucBusNumber;
+ unsigned8 ucSlotNumber;
+ unsigned32 ulDeviceID;
+ unsigned32 ulBAR0;
+ unsigned8 ucIntVector;
+ unsigned32 ulInitClkPCIAddr;
+ unsigned32 ulAPROM;
+ unsigned32 ulCSR0;
+
+ ucPCIBusCount=BusCountPCI();
+
+ /*
+ * Scan the available busses for instance of hardware
+ */
+ i=0;
+
+ dp=pAmd79c970Context[instance];
+ dp->pPCNet=(pc_net_t *)NULL;
+
+ for(ucBusNumber=0;
+ (ucBusNumber<ucPCIBusCount) && (dp->pPCNet==(pc_net_t *)NULL);
+ ucBusNumber++)
+ {
+ for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++)
+ {
+ PCIConfigRead32(ucBusNumber,
+ ucSlotNumber,
+ 0,
+ PCI_CONFIG_VENDOR_LOW,
+ &ulDeviceID);
+ if(ulDeviceID!=PCI_ID(0x1022, 0x2000))
+ {
+ continue;
+ }
+
+ /*
+ * We've found a PC-NET controller
+ */
+ if(i++<instance)
+ {
+ continue;
+ }
+
+ /*
+ * Read base address
+ */
+ PCIConfigRead32(ucBusNumber,
+ ucSlotNumber,
+ 0,
+ PCI_CONFIG_BAR_0,
+ &ulBAR0);
+ dp->pPCNet=(pc_net_t *)(ulBAR0&~PCI_ADDRESS_IO_SPACE);
+
+ /*
+ * Read interrupt vector
+ */
+ PCIConfigRead8(ucBusNumber,
+ ucSlotNumber,
+ 0,
+ PCI_CONFIG_INTERRUPTLINE,
+ &ucIntVector);
+ dp->ulIntVector=PPCN_60X_IRQ_PCI(ucIntVector);
+
+ /*
+ * Ensure that device is enabled
+ */
+ PCIConfigWrite16(ucBusNumber,
+ ucSlotNumber,
+ 0,
+ PCI_CONFIG_COMMAND,
+ PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+ break;
+ }
+ }
+
+ if(dp->pPCNet==(pc_net_t *)NULL)
+ {
+ return(FALSE);
+ }
+
+ /*
+ * Read the ethernet number
+ */
+ if(!dp->iface->hwaddr)
+ {
+ dp->iface->hwaddr=mallocw (EADDR_LEN);
+ PCNET_IO_RD32(dp, aprom[0], ulAPROM);
+ for(i=0;i<4;i++)
+ {
+ dp->iface->hwaddr[i]=(ulAPROM>>(i*8))&0xff;
+ }
+ PCNET_IO_RD32(dp, aprom[1], ulAPROM);
+ for(i=0;i<2;i++)
+ {
+ dp->iface->hwaddr[i+4]=(ulAPROM>>(i*8))&0xff;
+ }
+ }
+
+ /*
+ * Allocate mbuf pointers
+ */
+ dp->rxMbuf=mallocw (dp->rxBdCount * sizeof(*dp->rxMbuf));
+ dp->txMbuf=mallocw (dp->txBdCount * sizeof(*dp->txMbuf));
+
+ /*
+ * Allocate space for incoming packets
+ */
+ for(i=0; i<dp->rxBdCount; i++)
+ {
+ dp->rxMbuf[i]=bp=ambufw (RBUF_SIZE);
+ bp->data += sizeof (struct iface *);
+ dp->rxBdBase[i].rmde_addr=
+ Swap32((unsigned32)bp->data+PCI_SYS_MEM_BASE);
+ dp->rxBdBase[i].rmde_bcnt=
+ Swap16(-(bp->size-sizeof (struct iface *)));
+ dp->rxBdBase[i].rmde_flags=Swap16(RFLG_OWN);
+ }
+
+ /*
+ * Set up transmit buffer descriptors
+ */
+ for(i=0; i<dp->txBdCount; i++)
+ {
+ dp->txBdBase[i].tmde_status=Swap16(TST_STP | TST_ENP);
+ dp->txBdBase[i].tmde_error=0;
+ dp->txMbuf[i]=NULL;
+ }
+
+ /*
+ * Initialise initblk
+ */
+ if(broadcastFlag)
+ {
+ dp->initBlk.ib_mode=0;
+ }
+ else
+ {
+ dp->initBlk.ib_mode=Swap16(CSR15_DRCVBC);
+ }
+
+ /*
+ * Set the receive descriptor ring length
+ */
+ dp->initBlk.ib_rlen=RX_RING_LEN_BITS;
+ /*
+ * Set the receive descriptor ring address
+ */
+ dp->initBlk.ib_rdra=Swap32((unsigned32)&dp->rxBdBase[0]+
+ PCI_SYS_MEM_BASE);
+
+ /*
+ * Set the transmit descriptor ring length
+ */
+ dp->initBlk.ib_tlen=TX_RING_LEN_BITS;
+ /*
+ * Set the tranmit descriptor ring address
+ */
+ dp->initBlk.ib_tdra=Swap32((unsigned32)&dp->txBdBase[0]+
+ PCI_SYS_MEM_BASE);
+
+ for(i=0;i<6;i++)
+ {
+ dp->initBlk.ib_padr[i]=dp->iface->hwaddr[i];
+ }
+
+ /*
+ * Ensure that we are in DWIO mode
+ */
+ PCNET_IO_WR32(dp, rdp, 0);
+
+ WR_CSR32(dp, 58,CSR58_PCISTYLE);
+
+ WR_CSR32(dp, CSR3,
+ CSR3_BABLM | CSR3_MERRM | CSR3_IDONM | CSR3_DXSUFLO);
+
+ WR_CSR32(dp, CSR4,
+ CSR4_APADXMIT | CSR4_MFCOM | CSR4_RCVCCOM |
+ CSR4_TXSTRTM | CSR4_JABM);
+
+ WR_CSR32(dp, CSR5, 0);
+
+ ulInitClkPCIAddr=(unsigned32)&dp->initBlk+PCI_SYS_MEM_BASE;
+ /*
+ * CSR2 must contain the high order 16 bits of the first word in
+ * the initialization block
+ */
+ WR_CSR32(dp, CSR2, (ulInitClkPCIAddr >> 16) & 0xffff);
+ /*
+ * CSR1 must contain the low order 16 bits of the first word in
+ * the initialization block
+ */
+ WR_CSR32(dp, CSR1, (ulInitClkPCIAddr & 0xffff));
+
+ /*
+ * Set up interrupts
+ */
+ set_vector(amd79c970_isr,
+ dp->ulIntVector,
+ instance);
+
+ /*
+ * Start the device
+ */
+ WR_CSR32(dp, CSR0, CSR0_INIT | CSR0_STRT);
+
+ /*
+ * Wait for 100mS for the device to initialise
+ */
+ for(i=0; i<100; i++)
+ {
+ RD_CSR32(dp, CSR0, ulCSR0);
+ if(ulCSR0 & CSR0_IDON)
+ {
+ break;
+ }
+ rtems_ka9q_ppause(1); /* 1mS */
+ }
+ if(i >= 100)
+ {
+ return(FALSE);
+ }
+
+ /*
+ * Enable interrupts
+ */
+ WR_CSR32(dp, CSR0, CSR0_IENA);
+
+ dp->txBdHead=dp->txBdTail=0;
+ dp->txBdActiveCount=0;
+
+ return(TRUE);
+}
+
+/*
+ * Soak up buffer descriptors that have been sent
+ */
+static void
+amd79c970_retire_tx_bd (amd79c970Context_t *dp)
+{
+ unsigned16 status;
+ unsigned32 error;
+ int i;
+ int nRetired;
+
+ i = dp->txBdTail;
+ nRetired = 0;
+ while((dp->txBdActiveCount != 0) &&
+ (((status=Swap16(dp->txBdBase[i].tmde_status)) & TST_OWN)==0))
+ {
+ /*
+ * See if anything went wrong
+ */
+ if(status & TST_ERR)
+ {
+ /*
+ * Check for errors
+ */
+ error=Swap16(dp->txBdBase[i].tmde_error);
+
+ if (error & TERR_LCOL)
+ dp->txLateCollision++;
+ if (error & TERR_RTRY)
+ dp->txRetryLimit++;
+ if (error & TERR_UFLO)
+ dp->txUnderrun++;
+ if (error & TERR_EXDEF)
+ dp->txDeferred++;
+ if (error & TERR_LCAR)
+ dp->txLostCarrier++;
+ }
+ nRetired++;
+ if (status & TST_ENP)
+ {
+ /*
+ * A full frame has been transmitted.
+ * Free all the associated buffer descriptors.
+ */
+ dp->txBdActiveCount -= nRetired;
+ while (nRetired) {
+ nRetired--;
+ free_mbuf (&dp->txMbuf[dp->txBdTail]);
+ if (++dp->txBdTail == dp->txBdCount)
+ dp->txBdTail = 0;
+ }
+ }
+ if (++i == dp->txBdCount)
+ {
+ i = 0;
+ }
+ }
+}
+
+/*
+ * Send raw packet (caller provides header).
+ * This code runs in the context of the interface transmit
+ * task or in the context of the network task.
+ */
+static int
+amd79c970_raw (struct iface *iface, struct mbuf **bpp)
+{
+ amd79c970Context_t *dp;
+ struct mbuf *bp;
+ tmde_t *firstTxBd, *txBd;
+ unsigned16 status;
+ int nAdded;
+
+ dp = pAmd79c970Context[iface->dev];
+
+ /*
+ * Fill in some logging data
+ */
+ 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 buffer descriptors
+ */
+ amd79c970_retire_tx_bd (dp);
+
+ /*
+ * Set up the transmit buffer descriptors.
+ * No need to pad out short packets since the
+ * hardware takes care of that automatically.
+ * No need to copy the packet to a contiguous buffer
+ * since the hardware is capable of scatter/gather DMA.
+ */
+ bp = *bpp;
+ nAdded = 0;
+ txBd = firstTxBd = dp->txBdBase + dp->txBdHead;
+ for (;;) {
+ /*
+ * Wait for buffer descriptor to become available.
+ */
+ if ((dp->txBdActiveCount + nAdded) == dp->txBdCount) {
+ /*
+ * Find out who we are
+ */
+ if (dp->txWaitTid == 0)
+ rtems_task_ident (0, 0, &dp->txWaitTid);
+
+ /*
+ * Wait for buffer descriptor to become available.
+ * Note that the buffer descriptors are checked
+ * *before* * entering the wait loop -- this catches
+ * the possibility that a buffer descriptor became
+ * available between the `if' above, and the clearing
+ * of the event register.
+ * Also, the event receive doesn't wait forever.
+ * This is to catch the case where the transmitter
+ * stops in the middle of a frame -- and only the
+ * last buffer descriptor in a frame can generate
+ * an interrupt.
+ */
+ amd79c970_retire_tx_bd (dp);
+ while ((dp->txBdActiveCount + nAdded) == dp->txBdCount) {
+ rtems_ka9q_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ 1 + 1000000/BSP_Configuration.microseconds_per_tick);
+ amd79c970_retire_tx_bd (dp);
+ }
+ }
+
+ /*
+ * Fill in the buffer descriptor
+ */
+ txBd->tmde_addr=Swap32((unsigned32)bp->data+PCI_SYS_MEM_BASE);
+ txBd->tmde_bcnt=Swap16(-bp->cnt);
+ dp->txMbuf[dp->txBdHead] = bp;
+
+ nAdded++;
+ if (++dp->txBdHead == dp->txBdCount)
+ {
+ dp->txBdHead = 0;
+ }
+
+ /*
+ * Set the transmit buffer status.
+ * Break out of the loop if this mbuf is the last in the frame.
+ */
+ if ((bp = bp->next) == NULL) {
+ if(txBd==firstTxBd)
+ {
+ /*
+ * There is only one frame
+ */
+ txBd->tmde_status=Swap16(TST_OWN |
+ TST_STP |
+ TST_ENP);
+ }
+ else
+ {
+ /*
+ * Mark the last buffer
+ */
+ txBd->tmde_status=Swap16(TST_OWN |
+ TST_ENP);
+ /*
+ * Trigger the first transmit
+ */
+ firstTxBd->tmde_status=Swap16(TST_OWN |
+ TST_STP);
+ }
+ /*
+ * Sync instruction required to overcome the Grackle
+ * stale data bug
+ */
+ asm volatile("sync");
+ dp->txBdActiveCount += nAdded;
+ break;
+ }
+ else if(txBd!=firstTxBd)
+ {
+ txBd->tmde_status = Swap16(TST_OWN);
+ }
+ txBd = dp->txBdBase + dp->txBdHead;
+ }
+
+ /*
+ * Show that we've finished with the packet
+ */
+ dp->txWaitTid = 0;
+ *bpp = NULL;
+ return 0;
+}
+
+/*
+ * PC-NET reader task
+ */
+static void
+amd79c970_rx (int dev, void *p1, void *p2)
+{
+ struct iface *iface=(struct iface *)p1;
+ amd79c970Context_t *dp=(amd79c970Context_t *)p2;
+ struct mbuf *bp;
+ rtems_unsigned16 status;
+ rmde_t *rxBd;
+ int rxBdIndex;
+ int continuousCount;
+
+ /*
+ * Input packet handling loop
+ */
+ continuousCount=0;
+ rxBdIndex=0;
+
+ while(TRUE)
+ {
+ rxBd=&dp->rxBdBase[rxBdIndex];
+
+ /*
+ * Wait for packet if there's not one ready
+ */
+ if((status=Swap16(rxBd->rmde_flags)) & RFLG_OWN)
+ {
+ /*
+ * Reset `continuous-packet' count
+ */
+ continuousCount=0;
+
+ /*
+ * Wait for packet
+ * Note that the buffer descriptor is checked
+ * *before* the event wait -- this catches the
+ * possibility that a packet arrived between the
+ * `if' above, and the clearing of the event register.
+ */
+ while ((status=Swap16(rxBd->rmde_flags)) & RFLG_OWN)
+ {
+ rtems_ka9q_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT);
+ }
+ }
+
+ /*
+ * Check that packet is valid
+ */
+ if((status & RFLG_ERR) ||
+ ((status & (RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP)))
+ {
+ /*
+ * Something went wrong with the reception
+ */
+ if(!(status & RFLG_ENP))
+ dp->rxNotLast++;
+ if(!(status & RFLG_STP))
+ dp->rxNotFirst++;
+ if(status & RFLG_OFLO)
+ dp->rxGiant++;
+ if(status & RFLG_FRAM)
+ dp->rxNonOctet++;
+ if(status & RFLG_CRC)
+ dp->rxBadCRC++;
+ if(status & RFLG_BUFF)
+ dp->rxOverrun++;
+ }
+ else
+ {
+ /*
+ * Pass the packet up the chain
+ * The mbuf count is reduced to remove
+ * the frame check sequence at the end
+ * of the packet.
+ */
+ bp=dp->rxMbuf[rxBdIndex];
+ bp->cnt=Swap16(rxBd->rmde_mcnt) - 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->rxBdCount)
+ kwait_null ();
+
+ /*
+ * Allocate a new mbuf
+ * FIXME: It seems to me that it would be better
+ * if there were some way to limit number of mbufs
+ * in use by this interface, but I don't see any
+ * way of determining when the mbuf we pass up
+ * is freed.
+ */
+ dp->rxMbuf[rxBdIndex]=bp=ambufw (RBUF_SIZE);
+ bp->data += sizeof (struct iface *);
+ rxBd->rmde_addr=Swap32(
+ (unsigned32)bp->data+PCI_SYS_MEM_BASE);
+ rxBd->rmde_bcnt=Swap16(
+ -(bp->size-sizeof (struct iface *)));
+ }
+
+ /*
+ * Reenable the buffer descriptor
+ */
+ rxBd->rmde_flags=Swap16(RFLG_OWN);
+
+ /*
+ * Move to next buffer descriptor
+ */
+ if(++rxBdIndex==dp->rxBdCount)
+ rxBdIndex=0;
+ }
+}
+
+/*
+ * Shut down the interface
+ * FIXME: This is a pretty simple-minded routine. It doesn't worry
+ * about cleaning up mbufs, shutting down daemons, etc.
+ */
+static int
+amd79c970_stop (struct iface *iface)
+{
+ amd79c970Context_t *dp;
+ unsigned32 ulCSR0;
+ int i;
+
+ dp=pAmd79c970Context[iface->dev];
+
+ /*
+ * Stop the device
+ */
+ WR_CSR32(dp, CSR0, CSR0_STOP);
+
+ /*
+ * Wait for 100mS for the device to stop
+ */
+ for(i=0; i<100; i++)
+ {
+ RD_CSR32(dp, CSR0, ulCSR0);
+ if(!(ulCSR0 & (CSR0_RXON | CSR0_TXON)))
+ {
+ break;
+ }
+ rtems_ka9q_ppause(1); /* 1mS */
+ }
+ if(i >= 100)
+ {
+ return(-1);
+ }
+
+ /*
+ * Free up all the mbufs we've allocated
+ */
+ for(i=0; i<dp->rxBdCount; i++)
+ {
+ free_mbuf(&dp->rxMbuf[i]);
+ }
+
+ return 0;
+}
+
+/*
+ * Show interface statistics
+ */
+static void
+amd79c970_show (struct iface *iface)
+{
+ int i;
+
+ i=iface->dev;
+
+ printf (" Rx Interrupts:%-8lu", pAmd79c970Context[i]->rxInterrupts);
+ printf (" Not First:%-8lu", pAmd79c970Context[i]->rxNotFirst);
+ printf (" Not Last:%-8lu\n", pAmd79c970Context[i]->rxNotLast);
+ printf (" Giant:%-8lu", pAmd79c970Context[i]->rxGiant);
+ printf (" Runt:%-8lu", pAmd79c970Context[i]->rxRunt);
+ printf (" Non-octet:%-8lu\n", pAmd79c970Context[i]->rxNonOctet);
+ printf (" Bad CRC:%-8lu", pAmd79c970Context[i]->rxBadCRC);
+ printf (" Overrun:%-8lu", pAmd79c970Context[i]->rxOverrun);
+ printf (" Collision:%-8lu\n", pAmd79c970Context[i]->rxCollision);
+ printf (" Discarded:%-8lu\n", pAmd79c970Context[i]->rxDiscarded);
+
+ printf (" Tx Interrupts:%-8lu", pAmd79c970Context[i]->txInterrupts);
+ printf (" Deferred:%-8lu", pAmd79c970Context[i]->txDeferred);
+ printf (" Missed Hearbeat:%-8lu\n", pAmd79c970Context[i]->txHeartbeat);
+ printf (" No Carrier:%-8lu", pAmd79c970Context[i]->txLostCarrier);
+ printf ("Retransmit Limit:%-8lu", pAmd79c970Context[i]->txRetryLimit);
+ printf (" Late Collision:%-8lu\n", pAmd79c970Context[i]->txLateCollision);
+ printf (" Underrun:%-8lu", pAmd79c970Context[i]->txUnderrun);
+ printf (" Raw output wait:%-8lu\n", pAmd79c970Context[i]->txRawWait);
+}
+
+/*
+ * Attach an PC-NET driver to the system
+ * This is the only `extern' function in the driver.
+ *
+ * argv[0]: interface label, e.g., "amd79c970"
+ * argv[1]: maximum transmission unit, bytes, e.g., "1500"
+ * argv[2]: accept ("broadcast") or ignore ("nobroadcast") broadcast packets
+ * Following arguments are optional, but if present, must appear in
+ * the following order:
+ * Following arguments are optional, but if Ethernet address is
+ * specified, Internet address must also be specified.
+ * ###.###.###.### -- IP address
+ * ##:##:##:##:##:## -- Ethernet address
+ */
+int
+rtems_ka9q_driver_attach (int argc, char *argv[], void *p)
+{
+ struct iface *iface;
+ struct amd79c970Context *dp;
+ char *cp;
+ int i;
+ int argIndex;
+ int broadcastFlag;
+
+ /*
+ * Find a free driver
+ */
+ for(i=0; i<NPCNETDRIVER; i++)
+ {
+ if(pAmd79c970Context[i]==NULL)
+ break;
+ }
+ if(i==NPCNETDRIVER)
+ {
+ printf ("Too many PC-NET drivers.\n");
+ return -1;
+ }
+ if(if_lookup (argv[0]) != NULL)
+ {
+ printf ("Interface %s already exists\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Note that this structure must be aligned to a 16 byte boundary
+ */
+ pAmd79c970Context[i]=(amd79c970Context_t *)
+ (((unsigned32)callocw(1,
+ sizeof(amd79c970Context_t)+16)+16) & ~15);
+ dp=pAmd79c970Context[i];
+
+ /*
+ * Create an interface descriptor
+ */
+ iface=callocw (1, sizeof *iface);
+ iface->name=strdup (argv[0]);
+ iface->mtu=atoi (argv[1]);
+
+ /*
+ * Select broadcast packet handling
+ */
+ cp=argv[2];
+ if(strnicmp (cp, "broadcast", strlen (cp))==0)
+ {
+ broadcastFlag=1;
+ }
+ else if(strnicmp (cp, "nobroadcast", strlen (cp))==0)
+ {
+ broadcastFlag=0;
+ }
+ else {
+ printf ("Argument `%s' is neither `broadcast' nor `nobroadcast'.\n", cp);
+ return -1;
+ }
+ argIndex=3;
+
+ /*
+ * Set receive buffer descriptor count
+ */
+ dp->rxBdCount=RX_RING_SIZE;
+
+ /*
+ * Set transmit buffer descriptor count
+ */
+ dp->txWaitTid=0;
+ dp->txBdCount=TX_RING_SIZE;
+
+ /*
+ * Set Internet address
+ */
+ if(argIndex<argc)
+ iface->addr=resolve (argv[argIndex++]);
+ else
+ iface->addr=Ip_addr;
+
+ /*
+ * Set Ethernet address
+ */
+ if(argIndex<argc)
+ {
+ iface->hwaddr=mallocw (EADDR_LEN);
+ gether (iface->hwaddr, argv[argIndex++]);
+ }
+
+ iface->dev=i;
+ iface->raw=amd79c970_raw;
+ iface->stop=amd79c970_stop;
+ iface->show=amd79c970_show;
+ dp->iface=iface;
+ setencap (iface, "Ethernet");
+
+ /*
+ * Set up PC-NET hardware
+ */
+ if(!amd79c970_initialize_hardware (i, broadcastFlag))
+ {
+ printf ("Unable to initialize hardware for %s\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Chain onto list of interfaces
+ */
+ iface->next=Ifaces;
+ Ifaces=iface;
+
+ /*
+ * Start I/O daemons
+ */
+ cp=if_name (iface, " tx");
+ iface->txproc=newproc (cp, 1024, if_tx, iface->dev, iface, NULL, 0);
+ free (cp);
+ cp=if_name (iface, " rx");
+ iface->rxproc=newproc (cp, 1024, amd79c970_rx, iface->dev, iface, dp, 0);
+ free (cp);
+ return 0;
+}
+
+/*
+ * FIXME: There should be an ioctl routine to allow things like
+ * enabling/disabling reception of broadcast packets.
+ */
diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.h b/c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.h
new file mode 100644
index 0000000000..dd30d90b0d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/ppcn_60x/network/amd79c970.h
@@ -0,0 +1,426 @@
+/*
+ * COPYRIGHT (c) 1998 by Radstone Technology
+ *
+ *
+ * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
+ * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
+ *
+ * You are hereby granted permission to use, copy, modify, and distribute
+ * this file, provided that this notice, plus the above copyright notice
+ * and disclaimer, appears in all copies. Radstone Technology will provide
+ * no support for this code.
+ *
+ */
+#ifndef _PCNET_H
+#define _PCNET_H
+
+/*
+ * IO space structure for the AMD79C970 device
+ */
+
+typedef volatile struct pc_net
+{
+ union
+ {
+ struct {
+ unsigned16 aprom[8]; /* 0x00 */
+ unsigned16 rdp; /* 0x10 */
+ unsigned16 rap; /* 0x14 */
+ unsigned16 reset; /* 0x18 */
+ unsigned16 bdp; /* 0x1C */
+ } wio;
+ struct {
+ unsigned32 aprom[4]; /* 0x00 */
+ unsigned32 rdp; /* 0x10 */
+ unsigned32 rap; /* 0x12 */
+ unsigned32 reset; /* 0x14 */
+ unsigned32 bdp; /* 0x16 */
+ } dwio;
+ } u;
+} pc_net_t;
+
+/*
+ * The EEPROM is 2Kbit (128bytes)
+ */
+#define EEPROM_SIZE 128
+#define EEPROM_HEAD_SIZE 36
+
+typedef struct pc_net_eeprom {
+ unsigned8 EthNumber[6];
+ unsigned16 Reserved1; /* Must be 0x0000 */
+ unsigned16 Reserved2; /* Must be 0x1000 */
+ unsigned16 User1;
+ unsigned16 checksum;
+ unsigned16 Reserved3; /* Must be 0x5757 */
+ unsigned16 bcr16;
+ unsigned16 bcr17;
+ unsigned16 bcr18;
+ unsigned16 bcr2;
+ unsigned16 bcr21;
+ unsigned16 Reserved4; /* Must be 0x0000 */
+ unsigned16 Reserved5; /* Must be 0x0000 */
+ unsigned8 Reserved6; /* Must be 0x00 */
+ unsigned8 checksumAdjust;
+ unsigned16 Reserved7; /* Must be 0x0000 */
+ unsigned16 crc; /* CCITT checksum from Serial[] onwards */
+ unsigned8 Serial[16]; /* Radstone Serial Number */
+} pc_net_eeprom_t;
+
+/*
+ * PCnet-PCI Single Chip Ethernet Controller for PCI Local Bus
+ */
+/*
+ * Register and bit definitions
+ */
+
+#define CSR0 0
+#define CSR1 1
+#define CSR2 2
+#define CSR3 3
+#define CSR4 4
+#define CSR5 5
+#define CSR6 6
+#define CSR7 7
+#define CSR8 8
+#define CSR9 9
+#define CSR15 15
+#define CSR47 47
+#define CSR82 82 /* Bus Activity Timer */
+#define CSR100 100 /* Memory Error Timeout register */
+#define CSR114 114
+#define CSR122 122 /* Receiver Packet Alignment Register */
+
+#define BCR2 2 /* Misc. Configuration */
+#define BCR18 18 /* Bus size and burst control */
+#define DEFAULT_BCR18 0x2162 /* default BCR18 value - was 0x21e2*/
+#define BCR19 19
+#define BCR20 20 /* Software Style */
+#define BCR21 21
+
+#define APROM0 0x00
+#define APROM1 0x04
+#define APROM2 0x08
+
+/*
+ * CSR0: Bit definitions
+ */
+#define CSR0_ERR 0x8000 /* error summary */
+#define CSR0_BABL 0x4000 /* babble error */
+#define CSR0_CERR 0x2000 /* collision error */
+#define CSR0_MISS 0x1000 /* missed packet */
+#define CSR0_MERR 0x0800 /* memory error */
+#define CSR0_RINT 0x0400 /* receiver interrupt */
+#define CSR0_TINT 0x0200 /* transmitter interrupt */
+#define CSR0_IDON 0x0100 /* initialization done */
+#define CSR0_INTR 0x0080 /* interrupt flag */
+#define CSR0_IENA 0x0040 /* interrupt enable */
+#define CSR0_RXON 0x0020 /* receiver on */
+#define CSR0_TXON 0x0010 /* transmitter on */
+#define CSR0_TDMD 0x0008 /* transmit demand */
+#define CSR0_STOP 0x0004 /* stop the ilacc */
+#define CSR0_STRT 0x0002 /* start the ilacc */
+#define CSR0_INIT 0x0001 /* initialize the ilacc */
+
+#define CSR3_BABLM 0x4000 /* BABL Mask */
+#define CSR3_MISSM 0x1000 /* Missed packet Mask */
+#define CSR3_MERRM 0x0800 /* Memory error Mask */
+#define CSR3_RINTM 0x0400 /* Receive Interrupt Mask */
+#define CSR3_TINTM 0x0200 /* Transmit Interrupt Mask */
+#define CSR3_IDONM 0x0100 /* Initialization Done Mask */
+#define CSR3_DXSUFLO 0x0040 /* Disable tx stop on underrun */
+#define CSR3_LAPPEN 0x0020 /* lookahead packet proc enable */
+#define CSR3_DXMT2PD 0x0010 /* disable 2 part deferral */
+#define CSR3_EMBA 0x0008 /* enable modified backoff */
+#define CSR3_BSWP 0x0004 /* byte swap */
+
+#define CSR4_DMAPLUS 0x4000 /* DMA burst transfer until FIFO empty */
+#define CSR4_BACON_68K 0x0040 /* 32 bit 680x0 */
+#define CSR4_TXSTRT 0x0008 /* Transmit STaRT status */
+#define CSR4_TXSTRTM 0x0004 /* Transmit STaRT interrupt Mask */
+#define CSR4_ENTST 0x8000 /* enable test mode */
+#define CSR4_TIMER 0x2000 /* enable bus timer csr82 */
+#define CSR4_DPOLL 0x1000 /* disable tx polling */
+#define CSR4_APADXMIT 0x0800 /* auto pad tx to 64 */
+#define CSR4_ASTRPRCV 0x0400 /* auto strip rx pad and fcs */
+#define CSR4_MFCO 0x0200 /* missed frame counter oflo interrupt */
+#define CSR4_MFCOM 0x0100 /* mask to disable */
+#define CSR4_RCVCCO 0x0020 /* rx collision counter oflo interrupt */
+#define CSR4_RCVCCOM 0x0010 /* mask to disable */
+#define CSR4_JAB 0x0002 /* jabber error 10baseT interrupt */
+#define CSR4_JABM 0x0001 /* mask to disable */
+
+#define CSR5_SPND 0x0001 /* Suspend */
+
+#define CSR15_PROM 0x8000 /* Promiscuous */
+#define CSR15_DRCVBC 0x4000 /* Disable receiver broadcast */
+#define CSR15_DRCVPA 0x2000 /* Disable receiver phys. addr. */
+#define CSR15_DLNKTST 0x1000 /* Disable link status */
+#define CSR15_DAPC 0x0800 /* Disable auto polarity det. */
+#define CSR15_MENDECL 0x0400 /* MENDEC loopback mode */
+#define CSR15_LRT 0x0200 /* Low receiver threshold */
+#define CSR15_TSEL 0x0200 /* Transmit mode select */
+#define CSR15_INTL 0x0040 /* Internal loopback */
+#define CSR15_DRTY 0x0020 /* Disable retry */
+#define CSR15_FCOLL 0x0010 /* Force collision */
+#define CSR15_DXMTFCS 0x0008 /* Disable transmit CRC */
+#define CSR15_LOOP 0x0004 /* Loopback enable */
+#define CSR15_DTX 0x0002 /* Disable transmitter */
+#define CSR15_DRX 0x0001 /* Disable receiver */
+
+#define CSR58_PCISTYLE 0x0002 /* software style */
+
+#define CSR80_RCVFW16 (0<<12) /* fifo level to trigger rx dma */
+#define CSR80_RCVFW32 (1<<12)
+#define CSR80_RCVFW64 (2<<12)
+#define CSR80_XMTSP4 (0<<10) /* fifo level to trigger tx */
+#define CSR80_XMTSP16 (1<<10)
+#define CSR80_XMTSP64 (2<<10)
+#define CSR80_XMTSP112 (3<<10)
+#define CSR80_XMTFW16 (0<<8) /* fifo level to stop dma */
+#define CSR80_XMTFW32 (1<<8)
+#define CSR80_XMTFW64 (2<<8)
+/* must also clear csr4 CSR4_DMAPLUS: */
+#define CSR80_DMATC(x) ((x)&0xff) /* max transfers per burst. deflt 16 */
+/*
+ * must also set csr4 CSR4_TIMER:
+ */
+#define CSR82_DMABAT(x) ((x)&0xffff) /* max burst time nanosecs*100 */
+
+#define BCR18_MUSTSET 0x0100 /* this bit must be written as 1 !! */
+#define BCR18_BREADE 0x0040 /* linear burst enable. yes ! on pci */
+#define BCR18_BWRITE 0x0020 /* in write direction */
+#define BCR18_LINBC4 0x0001 /* linear burst count 4 8 or 16 */
+#define BCR18_LINBC8 0x0002 /* NOTE LINBC must be <= fifo trigger*/
+#define BCR18_LINBC16 0x0004
+
+#define BCR19_PVALID 0x8000 /* aprom (eeprom) read checksum ok */
+
+/*
+ * initial setting of csr0
+ */
+#define CSR0_IVALUE (CSR0_IDON | CSR0_IENA | CSR0_STRT | CSR0_INIT)
+
+/*
+ * our setting of csr3
+ */
+#define CSR3_VALUE (CSR3_ACON | CSR3_BSWP)
+
+/*
+ * Initialization Block.
+ * Chip initialization includes the reading of the init block to obtain
+ * the operating parameters.
+ *
+ * This essentially consists of 7, 32 bit LE words. In the following the
+ * fields are ordered so that they map correctly in BE mode, however each
+ * 16 and 32 byte field will require swapping.
+ */
+
+typedef volatile struct initblk {
+ /* mode can be set in csr15 */
+ unsigned16 ib_mode; /* Chip's operating parameters */
+ unsigned8 ib_rlen; /* rx ring length (power of 2) */
+ unsigned8 ib_tlen; /* tx ring length (power of 2) */
+/*
+ * The bytes must be swapped within the word, so that, for example,
+ * the address 8:0:20:1:25:5a is written in the order
+ * 0 8 1 20 5a 25
+ * For PCI970 that is long word swapped: so no swapping needed, since
+ * the bus will swap.
+ */
+ unsigned8 ib_padr[8]; /* physical address */
+ unsigned16 ib_ladrf[4]; /* logical address filter */
+ unsigned32 ib_rdra; /* rcv ring desc addr */
+ unsigned32 ib_tdra; /* xmit ring desc addr */
+} initblk_t;
+
+
+/*
+ * bits in mode register: allows alteration of the chips operating parameters
+ */
+#define IBM_PROM 0x8000 /* promiscuous mode */
+/*
+ * mode is also in cr15
+ */
+#define MODE_DRCVBC 0x4000 /* disable receive broadcast */
+#define MODE_DRCVPA 0x2000 /* disable receive physical address */
+#define MODE_DLNKTST 0x1000 /* disable link status monitoring 10T */
+#define MODE_DAPC 0x0800 /* disable auto polarity 10T */
+#define MODE_MENDECL 0x0400 /* mendec loopback */
+#define MODE_LRT 0x0200 /* low receive threshold/tx mode sel tmau */
+#define MODE_PORTSEL10T 0x0080 /* port select 10T ?? */
+#define MODE_PORTSELAUI 0x0000 /* port select aui ?? */
+#define IBM_INTL 0x0040 /* internal loopback */
+#define IBM_DRTY 0x0020 /* disable retry */
+#define IBM_COLL 0x0010 /* force collision */
+#define IBM_DTCR 0x0008 /* disable transmit crc */
+#define IBM_LOOP 0x0004 /* loopback */
+#define IBM_DTX 0x0002 /* disable transmitter */
+#define IBM_DRX 0x0001 /* disable receiver */
+
+/*
+ * Buffer Management is accomplished through message descriptors organized
+ * in ring structures in main memory. There are two rings allocated for the
+ * device: a receive ring and a transmit ring. The following defines the
+ * structure of the descriptor rings.
+ */
+
+/*
+ * Receive List type definition
+ *
+ * This essentially consists of 4, 32 bit LE words. In the following the
+ * fields are ordered so that they map correctly in BE mode, however each
+ * 16 and 32 byte field will require swapping.
+ */
+
+typedef volatile struct rmde {
+ unsigned32 rmde_addr; /* buf addr */
+
+ unsigned16 rmde_bcnt;
+ unsigned16 rmde_flags;
+
+ unsigned16 rmde_mcnt;
+ unsigned16 rmde_misc;
+
+ unsigned32 align;
+} rmde_t;
+
+
+/*
+ * bits in the flags field
+ */
+#define RFLG_OWN 0x8000 /* ownership bit, 1==LANCE */
+#define RFLG_ERR 0x4000 /* error summary */
+#define RFLG_FRAM 0x2000 /* framing error */
+#define RFLG_OFLO 0x1000 /* overflow error */
+#define RFLG_CRC 0x0800 /* crc error */
+#define RFLG_BUFF 0x0400 /* buffer error */
+#define RFLG_STP 0x0200 /* start of packet */
+#define RFLG_ENP 0x0100 /* end of packet */
+
+/*
+ * bits in the buffer byte count field
+ */
+#define RBCNT_ONES 0xf000 /* must be ones */
+#define RBCNT_BCNT 0x0fff /* buf byte count, in 2's compl */
+
+/*
+ * bits in the message byte count field
+ */
+#define RMCNT_RES 0xf000 /* reserved, read as zeros */
+#define RMCNT_BCNT 0x0fff /* message byte count */
+
+/*
+ * Transmit List type definition
+ *
+ * This essentially consists of 4, 32 bit LE words. In the following the
+ * fields are ordered so that they map correctly in BE mode, however each
+ * 16 and 32 byte field will require swapping.
+ */
+typedef volatile struct tmde {
+ unsigned32 tmde_addr; /* buf addr */
+
+ unsigned16 tmde_bcnt;
+ unsigned16 tmde_status; /* misc error and status bits */
+
+ unsigned32 tmde_error;
+
+ unsigned32 align;
+} tmde_t;
+
+/*
+ * bits in the status field
+ */
+#define TST_OWN 0x8000 /* ownership bit, 1==LANCE */
+#define TST_ERR 0x4000 /* error summary */
+#define TST_RES 0x2000 /* reserved bit */
+#define TST_MORE 0x1000 /* more than one retry was needed */
+#define TST_ONE 0x0800 /* one retry was needed */
+#define TST_DEF 0x0400 /* defer while trying to transmit */
+#define TST_STP 0x0200 /* start of packet */
+#define TST_ENP 0x0100 /* end of packet */
+
+/*
+ * setting of status field when packet is to be transmitted
+ */
+#define TST_XMIT (TST_STP | TST_ENP | TST_OWN)
+
+/*
+ * bits in the buffer byte count field
+ */
+#define TBCNT_ONES 0xf000 /* must be ones */
+#define TBCNT_BCNT 0x0fff /* buf byte count, in 2's compl */
+
+/*
+ * bits in the error field
+ */
+#define TERR_BUFF 0x8000 /* buffer error */
+#define TERR_UFLO 0x4000 /* underflow error */
+#define TERR_EXDEF 0x2000 /* excessive deferral */
+#define TERR_LCOL 0x1000 /* late collision */
+#define TERR_LCAR 0x0800 /* loss of carrier */
+#define TERR_RTRY 0x0400 /* retry error */
+#define TERR_TDR 0x03ff /* time domain reflectometry */
+
+/*
+ * Defines pertaining to statistics gathering (diagnostic only)
+ */
+
+/*
+ * receive errors
+ */
+#define ERR_FRAM 0 /* framing error */
+#define ERR_OFLO 1 /* overflow error */
+#define ERR_CRC 2 /* crc error */
+#define ERR_RBUFF 3 /* receive buffer error */
+
+/*
+ * transmit errors
+ */
+#define ERR_MORE 4 /* more than one retry */
+#define ERR_ONE 5 /* one retry */
+#define ERR_DEF 6 /* defer'd packet */
+#define ERR_TBUFF 7 /* transmit buffer error */
+#define ERR_UFLO 8 /* underflow error */
+#define ERR_LCOL 9 /* late collision */
+#define ERR_LCAR 10 /* loss of carrier */
+#define ERR_RTRY 11 /* retry error, >16 retries */
+
+/*
+ * errors reported in csr0
+ */
+#define ERR_BABL 12 /* transmitter timeout error */
+#define ERR_MISS 13 /* missed packet */
+#define ERR_MEM 14 /* memory error */
+#define ERR_CERR 15 /* collision errors */
+#define XMIT_INT 16 /* transmit interrupts */
+#define RCV_INT 17 /* receive interrupts */
+
+#define NHARD_ERRORS 18 /* error types used in diagnostic */
+
+/*
+ * other statistics
+ */
+#define ERR_TTOUT 18 /* transmit timeouts */
+#define ERR_ITOUT 19 /* init timeouts */
+#define ERR_INITS 20 /* reinitializations */
+#define ERR_RSILO 21 /* silo ptrs misaligned on recv */
+#define ERR_TSILO 22 /* silo ptrs misaligned on xmit */
+#define ERR_SINTR 23 /* spurious interrupts */
+
+#define NUM_ERRORS 24 /* number of errors types */
+
+/*
+ * Bit definitions for BCR19
+ */
+#define prom_EDI (unsigned16)0x0001
+#define prom_EDO (unsigned16)0x0001
+#define prom_ESK (unsigned16)0x0002
+#define prom_ECS (unsigned16)0x0004
+#define prom_EEN (unsigned16)0x0010
+#define prom_EEDET (unsigned16)0x2000
+#define prom_PVALID (unsigned16)0x8000
+#define prom_PREAD (unsigned16)0x4000
+
+#endif