diff options
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/powerpc/dmv177/include/bsp.h | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/dmv177/sonic/dmvsonic.c | 114 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in | 2 | ||||
-rw-r--r-- | c/src/lib/libchip/Makefile.in | 6 | ||||
-rw-r--r-- | c/src/lib/libchip/network/Makefile.in | 57 | ||||
-rw-r--r-- | c/src/lib/libchip/network/README | 16 | ||||
-rw-r--r-- | c/src/lib/libchip/network/README.sonic | 21 | ||||
-rw-r--r-- | c/src/lib/libchip/network/sonic.c (renamed from c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c) | 192 | ||||
-rw-r--r-- | c/src/lib/libchip/network/sonic.h (renamed from c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h) | 71 | ||||
-rw-r--r-- | c/src/lib/wrapup/Makefile.in | 1 | ||||
-rw-r--r-- | c/src/libchip/network/Makefile.in | 57 | ||||
-rw-r--r-- | c/src/libchip/network/README | 16 | ||||
-rw-r--r-- | c/src/libchip/network/README.sonic | 21 | ||||
-rw-r--r-- | c/src/libchip/network/sonic.c | 1629 | ||||
-rw-r--r-- | c/src/libchip/network/sonic.h | 416 | ||||
-rw-r--r-- | c/src/wrapup/Makefile.in | 1 |
17 files changed, 2445 insertions, 181 deletions
diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h b/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h index 34d15e59df..d0c5574348 100644 --- a/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h +++ b/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h @@ -48,9 +48,9 @@ extern "C" { * Network driver configuration */ struct rtems_bsdnet_ifconfig; -extern int rtems_sonic_driver_attach (struct rtems_bsdnet_ifconfig *config); +int rtems_dmv177_sonic_driver_attach(struct rtems_bsdnet_ifconfig *config); #define RTEMS_BSP_NETWORK_DRIVER_NAME "sonic1" -#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_sonic_driver_attach +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_dmv177_sonic_driver_attach /* diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in index b6c1bed0c4..bad013f7a2 100644 --- a/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in +++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in @@ -8,7 +8,7 @@ VPATH = @srcdir@ RTEMS_ROOT = @top_srcdir@ PROJECT_ROOT = @PROJECT_ROOT@ -PGM=${ARCH}/sonic.rel +PGM=${ARCH}/dmvsonic.rel # C source names, if any, go here -- minus the .c C_PIECES=sonic diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/dmvsonic.c b/c/src/lib/libbsp/powerpc/dmv177/sonic/dmvsonic.c new file mode 100644 index 0000000000..a068c74f31 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/dmvsonic.c @@ -0,0 +1,114 @@ +/* + * DMV177 SONIC Configuration Information + * + * References: + * + * 1) SVME/DMV-171 Single Board Computer Documentation Package, #805905, + * DY 4 Systems Inc., Kanata, Ontario, September, 1996. + * + * $Id$ + */ + +#include <bsp.h> +#include <rtems/rtems_bsdnet.h> +#include <libchip/sonic.h> + +void dmv177_sonic_write_register( + void *base, + unsigned32 regno, + unsigned32 value +) +{ + volatile unsigned32 *p = base; + +#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) + printf( "%p Write 0x%04x to %s (0x%02x)\n", + &p[regno], value, SONIC_Reg_name[regno], regno ); + fflush( stdout ); +#endif + p[regno] = value; +} + +unsigned32 dmv177_sonic_read_register( + void *base, + unsigned32 regno +) +{ + volatile unsigned32 *p = base; + unsigned32 value; + + value = p[regno]; +#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) + printf( "%p Read 0x%04x from %s (0x%02x)\n", + &p[regno], value, SONIC_Reg_name[regno], regno ); + fflush( stdout ); +#endif + return value; +} + +/* + * Default sizes of transmit and receive descriptor areas + */ +#define RDA_COUNT 20 /* 20 */ +#define TDA_COUNT 20 /* 10 */ + +/* + * Default device configuration register values + * Conservative, generic values. + * DCR: + * No extended bus mode + * Unlatched bus retry + * Programmable outputs unused + * Asynchronous bus mode + * User definable pins unused + * No wait states (access time controlled by DTACK*) + * 32-bit DMA + * Empty/Fill DMA mode + * Maximum Transmit/Receive FIFO + * DC2: + * Extended programmable outputs unused + * Normal HOLD request + * Packet compress output unused + * No reject on CAM match + */ +#define SONIC_DCR \ + (DCR_DW32 | DCR_WAIT0 | DCR_PO0 | DCR_PO1 | DCR_RFT24 | DCR_TFT28) +#ifndef SONIC_DCR +# define SONIC_DCR (DCR_DW32 | DCR_TFT28) +#endif +#ifndef SONIC_DC2 +# define SONIC_DC2 (0) +#endif + +/* + * Default location of device registers + */ +#ifndef SONIC_BASE_ADDRESS +# define SONIC_BASE_ADDRESS 0xF3000000 +# warning "Using default SONIC_BASE_ADDRESS." +#endif + +/* + * Default interrupt vector + */ +#ifndef SONIC_VECTOR +# define SONIC_VECTOR 1 +# warning "Using default SONIC_VECTOR." +#endif + +sonic_configuration_t dmv177_sonic_configuration = { + SONIC_BASE_ADDRESS, /* base address */ + SONIC_VECTOR, /* vector number */ + SONIC_DCR, /* DCR register value */ + SONIC_DC2, /* DC2 register value */ + TDA_COUNT, /* number of transmit descriptors */ + RDA_COUNT, /* number of receive descriptors */ + dmv177_sonic_write_register, + dmv177_sonic_read_register +}; + +int rtems_dmv177_sonic_driver_attach(struct rtems_bsdnet_ifconfig *config) +{ + return rtems_sonic_driver_attach( config, &dmv177_sonic_configuration ); + +} diff --git a/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in index 7119536c6a..c5f0464a06 100644 --- a/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in +++ b/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in @@ -9,7 +9,7 @@ RTEMS_ROOT = @top_srcdir@ PROJECT_ROOT = @PROJECT_ROOT@ # We only build the networking device driver if HAS_NETWORKING was defined -NETWORKING_DRIVER_yes_V = sonic +NETWORKING_DRIVER_yes_V = dmvsonic NETWORKING_DRIVER = $(NETWORKING_DRIVER_$(HAS_NETWORKING)_V) # pieces specific to this BSP diff --git a/c/src/lib/libchip/Makefile.in b/c/src/lib/libchip/Makefile.in index a5144ec02d..c1d0ffb462 100644 --- a/c/src/lib/libchip/Makefile.in +++ b/c/src/lib/libchip/Makefile.in @@ -11,4 +11,8 @@ PROJECT_ROOT = @PROJECT_ROOT@ include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg include $(RTEMS_ROOT)/make/directory.cfg -SUB_DIRS=rtc serial +# We only build the networking chip drivers if HAS_NETWORKING was defined +LIBNETWORKING_yes_V = network +LIBNETWORKING = $(LIBNETWORKING_$(HAS_NETWORKING)_V) + +SUB_DIRS=rtc serial $(LIBNETWORKING) diff --git a/c/src/lib/libchip/network/Makefile.in b/c/src/lib/libchip/network/Makefile.in new file mode 100644 index 0000000000..aaaf460aa1 --- /dev/null +++ b/c/src/lib/libchip/network/Makefile.in @@ -0,0 +1,57 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +LIBNAME=libnetchip.a +LIB=${ARCH}/${LIBNAME} + +C_PIECES=\ + sonic + +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +INSTALLED_H_FILES=$(srcdir)/sonic.h +SRCS=$(C_FILES) $(H_FILES) $(SYS_H_FILES) $(RTEMS_H_FILES) $(PRIVATE_H_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \ + -DDIAGNOSTIC -DBOOTP_COMPAT +CPPFLAGS += +CFLAGS += $(LIBC_DEFINES) + +# +# 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 += $(LIB) +CLOBBER_ADDITIONS += + +all: ${ARCH} preinstall $(LIB) + $(INSTALL_VARIANT) -m 644 ${LIB} ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + +# Install the library, appending _g or _p as appropriate. +# for include files, just use $(INSTALL) +preinstall: + $(INSTALL) -m 444 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/libchip + + diff --git a/c/src/lib/libchip/network/README b/c/src/lib/libchip/network/README new file mode 100644 index 0000000000..fd5853ef16 --- /dev/null +++ b/c/src/lib/libchip/network/README @@ -0,0 +1,16 @@ +# +# $Id$ +# + +This is the network interface controller portion of the libchip library. +This directory contains the source code for reusable TCP/IP network driver +support code. Each driver has its own configuration table and its +chip specific attach routine must be called by a board specific +attach routine. The board specific chip routine passes the chip +configuration and network configuration to the resuable device driver. + +The reusable chip drivers do not directly access the controller. +They access the registers on the controller via a set of +functions which are provided by the BSP. These functions set and get +general registers and data buffers. + diff --git a/c/src/lib/libchip/network/README.sonic b/c/src/lib/libchip/network/README.sonic new file mode 100644 index 0000000000..ef9641d6a2 --- /dev/null +++ b/c/src/lib/libchip/network/README.sonic @@ -0,0 +1,21 @@ +# +# $Id$ +# + +This SONIC driver does not make any attempt to support the SONIC chip +in any of the following modes: + + + 16-bit + + little endian + +It does not attempt to handle SONIC's older than Revision C. There is +a bug in chips before that revision that must be handled in the driver. + +The configuration table should be discussed here but if you look in the +include file for the sonic, it is reasonably obvious. :) + +The performance impact of transforming this driver into libchip format +was minimal. + +The powerpc/dmv177 BSP uses this driver and can serve as an example +configuration table. diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c b/c/src/lib/libchip/network/sonic.c index dd7cefe030..2dd8e32e79 100644 --- a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c +++ b/c/src/lib/libchip/network/sonic.c @@ -1,62 +1,33 @@ /* - ******************************************************************* - ******************************************************************* - ** ** - ** RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' ** - ** SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER ** - ** ** - ******************************************************************* - ******************************************************************* - */ - -/* - * $Revision$ $Date$ $Author$ - * $State$ - * $Id$ - */ - -/* + * RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' + * SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER + * + * REUSABLE CHIP DRIVER + * * References: - * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface - * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, - * 1995. * - * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), - * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, - * RRD-B30M75, National Semiconductor, March, 1991. + * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface + * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, + * 1995. * - * 3) SVME/DMV-171 Single Board Computer Documentation Package, #805905, - * DY 4 Systems Inc., Kanata, Ontario, September, 1996. + * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), + * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, + * RRD-B30M75, National Semiconductor, March, 1991. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ */ -#include <bsp.h> /* XXX JRS changed order */ -#include "sonic.h" +#include <rtems.h> #include <rtems/rtems_bsdnet.h> - -/***** CONFIGURATION ****/ -typedef void (*sonic_write_register_t)( - void *base, - unsigned32 regno, - unsigned32 value -); - -typedef unsigned32 (*sonic_read_register_t)( - void *base, - unsigned32 regno -); - -typedef struct { - unsigned32 base_address; - unsigned32 vector; - unsigned32 dcr_value; - unsigned32 dc2_value; - unsigned32 tda_count; - unsigned32 rda_count; - sonic_write_register_t write_register; - sonic_read_register_t read_register; -} sonic_configuration_t; - -/***** CONFIGURATION ****/ +#include <libchip/sonic.h> #include <stdio.h> @@ -75,6 +46,12 @@ typedef struct { #include <netinet/if_ether.h> /* + * XXX fix this + */ + +void *set_vector(void *, unsigned32, unsigned32); + +/* * Debug levels * */ @@ -108,12 +85,6 @@ typedef struct { #endif /* - * XXX - */ - -#include <dmv170.h> - -/* * Use the top line if you want more symbols. */ @@ -1499,7 +1470,7 @@ sonic_ioctl (struct ifnet *ifp, int command, caddr_t data) */ int -rtems_sonic_driver_attach_chip ( +rtems_sonic_driver_attach ( struct rtems_bsdnet_ifconfig *config, sonic_configuration_t *chip ) @@ -1656,106 +1627,3 @@ char SONIC_Reg_name[64][6]= { "DCR2" /* 0x3F */ }; #endif - -void dmv177_sonic_write_register( - void *base, - unsigned32 regno, - unsigned32 value -) -{ - volatile unsigned32 *p = base; - -#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) - printf( "%p Write 0x%04x to %s (0x%02x)\n", - &p[regno], value, SONIC_Reg_name[regno], regno ); - fflush( stdout ); -#endif - p[regno] = value; -} - -unsigned32 dmv177_sonic_read_register( - void *base, - unsigned32 regno -) -{ - volatile unsigned32 *p = base; - unsigned32 value; - - value = p[regno]; -#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) - printf( "%p Read 0x%04x from %s (0x%02x)\n", - &p[regno], value, SONIC_Reg_name[regno], regno ); - fflush( stdout ); -#endif - return value; -} -/******** DMV177 SPECIFIC INFORMATION ***********/ -/* - * Default sizes of transmit and receive descriptor areas - */ -#define RDA_COUNT 20 /* 20 */ -#define TDA_COUNT 20 /* 10 */ - -/* - * Default device configuration register values - * Conservative, generic values. - * DCR: - * No extended bus mode - * Unlatched bus retry - * Programmable outputs unused - * Asynchronous bus mode - * User definable pins unused - * No wait states (access time controlled by DTACK*) - * 32-bit DMA - * Empty/Fill DMA mode - * Maximum Transmit/Receive FIFO - * DC2: - * Extended programmable outputs unused - * Normal HOLD request - * Packet compress output unused - * No reject on CAM match - */ -#define SONIC_DCR \ - (DCR_DW32 | DCR_WAIT0 | DCR_PO0 | DCR_PO1 | DCR_RFT24 | DCR_TFT28) -#ifndef SONIC_DCR -# define SONIC_DCR (DCR_DW32 | DCR_TFT28) -#endif -#ifndef SONIC_DC2 -# define SONIC_DC2 (0) -#endif - -/* - * Default location of device registers - */ -#ifndef SONIC_BASE_ADDRESS -# define SONIC_BASE_ADDRESS 0xF3000000 -# warning "Using default SONIC_BASE_ADDRESS." -#endif - -/* - * Default interrupt vector - */ -#ifndef SONIC_VECTOR -# define SONIC_VECTOR 1 -# warning "Using default SONIC_VECTOR." -#endif - -sonic_configuration_t dmv177_sonic_configuration = { - SONIC_BASE_ADDRESS, /* base address */ - SONIC_VECTOR, /* vector number */ - SONIC_DCR, /* DCR register value */ - SONIC_DC2, /* DC2 register value */ - TDA_COUNT, /* number of transmit descriptors */ - RDA_COUNT, /* number of receive descriptors */ - dmv177_sonic_write_register, - dmv177_sonic_read_register -}; - -int rtems_sonic_driver_attach (struct rtems_bsdnet_ifconfig *config) -{ - return rtems_sonic_driver_attach_chip ( config, &dmv177_sonic_configuration ); - -} - -/******** DMV177 SPECIFIC INFORMATION ***********/ - diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h b/c/src/lib/libchip/network/sonic.h index 7ce0eccebb..47f50d3356 100644 --- a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h +++ b/c/src/lib/libchip/network/sonic.h @@ -1,24 +1,58 @@ /* - ******************************************************************. - ******************************************************************* - ** ** - ** DECLARATIONS FOR NATIONAL DP83932 `SONIC' ** - ** SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER ** - ** ** - ******************************************************************* - ******************************************************************* + * RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' + * SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER + * + * REUSABLE CHIP DRIVER CONFIGURATION + * + * References: + * + * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface + * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, + * 1995. + * + * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), + * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, + * RRD-B30M75, National Semiconductor, March, 1991. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ */ +#ifndef _SONIC_DP83932_ +#define _SONIC_DP83932_ + /* - * $Revision$ $Date$ $Author$ - * $State$ - * $Id$ + * Configuration Information */ -#ifndef _SONIC_DP83932_ -#define _SONIC_DP83932_ +typedef void (*sonic_write_register_t)( + void *base, + unsigned32 regno, + unsigned32 value +); -#include <bsp.h> +typedef unsigned32 (*sonic_read_register_t)( + void *base, + unsigned32 regno +); + +typedef struct { + unsigned32 base_address; + unsigned32 vector; + unsigned32 dcr_value; + unsigned32 dc2_value; + unsigned32 tda_count; + unsigned32 rda_count; + sonic_write_register_t write_register; + sonic_read_register_t read_register; +} sonic_configuration_t; /* ****************************************************************** @@ -370,4 +404,13 @@ typedef volatile CamDescriptor_t *CamDescriptorPointer_t; /* and the driver can process it */ #define RDA_FREE 0xFFFF /* SONIC can use it */ +/* + * Attatch routine + */ + +int rtems_sonic_driver_attach ( + struct rtems_bsdnet_ifconfig *config, + sonic_configuration_t *chip +); + #endif /* _SONIC_DP83932_ */ diff --git a/c/src/lib/wrapup/Makefile.in b/c/src/lib/wrapup/Makefile.in index 5e73848490..d3e0f76ac9 100644 --- a/c/src/lib/wrapup/Makefile.in +++ b/c/src/lib/wrapup/Makefile.in @@ -24,6 +24,7 @@ SRCS=$(wildcard $(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libcpu$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/librtcio$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libserialio$(LIB_VARIANT).a) \ + $(wildcard $(PROJECT_RELEASE)/lib/libnetchip$(LIB_VARIANT).a) \ $(PROJECT_RELEASE)/lib/libcsupport$(LIB_VARIANT).a \ $(PROJECT_RELEASE)/lib/libmisc$(LIB_VARIANT).a \ $(wildcard $(PROJECT_RELEASE)/lib/rtems-ctor$(LIB_VARIANT).o) \ diff --git a/c/src/libchip/network/Makefile.in b/c/src/libchip/network/Makefile.in new file mode 100644 index 0000000000..aaaf460aa1 --- /dev/null +++ b/c/src/libchip/network/Makefile.in @@ -0,0 +1,57 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +LIBNAME=libnetchip.a +LIB=${ARCH}/${LIBNAME} + +C_PIECES=\ + sonic + +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +INSTALLED_H_FILES=$(srcdir)/sonic.h +SRCS=$(C_FILES) $(H_FILES) $(SYS_H_FILES) $(RTEMS_H_FILES) $(PRIVATE_H_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \ + -DDIAGNOSTIC -DBOOTP_COMPAT +CPPFLAGS += +CFLAGS += $(LIBC_DEFINES) + +# +# 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 += $(LIB) +CLOBBER_ADDITIONS += + +all: ${ARCH} preinstall $(LIB) + $(INSTALL_VARIANT) -m 644 ${LIB} ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + +# Install the library, appending _g or _p as appropriate. +# for include files, just use $(INSTALL) +preinstall: + $(INSTALL) -m 444 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/libchip + + diff --git a/c/src/libchip/network/README b/c/src/libchip/network/README new file mode 100644 index 0000000000..fd5853ef16 --- /dev/null +++ b/c/src/libchip/network/README @@ -0,0 +1,16 @@ +# +# $Id$ +# + +This is the network interface controller portion of the libchip library. +This directory contains the source code for reusable TCP/IP network driver +support code. Each driver has its own configuration table and its +chip specific attach routine must be called by a board specific +attach routine. The board specific chip routine passes the chip +configuration and network configuration to the resuable device driver. + +The reusable chip drivers do not directly access the controller. +They access the registers on the controller via a set of +functions which are provided by the BSP. These functions set and get +general registers and data buffers. + diff --git a/c/src/libchip/network/README.sonic b/c/src/libchip/network/README.sonic new file mode 100644 index 0000000000..ef9641d6a2 --- /dev/null +++ b/c/src/libchip/network/README.sonic @@ -0,0 +1,21 @@ +# +# $Id$ +# + +This SONIC driver does not make any attempt to support the SONIC chip +in any of the following modes: + + + 16-bit + + little endian + +It does not attempt to handle SONIC's older than Revision C. There is +a bug in chips before that revision that must be handled in the driver. + +The configuration table should be discussed here but if you look in the +include file for the sonic, it is reasonably obvious. :) + +The performance impact of transforming this driver into libchip format +was minimal. + +The powerpc/dmv177 BSP uses this driver and can serve as an example +configuration table. diff --git a/c/src/libchip/network/sonic.c b/c/src/libchip/network/sonic.c new file mode 100644 index 0000000000..2dd8e32e79 --- /dev/null +++ b/c/src/libchip/network/sonic.c @@ -0,0 +1,1629 @@ +/* + * RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' + * SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER + * + * REUSABLE CHIP DRIVER + * + * References: + * + * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface + * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, + * 1995. + * + * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), + * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, + * RRD-B30M75, National Semiconductor, March, 1991. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <rtems/rtems_bsdnet.h> +#include <libchip/sonic.h> + +#include <stdio.h> + +#include <errno.h> +#include <rtems/error.h> + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/sockio.h> + +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +/* + * XXX fix this + */ + +void *set_vector(void *, unsigned32, unsigned32); + +/* + * Debug levels + * + */ + +#define SONIC_DEBUG_NONE 0x0000 +#define SONIC_DEBUG_ALL 0xFFFF +#define SONIC_DEBUG_PRINT_REGISTERS 0x0001 +#define SONIC_DEBUG_MEMORY 0x0002 +#define SONIC_DEBUG_MEMORY_ALLOCATE 0x0004 +#define SONIC_DEBUG_MEMORY_DESCRIPTORS 0x0008 +#define SONIC_DEBUG_FRAGMENTS 0x0008 +#define SONIC_DEBUG_CAM 0x0010 +#define SONIC_DEBUG_DESCRIPTORS 0x0020 +#define SONIC_DEBUG_ERRORS 0x0040 +#define SONIC_DEBUG_DUMP_TX_MBUFS 0x0080 +#define SONIC_DEBUG_DUMP_RX_MBUFS 0x0100 + +#define SONIC_DEBUG_DUMP_MBUFS \ + (SONIC_DEBUG_DUMP_TX_MBUFS|SONIC_DEBUG_DUMP_RX_MBUFS) + +#define SONIC_DEBUG (SONIC_DEBUG_ERRORS) + +/* + ((SONIC_DEBUG_ALL) & ~(SONIC_DEBUG_PRINT_REGISTERS|SONIC_DEBUG_DUMP_MBUFS)) + ((SONIC_DEBUG_ALL) & ~(SONIC_DEBUG_DUMP_MBUFS)) +*/ + + +#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_MBUFS) +#include <rtems/dumpbuf.h> +#endif + +/* + * Use the top line if you want more symbols. + */ + +#define SONIC_STATIC +/* #define SONIC_STATIC static */ + +/* + * Number of devices supported by this driver + */ +#ifndef NSONIC +# define NSONIC 1 +#endif + +/* + * + * As suggested by National Application Note 746, make the + * receive resource area bigger than the receive descriptor area. + * + * NOTE: Changing this may break this driver since it currently + * assumes a 1<->1 mapping. + */ +#define RRA_EXTRA_COUNT 0 + +/* + * RTEMS event used by interrupt handler to signal daemons. + */ +#define INTERRUPT_EVENT RTEMS_EVENT_1 + +/* + * RTEMS event used to start transmit daemon. + * This must not be the same as INTERRUPT_EVENT. + */ +#define START_TRANSMIT_EVENT RTEMS_EVENT_2 + +/* + * Largest Ethernet frame. + */ +#define MAXIMUM_FRAME_SIZE 1518 + +/* + * Receive buffer size. + * Allow for a pointer, plus a full ethernet frame (including Frame + * Check Sequence) rounded up to a 4-byte boundary. + */ +#define RBUF_SIZE ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3) +/* #define RBUF_WC ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2) */ +#define RBUF_WC (RBUF_SIZE / 2) + +/* + * Macros for manipulating 32-bit pointers as 16-bit fragments + */ +#define LSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p))) +#define MSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16)) +#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l))) + +/* + * Hardware-specific storage + */ +struct sonic_softc { + /* + * Connection to networking code + * This entry *must* be the first in the sonic_softc structure. + */ + struct arpcom arpcom; + + /* + * Default location of device registers + * ===CACHE=== + * This area must be non-cacheable, guarded. + */ + void *sonic; + + /* + * Register access routines + */ + sonic_write_register_t write_register; + sonic_read_register_t read_register; + + /* + * Interrupt vector + */ + rtems_vector_number vector; + + /* + * Data Configuration Register values + */ + rtems_unsigned32 dcr_value; + rtems_unsigned32 dc2_value; + + /* + * Indicates configuration + */ + int acceptBroadcast; + + /* + * Task waiting for interrupts + */ + rtems_id rxDaemonTid; + rtems_id txDaemonTid; + + /* + * Receive resource area + */ + int rdaCount; + ReceiveResourcePointer_t rsa; + ReceiveResourcePointer_t rea; + CamDescriptorPointer_t cdp; + ReceiveDescriptorPointer_t rda; + ReceiveDescriptorPointer_t rdp_last; + + /* + * Transmit descriptors + */ + int tdaCount; + TransmitDescriptorPointer_t tdaHead; /* Last filled */ + TransmitDescriptorPointer_t tdaTail; /* Next to retire */ + int tdaActiveCount; + + /* + * Statistics + */ + unsigned long Interrupts; + unsigned long rxInterrupts; + unsigned long rxMissed; + unsigned long rxGiant; + unsigned long rxNonOctet; + unsigned long rxBadCRC; + unsigned long rxCollision; + + unsigned long txInterrupts; + unsigned long txSingleCollision; + unsigned long txMultipleCollision; + unsigned long txCollision; + unsigned long txDeferred; + unsigned long txUnderrun; + unsigned long txLateCollision; + unsigned long txExcessiveCollision; + unsigned long txExcessiveDeferral; + unsigned long txLostCarrier; + unsigned long txRawWait; +}; +SONIC_STATIC struct sonic_softc sonic_softc[NSONIC]; + + +/* + ****************************************************************** + * * + * Debug Routines * + * * + ****************************************************************** + */ + +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) +void sonic_print_tx_descriptor( + TransmitDescriptorPointer_t tdp +) +{ + printf( "TXD ==> %p", tdp ); + printf( " pkt_config = 0x%04x", tdp->pkt_config & 0xffff); + printf( " pkt_size = 0x%04x\n", tdp->pkt_size & 0xffff ); + printf( " frag_count = %d", tdp->frag_count & 0xffff ); + /* could print all the fragments */ + printf( " next = %p", tdp->next ); + printf( " linkp = %p\n", tdp->linkp ); + printf( " mbufp = %p", tdp->mbufp ); + if ( tdp->mbufp ) + printf( " mbufp->data = %p", mtod ( tdp->mbufp, void *) ); + puts(""); +} + +void sonic_print_rx_descriptor( + ReceiveDescriptorPointer_t rdp +) +{ + printf( "RXD ==> %p\n", rdp ); + printf( " status = 0x%04x", rdp->status & 0xffff ); + printf( " byte_count = 0x%04x\n", rdp->byte_count & 0xffff ); + printf( " pkt = 0x%04x%04x", rdp->pkt_msw, rdp->pkt_lsw ); + printf( " seq_no = %d", rdp->seq_no ); + printf( " link = %d\n", rdp->link ); + printf( " in_use = %d", rdp->in_use ); + printf( " next = %p", rdp->next ); + printf( " mbufp = %p", rdp->mbufp ); + if ( rdp->mbufp ) + printf( " mbufp->data = %p", mtod ( rdp->mbufp, void *) ); + puts(""); +} +#endif + +/* + ****************************************************************** + * * + * Support Routines * + * * + ****************************************************************** + */ + +void sonic_enable_interrupts( + struct sonic_softc *sc, + unsigned32 mask +) +{ + void *rp = sc->sonic; + rtems_interrupt_level level; + + rtems_interrupt_disable( level ); + (*sc->write_register)( + rp, + SONIC_REG_IMR, + (*sc->read_register)(rp, SONIC_REG_IMR) | mask + ); + rtems_interrupt_enable( level ); +} + +/* + * Allocate non-cacheable memory on a single 64k page. + * Very simple minded -- just keeps trying till the memory is on a single page. + */ +SONIC_STATIC void * sonic_allocate(unsigned int nbytes) +{ + void *p; + unsigned long a1, a2; + + for (;;) { + /* + * ===CACHE=== + * Change malloc to malloc_noncacheable_guarded. + */ + p = malloc( nbytes, M_MBUF, M_NOWAIT ); + if (p == NULL) + rtems_panic ("No memory!"); + memset (p, '\0', nbytes); + a1 = (unsigned long)p; + a2 = a1 + nbytes - 1; + if ((a1 >> 16) == (a2 >> 16)) + break; + } +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_ALLOCATE) + printf( "sonic_allocate %d bytes at %p\n", nbytes, p ); +#endif + return p; +} + +/* + * Shut down the interface. + */ + +SONIC_STATIC void sonic_stop (struct sonic_softc *sc) +{ + void *rp = sc->sonic; + struct ifnet *ifp = &sc->arpcom.ac_if; + + ifp->if_flags &= ~IFF_RUNNING; + + /* + * Stop the transmitter and receiver. + */ + (*sc->write_register)( rp, SONIC_REG_CR, CR_HTX | CR_RXDIS ); +} + +/* + * Show interface statistics + */ +SONIC_STATIC void sonic_stats (struct sonic_softc *sc) +{ + printf (" Total Interrupts:%-8lu", sc->Interrupts); + printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); + printf (" Giant:%-8lu", sc->rxGiant); + printf (" Non-octet:%-8lu\n", sc->rxNonOctet); + printf (" Bad CRC:%-8lu", sc->rxBadCRC); + printf (" Collision:%-8lu", sc->rxCollision); + printf (" Missed:%-8lu\n", sc->rxMissed); + + printf ( " Tx Interrupts:%-8lu", sc->txInterrupts); + printf ( " Deferred:%-8lu", sc->txDeferred); + printf (" Lost Carrier:%-8lu\n", sc->txLostCarrier); + printf ( "Single Collisions:%-8lu", sc->txSingleCollision); + printf ( "Multiple Collisions:%-8lu", sc->txMultipleCollision); + printf ("Excessive Collisions:%-8lu\n", sc->txExcessiveCollision); + printf ( " Total Collisions:%-8lu", sc->txCollision); + printf ( " Late Collision:%-8lu", sc->txLateCollision); + printf (" Underrun:%-8lu\n", sc->txUnderrun); + printf ( " Raw output wait:%-8lu\n", sc->txRawWait); +} + +/* + ****************************************************************** + * * + * Interrupt Handler * + * * + ****************************************************************** + */ + +SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v) +{ + struct sonic_softc *sc = sonic_softc; + unsigned32 isr, imr; + void *rp; + +#if (NSONIC > 1) + /* + * Find the device which requires service + */ + for (;;) { + if (sc->vector == v) + break; + if (++sc == &sonic[NSONIC]) + return; /* Spurious interrupt? */ + } +#endif /* NSONIC > 1 */ + + /* + * Get pointer to SONIC registers + */ + rp = sc->sonic; + + sc->Interrupts++; + + isr = (*sc->read_register)( rp, SONIC_REG_ISR ); + imr = (*sc->read_register)( rp, SONIC_REG_IMR ); + + /* + * Packet received or receive buffer area exceeded? + */ + if ((imr & (IMR_PRXEN | IMR_RBAEEN)) && + (isr & (ISR_PKTRX | ISR_RBAE))) { + imr &= ~(IMR_PRXEN | IMR_RBAEEN); + sc->rxInterrupts++; + rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT); + } + + /* + * Packet started, transmitter done or transmitter error? + */ + if ((imr & (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)) && + (isr & (ISR_PINT | ISR_TXDN | ISR_TXER))) { + imr &= ~(IMR_PINTEN | IMR_PTXEN | IMR_TXEREN); + sc->txInterrupts++; + rtems_event_send (sc->txDaemonTid, INTERRUPT_EVENT); + } + + (*sc->write_register)( rp, SONIC_REG_IMR, imr ); +} + +/* + ****************************************************************** + * * + * Transmitter Routines * + * * + ****************************************************************** + */ + +/* + * Soak up transmit descriptors that have been sent. + */ + +SONIC_STATIC void sonic_retire_tda (struct sonic_softc *sc) +{ + rtems_unsigned16 status; + unsigned int collisions; + struct mbuf *m, *n; + + /* + * Repeat for all completed transmit descriptors. + */ + while ((sc->tdaActiveCount != 0) + && ((status = sc->tdaTail->status) != 0)) { + +#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) + printf( "retire TDA %p (0x%04x)\n", sc->tdaTail, status ); +#endif + +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + /* + * If there is an error that was not a collision, + * then someone may want to see it. + */ + + if ( (status & ~(TDA_STATUS_COLLISION_MASK|TDA_STATUS_DEF)) != 0x0001 ) + printf( "ERROR: retire TDA %p (0x%08x)\n", + sc->tdaTail, sc->tdaTail->status ); +#endif + + /* + * Check for errors which stop the transmitter. + */ + if (status & (TDA_STATUS_EXD | + TDA_STATUS_EXC | + TDA_STATUS_FU | + TDA_STATUS_BCM)) { + /* + * Restart the transmitter if there are + * packets waiting to go. + */ + rtems_unsigned16 link; +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + printf("restarting sonic after error\n"); +#endif + + link = *(sc->tdaTail->linkp); + + if ((link & TDA_LINK_EOL) == 0) { + void *rp = sc->sonic; + + (*sc->write_register)( rp, SONIC_REG_CTDA, link ); + (*sc->write_register)( rp, SONIC_REG_CR, CR_TXP ); + } + } + + /* + * Update network statistics + */ + collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT; + if (collisions) { + if (collisions == 1) + sc->txSingleCollision++; + else + sc->txMultipleCollision++; + sc->txCollision += collisions; + } + if (status & TDA_STATUS_EXC) + sc->txExcessiveCollision++; + if (status & TDA_STATUS_OWC) + sc->txLateCollision++; + if (status & TDA_STATUS_EXD) + sc->txExcessiveDeferral++; + if (status & TDA_STATUS_DEF) + sc->txDeferred++; + if (status & TDA_STATUS_FU) + sc->txUnderrun++; + if (status & TDA_STATUS_CRSL) + sc->txLostCarrier++; + + /* + * Free the packet and reset a couple of fields + */ + sc->tdaActiveCount--; + m = sc->tdaTail->mbufp; + while ( m ) { + MFREE(m, n); + m = n; + } + + sc->tdaTail->frag[0].frag_link = LSW(sc->tdaTail->link_pad); + sc->tdaTail->frag_count = 0; + + /* + * Move to the next transmit descriptor + */ + sc->tdaTail = sc->tdaTail->next; +#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) + printf( "next TDA %p\n", sc->tdaTail ); +#endif + } +} + +/* + * Send packet + */ +SONIC_STATIC void sonic_sendpacket (struct ifnet *ifp, struct mbuf *m) +{ + struct sonic_softc *sc = ifp->if_softc; + void *rp = sc->sonic; + struct mbuf *l = NULL; + TransmitDescriptorPointer_t tdp; + volatile struct TransmitDescriptorFragLink *fp; + unsigned int packetSize; + int i; + static char padBuf[64]; + + /* printf( "sonic_sendpacket %p\n", m ); */ + /* + * Free up transmit descriptors. + */ + sonic_retire_tda (sc); + + /* + * Wait for transmit descriptor to become available. + */ + if (sc->tdaActiveCount == sc->tdaCount) { +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + puts( "Wait for more TDAs" ); +#endif + + /* + * Clear old events. + */ + (*sc->write_register)( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER ); + + /* + * Wait for transmit descriptor to become available. + * Note that the transmit descriptors are checked + * *before* * entering the wait loop -- this catches + * the possibility that a transmit descriptor became + * available between the `if' the started this block, + * and the clearing of the interrupt status register. + */ + sonic_retire_tda (sc); + while (sc->tdaActiveCount == sc->tdaCount) { + rtems_event_set events; + +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + printf("blocking until TDAs are available\n"); +#endif + /* + * Enable transmitter interrupts. + */ + sonic_enable_interrupts( sc, (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN) ); + + /* + * Wait for interrupt + */ + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + (*sc->write_register)( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER ); + sonic_retire_tda (sc); + } + } + + /* + * Fill in the transmit descriptor fragment descriptors. + * ===CACHE=== + * If data cache is operating in write-back mode, flush cached + * data to memory. + */ + tdp = sc->tdaHead->next; + tdp->mbufp = m; + packetSize = 0; + fp = tdp->frag; + for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) { + /* + * Throw away empty mbufs + */ + if (m->m_len) { + void *p = mtod (m, void *); + fp->frag_lsw = LSW(p); + fp->frag_msw = MSW(p); + fp->frag_size = m->m_len; + packetSize += m->m_len; +#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS) + printf( "fp %p 0x%04x%04x %d=%d .. %d\n", + fp, fp->frag_msw, fp->frag_lsw, fp->frag_size, m->m_len, packetSize ); +#endif +#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_TX_MBUFS) + Dump_Buffer( + p, + (fp->frag_size > MAXIMUM_FRAME_SIZE) ? MAXIMUM_FRAME_SIZE : fp->frag_size + ); +#endif + l = m; + m = m->m_next; + } + else { + struct mbuf *n; + MFREE (m, n); + m = n; + if (l != NULL) + l->m_next = m; + } + /* + * Break out of the loop if this mbuf is the last in the frame. + */ + if (m == NULL) + break; + } + + /* + * Pad short packets. + */ + if ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) { + int padSize = 64 - packetSize; + fp++; + fp->frag_lsw = LSW(padBuf); + fp->frag_msw = MSW(padBuf); + fp->frag_size = padSize; +#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS) + printf( "PAD fp %p 0x%04x%04x %d\n", + fp, fp->frag_msw, fp->frag_lsw, fp->frag_size ); +#endif + packetSize += padSize; + i++; + } + + /* + * Fill Transmit Descriptor + */ + tdp->pkt_size = packetSize; + tdp->frag_count = i + 1; + tdp->status = 0; + + /* + * Chain onto list and start transmission. + */ + + tdp->linkp = &(fp+1)->frag_link; + *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL; + if ( sc->tdaHead->frag_count ) + *sc->tdaHead->linkp &= ~TDA_LINK_EOL; + sc->tdaActiveCount++; + sc->tdaHead = tdp; + +/* XXX not in KA9Q */ + sonic_enable_interrupts( sc, (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN) ); + (*sc->write_register)( rp, SONIC_REG_CR, CR_TXP ); +} + +/* + * Driver transmit daemon + */ +SONIC_STATIC void sonic_txDaemon (void *arg) +{ + struct sonic_softc *sc = (struct sonic_softc *)arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mbuf *m; + rtems_event_set events; + + for (;;) { + /* + * Wait for packet + */ + rtems_bsdnet_event_receive ( + START_TRANSMIT_EVENT, + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &events + ); + + /* + * Send packets till queue is empty + */ + for (;;) { + /* + * Get the next mbuf chain to transmit. + */ + IF_DEQUEUE(&ifp->if_snd, m); + if (!m) + break; + sonic_sendpacket (ifp, m); + } + ifp->if_flags &= ~IFF_OACTIVE; + } +} + +/* + ****************************************************************** + * * + * Receiver Routines * + * * + ****************************************************************** + */ + +/* + * Wait for SONIC to hand over a Receive Descriptor. + */ + +SONIC_STATIC void sonic_rda_wait( + struct sonic_softc *sc, + ReceiveDescriptorPointer_t rdp +) +{ + int i; + void *rp = sc->sonic; + rtems_event_set events; + + /* + * Wait for Receive Descriptor. + * The order of the tests is very important. + * The RDA is checked after RBAE is detected. This ensures that + * the driver processes all RDA entries before reusing the RRA + * entry holding the giant packet. + * The event wait is done after the RDA and RBAE checks. This + * catches the possibility that a Receive Descriptor became ready + * between the call to this function and the clearing of the + * interrupt status register bit. + */ + for (;;) { + /* + * Has a giant packet arrived? + * The National DP83932C data sheet is very vague on what + * happens under this condition. The description of the + * Interrupt Status Register (Section 4.3.6) states, + * ``Reception is aborted and the SONIC fetches the next + * available resource descriptors in the RRA. The buffer + * space is not re-used and an RDA is not setup for the + * truncated packet.'' + * I take ``Reception is aborted'' to mean that the RXEN + * bit in the Command Register is cleared and must be set + * by the driver to begin reception again. + * Unfortunately, an alternative interpretation could be + * that only reception of the current packet is aborted. + * This would be more difficult to recover from.... + */ + if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBAE) { + +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + printf( "ERROR: looks like a giant packet -- RBAE\n" ); +#endif + + /* + * One more check to soak up any Receive Descriptors + * that may already have been handed back to the driver. + */ + if (rdp->in_use == RDA_IN_USE) { +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + printf( "ERROR: nope just an RBAE\n" ); +#endif + break; + } + + /* + * Check my interpretation of the SONIC manual. + */ + if ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RXEN) + rtems_panic ("SONIC RBAE/RXEN"); + + /* + * Update statistics + */ + sc->rxGiant++; + + /* + * Reuse receive buffer. + * Again, the manual is subject to interpretation. The + * RRP register is described as, `the lower address of + * the next descriptor the SONIC will read.'' + * Since, acording to the ISR/RBAE notes, the SONIC has + * ``fetched the next available resource descriptor in + * the RRA'', I interpret this to mean that that the + * driver has to move the RRP back *two* entries to + * reuse the receive buffer holding the giant packet. + */ + for (i = 0 ; i < 2 ; i++) { + if ((*sc->read_register)( rp, SONIC_REG_RRP ) == + (*sc->read_register)( rp, SONIC_REG_RSA )) + (*sc->write_register)( + rp, + SONIC_REG_RRP, + (*sc->read_register)( rp, SONIC_REG_REA ) + ); + (*sc->write_register)( + rp, + SONIC_REG_RRP, + (*sc->read_register)(rp, SONIC_REG_RRP) - sizeof(ReceiveResource_t) + ); + } + + /* + * Restart reception + */ + (*sc->write_register)( rp, SONIC_REG_ISR, ISR_RBAE ); + (*sc->write_register)( rp, SONIC_REG_CR, CR_RXEN ); + } + + /* + * Clear old packet-received events. + */ + (*sc->write_register)( rp, SONIC_REG_ISR, ISR_PKTRX ); + + /* + * Has Receive Descriptor become available? + */ + if (rdp->in_use == RDA_IN_USE) + break; + + /* + * Enable interrupts. + */ + sonic_enable_interrupts( sc, (IMR_PRXEN | IMR_RBAEEN) ); + + /* + * Wait for interrupt. + */ + rtems_bsdnet_event_receive( + INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events + ); + } +#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) + printf( "RDA %p\n", rdp ); +#endif + +#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) + if (rdp->status & 0x000E) + printf( "ERROR: RDA %p (0x%04x)\n", rdp, rdp->status ); +#endif + +} + +/* + * SONIC reader task + */ +SONIC_STATIC void sonic_rxDaemon (void *arg) +{ + struct sonic_softc *sc = (struct sonic_softc *)arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + void *rp = sc->sonic; + struct mbuf *m; + rtems_unsigned16 status; + ReceiveDescriptorPointer_t rdp; + ReceiveResourcePointer_t rwp, rea; + rtems_unsigned16 newMissedTally, oldMissedTally; + + rwp = sc->rsa; + rea = sc->rea; + rdp = sc->rda; + + /* + * Start the receiver + */ + oldMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT ); + + /* + * Input packet handling loop + */ + for (;;) { + /* + * Wait till SONIC supplies a Receive Descriptor. + */ + if (rdp->in_use == RDA_FREE) { + sonic_rda_wait (sc, rdp); + } + +#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) + printf( "Incoming packet %p status=0x%04x\n", rdp, rdp->status ); +#endif + + /* + * Check that packet is valid + */ + status = rdp->status; + if (status & RDA_STATUS_PRX) { + struct ether_header *eh; + void *p; + + /* + * Pass the packet up the chain. + * The mbuf count is reduced to remove + * the frame check sequence at the end + * of the packet. + * ===CACHE=== + * Invalidate cache entries for this memory. + */ +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) + sonic_print_rx_descriptor( rdp ); +#endif + m = rdp->mbufp; + m->m_len = m->m_pkthdr.len = rdp->byte_count - + sizeof(rtems_unsigned32) - + sizeof(struct ether_header); + eh = mtod (m, struct ether_header *); + m->m_data += sizeof(struct ether_header); + +#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_RX_MBUFS) + Dump_Buffer( (void *) eh, sizeof(struct ether_header) ); + Dump_Buffer( (void *) m, 96 /* m->m_len*/ ); +#endif + + /* printf( "ether_input %p\n", m ); */ + ether_input (ifp, eh, m); + + /* + * Sanity check that Receive Resource Area is + * still in sync with Receive Descriptor Area + * The buffer reported in the Receive Descriptor + * should be the same as the buffer in the Receive + * Resource we are about to reuse. + */ +/* XXX figure out whether this is valid or not */ +#if 0 + if ((LSW(p) != rwp->buff_ptr_lsw) + || (MSW(p) != rwp->buff_ptr_msw)) + rtems_panic ("SONIC RDA/RRA"); +#endif + + /* + * Allocate a new mbuf. + */ + + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + rdp->mbufp = m; + p = mtod (m, void *); + + /* + * Reuse Receive Resource. + */ + + rwp->buff_ptr_lsw = LSW(p); + rwp->buff_ptr_msw = MSW(p); + rwp->buff_wc_lsw = RBUF_WC; + rwp->buff_wc_msw = 0; + rwp++; + + if (rwp == rea) { +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) + printf( "Wrapping RWP from %p to %p\n", rwp, sc->rsa ); +#endif + rwp = sc->rsa; + } + (*sc->write_register)( rp, SONIC_REG_RWP , LSW(rwp) ); + + /* + * Tell the SONIC to reread the RRA. + */ + if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBE) + (*sc->write_register)( rp, SONIC_REG_ISR, ISR_RBE ); + } + else { + if (status & RDA_STATUS_COL) + sc->rxCollision++; + if (status & RDA_STATUS_FAER) + sc->rxNonOctet++; + else if (status & RDA_STATUS_CRCR) + sc->rxBadCRC++; + } + + /* + * Count missed packets + */ + newMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT ); + if (newMissedTally != oldMissedTally) { + sc->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF; + newMissedTally = oldMissedTally; + } + + /* + * Move to next receive descriptor + */ + + rdp->in_use = RDA_FREE; + rdp = rdp->next; + rdp->link &= ~RDA_LINK_EOL; + + } +} + +/* + ****************************************************************** + * * + * Initialization Routines * + * * + ****************************************************************** + */ + +/* + * Initialize the SONIC hardware + */ +SONIC_STATIC void sonic_initialize_hardware(struct sonic_softc *sc) +{ + void *rp = sc->sonic; + int i; + unsigned char *hwaddr; + rtems_isr_entry old_handler; + TransmitDescriptorPointer_t tdp; + ReceiveDescriptorPointer_t ordp, rdp; + ReceiveResourcePointer_t rwp; + struct mbuf *m; + void *p; + CamDescriptorPointer_t cdp; + + /* + * The Revision B SONIC has a horrible bug known as the "Zero + * Length Packet bug". The initial board used to develop this + * driver had a newer revision of the SONIC so there was no reason + * to check for this. If you have the Revision B SONIC chip, then + * you need to add some code to the RX path to handle this weirdness. + */ + + if ( (*sc->read_register)( rp, SONIC_REG_SR ) < SONIC_REVISION_C ) { + rtems_fatal_error_occurred( 0x0BADF00D ); /* don't eat this part :) */ + } + + /* + * Set up circular linked list in Transmit Descriptor Area. + * Use the PINT bit in the transmit configuration field to + * request an interrupt on every other transmitted packet. + * + * NOTE: sonic_allocate() zeroes all of the memory allocated. + */ + + sc->tdaActiveCount = 0; + sc->tdaTail = sonic_allocate(sc->tdaCount * sizeof *tdp); +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) + printf( "tdaTail = %p\n", sc->tdaTail ); +#endif + tdp = sc->tdaTail; + for (i = 0 ; i < sc->tdaCount ; i++) { + /* + * Start off with the table of outstanding mbuf's + */ + + /* + * status, pkt_config, pkt_size, and all fragment fields + * are set to zero by sonic_allocate. + */ + +/* XXX not used by the BSD drivers +*/ + if (i & 1) + tdp->pkt_config = TDA_CONFIG_PINT; + + tdp->frag_count = 0; + tdp->frag[0].frag_link = LSW(tdp + 1); + tdp->link_pad = LSW(tdp + 1) | TDA_LINK_EOL; + tdp->linkp = &((tdp + 1)->frag[0].frag_link); + tdp->next = (TransmitDescriptor_t *)(tdp + 1); +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) + sonic_print_tx_descriptor( tdp ); +#endif + tdp++; + } + tdp--; + sc->tdaHead = tdp; + tdp->link_pad = LSW(sc->tdaTail) | TDA_LINK_EOL; + tdp->next = (TransmitDescriptor_t *)sc->tdaTail; + tdp->linkp = &sc->tdaTail->frag[0].frag_link; + + /* + * Set up circular linked list in Receive Descriptor Area. + * Leaves sc->rda pointing at the `beginning' of the list. + * + * NOTE: The RDA and CDP must have the same MSW for their addresses. + */ + + sc->rda = sonic_allocate( + (sc->rdaCount * sizeof(ReceiveDescriptor_t)) + + sizeof(CamDescriptor_t) ); + sc->cdp = (CamDescriptorPointer_t) ((unsigned char *)sc->rda + + (sc->rdaCount * sizeof(ReceiveDescriptor_t))); +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) + printf( "rda area = %p\n", sc->rda ); + printf( "cdp area = %p\n", sc->cdp ); +#endif + + ordp = rdp = sc->rda; + for (i = 0 ; i < sc->rdaCount ; i++) { + /* + * status, byte_count, pkt_ptr0, pkt_ptr1, and seq_no are set + * to zero by sonic_allocate. + */ + rdp->link = LSW(rdp + 1); + rdp->in_use = RDA_FREE; + rdp->next = (ReceiveDescriptor_t *)(rdp + 1); + ordp = rdp; + rdp++; + } + /* + * Link the last desriptor to the 1st one and mark it as the end + * of the list. + */ + ordp->next = sc->rda; + ordp->link = LSW(sc->rda) | RDA_LINK_EOL; + sc->rdp_last = rdp; + + /* + * Allocate the receive resource area. + * In accordance with National Application Note 746, make the + * receive resource area bigger than the receive descriptor area. + * This has the useful side effect of making the receive resource + * area big enough to hold the CAM descriptor area. + */ + + sc->rsa = sonic_allocate((sc->rdaCount + RRA_EXTRA_COUNT) * sizeof *sc->rsa); +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) + printf( "rsa area = %p\n", sc->rsa ); +#endif + + /* + * Set up list in Receive Resource Area. + * Allocate space for incoming packets. + */ + + rwp = sc->rsa; + for (i = 0 ; i < (sc->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) { + + /* + * Allocate memory for buffer. + * Place a pointer to the mbuf at the beginning of the buffer + * so we can find the mbuf when the SONIC returns the buffer + * to the driver. + */ + + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = &sc->arpcom.ac_if; + sc->rda[i].mbufp = m; + + p = mtod (m, void *); + + /* + * Set up RRA entry + */ + rwp->buff_ptr_lsw = LSW(p); + rwp->buff_ptr_msw = MSW(p); + rwp->buff_wc_lsw = RBUF_WC; + rwp->buff_wc_msw = 0; +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) + sonic_print_rx_descriptor( &sc->rda[i] ); +#endif + } + sc->rea = rwp; +#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) + printf( "rea area = %p\n", sc->rea ); +#endif + + + /* + * Issue a software reset. + */ + (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX ); + + /* + * Set up data configuration registers. + */ + (*sc->write_register)( rp, SONIC_REG_DCR, sc->dcr_value ); + (*sc->write_register)( rp, SONIC_REG_DCR2, sc->dc2_value ); + + (*sc->write_register)( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX ); + + /* + * Mask all interrupts + */ + (*sc->write_register)( rp, SONIC_REG_IMR, 0x0 ); /* XXX was backwards */ + + /* + * Clear outstanding interrupts. + */ + (*sc->write_register)( rp, SONIC_REG_ISR, 0x7FFF ); + + /* + * Clear the tally counters + */ + + (*sc->write_register)( rp, SONIC_REG_CRCT, 0xFFFF ); + (*sc->write_register)( rp, SONIC_REG_FAET, 0xFFFF ); + (*sc->write_register)( rp, SONIC_REG_MPT, 0xFFFF ); + (*sc->write_register)( rp, SONIC_REG_RSC, 0 ); + + /* + * Set the Receiver mode + * + * Enable/disable reception of broadcast packets + */ + + if (sc->acceptBroadcast) + (*sc->write_register)( rp, SONIC_REG_RCR, RCR_BRD ); + else + (*sc->write_register)( rp, SONIC_REG_RCR, 0 ); + + /* + * Set up Resource Area pointers + */ + + (*sc->write_register)( rp, SONIC_REG_URRA, MSW(sc->rsa) ); + (*sc->write_register)( rp, SONIC_REG_RSA, LSW(sc->rsa) ); + + (*sc->write_register)( rp, SONIC_REG_REA, LSW(sc->rea) ); + + (*sc->write_register)( rp, SONIC_REG_RRP, LSW(sc->rsa) ); + (*sc->write_register)( rp, SONIC_REG_RWP, LSW(sc->rsa) ); /* XXX was rea */ + + (*sc->write_register)( rp, SONIC_REG_URDA, MSW(sc->rda) ); + (*sc->write_register)( rp, SONIC_REG_CRDA, LSW(sc->rda) ); + + (*sc->write_register)( rp, SONIC_REG_UTDA, MSW(sc->tdaTail) ); + (*sc->write_register)( rp, SONIC_REG_CTDA, LSW(sc->tdaTail) ); + + /* + * Set End Of Buffer Count register to the value recommended + * in Note 1 of Section 3.4.4.4 of the SONIC data sheet. + */ + + (*sc->write_register)( rp, SONIC_REG_EOBC, RBUF_WC - 2 ); + + /* + * Issue the load RRA command + */ + + (*sc->write_register)( rp, SONIC_REG_CR, CR_RRRA ); + while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RRRA) + continue; + + /* + * Remove device reset + */ + + (*sc->write_register)( rp, SONIC_REG_CR, 0 ); + + /* + * Set up the SONIC CAM with our hardware address. + */ + + hwaddr = sc->arpcom.ac_enaddr; + cdp = sc->cdp; + +#if (SONIC_DEBUG & SONIC_DEBUG_CAM) + printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n", + hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] ); +#endif + + cdp->cep = 0; /* Fill first and only entry in CAM */ + cdp->cap0 = hwaddr[1] << 8 | hwaddr[0]; + cdp->cap1 = hwaddr[3] << 8 | hwaddr[2]; + cdp->cap2 = hwaddr[5] << 8 | hwaddr[4]; + cdp->ce = 0x0001; /* Enable first entry in CAM */ + + (*sc->write_register)( rp, SONIC_REG_CDC, 1 ); /* 1 entry in CDA */ + (*sc->write_register)( rp, SONIC_REG_CDP, LSW(cdp) ); + (*sc->write_register)( rp, SONIC_REG_CR, CR_LCAM ); /* Load the CAM */ + + while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_LCAM) + continue; + + /* + * Verify that CAM was properly loaded. + */ + + (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX ); + +#if (SONIC_DEBUG & SONIC_DEBUG_CAM) + (*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */ + printf ("Loaded Ethernet address into SONIC CAM.\n" + " Wrote %04x%04x%04x - %#x\n" + " Read %04x%04x%04x - %#x\n", + cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, + (*sc->read_register)( rp, SONIC_REG_CAP2 ), + (*sc->read_register)( rp, SONIC_REG_CAP1 ), + (*sc->read_register)( rp, SONIC_REG_CAP0 ), + (*sc->read_register)( rp, SONIC_REG_CE )); +#endif + + (*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */ + if (((*sc->read_register)( rp, SONIC_REG_CAP2 ) != cdp->cap2) + || ((*sc->read_register)( rp, SONIC_REG_CAP1 ) != cdp->cap1) + || ((*sc->read_register)( rp, SONIC_REG_CAP0 ) != cdp->cap0) + || ((*sc->read_register)( rp, SONIC_REG_CE ) != cdp->ce)) { + printf ("Failed to load Ethernet address into SONIC CAM.\n" + " Wrote %04x%04x%04x - %#x\n" + " Read %04x%04x%04x - %#x\n", + cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, + (*sc->read_register)( rp, SONIC_REG_CAP2 ), + (*sc->read_register)( rp, SONIC_REG_CAP1 ), + (*sc->read_register)( rp, SONIC_REG_CAP0 ), + (*sc->read_register)( rp, SONIC_REG_CE )); + rtems_panic ("SONIC LCAM"); + } + + (*sc->write_register)(rp, SONIC_REG_CR, /* CR_TXP | */CR_RXEN | CR_STP); + + /* + * Attach SONIC interrupt handler + */ +/* XXX + (*sc->write_register)( rp, SONIC_REG_IMR, 0 ); +*/ + old_handler = set_vector(sonic_interrupt_handler, sc->vector, 0); + + /* + * Remainder of hardware initialization is + * done by the receive and transmit daemons. + */ +} + +/* + * Send packet (caller provides header). + */ + +SONIC_STATIC void sonic_start(struct ifnet *ifp) +{ + struct sonic_softc *sc = ifp->if_softc; + + rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); + ifp->if_flags |= IFF_OACTIVE; +} + +/* + * Initialize and start the device + */ + +SONIC_STATIC void sonic_init (void *arg) +{ + struct sonic_softc *sc = arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + void *rp = sc->sonic; + int rcr; + + if (sc->txDaemonTid == 0) { + + /* + * Set up SONIC hardware + */ + sonic_initialize_hardware (sc); + + /* + * Start driver tasks + */ + sc->txDaemonTid = rtems_bsdnet_newproc ("SNtx", 4096, sonic_txDaemon, sc); + sc->rxDaemonTid = rtems_bsdnet_newproc ("SNrx", 4096, sonic_rxDaemon, sc); + } + + /* + * Set flags appropriately + */ + rcr = (*sc->read_register)( rp, SONIC_REG_RCR ); + if (ifp->if_flags & IFF_PROMISC) + rcr |= RCR_PRO; + else + rcr &= ~RCR_PRO; + (*sc->write_register)( rp, SONIC_REG_RCR, rcr); + + /* + * Tell the world that we're running. + */ + ifp->if_flags |= IFF_RUNNING; + + /* + * Enable receiver and transmitter + */ + /* (*sc->write_register)( rp, SONIC_REG_IMR, 0 ); */ + sonic_enable_interrupts( sc, + (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN) | (IMR_PRXEN | IMR_RBAEEN) ); + + (*sc->write_register)(rp, SONIC_REG_CR, /* CR_TXP | */ CR_RXEN); +} + +/* + * Driver ioctl handler + */ +static int +sonic_ioctl (struct ifnet *ifp, int command, caddr_t data) +{ + struct sonic_softc *sc = ifp->if_softc; + int error = 0; + + switch (command) { + case SIOCGIFADDR: + case SIOCSIFADDR: + ether_ioctl (ifp, command, data); + break; + + case SIOCSIFFLAGS: + switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { + case IFF_RUNNING: + sonic_stop (sc); + break; + + case IFF_UP: + sonic_init (sc); + break; + + case IFF_UP | IFF_RUNNING: + sonic_stop (sc); + sonic_init (sc); + break; + + default: + break; + } + break; + + case SIO_RTEMS_SHOW_STATS: + sonic_stats (sc); + break; + + /* + * FIXME: All sorts of multicast commands need to be added here! + */ + default: + error = EINVAL; + break; + } + return error; +} + +/* + * Attach an SONIC driver to the system + * This is the only `extern' function in the driver. + */ + +int +rtems_sonic_driver_attach ( + struct rtems_bsdnet_ifconfig *config, + sonic_configuration_t *chip +) +{ + struct sonic_softc *sc; + struct ifnet *ifp; + int mtu; + int i; + + /* + * Find an unused entry + */ + i = 0; + sc = sonic_softc; + for (;;) { + if (sc == &sonic_softc[NSONIC]) { + printf ("No more SONIC devices.\n"); + return 0; + } + ifp = &sc->arpcom.ac_if; + if (ifp->if_softc == NULL) + break; + sc++; + i++; + } + + /* + * zero out the control structure + */ + + memset( sc, 0, sizeof(*sc) ); + + + /* + * Process options + */ + if (config->hardware_address) { + memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); + } + else { + memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); + } + if (config->mtu) + mtu = config->mtu; + else + mtu = ETHERMTU; + if (config->rbuf_count) + sc->rdaCount = config->rbuf_count; + else + sc->rdaCount = chip->rda_count; + if (config->xbuf_count) + sc->tdaCount = config->xbuf_count; + else + sc->tdaCount = chip->tda_count; + sc->acceptBroadcast = !config->ignore_broadcast; + + sc->sonic = (void *) chip->base_address; + sc->vector = chip->vector; + sc->dcr_value = chip->dcr_value; + sc->dc2_value = chip->dc2_value; + sc->write_register = chip->write_register; + sc->read_register = chip->read_register; + + /* + * Set up network interface values + */ + ifp->if_softc = sc; + ifp->if_unit = i + 1; + ifp->if_name = "sonic"; + ifp->if_mtu = mtu; + ifp->if_init = sonic_init; + ifp->if_ioctl = sonic_ioctl; + ifp->if_start = sonic_start; + ifp->if_output = ether_output; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; + + /* + * Attach the interface + */ + if_attach (ifp); + ether_ifattach (ifp); + return 1; +} + +#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) +#include <stdio.h> + +char SONIC_Reg_name[64][6]= { + "CR", /* 0x00 */ + "DCR", /* 0x01 */ + "RCR", /* 0x02 */ + "TCR", /* 0x03 */ + "IMR", /* 0x04 */ + "ISR", /* 0x05 */ + "UTDA", /* 0x06 */ + "CTDA", /* 0x07 */ + "0x08", /* 0x08 */ + "0x09", /* 0x09 */ + "0x0A", /* 0x0A */ + "0x0B", /* 0x0B */ + "0x0C", /* 0x0C */ + "URDA", /* 0x0D */ + "CRDA", /* 0x0E */ + "0x0F", /* 0x0F */ + "0x10", /* 0x10 */ + "0x11", /* 0x11 */ + "0x12", /* 0x12 */ + "EOBC", /* 0x13 */ + "URRA", /* 0x14 */ + "RSA", /* 0x15 */ + "REA", /* 0x16 */ + "RRP", /* 0x17 */ + "RWP", /* 0x18 */ + "0x19", /* 0x19 */ + "0x1A", /* 0x1A */ + "0x1B", /* 0x1B */ + "0x1C", /* 0x1C */ + "0x0D", /* 0x1D */ + "0x1E", /* 0x1E */ + "0x1F", /* 0x1F */ + "0x20", /* 0x20 */ + "CEP", /* 0x21 */ + "CAP2", /* 0x22 */ + "CAP1", /* 0x23 */ + "CAP0", /* 0x24 */ + "CE", /* 0x25 */ + "CDP", /* 0x26 */ + "CDC", /* 0x27 */ + "SR", /* 0x28 */ + "WT0", /* 0x29 */ + "WT1", /* 0x2A */ + "RSC", /* 0x2B */ + "CRCT", /* 0x2C */ + "FAET", /* 0x2D */ + "MPT", /* 0x2E */ + "MDT", /* 0x2F */ + "0x30", /* 0x30 */ + "0x31", /* 0x31 */ + "0x32", /* 0x32 */ + "0x33", /* 0x33 */ + "0x34", /* 0x34 */ + "0x35", /* 0x35 */ + "0x36", /* 0x36 */ + "0x37", /* 0x37 */ + "0x38", /* 0x38 */ + "0x39", /* 0x39 */ + "0x3A", /* 0x3A */ + "0x3B", /* 0x3B */ + "0x3C", /* 0x3C */ + "0x3D", /* 0x3D */ + "0x3E", /* 0x3E */ + "DCR2" /* 0x3F */ +}; +#endif diff --git a/c/src/libchip/network/sonic.h b/c/src/libchip/network/sonic.h new file mode 100644 index 0000000000..47f50d3356 --- /dev/null +++ b/c/src/libchip/network/sonic.h @@ -0,0 +1,416 @@ +/* + * RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' + * SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER + * + * REUSABLE CHIP DRIVER CONFIGURATION + * + * References: + * + * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface + * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, + * 1995. + * + * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), + * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, + * RRD-B30M75, National Semiconductor, March, 1991. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef _SONIC_DP83932_ +#define _SONIC_DP83932_ + +/* + * Configuration Information + */ + +typedef void (*sonic_write_register_t)( + void *base, + unsigned32 regno, + unsigned32 value +); + +typedef unsigned32 (*sonic_read_register_t)( + void *base, + unsigned32 regno +); + +typedef struct { + unsigned32 base_address; + unsigned32 vector; + unsigned32 dcr_value; + unsigned32 dc2_value; + unsigned32 tda_count; + unsigned32 rda_count; + sonic_write_register_t write_register; + sonic_read_register_t read_register; +} sonic_configuration_t; + +/* + ****************************************************************** + * * + * Device Registers * + * * + ****************************************************************** + */ +#define SONIC_REG_CR 0x00 /* Command */ +#define SONIC_REG_DCR 0x01 /* Data configuration */ +#define SONIC_REG_RCR 0x02 /* Receive control */ +#define SONIC_REG_TCR 0x03 /* Transmit control */ +#define SONIC_REG_IMR 0x04 /* Interrupt mask */ +#define SONIC_REG_ISR 0x05 /* Interrupt status */ +#define SONIC_REG_UTDA 0x06 /* Upper transmit descriptor address */ +#define SONIC_REG_CTDA 0x07 /* Current transmit descriptor address */ +#define SONIC_REG_URDA 0x0D /* Upper receive descriptor address */ +#define SONIC_REG_CRDA 0x0E /* Current receive descriptor address */ +#define SONIC_REG_EOBC 0x13 /* End of buffer word count */ +#define SONIC_REG_URRA 0x14 /* Upper receive resource */ +#define SONIC_REG_RSA 0x15 /* Resource start address */ +#define SONIC_REG_REA 0x16 /* Resource end address */ +#define SONIC_REG_RRP 0x17 /* Resouce read pointer */ +#define SONIC_REG_RWP 0x18 /* Resouce write pointer */ +#define SONIC_REG_CEP 0x21 /* CAM entry pointer */ +#define SONIC_REG_CAP2 0x22 /* CAM address port 2 */ +#define SONIC_REG_CAP1 0x23 /* CAM address port 1 */ +#define SONIC_REG_CAP0 0x24 /* CAM address port 0 */ +#define SONIC_REG_CE 0x25 /* CAM enable */ +#define SONIC_REG_CDP 0x26 /* CAM descriptor pointer */ +#define SONIC_REG_CDC 0x27 /* CAM descriptor count */ +#define SONIC_REG_SR 0x28 /* Silicon revision */ +#define SONIC_REG_WT0 0x29 /* Watchdog timer 0 */ +#define SONIC_REG_WT1 0x2A /* Watchdog timer 1 */ +#define SONIC_REG_RSC 0x2B /* Receive sequence counter */ +#define SONIC_REG_CRCT 0x2C /* CRC error tally */ +#define SONIC_REG_FAET 0x2D /* FAE tally */ +#define SONIC_REG_MPT 0x2E /* Missed packet tally */ +#define SONIC_REG_MDT 0x2F /* TX Maximum Deferral */ +#define SONIC_REG_DCR2 0x3F /* Data configuration 2 */ + +/* + * Command register + */ +#define CR_LCAM 0x0200 +#define CR_RRRA 0x0100 +#define CR_RST 0x0080 +#define CR_ST 0x0020 +#define CR_STP 0x0010 +#define CR_RXEN 0x0008 +#define CR_RXDIS 0x0004 +#define CR_TXP 0x0002 +#define CR_HTX 0x0001 + +/* + * Data configuration register + */ +#define DCR_EXBUS 0x8000 +#define DCR_LBR 0x2000 +#define DCR_PO1 0x1000 +#define DCR_PO0 0x0800 +#define DCR_SBUS 0x0400 +#define DCR_USR1 0x0200 +#define DCR_USR0 0x0100 +#define DCR_WC1 0x0080 +#define DCR_WC0 0x0040 +#define DCR_DW 0x0020 +#define DCR_BMS 0x0010 +#define DCR_RFT1 0x0008 +#define DCR_RFT0 0x0004 +#define DCR_TFT1 0x0002 +#define DCR_TFT0 0x0001 + +/* data configuration register aliases */ +#define DCR_SYNC DCR_SBUS /* synchronous (memory cycle 2 clocks) */ +#define DCR_ASYNC 0 /* asynchronous (memory cycle 3 clocks) */ + +#define DCR_WAIT0 0 /* 0 wait states added */ +#define DCR_WAIT1 DCR_WC0 /* 1 wait state added */ +#define DCR_WAIT2 DCR_WC1 /* 2 wait states added */ +#define DCR_WAIT3 (DCR_WC1|DCR_WC0) /* 3 wait states added */ + +#define DCR_DW16 0 /* use 16-bit DMA accesses */ +#define DCR_DW32 DCR_DW /* use 32-bit DMA accesses */ + +#define DCR_DMAEF 0 /* DMA until TX/RX FIFO has emptied/filled */ +#define DCR_DMABLOCK DCR_BMS /* DMA until RX/TX threshold crossed */ + +#define DCR_RFT4 0 /* receive threshold 4 bytes */ +#define DCR_RFT8 DCR_RFT0 /* receive threshold 8 bytes */ +#define DCR_RFT16 DCR_RFT1 /* receive threshold 16 bytes */ +#define DCR_RFT24 (DCR_RFT1|DCR_RFT0) /* receive threshold 24 bytes */ + +#define DCR_TFT8 0 /* transmit threshold 8 bytes */ +#define DCR_TFT16 DCR_TFT0 /* transmit threshold 16 bytes */ +#define DCR_TFT24 DCR_TFT1 /* transmit threshold 24 bytes */ +#define DCR_TFT28 (DCR_TFT1|DCR_TFT0) /* transmit threshold 28 bytes */ + +/* + * Receive control register + */ +#define RCR_ERR 0x8000 +#define RCR_RNT 0x4000 +#define RCR_BRD 0x2000 +#define RCR_PRO 0x1000 +#define RCR_AMC 0x0800 +#define RCR_LB1 0x0400 +#define RCR_LB0 0x0200 +#define RCR_MC 0x0100 +#define RCR_BC 0x0080 +#define RCR_LPKT 0x0040 +#define RCR_CRS 0x0020 +#define RCR_COL 0x0010 +#define RCR_CRCR 0x0008 +#define RCR_FAER 0x0004 +#define RCR_LBK 0x0002 +#define RCR_PRX 0x0001 + +/* + * Transmit control register + */ +#define TCR_PINT 0x8000 +#define TCR_POWC 0x4000 +#define TCR_CRCI 0x2000 +#define TCR_EXDIS 0x1000 +#define TCR_EXD 0x0400 +#define TCR_DEF 0x0200 +#define TCR_NCRS 0x0100 +#define TCR_CRSL 0x0080 +#define TCR_EXC 0x0040 +#define TCR_OWC 0x0020 +#define TCR_PMB 0x0008 +#define TCR_FU 0x0004 +#define TCR_BCM 0x0002 +#define TCR_PTX 0x0001 + +/* + * Interrupt mask register + */ +#define IMR_BREN 0x4000 +#define IMR_HBLEN 0x2000 +#define IMR_LCDEN 0x1000 +#define IMR_PINTEN 0x0800 +#define IMR_PRXEN 0x0400 +#define IMR_PTXEN 0x0200 +#define IMR_TXEREN 0x0100 +#define IMR_TCEN 0x0080 +#define IMR_RDEEN 0x0040 +#define IMR_RBEEN 0x0020 +#define IMR_RBAEEN 0x0010 +#define IMR_CRCEN 0x0008 +#define IMR_FAEEN 0x0004 +#define IMR_MPEN 0x0002 +#define IMR_RFOEN 0x0001 + +/* + * Interrupt status register + */ +#define ISR_BR 0x4000 +#define ISR_HBL 0x2000 +#define ISR_LCD 0x1000 +#define ISR_PINT 0x0800 +#define ISR_PKTRX 0x0400 +#define ISR_TXDN 0x0200 +#define ISR_TXER 0x0100 +#define ISR_TC 0x0080 +#define ISR_RDE 0x0040 +#define ISR_RBE 0x0020 +#define ISR_RBAE 0x0010 +#define ISR_CRC 0x0008 +#define ISR_FAE 0x0004 +#define ISR_MP 0x0002 +#define ISR_RFO 0x0001 + +/* + * Data configuration register 2 + */ +#define DCR2_EXPO3 0x8000 +#define DCR2_EXPO2 0x4000 +#define DCR2_EXPO1 0x2000 +#define DCR2_EXPO0 0x1000 +#define DCR2_PH 0x0010 +#define DCR2_PCM 0x0004 +#define DCR2_PCNM 0x0002 +#define DCR2_RJCM 0x0001 + +/* + * Known values for the Silicon Revision Register + */ + +#define SONIC_REVISION_B 4 +#define SONIC_REVISION_C 6 + +/* + ****************************************************************** + * * + * Transmit Buffer Management * + * * + ****************************************************************** + */ + +/* + * Transmit descriptor area entry. + * There is one transmit descriptor for each packet to be transmitted. + * Statically reserve space for up to MAXIMUM_FRAGS_PER_PACKET fragments + * per descriptor. + */ +#define MAXIMUM_FRAGS_PER_DESCRIPTOR 6 +struct TransmitDescriptor { + rtems_unsigned32 status; + rtems_unsigned32 pkt_config; + rtems_unsigned32 pkt_size; + rtems_unsigned32 frag_count; + + /* + * Packet fragment pointers + */ + struct TransmitDescriptorFragLink { + rtems_unsigned32 frag_lsw; /* LSW of fragment address */ +#define frag_link frag_lsw + rtems_unsigned32 frag_msw; /* MSW of fragment address */ + rtems_unsigned32 frag_size; + } frag[MAXIMUM_FRAGS_PER_DESCRIPTOR]; + + /* + * Space for link if all fragment pointers are used. + */ + rtems_unsigned32 link_pad; + + /* + * Extra RTEMS stuff + */ + struct TransmitDescriptor *next; /* Circularly-linked list */ + struct mbuf *mbufp; /* First mbuf in packet */ + volatile rtems_unsigned32 *linkp; /* Pointer to un[xxx].link */ +}; +typedef struct TransmitDescriptor TransmitDescriptor_t; +typedef volatile TransmitDescriptor_t *TransmitDescriptorPointer_t; + +/* + * Transmit Configuration. + * For standard Ethernet transmission, all bits in the transmit + * configuration field are set to 0. + */ +#define TDA_CONFIG_PINT 0x8000 +#define TDA_CONFIG_POWC 0x4000 +#define TDA_CONFIG_CRCI 0x2000 +#define TDA_CONFIG_EXDIS 0x1000 + +/* + * Transmit status + */ +#define TDA_STATUS_COLLISION_MASK 0xF800 +#define TDA_STATUS_COLLISION_SHIFT 11 +#define TDA_STATUS_EXD 0x0400 +#define TDA_STATUS_DEF 0x0200 +#define TDA_STATUS_NCRS 0x0100 +#define TDA_STATUS_CRSL 0x0080 +#define TDA_STATUS_EXC 0x0040 +#define TDA_STATUS_OWC 0x0020 +#define TDA_STATUS_PMB 0x0008 +#define TDA_STATUS_FU 0x0004 +#define TDA_STATUS_BCM 0x0002 +#define TDA_STATUS_PTX 0x0001 + +#define TDA_LINK_EOL 0x0001 +#define TDA_LINK_EOL_MASK 0xFFFE + + + +/* + ****************************************************************** + * * + * Receive Buffer Management * + * * + ****************************************************************** + */ + +/* + * Receive resource area entry. + * There is one receive resource entry for each receive buffer area (RBA). + * This driver allows only one packet per receive buffer area, so one + * receive resource entry corresponds to one correctly-received packet. + */ +struct ReceiveResource { + rtems_unsigned32 buff_ptr_lsw; /* LSW of RBA address */ + rtems_unsigned32 buff_ptr_msw; /* MSW of RBA address */ + rtems_unsigned32 buff_wc_lsw; /* LSW of RBA size (16-bit words) */ + rtems_unsigned32 buff_wc_msw; /* MSW of RBA size (16-bit words) */ +}; +typedef struct ReceiveResource ReceiveResource_t; +typedef volatile ReceiveResource_t *ReceiveResourcePointer_t; + +/* + * Receive descriptor area entry. + * There is one receive descriptor for each packet received. + */ +struct ReceiveDescriptor { + rtems_unsigned32 status; + rtems_unsigned32 byte_count; + rtems_unsigned32 pkt_lsw; /* LSW of packet address */ + rtems_unsigned32 pkt_msw; /* MSW of packet address */ + rtems_unsigned32 seq_no; + rtems_unsigned32 link; + rtems_unsigned32 in_use; + + /* + * Extra RTEMS stuff + */ + volatile struct ReceiveDescriptor *next; /* Circularly-linked list */ + struct mbuf *mbufp; /* First mbuf in packet */ +}; +typedef struct ReceiveDescriptor ReceiveDescriptor_t; +typedef volatile ReceiveDescriptor_t *ReceiveDescriptorPointer_t; + +typedef struct { + rtems_unsigned32 cep; /* CAM Entry Pointer */ + rtems_unsigned32 cap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */ + rtems_unsigned32 cap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */ + rtems_unsigned32 cap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */ + rtems_unsigned32 ce; +} CamDescriptor_t; + +typedef volatile CamDescriptor_t *CamDescriptorPointer_t; + +/* + * Receive status + */ +#define RDA_STATUS_ERR 0x8800 +#define RDA_STATUS_RNT 0x4000 +#define RDA_STATUS_BRD 0x2000 +#define RDA_STATUS_PRO 0x1000 +#define RDA_STATUS_AMC 0x0800 +#define RDA_STATUS_LB1 0x0400 +#define RDA_STATUS_LB0 0x0200 +#define RDA_STATUS_MC 0x0100 +#define RDA_STATUS_BC 0x0080 +#define RDA_STATUS_LPKT 0x0040 +#define RDA_STATUS_CRS 0x0020 +#define RDA_STATUS_COL 0x0010 +#define RDA_STATUS_CRCR 0x0008 +#define RDA_STATUS_FAER 0x0004 +#define RDA_STATUS_LBK 0x0002 +#define RDA_STATUS_PRX 0x0001 + +#define RDA_LINK_EOL 0x0001 +#define RDA_LINK_EOL_MASK 0xFFFE +#define RDA_IN_USE 0x0000 /* SONIC has finished with the packet */ + /* and the driver can process it */ +#define RDA_FREE 0xFFFF /* SONIC can use it */ + +/* + * Attatch routine + */ + +int rtems_sonic_driver_attach ( + struct rtems_bsdnet_ifconfig *config, + sonic_configuration_t *chip +); + +#endif /* _SONIC_DP83932_ */ diff --git a/c/src/wrapup/Makefile.in b/c/src/wrapup/Makefile.in index 5e73848490..d3e0f76ac9 100644 --- a/c/src/wrapup/Makefile.in +++ b/c/src/wrapup/Makefile.in @@ -24,6 +24,7 @@ SRCS=$(wildcard $(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libcpu$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/librtcio$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libserialio$(LIB_VARIANT).a) \ + $(wildcard $(PROJECT_RELEASE)/lib/libnetchip$(LIB_VARIANT).a) \ $(PROJECT_RELEASE)/lib/libcsupport$(LIB_VARIANT).a \ $(PROJECT_RELEASE)/lib/libmisc$(LIB_VARIANT).a \ $(wildcard $(PROJECT_RELEASE)/lib/rtems-ctor$(LIB_VARIANT).o) \ |