Modification from Emmanuel Raguet <raguet@crf.canon.fr> to merge the

dec21140 drivers from the i386/pc386 and powerpc/mcp750 (all Motorola
PowerPC boards) and move the network driver to libchip.  This driver
should work on all PCI based uses of this chip.
This commit is contained in:
Joel Sherrill
1999-12-03 13:42:34 +00:00
parent fc81cc9933
commit 5a8203085e
12 changed files with 435 additions and 358 deletions

View File

@@ -19,7 +19,8 @@ include $(RTEMS_ROOT)/make/directory.cfg
INSTALL_CHANGE = @INSTALL_CHANGE@ INSTALL_CHANGE = @INSTALL_CHANGE@
# We only build the Network library if HAS_NETWORKING was defined # We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = dec21140 ne2000 wd8003 3c509 # dec21140 is supported via libchip
NETWORK_yes_V = ne2000 wd8003 3c509
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V) NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# wrapup is the one that actually builds and installs the library # wrapup is the one that actually builds and installs the library

View File

@@ -0,0 +1,5 @@
#
# $Id$
#
The dec21140 network driver is found in libchip/networking.

View File

@@ -1,65 +0,0 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = ../../..
subdir = i386/pc386/dec21140
RTEMS_ROOT = @RTEMS_ROOT@
PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@
PGM = ${ARCH}/dec21140.rel
# C source names, if any, go here -- minus the .c
C_PIECES = dec21140
C_FILES = $(C_PIECES:%=%.c)
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)
H_FILES =
SRCS = $(C_FILES) $(H_FILES)
OBJS = $(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(RTEMS_ROOT)/make/leaf.cfg
INSTALL_CHANGE = @INSTALL_CHANGE@
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
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): ${OBJS}
$(make-rel)
all: ${ARCH} $(SRCS) $(PGM)
# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
install: all
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status

View File

@@ -14,7 +14,8 @@ PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@ VPATH = @srcdir@
# We only build the Network library if HAS_NETWORKING was defined # We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = dec21140 ne2000 wd8003 3c509 # dec21140 is supported via libchip
NETWORK_yes_V = ne2000 wd8003 3c509
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V) NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES = startup clock console timer $(NETWORK) BSP_PIECES = startup clock console timer $(NETWORK)

View File

@@ -22,14 +22,10 @@ SRCS = README
all: $(SRCS) all: $(SRCS)
# We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = dec21140
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# wrapup is the one that actually builds and installs the library # wrapup is the one that actually builds and installs the library
# from the individual .rel files built in other directories # from the individual .rel files built in other directories
SUBDIRS = clock console include pci residual openpic irq vectors start \ SUBDIRS = clock console include pci residual openpic irq vectors start \
startup bootloader $(NETWORK) motorola wrapup startup bootloader motorola wrapup
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \ cd $(top_builddir) \

View File

@@ -0,0 +1,5 @@
#
# $Id$
#
The dec21140 network driver is found in libchip/networking.

View File

@@ -13,12 +13,7 @@ PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@ VPATH = @srcdir@
# We only build the Network library if HAS_NETWORKING was defined BSP_PIECES = clock console irq openpic pci residual startup vectors motorola
NETWORK_yes_V = dec21140
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES = clock console irq openpic pci residual startup $(NETWORK) \
vectors motorola
GENERIC_PIECES = GENERIC_PIECES =
# bummer; have to use $foreach since % pattern subst rules only replace 1x # bummer; have to use $foreach since % pattern subst rules only replace 1x

View File

@@ -22,14 +22,10 @@ SRCS = README
all: $(SRCS) all: $(SRCS)
# We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = dec21140
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# wrapup is the one that actually builds and installs the library # wrapup is the one that actually builds and installs the library
# from the individual .rel files built in other directories # from the individual .rel files built in other directories
SUBDIRS = clock console include pci residual openpic irq vectors start \ SUBDIRS = clock console include pci residual openpic irq vectors start \
startup bootloader $(NETWORK) motorola wrapup startup bootloader motorola wrapup
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \ cd $(top_builddir) \

View File

@@ -0,0 +1,5 @@
#
# $Id$
#
The dec21140 network driver is found in libchip/networking.

View File

@@ -13,12 +13,7 @@ PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@ VPATH = @srcdir@
# We only build the Network library if HAS_NETWORKING was defined BSP_PIECES = clock console irq openpic pci residual startup vectors motorola
NETWORK_yes_V = dec21140
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES = clock console irq openpic pci residual startup $(NETWORK) \
vectors motorola
GENERIC_PIECES = GENERIC_PIECES =
# bummer; have to use $foreach since % pattern subst rules only replace 1x # bummer; have to use $foreach since % pattern subst rules only replace 1x

View File

