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@
# 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)
# 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@
# 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)
BSP_PIECES = startup clock console timer $(NETWORK)

View File

@@ -22,14 +22,10 @@ SRCS = README
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
# from the individual .rel files built in other directories
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
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@
# We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = dec21140
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES = clock console irq openpic pci residual startup $(NETWORK) \
vectors motorola
BSP_PIECES = clock console irq openpic pci residual startup vectors motorola
GENERIC_PIECES =
# bummer; have to use $foreach since % pattern subst rules only replace 1x

View File

@@ -22,14 +22,10 @@ SRCS = README
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
# from the individual .rel files built in other directories
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
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@
# We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = dec21140
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES = clock console irq openpic pci residual startup $(NETWORK) \
vectors motorola
BSP_PIECES = clock console irq openpic pci residual startup vectors motorola
GENERIC_PIECES =
# 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>
#if defined(i386)
#include <pcibios.h>
#endif
#if defined(__PPC)
#include <bsp/pci.h>
#include <libcpu/byteorder.h>
#include <libcpu/io.h>
#endif
#include <stdlib.h>
#include <stdio.h>
@@ -24,7 +37,12 @@
#include <netinet/in.h>
#include <netinet/if_ether.h>
#if defined(i386)
#include <irq.h>
#endif
#if defined(__PPC)
#include <bsp/irq.h>
#endif
#ifdef malloc
#undef malloc
@@ -33,11 +51,15 @@
#undef free
#endif
#define DEC_DEBUG
#define PCI_INVALID_VENDORDEVICEID 0xffffffff
#define PCI_VENDOR_ID_DEC 0x1011
#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009
#define IO_MASK 0x3
#define MEM_MASK 0xF
#define MASK_OFFSET 0xF
/* command and status registers, 32-bit access, only if IO-ACCESS */
#define ioCSR0 0x00 /* bus mode register */
@@ -78,27 +100,35 @@
#define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */
#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 CSR6_INIT 0x020c0000 /* 020c0000 */
#define CSR6_INIT 0x022cc000 /* 022c0000 020c0000 */
#define CSR6_TX 0x00002000
#define CSR6_TXRX 0x00002002
#define IT_SETUP 0x00010040 /* 0001ebef */
#define IT_SETUP 0x000100c0 /* 000100e0 */
#define CLEAR_IT 0xFFFFFFFF
#define NO_IT 0x00000000
#define NRXBUFS 7 /* number of receive buffers */
#define NTXBUFS 1 /* number of transmit buffers */
#define NRXBUFS 32 /* number of receive buffers */
#define NTXBUFS 16 /* number of transmit buffers */
/* message descriptor entry */
struct MD {
volatile unsigned long status;
volatile unsigned long counts;
unsigned long buf1, buf2;
/* used by hardware */
volatile unsigned32 status;
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
@@ -121,6 +151,28 @@ struct MD {
*/
#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)
# error "Driver must have MCLBYTES > RBUF_SIZE"
#endif
@@ -129,19 +181,24 @@ struct MD {
* Per-device data
*/
struct dec21140_softc {
struct arpcom arpcom;
rtems_irq_connect_data irqInfo;
struct MD *MDbase;
char *bufferBase;
int acceptBroadcast;
int rxBdCount;
int txBdCount;
rtems_id rxDaemonTid;
rtems_id txDaemonTid;
struct arpcom arpcom;
rtems_irq_connect_data irqInfo;
volatile struct MD *MDbase;
volatile unsigned char *bufferBase;
int acceptBroadcast;
rtems_id rxDaemonTid;
rtems_id txDaemonTid;
volatile struct MD *TxMD;
volatile struct MD *SentTxMD;
int PendingTxCount;
int TxSuspended;
unsigned int port;
unsigned int *base;
unsigned long bpar;
volatile unsigned int *base;
/*
* Statistics
@@ -174,27 +231,26 @@ static struct dec21140_softc dec21140_softc[NDECDRIVER];
static rtems_isr
dec21140Enet_interrupt_handler (rtems_vector_number v)
{
unsigned int *tbase;
unsigned long status;
volatile unsigned32 *tbase;
unsigned32 status;
struct dec21140_softc *sc;
unsigned int sc;
tbase = dec21140_softc[0].base ;
sc = &dec21140_softc[0];
tbase = (unsigned32 *)(sc->base) ;
/*
* Read status
*/
*(tbase+memCSR7) = NO_IT;
status = *(tbase+memCSR5);
*(tbase+memCSR5) = CLEAR_IT;
/*
* Read status
*/
status = ld_le32(tbase+memCSR5);
st_le32((tbase+memCSR5), status); /* clear the bits we've read */
/*
* Frame received?
*/
if (status & 0x00000040){
dec21140_softc[0].rxInterrupts++;
sc = rtems_event_send (dec21140_softc[0].rxDaemonTid, INTERRUPT_EVENT);
}
/*
* Frame received?
*/
if (status & 0x000000c0){
sc->rxInterrupts++;
rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
}
}
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);
}
/*
* 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.
@@ -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_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;
int read_cmd = location | EE_READ_CMD;
*ioaddr = EE_ENB & ~EE_CS;
*ioaddr = EE_ENB;
st_le32(ioaddr, EE_ENB & ~EE_CS);
st_le32(ioaddr, EE_ENB);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
*ioaddr = EE_ENB | dataval;
for (i3=0; i3<1000; i3++) ;
*ioaddr = EE_ENB | dataval | EE_SHIFT_CLK;
for (i3=0; i3<1000; i3++) ;
*ioaddr = EE_ENB | dataval; /* Finish EEPROM a clock tick. */
for (i3=0; i3<1000; i3++) ;
st_le32(ioaddr, EE_ENB | dataval);
delay_in_bus_cycles(200);
st_le32(ioaddr, EE_ENB | dataval | EE_SHIFT_CLK);
delay_in_bus_cycles(200);
st_le32(ioaddr, EE_ENB | dataval); /* Finish EEPROM a clock tick. */
delay_in_bus_cycles(200);
}
*ioaddr = EE_ENB;
st_le32(ioaddr, EE_ENB);
for (i = 16; i > 0; i--) {
*ioaddr = EE_ENB | EE_SHIFT_CLK;
for (i3=0; i3<1000; i3++) ;
retval = (retval << 1) | ((*ioaddr & EE_DATA_READ) ? 1 : 0);
*ioaddr = EE_ENB;
for (i3=0; i3<1000; i3++) ;
st_le32(ioaddr, EE_ENB | EE_SHIFT_CLK);
delay_in_bus_cycles(200);
retval = (retval << 1) | ((ld_le32(ioaddr) & EE_DATA_READ) ? 1 : 0);
st_le32(ioaddr, EE_ENB);
delay_in_bus_cycles(200);
}
/* Terminate the EEPROM access. */
*ioaddr = EE_ENB & ~EE_CS;
return retval;
st_le32(ioaddr, EE_ENB & ~EE_CS);
return ( ((retval<<8)&0xff00) | ((retval>>8)&0xff) );
}
/*
@@ -356,96 +325,110 @@ static void
dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
{
rtems_status_code st;
unsigned int *tbase;
volatile unsigned int *tbase;
union {char c[64]; unsigned short s[32];} rombuf;
int i, i2, i3;
char *cp, direction, *setup_frm, *eaddrs;
unsigned long csr12_val, mii_reg0;
unsigned char *buffer;
struct MD *rmd;
int i;
volatile unsigned char *cp, *setup_frm, *eaddrs;
volatile unsigned char *buffer;
volatile struct MD *rmd;
tbase = sc->base;
/*
* WARNING : First write in CSR6
* Then Reset the chip ( 1 in CSR0)
*/
*(tbase+memCSR6) = CSR6_INIT;
*(tbase+memCSR0) = RESET_CHIP;
for(i3=0; i3<1000; i3++);
st_le32( (tbase+memCSR6), CSR6_INIT);
st_le32( (tbase+memCSR0), RESET_CHIP);
delay_in_bus_cycles(200);
/*
* Init CSR0
*/
*(tbase+memCSR0) = CSR0_MODE;
st_le32( (tbase+memCSR0), CSR0_MODE);
csr12_val = *(tbase+memCSR8);
for (i=0; i<32; i++)
/* csr12_val = ld_le32( (tbase+memCSR8) );*/
for (i=0; i<32; i++){
rombuf.s[i] = eeget16(tbase+memCSR9, i);
}
memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN);
mii_reg0 = mdio_read(tbase+memCSR9, 0, 0);
mdio_write(tbase+memCSR9, 0, 0, mii_reg0 | 0x1000);
#ifdef DEC_DEBUG
printk("DC21140 %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n",
sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5],
sc->irqInfo.name, sc->port, sc->base);
sc->irqInfo.name, sc->port, (unsigned) sc->base);
#endif
/*
* Init RX ring
*/
sc->rxBdCount = 0;
cp = (char *)malloc((NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE) + PG_SIZE);
cp = (volatile unsigned char *)malloc(((NRXBUFS+NTXBUFS)*sizeof(struct MD))
+ (NTXBUFS*RBUF_SIZE)
+ CPU_CACHE_ALIGNMENT_FOR_BUFFER);
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
if (_CPU_is_paging_enabled())
_CPU_change_memory_mapping_attribute
(NULL, cp,
(NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE),
((NRXBUFS+NTXBUFS)*sizeof(struct MD))
+ (NTXBUFS*RBUF_SIZE),
PTE_CACHE_DISABLE | PTE_WRITABLE);
#endif
rmd = (struct MD*)cp;
#endif
rmd = (volatile struct MD*)cp;
sc->MDbase = rmd;
buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD));
*(tbase+memCSR3) = (long)(sc->MDbase);
st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase))));
for (i=0 ; i<NRXBUFS; i++){
rmd->buf2 = 0;
rmd->buf1 = (unsigned long)(buffer + (i*RBUF_SIZE));
if (i == NRXBUFS-1)
rmd->counts = 0xfec00000 | (RBUF_SIZE);
else
rmd->counts = 0xfcc00000 | (RBUF_SIZE);
struct mbuf *m;
/* allocate an mbuf for each receive descriptor */
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
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->next = rmd + 1;
rmd++;
}
/*
* mark last RX buffer.
*/
sc->MDbase [NRXBUFS-1].counts = 0xfec00000 | (RBUF_SIZE);
sc->MDbase [NRXBUFS-1].next = sc->MDbase;
/*
* Init TX ring
*/
sc->txBdCount = 0;
*(tbase+memCSR4) = (long)(rmd);
rmd->buf2 = 0;
rmd->buf1 = (unsigned long)(buffer + (NRXBUFS*RBUF_SIZE));
rmd->counts = 0x62000000;
rmd->status = 0x0;
st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) );
for (i=0 ; i<NTXBUFS; i++){
(rmd+i)->buf2 = phys_to_bus(rmd+i+1);
(rmd+i)->buf1 = phys_to_bus(buffer + (i*RBUF_SIZE));
(rmd+i)->counts = 0x01000000;
(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
*/
*(tbase+memCSR5) = IT_SETUP;
*(tbase+memCSR7) = IT_SETUP;
sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
sc->irqInfo.on = nopOn;
sc->irqInfo.off = nopOn;
@@ -455,72 +438,61 @@ dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
sc->irqInfo.name);
/*
* Start TX for setup frame
*/
*(tbase+memCSR6) = CSR6_INIT | CSR6_TX;
st_le32( (tbase+memCSR7), NO_IT);
/*
* Build setup frame
*/
setup_frm = (char *)(rmd->buf1);
setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1));
eaddrs = (char *)(sc->arpcom.ac_enaddr);
/* Fill the buffer with our physical address. */
for (i = 1; i < 16; i++) {
*setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1];
setup_frm += 2;
*setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1];
*setup_frm++ = eaddrs[2];
*setup_frm++ = eaddrs[3];
*setup_frm++ = eaddrs[2];
*setup_frm++ = eaddrs[3];
setup_frm += 2;
*setup_frm++ = eaddrs[4];
*setup_frm++ = eaddrs[5];
setup_frm += 2;
*setup_frm++ = eaddrs[4];
*setup_frm++ = eaddrs[5];
}
/* Add the broadcast address when doing perfect filtering */
memset(setup_frm, 0xff, 12);
rmd->counts = 0x0a000000 | 192 ;
memset((void*) setup_frm, 0xff, 12);
rmd->counts = 0x09000000 | 192 ;
rmd->status = 0x80000000;
*(tbase+memCSR1) = 1;
st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX);
st_le32( (tbase+memCSR1), 1);
while (rmd->status != 0x7fffffff);
rmd->counts = 0x01000000;
sc->TxMD = rmd+1;
/*
* 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
dec21140_rxDaemon (void *arg)
{
unsigned int *tbase;
volatile unsigned int *tbase;
struct ether_header *eh;
struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0];
struct ifnet *ifp = &dp->arpcom.ac_if;
struct mbuf *m;
struct MD *rmd;
volatile struct MD *rmd;
unsigned int len;
char *temp;
rtems_event_set events;
int nbMD;
tbase = dec21140_softc[0].base ;
rmd = dec21140_softc[0].MDbase;
for (;;){
@@ -528,27 +500,27 @@ dec21140_rxDaemon (void *arg)
RTEMS_WAIT|RTEMS_EVENT_ANY,
RTEMS_NO_TIMEOUT,
&events);
rmd = dec21140_softc[0].MDbase;
nbMD = 0;
while (nbMD < NRXBUFS){
if ( (rmd->status & 0x80000000) == 0){
len = (rmd->status >> 16) & 0x7ff;
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
m->m_pkthdr.rcvif = ifp;
temp = m->m_data;
m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
memcpy(temp, (char *)rmd->buf1, len);
rmd->status = 0x80000000;
eh = mtod (m, struct ether_header *);
m->m_data += sizeof(struct ether_header);
ether_input (ifp, eh, m);
}
rmd++;
nbMD++;
while((rmd->status & 0x80000000) == 0){
/* pass on the packet in the mbuf */
len = (rmd->status >> 16) & 0x7ff;
m = (struct mbuf *)(rmd->m);
m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
eh = mtod (m, struct ether_header *);
m->m_data += sizeof(struct ether_header);
ether_input (ifp, eh, m);
/* get a new mbuf for the 21140 */
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
m->m_pkthdr.rcvif = ifp;
rmd->m = m;
rmd->buf1 = phys_to_bus(mtod(m, void *));
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;
volatile struct MD *tmd;
unsigned char *temp;
volatile unsigned char *temp;
struct mbuf *n;
unsigned int len;
unsigned int *tbase;
volatile unsigned int *tbase;
tbase = dp->base;
/*
* Waiting for Transmitter ready
*/
tmd = dec21140_softc[0].MDbase + NRXBUFS;
while ( (tmd->status & 0x80000000) != 0 );
len = 0;
tmd = dec21140_softc[0].TxMD;
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 (;;){
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 ;
if ((m = m->m_next) == NULL)
break;
}
if (len < ET_MINLEN) len = ET_MINLEN;
tmd->counts = 0xe2000000 | len;
tmd->counts = 0xe1000000 | (len & 0x7ff);
tmd->status = 0x80000000;
*(tbase+memCSR1) = 0x1;
st_le32( (tbase+memCSR1), 0x1);
m_freem(n);
dec21140_softc[0].TxMD = tmd->next;
}
/*
@@ -672,7 +648,7 @@ dec21140_init (void *arg)
static void
dec21140_stop (struct dec21140_softc *sc)
{
unsigned int *tbase;
volatile unsigned int *tbase;
struct ifnet *ifp = &sc->arpcom.ac_if;
ifp->if_flags &= ~IFF_RUNNING;
@@ -681,9 +657,9 @@ dec21140_stop (struct dec21140_softc *sc)
* Stop the transmitter
*/
tbase=dec21140_softc[0].base ;
*(tbase+memCSR7) = NO_IT;
*(tbase+memCSR6) = CSR6_INIT;
free(sc->bufferBase);
st_le32( (tbase+memCSR7), NO_IT);
st_le32( (tbase+memCSR6), CSR6_INIT);
free((void*)sc->bufferBase);
}
@@ -759,6 +735,7 @@ dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data)
error = EINVAL;
break;
}
return error;
}
@@ -772,14 +749,16 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
struct ifnet *ifp;
int mtu;
int i;
/*
* First, find a DEC board
*/
#if defined(__i386)
int signature;
int value;
char interrupt;
int diag;
/*
* Initialise PCI module
*/
if (pcib_init() == PCIB_ERR_NOTPRESENT)
rtems_panic("PCI BIOS not found !!");
@@ -794,7 +773,37 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
else {
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
*/
@@ -812,7 +821,7 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
/*
* Process options
*/
#if defined(__i386)
pcib_conf_read32(signature, 16, &value);
sc->port = value & ~IO_MASK;
@@ -827,7 +836,34 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
pcib_conf_read8(signature, 60, &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) {
memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
ETHER_ADDR_LEN);
@@ -866,13 +902,3 @@ rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
return 1;
};