@@ -0,0 +1,117 @@
#
# $Id$
#
This TULIP driver can be used on BSPs that support PCI bus.
It can handle any DEC21140 based Ethernet controller.
It works on big or little endian target.
It has been tested with powerpc/mcp750 BSP (OnBoard Ethernet
controller) and i386/pc386 BSP (D-Link DFE-500TX Ethernet board).
*****************************************************************
******** ***************
******** tests with ttcp benchmark for DEC driver ***************
******** optimization ***************
******** ***************
*****************************************************************
LINUX -> LINUX-ix86
Transmitter :
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> genesis
ttcp-t: 16777216 bytes in 1.87 real seconds = 8775.25 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 0.93, calls/sec = 1096.91
ttcp-t: 0.0user 0.9sys 0:01real 51% 0i+0d 0maxrss 0+2pf 0+0csw
Receiver :
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 1.88 real seconds = 8706.53 KB/sec +++
ttcp-r: 10802 I/O calls, msec/call = 0.18, calls/sec = 5740.23
ttcp-r: 0.0user 0.2sys 0:01real 13% 0i+0d 0maxrss 0+2pf 0+0csw
==============================================================
==============================================================
==============================================================
LINUX -> RTEMS-ix86 with tulip driver from pc386 bsp
Transmitter :
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> neil-young-100
ttcp-t: 16777216 bytes in 1.98 real seconds = 8294.76 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 0.99, calls/sec = 1036.85
ttcp-t: 0.0user 0.1sys 0:01real 9% 0i+0d 0maxrss 0+2pf 0+0csw
Receiver :
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 2.03 real seconds = 8065.14 KB/sec +++
ttcp-r: 3088 I/O calls, msec/call = 0.67, calls/sec = 1520.09
ttcp-r: 0.0user 2.0sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw
==============================================================
==============================================================
==============================================================
RTEMS-ix86 with tulip driver from pc386 bsp -> LINUX
Transmitter :
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> 194.2.81.126
ttcp-t: 16777216 bytes in 2.76 real seconds = 5938.77 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 1.38, calls/sec = 742.35
ttcp-t: 0.0user 2.5sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw
Receiver :
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 2.75 real seconds = 5948.53 KB/sec +++
ttcp-r: 11349 I/O calls, msec/call = 0.25, calls/sec = 4120.48
ttcp-r: 0.0user 0.1sys 0:02real 6% 0i+0d 0maxrss 0+2pf 0+0csw
==============================================================
==============================================================
==============================================================
LINUX -> RTEMS-ix86 with optimized tulip driver
Transmitter :
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> neil-young-100
ttcp-t: 16777216 bytes in 1.73 real seconds = 9470.13 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 0.87, calls/sec = 1183.77
ttcp-t: 0.0user 0.1sys 0:01real 6% 0i+0d 0maxrss 0+2pf 0+0csw
Receiver :
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 1.76 real seconds = 9315.33 KB/sec +++
ttcp-r: 4558 I/O calls, msec/call = 0.40, calls/sec = 2591.51
ttcp-r: 0.0user 1.7sys 0:01real 100% 0i+0d 0maxrss 0+0pf 0+0csw
==============================================================
==============================================================
==============================================================
RTEMS-ix86 with optimized tulip driver -> LINUX
Transmitter :
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> 194.2.81.126
ttcp-t: 16777216 bytes in 2.09 real seconds = 7847.80 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 1.04, calls/sec = 980.98
ttcp-t: 0.0user 2.0sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw
Receiver :
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 2.08 real seconds = 7874.23 KB/sec +++
ttcp-r: 11404 I/O calls, msec/call = 0.19, calls/sec = 5480.82
ttcp-r: 0.0user 0.1sys 0:02real 8% 0i+0d 0maxrss 0+2pf 0+0csw

View File

@@ -1,11 +1,24 @@
/* /*
* RTEMS driver for TULIP based Ethernet Controller * RTEMS driver for TULIP based Ethernet Controller
* *
* $Header$ * Copyright (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/ */
#include <bsp.h> #include <bsp.h>
#if defined(i386)
#include <pcibios.h> #include <pcibios.h>
#endif
#if defined(__PPC)
#include <bsp/pci.h>
#include <libcpu/byteorder.h>
#include <libcpu/io.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@@ -24,7 +37,12 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
#if defined(i386)
#include <irq.h> #include <irq.h>
#endif
#if defined(__PPC)
#include <bsp/irq.h>
#endif
#ifdef malloc #ifdef malloc
#undef malloc #undef malloc
@@ -33,11 +51,15 @@
#undef free #undef free
#endif #endif
#define DEC_DEBUG
#define PCI_INVALID_VENDORDEVICEID 0xffffffff
#define PCI_VENDOR_ID_DEC 0x1011 #define PCI_VENDOR_ID_DEC 0x1011
#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 #define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009
#define IO_MASK 0x3 #define IO_MASK 0x3
#define MEM_MASK 0xF #define MEM_MASK 0xF
#define MASK_OFFSET 0xF
/* command and status registers, 32-bit access, only if IO-ACCESS */ /* command and status registers, 32-bit access, only if IO-ACCESS */
#define ioCSR0 0x00 /* bus mode register */ #define ioCSR0 0x00 /* bus mode register */
@@ -78,27 +100,35 @@
#define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */ #define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */
#define RESET_CHIP 0x00000001 #define RESET_CHIP 0x00000001
#define CSR0_MODE 0x01a08000 /* 01a08000 */ #if defined(__PPC)
#define CSR0_MODE 0x0030e002 /* 01b08000 */
#else
#define CSR0_MODE 0x0020e002 /* 01b08000 */
#endif
#define ROM_ADDRESS 0x00004800 #define ROM_ADDRESS 0x00004800
#define CSR6_INIT 0x020c0000 /* 020c0000 */ #define CSR6_INIT 0x022cc000 /* 022c0000 020c0000 */
#define CSR6_TX 0x00002000 #define CSR6_TX 0x00002000
#define CSR6_TXRX 0x00002002 #define CSR6_TXRX 0x00002002
#define IT_SETUP 0x00010040 /* 0001ebef */ #define IT_SETUP 0x000100c0 /* 000100e0 */
#define CLEAR_IT 0xFFFFFFFF #define CLEAR_IT 0xFFFFFFFF
#define NO_IT 0x00000000 #define NO_IT 0x00000000
#define NRXBUFS 7 /* number of receive buffers */ #define NRXBUFS 32 /* number of receive buffers */
#define NTXBUFS 1 /* number of transmit buffers */ #define NTXBUFS 16 /* number of transmit buffers */
/* message descriptor entry */ /* message descriptor entry */
struct MD { struct MD {
volatile unsigned long status; /* used by hardware */
volatile unsigned long counts; volatile unsigned32 status;
unsigned long buf1, buf2; volatile unsigned32 counts;
unsigned32 buf1, buf2;
/* used by software */
volatile struct mbuf *m;
volatile struct MD *next;
}; };
/* /*
* Number of WDs supported by this driver * Number of DECs supported by this driver
*/ */
#define NDECDRIVER 1 #define NDECDRIVER 1
@@ -121,6 +151,28 @@ struct MD {
*/ */
#define START_TRANSMIT_EVENT RTEMS_EVENT_2 #define START_TRANSMIT_EVENT RTEMS_EVENT_2
#if defined(__PPC)
#define phys_to_bus(address) ((unsigned int)(address) + PREP_PCI_DRAM_OFFSET)
#define bus_to_phys(address) ((unsigned int)(address) - PREP_PCI_DRAM_OFFSET)
#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PPC_CACHE_ALIGNMENT
#else
#define phys_to_bus(address) address
#define bus_to_phys(address) address
#define delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100 )
#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE
inline void st_le32(volatile unsigned32 *addr, unsigned32 value)
{
*(addr)=value ;
}
inline unsigned32 ld_le32(volatile unsigned32 *addr)
{
return(*addr);
}
#endif
#if (MCLBYTES < RBUF_SIZE) #if (MCLBYTES < RBUF_SIZE)
# error "Driver must have MCLBYTES > RBUF_SIZE" # error "Driver must have MCLBYTES > RBUF_SIZE"
#endif #endif
@@ -129,19 +181,24 @@ struct MD {
* Per-device data * Per-device data
*/ */
struct dec21140_softc { struct dec21140_softc {
struct arpcom arpcom;
rtems_irq_connect_data irqInfo; struct arpcom arpcom;
struct MD *MDbase;
char *bufferBase; rtems_irq_connect_data irqInfo;
int acceptBroadcast;
int rxBdCount; volatile struct MD *MDbase;
int txBdCount; volatile unsigned char *bufferBase;
rtems_id rxDaemonTid; int acceptBroadcast;
rtems_id txDaemonTid; rtems_id rxDaemonTid;
rtems_id txDaemonTid;
volatile struct MD *TxMD;
volatile struct MD *SentTxMD;
int PendingTxCount;
int TxSuspended;
unsigned int port; unsigned int port;
unsigned int *base; volatile unsigned int *base;
unsigned long bpar;
/* /*
* Statistics * Statistics
@@ -174,27 +231,26 @@ static struct dec21140_softc dec21140_softc[NDECDRIVER];
static rtems_isr static rtems_isr
dec21140Enet_interrupt_handler (rtems_vector_number v) dec21140Enet_interrupt_handler (rtems_vector_number v)
{ {
unsigned int *tbase; volatile unsigned32 *tbase;
unsigned long status; unsigned32 status;
struct dec21140_softc *sc;
unsigned int sc; sc = &dec21140_softc[0];
tbase = (unsigned32 *)(sc->base) ;
tbase = dec21140_softc[0].base ;
/* /*
* Read status * Read status
*/ */
*(tbase+memCSR7) = NO_IT; status = ld_le32(tbase+memCSR5);
status = *(tbase+memCSR5); st_le32((tbase+memCSR5), status); /* clear the bits we've read */
*(tbase+memCSR5) = CLEAR_IT;
/* /*
* Frame received? * Frame received?
*/ */
if (status & 0x00000040){ if (status & 0x000000c0){
dec21140_softc[0].rxInterrupts++; sc->rxInterrupts++;
sc = rtems_event_send (dec21140_softc[0].rxDaemonTid, INTERRUPT_EVENT); rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
} }
} }
static void nopOn(const rtems_irq_connect_data* notUsed) static void nopOn(const rtems_irq_connect_data* notUsed)
@@ -210,93 +266,6 @@ static int dec21140IsOn(const rtems_irq_connect_data* irq)
return BSP_irq_enabled_at_i8259s (irq->name); return BSP_irq_enabled_at_i8259s (irq->name);
} }
/*
* Read and write the MII registers using software-generated serial
* MDIO protocol.
*/
#define MDIO_SHIFT_CLK 0x10000
#define MDIO_DATA_WRITE0 0x00000
#define MDIO_DATA_WRITE1 0x20000
#define MDIO_ENB 0x00000
#define MDIO_ENB_IN 0x40000
#define MDIO_DATA_READ 0x80000
static int mdio_read(unsigned int *ioaddr, int phy_id, int location)
{
int i, i3;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned short retval = 0;
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
*ioaddr = MDIO_ENB | MDIO_DATA_WRITE1;
for(i3=0; i3<1000; i3++);
*ioaddr = MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
}
/* Shift the read command bits out. */
for (i = 17; i >= 0; i--) {
int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
*ioaddr = dataval;
for(i3=0; i3<1000; i3++);
*ioaddr = dataval | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
*ioaddr = dataval;
for(i3=0; i3<1000; i3++);
}
*ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
*ioaddr = MDIO_ENB_IN;
for (i = 16; i > 0; i--) {
*ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
retval = (retval << 1) | ((*ioaddr & MDIO_DATA_READ) ? 1 : 0);
*ioaddr = MDIO_ENB_IN;
for(i3=0; i3<1000; i3++);
}
/* Clear out extra bits. */
for (i = 16; i > 0; i--) {
*ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
*ioaddr = MDIO_ENB_IN;
for(i3=0; i3<1000; i3++);
}
return retval;
}
static int mdio_write(unsigned int *ioaddr, int phy_id, int location, int value)
{
int i, i3;
int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
*ioaddr = MDIO_ENB | MDIO_DATA_WRITE1;
for(i3=0; i3<1000; i3++);
*ioaddr = MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
}
/* Shift the read command bits out. */
for (i = 31; i >= 0; i--) {
int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
*ioaddr = dataval;
for(i3=0; i3<1000; i3++);
*ioaddr = dataval | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
}
/* Clear out extra bits. */
for (i = 2; i > 0; i--) {
*ioaddr = MDIO_ENB_IN;
for(i3=0; i3<1000; i3++);
*ioaddr = MDIO_ENB_IN | MDIO_SHIFT_CLK;
for(i3=0; i3<1000; i3++);
}
return 0;
}
/* /*
* This routine reads a word (16 bits) from the serial EEPROM. * This routine reads a word (16 bits) from the serial EEPROM.
@@ -315,38 +284,38 @@ static int mdio_write(unsigned int *ioaddr, int phy_id, int location, int value)
#define EE_READ_CMD (6 << 6) #define EE_READ_CMD (6 << 6)
#define EE_ERASE_CMD (7 << 6) #define EE_ERASE_CMD (7 << 6)
static int eeget16(unsigned int *ioaddr, int location) static int eeget16(volatile unsigned int *ioaddr, int location)
{ {
int i, i3; int i;
unsigned short retval = 0; unsigned short retval = 0;
int read_cmd = location | EE_READ_CMD; int read_cmd = location | EE_READ_CMD;
*ioaddr = EE_ENB & ~EE_CS; st_le32(ioaddr, EE_ENB & ~EE_CS);
*ioaddr = EE_ENB; st_le32(ioaddr, EE_ENB);
/* Shift the read command bits out. */ /* Shift the read command bits out. */
for (i = 10; i >= 0; i--) { for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
*ioaddr = EE_ENB | dataval; st_le32(ioaddr, EE_ENB | dataval);
for (i3=0; i3<1000; i3++) ; delay_in_bus_cycles(200);
*ioaddr = EE_ENB | dataval | EE_SHIFT_CLK; st_le32(ioaddr, EE_ENB | dataval | EE_SHIFT_CLK);
for (i3=0; i3<1000; i3++) ; delay_in_bus_cycles(200);
*ioaddr = EE_ENB | dataval; /* Finish EEPROM a clock tick. */ st_le32(ioaddr, EE_ENB | dataval); /* Finish EEPROM a clock tick. */
for (i3=0; i3<1000; i3++) ; delay_in_bus_cycles(200);
} }
*ioaddr = EE_ENB; st_le32(ioaddr, EE_ENB);
for (i = 16; i > 0; i--) { for (i = 16; i > 0; i--) {
*ioaddr = EE_ENB | EE_SHIFT_CLK; st_le32(ioaddr, EE_ENB | EE_SHIFT_CLK);
for (i3=0; i3<1000; i3++) ; delay_in_bus_cycles(200);
retval = (retval << 1) | ((*ioaddr & EE_DATA_READ) ? 1 : 0); retval = (retval << 1) | ((ld_le32(ioaddr) & EE_DATA_READ) ? 1 : 0);
*ioaddr = EE_ENB; st_le32(ioaddr, EE_ENB);
for (i3=0; i3<1000; i3++) ; delay_in_bus_cycles(200);
} }
/* Terminate the EEPROM access. */ /* Terminate the EEPROM access. */
*ioaddr = EE_ENB & ~EE_CS; st_le32(ioaddr, EE_ENB & ~EE_CS);
return retval; return ( ((retval<<8)&0xff00) | ((retval>>8)&0xff) );
} }
/* /*
@@ -356,96 +325,110 @@ static void
dec21140Enet_initialize_hardware (struct dec21140_softc *sc) dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
{ {
rtems_status_code st; rtems_status_code st;
unsigned int *tbase; volatile unsigned int *tbase;
union {char c[64]; unsigned short s[32];} rombuf; union {char c[64]; unsigned short s[32];} rombuf;
int i, i2, i3; int i;
char *cp, direction, *setup_frm, *eaddrs; volatile unsigned char *cp, *setup_frm, *eaddrs;
unsigned long csr12_val, mii_reg0; volatile unsigned char *buffer;
unsigned char *buffer; volatile struct MD *rmd;
struct MD *rmd;
tbase = sc->base; tbase = sc->base;
/* /*
* WARNING : First write in CSR6 * WARNING : First write in CSR6
* Then Reset the chip ( 1 in CSR0) * Then Reset the chip ( 1 in CSR0)
*/ */
st_le32( (tbase+memCSR6), CSR6_INIT);
*(tbase+memCSR6) = CSR6_INIT; st_le32( (tbase+memCSR0), RESET_CHIP);
*(tbase+memCSR0) = RESET_CHIP; delay_in_bus_cycles(200);
for(i3=0; i3<1000; i3++);
/* /*
* Init CSR0 * Init CSR0
*/ */
*(tbase+memCSR0) = CSR0_MODE; st_le32( (tbase+memCSR0), CSR0_MODE);
csr12_val = *(tbase+memCSR8); /* csr12_val = ld_le32( (tbase+memCSR8) );*/
for (i=0; i<32; i++) for (i=0; i<32; i++){
rombuf.s[i] = eeget16(tbase+memCSR9, i); rombuf.s[i] = eeget16(tbase+memCSR9, i);
}
memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN); memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN);
mii_reg0 = mdio_read(tbase+memCSR9, 0, 0);
mdio_write(tbase+memCSR9, 0, 0, mii_reg0 | 0x1000);
#ifdef DEC_DEBUG #ifdef DEC_DEBUG
printk("DC21140 %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n", printk("DC21140 %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n",
sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1], sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3], sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5], sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5],
sc->irqInfo.name, sc->port, sc->base); sc->irqInfo.name, sc->port, (unsigned) sc->base);
#endif #endif
/* /*
* Init RX ring * Init RX ring
*/ */
sc->rxBdCount = 0; cp = (volatile unsigned char *)malloc(((NRXBUFS+NTXBUFS)*sizeof(struct MD))
+ (NTXBUFS*RBUF_SIZE)
cp = (char *)malloc((NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE) + PG_SIZE); + CPU_CACHE_ALIGNMENT_FOR_BUFFER);
sc->bufferBase = cp; sc->bufferBase = cp;
cp += (PG_SIZE - (int)cp) & MASK_OFFSET; cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp)
& (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1);
#if defined(__i386)
#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA #ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA
if (_CPU_is_paging_enabled()) if (_CPU_is_paging_enabled())
_CPU_change_memory_mapping_attribute _CPU_change_memory_mapping_attribute
(NULL, cp, (NULL, cp,
(NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE), ((NRXBUFS+NTXBUFS)*sizeof(struct MD))
+ (NTXBUFS*RBUF_SIZE),
PTE_CACHE_DISABLE | PTE_WRITABLE); PTE_CACHE_DISABLE | PTE_WRITABLE);
#endif #endif
rmd = (struct MD*)cp; #endif
rmd = (volatile struct MD*)cp;
sc->MDbase = rmd; sc->MDbase = rmd;
buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD)); buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD));
st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase))));
*(tbase+memCSR3) = (long)(sc->MDbase);
for (i=0 ; i<NRXBUFS; i++){ for (i=0 ; i<NRXBUFS; i++){
rmd->buf2 = 0; struct mbuf *m;
rmd->buf1 = (unsigned long)(buffer + (i*RBUF_SIZE));
if (i == NRXBUFS-1) /* allocate an mbuf for each receive descriptor */
rmd->counts = 0xfec00000 | (RBUF_SIZE); MGETHDR (m, M_WAIT, MT_DATA);
else MCLGET (m, M_WAIT);
rmd->counts = 0xfcc00000 | (RBUF_SIZE); m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
rmd->m = m;
rmd->buf2 = phys_to_bus(rmd+1);
rmd->buf1 = phys_to_bus(mtod(m, void *));
rmd->counts = 0xfdc00000 | (RBUF_SIZE);
rmd->status = 0x80000000; rmd->status = 0x80000000;
rmd->next = rmd + 1;
rmd++; rmd++;
} }
/*
* mark last RX buffer.
*/
sc->MDbase [NRXBUFS-1].counts = 0xfec00000 | (RBUF_SIZE);
sc->MDbase [NRXBUFS-1].next = sc->MDbase;
/* /*
* Init TX ring * Init TX ring
*/ */
sc->txBdCount = 0; st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) );
*(tbase+memCSR4) = (long)(rmd); for (i=0 ; i<NTXBUFS; i++){
rmd->buf2 = 0; (rmd+i)->buf2 = phys_to_bus(rmd+i+1);
rmd->buf1 = (unsigned long)(buffer + (NRXBUFS*RBUF_SIZE)); (rmd+i)->buf1 = phys_to_bus(buffer + (i*RBUF_SIZE));
rmd->counts = 0x62000000; (rmd+i)->counts = 0x01000000;
rmd->status = 0x0; (rmd+i)->status = 0x0;
(rmd+i)->next = rmd+i+1;
(rmd+i)->m = 0;
}
/*
* mark last TX buffer.
*/
(rmd+NTXBUFS-1)->buf2 = phys_to_bus(rmd);
(rmd+NTXBUFS-1)->next = rmd;
/* /*
* Set up interrupts * Set up interrupts
*/ */
*(tbase+memCSR5) = IT_SETUP;
*(tbase+memCSR7) = IT_SETUP;
sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler; sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
sc->irqInfo.on = nopOn; sc->irqInfo.on = nopOn;
sc->irqInfo.off = nopOn; sc->irqInfo.off = nopOn;
@@ -455,72 +438,61 @@ dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n", rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
sc->irqInfo.name); sc->irqInfo.name);
/* st_le32( (tbase+memCSR7), NO_IT);
* Start TX for setup frame
*/
*(tbase+memCSR6) = CSR6_INIT | CSR6_TX;
/* /*
* Build setup frame * Build setup frame
*/ */
setup_frm = (char *)(rmd->buf1); setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1));
eaddrs = (char *)(sc->arpcom.ac_enaddr); eaddrs = (char *)(sc->arpcom.ac_enaddr);
/* Fill the buffer with our physical address. */ /* Fill the buffer with our physical address. */
for (i = 1; i < 16; i++) { for (i = 1; i < 16; i++) {
*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
setup_frm += 2; *setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1];
*setup_frm++ = eaddrs[2];
*setup_frm++ = eaddrs[3];
*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
*setup_frm++ = eaddrs[3]; *setup_frm++ = eaddrs[3];
setup_frm += 2;
*setup_frm++ = eaddrs[4]; *setup_frm++ = eaddrs[4];
*setup_frm++ = eaddrs[5]; *setup_frm++ = eaddrs[5];
setup_frm += 2; *setup_frm++ = eaddrs[4];
*setup_frm++ = eaddrs[5];
} }
/* Add the broadcast address when doing perfect filtering */ /* Add the broadcast address when doing perfect filtering */
memset(setup_frm, 0xff, 12); memset((void*) setup_frm, 0xff, 12);
rmd->counts = 0x0a000000 | 192 ; rmd->counts = 0x09000000 | 192 ;
rmd->status = 0x80000000; rmd->status = 0x80000000;
*(tbase+memCSR1) = 1; st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX);
st_le32( (tbase+memCSR1), 1);
while (rmd->status != 0x7fffffff); while (rmd->status != 0x7fffffff);
rmd->counts = 0x01000000;
sc->TxMD = rmd+1;
/* /*
* Enable RX and TX * Enable RX and TX
*/ */
*(tbase+memCSR6) = CSR6_INIT | CSR6_TXRX; st_le32( (tbase+memCSR5), IT_SETUP);
st_le32( (tbase+memCSR7), IT_SETUP);
st_le32( (unsigned int*)(tbase+memCSR6), CSR6_INIT | CSR6_TXRX);
/*
* Set up PHY
*/
i = rombuf.c[27];
i+=2;
direction = rombuf.c[i];
i +=4;
*(tbase+memCSR12) = direction | 0x100;
for (i2 = 0; i2 < rombuf.c[(i+2) + rombuf.c[i+1]]; i2++){
*(tbase + memCSR12) = rombuf.c[(i+3) + rombuf.c[i+1] + i2];
}
for (i2 = 0; i2 < rombuf.c[i+1]; i2++){
*(tbase + memCSR12) = rombuf.c[(i+2) + i2];
}
} }
static void static void
dec21140_rxDaemon (void *arg) dec21140_rxDaemon (void *arg)
{ {
unsigned int *tbase; volatile unsigned int *tbase;
struct ether_header *eh; struct ether_header *eh;
struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0]; struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0];
struct ifnet *ifp = &dp->arpcom.ac_if; struct ifnet *ifp = &dp->arpcom.ac_if;
struct mbuf *m; struct mbuf *m;
struct MD *rmd; volatile struct MD *rmd;
unsigned int len; unsigned int len;
char *temp;
rtems_event_set events; rtems_event_set events;
int nbMD;
tbase = dec21140_softc[0].base ; tbase = dec21140_softc[0].base ;
rmd = dec21140_softc[0].MDbase;
for (;;){ for (;;){
@@ -528,27 +500,27 @@ dec21140_rxDaemon (void *arg)
RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_WAIT|RTEMS_EVENT_ANY,
RTEMS_NO_TIMEOUT, RTEMS_NO_TIMEOUT,
&events); &events);
rmd = dec21140_softc[0].MDbase;
nbMD = 0;
while (nbMD < NRXBUFS){ while((rmd->status & 0x80000000) == 0){
if ( (rmd->status & 0x80000000) == 0){ /* pass on the packet in the mbuf */
len = (rmd->status >> 16) & 0x7ff; len = (rmd->status >> 16) & 0x7ff;
MGETHDR (m, M_WAIT, MT_DATA); m = (struct mbuf *)(rmd->m);
MCLGET (m, M_WAIT); m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
m->m_pkthdr.rcvif = ifp; eh = mtod (m, struct ether_header *);
temp = m->m_data; m->m_data += sizeof(struct ether_header);
m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); ether_input (ifp, eh, m);
memcpy(temp, (char *)rmd->buf1, len);
rmd->status = 0x80000000; /* get a new mbuf for the 21140 */
eh = mtod (m, struct ether_header *); MGETHDR (m, M_WAIT, MT_DATA);
m->m_data += sizeof(struct ether_header); MCLGET (m, M_WAIT);
ether_input (ifp, eh, m); m->m_pkthdr.rcvif = ifp;
} rmd->m = m;
rmd++; rmd->buf1 = phys_to_bus(mtod(m, void *));
nbMD++;
rmd->status = 0x80000000;
rmd=rmd->next;
} }
*(tbase+memCSR7) = IT_SETUP;
} }
} }
@@ -557,37 +529,41 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
{ {
struct dec21140_softc *dp = ifp->if_softc; struct dec21140_softc *dp = ifp->if_softc;
volatile struct MD *tmd; volatile struct MD *tmd;
unsigned char *temp; volatile unsigned char *temp;
struct mbuf *n; struct mbuf *n;
unsigned int len; unsigned int len;
unsigned int *tbase; volatile unsigned int *tbase;
tbase = dp->base; tbase = dp->base;
/* /*
* Waiting for Transmitter ready * Waiting for Transmitter ready
*/ */
tmd = dec21140_softc[0].MDbase + NRXBUFS; tmd = dec21140_softc[0].TxMD;
while ( (tmd->status & 0x80000000) != 0 );
len = 0;
n = m; n = m;
temp = (char *)(tmd->buf1);
while ((tmd->status & 0x80000000) != 0){
tmd=tmd->next;
}
len = 0;
temp = (volatile unsigned char *)(bus_to_phys(tmd->buf1));
for (;;){ for (;;){
len += m->m_len; len += m->m_len;
memcpy(temp, (char *)m->m_data, m->m_len); memcpy((void*) temp, (char *)m->m_data, m->m_len);
temp += m->m_len ; temp += m->m_len ;
if ((m = m->m_next) == NULL) if ((m = m->m_next) == NULL)
break; break;
} }
if (len < ET_MINLEN) len = ET_MINLEN; if (len < ET_MINLEN) len = ET_MINLEN;
tmd->counts = 0xe2000000 | len; tmd->counts = 0xe1000000 | (len & 0x7ff);
tmd->status = 0x80000000; tmd->status = 0x80000000;
*(tbase+memCSR1) = 0x1; st_le32( (tbase+memCSR1), 0x1);
m_freem(n); m_freem(n);
dec21140_softc[0].TxMD = tmd->next;
} }
/* /*
@@ -672,7 +648,7 @@ dec21140_init (void *arg)
static void static void
dec21140_stop (struct dec21140_softc *sc) dec21140_stop (struct dec21140_softc *sc)
{ {
unsigned int *tbase; volatile unsigned int *tbase;
struct ifnet *ifp = &sc->arpcom.ac_if; struct ifnet *ifp = &sc->arpcom.ac_if;
ifp->if_flags &= ~IFF_RUNNING; ifp->if_flags &= ~IFF_RUNNING;
@@ -681,9 +657,9 @@ dec21140_stop (struct dec21140_softc *sc)
* Stop the transmitter * Stop the transmitter
*/ */
tbase=dec21140_softc[0].base ; tbase=dec21140_softc[0].base ;
*(tbase+memCSR7) = NO_IT; st_le32( (tbase+memCSR7), NO_IT);
*(tbase+memCSR6) = CSR6_INIT; st_le32( (tbase+memCSR6), CSR6_INIT);
free(sc->bufferBase); free((void*)sc->bufferBase);
} }
@@ -759,6 +735,7 @@ dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data)
error = EINVAL; error = EINVAL;
break; break;
} }
return error; return error;
} }
@@ -772,14 +749,16 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
struct ifnet *ifp; struct ifnet *ifp;
int mtu; int mtu;
int i; int i;
/*
* First, find a DEC board
*/
#if defined(__i386)
int signature; int signature;
int value; int value;
char interrupt; char interrupt;
int diag; int diag;
/*
* Initialise PCI module
*/
if (pcib_init() == PCIB_ERR_NOTPRESENT) if (pcib_init() == PCIB_ERR_NOTPRESENT)
rtems_panic("PCI BIOS not found !!"); rtems_panic("PCI BIOS not found !!");
@@ -794,7 +773,37 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
else { else {
printk("DEC PCI Device found\n"); printk("DEC PCI Device found\n");
} }
#endif
#if defined(__PPC)
unsigned char ucSlotNumber, ucFnNumber;
unsigned int ulDeviceID, lvalue, tmp;
unsigned char cvalue;
for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
for(ucFnNumber=0;ucFnNumber<PCI_MAX_FUNCTIONS;ucFnNumber++) {
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_VENDOR_ID,
&ulDeviceID);
if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
/*
* This slot is empty
*/
continue;
}
if (ulDeviceID == ((PCI_DEVICE_ID_DEC_TULIP_FAST<<16) + PCI_VENDOR_ID_DEC))
break;
}
if (ulDeviceID == ((PCI_DEVICE_ID_DEC_TULIP_FAST<<16) + PCI_VENDOR_ID_DEC)){
printk("DEC Adapter found !!\n");
break;
}
}
if(ulDeviceID==PCI_INVALID_VENDORDEVICEID)
rtems_panic("DEC PCI board not found !!\n");
#endif
/* /*
* Find a free driver * Find a free driver
*/ */
@@ -812,7 +821,7 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
/* /*
* Process options * Process options
*/ */
#if defined(__i386)
pcib_conf_read32(signature, 16, &value); pcib_conf_read32(signature, 16, &value);
sc->port = value & ~IO_MASK; sc->port = value & ~IO_MASK;
@@ -827,7 +836,34 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
pcib_conf_read8(signature, 60, &interrupt); pcib_conf_read8(signature, 60, &interrupt);
sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt; sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt;
#endif
#if defined(__PPC)
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_BASE_ADDRESS_0,
&lvalue);
sc->port = lvalue & (unsigned int)(~IO_MASK);
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_BASE_ADDRESS_1 ,
&lvalue);
tmp = (unsigned int)(lvalue & (unsigned int)(~MEM_MASK))
+ (unsigned int)PREP_ISA_MEM_BASE;
sc->base = (unsigned int *)(tmp);
(void)pci_read_config_byte(0,
ucSlotNumber,
ucFnNumber,
PCI_INTERRUPT_LINE,
&cvalue);
sc->irqInfo.name = (rtems_irq_symbolic_name)cvalue;
#endif
if (config->hardware_address) { if (config->hardware_address) {
memcpy (sc->arpcom.ac_enaddr, config->hardware_address, memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
ETHER_ADDR_LEN); ETHER_ADDR_LEN);
@@ -866,13 +902,3 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
return 1; return 1;
}; };