From a8bf95d0249565f4210ccab5c13232d501ce0c2d Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Wed, 22 Apr 2009 22:06:58 +0000 Subject: - importing updated version from SLAC as of 20090422 --- bsd_eth_drivers/ChangeLog | 20 + bsd_eth_drivers/Makefile | 11 + bsd_eth_drivers/Makefile.am | 2 +- bsd_eth_drivers/if_em/LICENSE | 31 ++ bsd_eth_drivers/if_em/Makefile | 158 +++++++ bsd_eth_drivers/if_em/README.rtems | 66 +++ bsd_eth_drivers/if_em/freebsd_cvs_status | 291 +++++++++++++ bsd_eth_drivers/if_le/Makefile | 152 +++++++ bsd_eth_drivers/if_le/README.rtems | 80 ++++ bsd_eth_drivers/if_le/am7990.c | 627 ++++++++++++++++++++++++++++ bsd_eth_drivers/if_le/if_le_cbus.c | 451 ++++++++++++++++++++ bsd_eth_drivers/if_le/if_le_isa.c | 509 ++++++++++++++++++++++ bsd_eth_drivers/if_le/if_le_lebuffer.c | 408 ++++++++++++++++++ bsd_eth_drivers/if_le/if_le_ledma.c | 490 ++++++++++++++++++++++ bsd_eth_drivers/if_le/lebuffer_sbus.c | 300 +++++++++++++ bsd_eth_drivers/if_pcn/Makefile | 143 +++++++ bsd_eth_drivers/if_pcn/README.rtems | 73 ++++ bsd_eth_drivers/libbsdport/Makefile | 116 +++++ bsd_eth_drivers/libbsdport/Makefile.am | 3 - bsd_eth_drivers/libbsdport/alldrv.c | 1 - bsd_eth_drivers/libbsdport/bus.h | 40 +- bsd_eth_drivers/libbsdport/devicet.c | 2 +- bsd_eth_drivers/libbsdport/libbsdport.h | 7 - bsd_eth_drivers/libbsdport/libbsdport_api.h | 2 - bsd_eth_drivers/libbsdport/modini.c | 100 +++++ bsd_eth_drivers/libbsdport/sysbus.c | 12 +- bsd_eth_drivers/libbsdport/taskqueue.h | 2 - 27 files changed, 4033 insertions(+), 64 deletions(-) create mode 100644 bsd_eth_drivers/ChangeLog create mode 100644 bsd_eth_drivers/Makefile create mode 100644 bsd_eth_drivers/if_em/LICENSE create mode 100644 bsd_eth_drivers/if_em/Makefile create mode 100644 bsd_eth_drivers/if_em/README.rtems create mode 100644 bsd_eth_drivers/if_em/freebsd_cvs_status create mode 100644 bsd_eth_drivers/if_le/Makefile create mode 100644 bsd_eth_drivers/if_le/README.rtems create mode 100644 bsd_eth_drivers/if_le/am7990.c create mode 100644 bsd_eth_drivers/if_le/if_le_cbus.c create mode 100644 bsd_eth_drivers/if_le/if_le_isa.c create mode 100644 bsd_eth_drivers/if_le/if_le_lebuffer.c create mode 100644 bsd_eth_drivers/if_le/if_le_ledma.c create mode 100644 bsd_eth_drivers/if_le/lebuffer_sbus.c create mode 100644 bsd_eth_drivers/if_pcn/Makefile create mode 100644 bsd_eth_drivers/if_pcn/README.rtems create mode 100644 bsd_eth_drivers/libbsdport/Makefile create mode 100644 bsd_eth_drivers/libbsdport/modini.c (limited to 'bsd_eth_drivers') diff --git a/bsd_eth_drivers/ChangeLog b/bsd_eth_drivers/ChangeLog new file mode 100644 index 0000000..33cb584 --- /dev/null +++ b/bsd_eth_drivers/ChangeLog @@ -0,0 +1,20 @@ + 2008/03/22 (TS) + - silence more compiler warnings: + * make DMA address void* instead of caddr_t to avoid strict-aliasing violation + * add dummy statement to silence 'unused variable' warning. + - added header with RTEMS version checking macro. Unfortunately, many small + details of the RTEMS APIs change with versions :-( [e.g., changed type + from unsigned -> uint32_t in st_le32()]. Individual files can include + the new and test for RTEMS version to switch conditional + compilation (aaargh). + - header clash; (and others) are present in newlib and in RTEMS/bsdnet + but they use a different multiple-inclusion guard :-(. Must pick the right one... + 2007/11/07 (TS) + - added ChangeLog + - moved arp_ifinit from libbsdport.h to libbsdport_post.h + - replaced inport_xxx/outport_xxx by in_xxx/out_xxx and _IO_BASE + - bookE has not mftb instruction :-( we must use mfspr + (but that wouldn't work on classic ppc if we were not + in supervisory mode). + - type adaptions in libbsdport.h to protect us against + alias rule and to silence warnings. diff --git a/bsd_eth_drivers/Makefile b/bsd_eth_drivers/Makefile new file mode 100644 index 0000000..175dea6 --- /dev/null +++ b/bsd_eth_drivers/Makefile @@ -0,0 +1,11 @@ +# +# Makefile.dir,v 1.4 2000/06/12 15:00:14 joel Exp +# + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc + +include $(RTEMS_CUSTOM) +include $(RTEMS_ROOT)/make/directory.cfg + +SUBDIRS=libbsdport if_em if_pcn if_le + diff --git a/bsd_eth_drivers/Makefile.am b/bsd_eth_drivers/Makefile.am index 4495d4a..347eb90 100644 --- a/bsd_eth_drivers/Makefile.am +++ b/bsd_eth_drivers/Makefile.am @@ -1,3 +1,3 @@ AUTOMAKE_OPTIONS=foreign -SUBDIRS=libbsdport if_pcn if_le if_em re +SUBDIRS=libbsdport if_pcn if_le if_em diff --git a/bsd_eth_drivers/if_em/LICENSE b/bsd_eth_drivers/if_em/LICENSE new file mode 100644 index 0000000..7e13aa1 --- /dev/null +++ b/bsd_eth_drivers/if_em/LICENSE @@ -0,0 +1,31 @@ +$FreeBSD: src/sys/dev/em/LICENSE,v 1.6 2007/05/04 00:00:11 jfv Exp $ + + Copyright (c) 2001-2007, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + diff --git a/bsd_eth_drivers/if_em/Makefile b/bsd_eth_drivers/if_em/Makefile new file mode 100644 index 0000000..ea0d776 --- /dev/null +++ b/bsd_eth_drivers/if_em/Makefile @@ -0,0 +1,158 @@ +# +# Makefile.leaf,v 1.7 2002/07/22 22:56:09 joel Exp +# +# Templates/Makefile.leaf +# Template leaf node Makefile +# +# +LIBNAME=libif_em.a + +ENBL_82542_SUPPORT=NO +ENBL_ICH8LAN_SUPPORT=YES + +CPPFLAGS_82542_SUPPORT_NO=-DNO_82542_SUPPORT +C_PIECES_82542_SUPPORT_YES=e1000_82542 +CPPFLAGS_ICH8LAN_SUPPORT_NO=-DNO_ICH8LAN_SUPPORT +C_PIECES_ICH8LAN_SUPPORT_YES=e1000_ich8lan + +# C source names, if any, go here -- minus the .c +C_PIECES= + +C_PIECES+=e1000_80003es2lan +C_PIECES+=e1000_82540 +C_PIECES+=e1000_82541 +C_PIECES+=$(C_PIECES_82542_SUPPORT_$(ENBL_82542_SUPPORT)) +C_PIECES+=e1000_82543 +C_PIECES+=e1000_82571 +C_PIECES+=e1000_82575 +C_PIECES+=e1000_api +C_PIECES+=$(C_PIECES_ICH8LAN_SUPPORT_$(ENBL_ICH8LAN_SUPPORT)) +C_PIECES+=e1000_mac +C_PIECES+=e1000_manage +C_PIECES+=e1000_nvm +C_PIECES+=e1000_phy + +C_PIECES+=if_em + +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +# C++ source names, if any, go here -- minus the .cc +CC_PIECES= +CC_FILES=$(CC_PIECES:%=%.cc) +CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .S +S_PIECES= +S_FILES=$(S_PIECES:%=%.S) +S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +# If your PGMS target has the '.exe' extension, a statically +# linked application is generated. +# If it has a '.obj' extension, a loadable module is built. +# +# +ifdef LIBNAME +LIB=${ARCH}/${LIBNAME} +else +PGMS=${ARCH}/if_em.obj +endif + +# List of RTEMS Classic API Managers to be included in the application +# goes here. Use: +# MANAGERS=all +# to include all RTEMS Classic API Managers in the application or +# something like this to include a specific set of managers. +# MANAGERS=io event message rate_monotonic semaphore timer +# +# UNUSED for loadable modules +MANAGERS=ALL + +ifndef RTEMS_MAKEFILE_PATH +$(error you need to set the RTEMS_MAKEFILE_PATH environment variable) +endif + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc + +include $(RTEMS_CUSTOM) +ifdef LIBNAME +include $(RTEMS_ROOT)/make/lib.cfg +else +include $(RTEMS_ROOT)/make/leaf.cfg +endif + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += -I. -I../libbsdport -I../libbsdport/dummyheaders +CPPFLAGS += $(CPPFLAGS_82542_SUPPORT_$(ENBL_82542_SUPPORT)) +CPPFLAGS += $(CPPFLAGS_ICH8LAN_SUPPORT_$(ENBL_ICH8LAN_SUPPORT)) +CFLAGS += + +# +# CFLAGS_DEBUG_V are used when the `make debug' target is built. +# To link your application with the non-optimized RTEMS routines, +# uncomment the following line: +# CFLAGS_DEBUG_V += -qrtems_debug +# + +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 += + +all: ${ARCH} $(SRCS) $(PGMS) ${LIB} + +#How to make a relocatable object +$(filter %.obj, $(PGMS)): ${OBJS} + $(make-obj) + +#How to make an executable (statically linked) +$(filter %.exe,$(PGMS)): ${LINK_FILES} + $(make-exe) +ifdef ELFEXT +ifdef XSYMS + $(XSYMS) $(@:%.exe=%.$(ELFEXT)) $(@:%.exe=%.sym) +endif +endif + +$(LIB): ${OBJS} + $(make-library) + +ifndef RTEMS_SITE_INSTALLDIR +RTEMS_SITE_INSTALLDIR = $(PROJECT_RELEASE) +endif + +${RTEMS_SITE_INSTALLDIR}/include \ +${RTEMS_SITE_INSTALLDIR}/lib \ +${RTEMS_SITE_INSTALLDIR}/bin: + test -d $@ || mkdir -p $@ +# Install the program(s), appending _g or _p as appropriate. +# for include files, just use $(INSTALL_CHANGE) +# +# - Some BSPs might generate bootable executables in yet another +# format (such as .srec) and you might need to extend the rule +# below so the essential files get installed. YMMV. +ifdef LIBNAME +install: all $(RTEMS_SITE_INSTALLDIR)/lib + $(INSTALL_VARIANT) -m 644 ${LIB} ${RTEMS_SITE_INSTALLDIR}/lib +else +install: all $(RTEMS_SITE_INSTALLDIR)/bin + $(INSTALL_VARIANT) -m 555 ${PGMS} ${PGMS:%.exe=%.bin} ${PGMS:%.exe=%.sym} ${RTEMS_SITE_INSTALLDIR}/bin +endif diff --git a/bsd_eth_drivers/if_em/README.rtems b/bsd_eth_drivers/if_em/README.rtems new file mode 100644 index 0000000..88fa2fb --- /dev/null +++ b/bsd_eth_drivers/if_em/README.rtems @@ -0,0 +1,66 @@ +RTEMS PORT OF THE 'em' ETHERNET DRIVER +====================================== + +This is a port of the intel / FreeBSD 'em' driver as of +2007/7/4 (checked out from FreeBSD/head on that date). + +SUPPORTED BSPs: +- you need 'libbsdport' which in turn needs 'libbspExt' + These work for i386/pc386 and powerpc/new-exception-processing + BSPs, i.e., the BSP must implement and . + +USAGE: +- to attach this driver: + * define a NULL terminated list with all libbsdport supported + drivers you want to include with your application: + + extern driver_t libbsdport_em_driver; + + driver_t *libbsdport_netdriver_table[] = { + &libbsdport_em_driver, + /* other drivers here or upstream of 'em' if they support + * the same hardware but are preferred. + */ + 0 + }; + + * specify libbsdport_netdriver_attach for the 'attach' function + pointer in struct rtems_bsdnet_ifconfig. + + * use the 'name' field in struct rtems_bsdnet_ifconfig to filter + drivers and device instances: + + + + either may be omitted which means that the next available + driver/hardware device is to be used. Here are a few examples: + + "" /* use first device found supported by any driver in the + * libbsdport_driver_table[]. + */ + + "em2" /* use second device supported by the 'em' driver */ + + Notes: Counting instances begins with 1 (not 0). + Consult libbsdport/README for more information. + + +KNOWN ISSUES: +- 'ignore_broadcast' and 'mtu' settings from + struct rtems_bsdnet_ifconfig are ignored. I haven't seen + many drivers that honour 'ignore_broadcast' and 'mtu' can be + set using a ioctl(). I'm trying to keep changes to BSD sources + minimal... +- ring sizes are restricted (driver validates sizes and uses + defaults if requested sizes don't meet requirements). + +TESTED WITH: + 82544 on motorola MVME5500 (PPC MVE board) + 82573 on concurrent technologies PP410 (intel x86) board + +TESTED ON: + rtems-4.7 + powerpc/beatnik (motorola MVME5500) + i386/pc686 (concurrent technologies PP410 compact PCI) + +T.S, 200707 diff --git a/bsd_eth_drivers/if_em/freebsd_cvs_status b/bsd_eth_drivers/if_em/freebsd_cvs_status new file mode 100644 index 0000000..da6f8b8 --- /dev/null +++ b/bsd_eth_drivers/if_em/freebsd_cvs_status @@ -0,0 +1,291 @@ +FreeBSD checkout at 2007-07-04 00:49 PDT + +? freebsd_cvs_status +=================================================================== +File: LICENSE Status: Up-to-date + + Working revision: 1.6 + Repository revision: 1.6 /home/ncvs/src/sys/dev/em/LICENSE,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: README Status: Up-to-date + + Working revision: 1.15 + Repository revision: 1.15 /home/ncvs/src/sys/dev/em/README,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_80003es2lan.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_80003es2lan.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_80003es2lan.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_80003es2lan.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82540.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82540.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82541.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82541.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82541.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82541.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82542.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82542.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82543.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82543.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82543.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82543.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82571.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82571.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82571.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82571.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82575.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82575.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_82575.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_82575.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_api.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_api.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_api.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_api.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_defines.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_defines.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_hw.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_hw.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_ich8lan.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_ich8lan.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_ich8lan.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_ich8lan.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_mac.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_mac.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_mac.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_mac.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_manage.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_manage.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_manage.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_manage.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_nvm.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_nvm.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_nvm.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_nvm.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_osdep.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_osdep.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_phy.c Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_phy.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_phy.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_phy.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: e1000_regs.h Status: Up-to-date + + Working revision: 1.3 + Repository revision: 1.3 /home/ncvs/src/sys/dev/em/e1000_regs.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: if_em.c Status: Up-to-date + + Working revision: 1.181 + Repository revision: 1.181 /home/ncvs/src/sys/dev/em/if_em.c,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + +=================================================================== +File: if_em.h Status: Up-to-date + + Working revision: 1.61 + Repository revision: 1.61 /home/ncvs/src/sys/dev/em/if_em.h,v + Sticky Tag: (none) + Sticky Date: (none) + Sticky Options: (none) + diff --git a/bsd_eth_drivers/if_le/Makefile b/bsd_eth_drivers/if_le/Makefile new file mode 100644 index 0000000..ab71264 --- /dev/null +++ b/bsd_eth_drivers/if_le/Makefile @@ -0,0 +1,152 @@ +# +# Makefile.leaf,v 1.7 2002/07/22 22:56:09 joel Exp +# +# Templates/Makefile.leaf +# Template leaf node Makefile +# +# +LIBNAME=libif_le.a + +# C source names, if any, go here -- minus the .c +C_PIECES= + +C_PIECES+=lance am79900 if_le_pci + +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +# C++ source names, if any, go here -- minus the .cc +CC_PIECES= +CC_FILES=$(CC_PIECES:%=%.cc) +CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o) + +H_FILES= + +LINKS+=dev/le/lancereg.h +LINKS+=dev/le/lancevar.h +LINKS+=dev/le/am79900reg.h +LINKS+=dev/le/am79900var.h + +# Assembly source names, if any, go here -- minus the .S +S_PIECES= +S_FILES=$(S_PIECES:%=%.S) +S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +# If your PGMS target has the '.exe' extension, a statically +# linked application is generated. +# If it has a '.obj' extension, a loadable module is built. +# +# +ifdef LIBNAME +LIB=${ARCH}/${LIBNAME} +else +PGMS=${ARCH}/if_pcn.obj +endif + +# List of RTEMS Classic API Managers to be included in the application +# goes here. Use: +# MANAGERS=all +# to include all RTEMS Classic API Managers in the application or +# something like this to include a specific set of managers. +# MANAGERS=io event message rate_monotonic semaphore timer +# +# UNUSED for loadable modules +MANAGERS=ALL + +all: + +depend: ${LINKS} + +ifndef RTEMS_MAKEFILE_PATH +$(error you need to set the RTEMS_MAKEFILE_PATH environment variable) +endif + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc + +include $(RTEMS_CUSTOM) +ifdef LIBNAME +include $(RTEMS_ROOT)/make/lib.cfg +else +include $(RTEMS_ROOT)/make/leaf.cfg +endif + +# +# (OPTIONAL) Add local stuff here using += +# + +#DEFINES += -DLEDEBUG +CPPFLAGS += -I. -I../libbsdport -I../libbsdport/dummyheaders +CPPFLAGS += $(CPPFLAGS_82542_SUPPORT_$(ENBL_82542_SUPPORT)) +CFLAGS += + +# +# CFLAGS_DEBUG_V are used when the `make debug' target is built. +# To link your application with the non-optimized RTEMS routines, +# uncomment the following line: +# CFLAGS_DEBUG_V += -qrtems_debug +# + +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 += $(sort $(foreach n,$(LINKS),$(firstword $(subst /, ,$(n))))) + +all: ${LINKS} ${ARCH} $(SRCS) $(PGMS) ${LIB} + +#How to make a relocatable object +$(filter %.obj, $(PGMS)): ${OBJS} + $(make-obj) + +#How to make an executable (statically linked) +$(filter %.exe,$(PGMS)): ${LINK_FILES} + $(make-exe) +ifdef ELFEXT +ifdef XSYMS + $(XSYMS) $(@:%.exe=%.$(ELFEXT)) $(@:%.exe=%.sym) +endif +endif + +$(LIB): ${OBJS} + $(make-library) + +ifndef RTEMS_SITE_INSTALLDIR +RTEMS_SITE_INSTALLDIR = $(PROJECT_RELEASE) +endif + +# for each name listed in LINKS, create parent directories (if needed) +# and a symlink to file in . +# E.g., LINKS=a/b/c.h +# creates a/b/c.h -> ../../c.h +$(LINKS): + @if [ ! -d $(dir $@) ] ; then mkdir -p $(dir $@); fi + @ln -s `echo $@ | sed -e 's%[^/]\+[/]\+%../%g'` $@ + +${RTEMS_SITE_INSTALLDIR}/include \ +${RTEMS_SITE_INSTALLDIR}/lib \ +${RTEMS_SITE_INSTALLDIR}/bin: + test -d $@ || mkdir -p $@ +# Install the program(s), appending _g or _p as appropriate. +# for include files, just use $(INSTALL_CHANGE) +# +# - Some BSPs might generate bootable executables in yet another +# format (such as .srec) and you might need to extend the rule +# below so the essential files get installed. YMMV. +ifdef LIBNAME +install: all $(RTEMS_SITE_INSTALLDIR)/lib + $(INSTALL_VARIANT) -m 644 ${LIB} ${RTEMS_SITE_INSTALLDIR}/lib +else +install: all $(RTEMS_SITE_INSTALLDIR)/bin + $(INSTALL_VARIANT) -m 555 ${PGMS} ${PGMS:%.exe=%.bin} ${PGMS:%.exe=%.sym} ${RTEMS_SITE_INSTALLDIR}/bin +endif diff --git a/bsd_eth_drivers/if_le/README.rtems b/bsd_eth_drivers/if_le/README.rtems new file mode 100644 index 0000000..829e1d8 --- /dev/null +++ b/bsd_eth_drivers/if_le/README.rtems @@ -0,0 +1,80 @@ +RTEMS PORT OF THE 'le' ETHERNET DRIVER +====================================== + +This is a port of the FreeBSD 'le' driver as of +2007/7/21 (checked out from FreeBSD/head on that date). + +SUPPORTED BSPs: +- you need 'libbsdport' which in turn needs 'libbspExt' + These work for i386/pc386 and powerpc/new-exception-processing + BSPs, i.e., the BSP must implement and . + +USAGE: +- to attach this driver: + * define a NULL terminated list with all libbsdport supported + drivers you want to include with your application: + + extern driver_t libbsdport_le_pci_driver; + + driver_t *libbsdport_netdriver_table[] = { + &libbsdport_le_pci_driver, + /* other drivers here or upstream of 'le' if they support + * the same hardware but are preferred. + */ + 0 + }; + + * specify libbsdport_netdriver_attach for the 'attach' function + pointer in struct rtems_bsdnet_ifconfig. + + * use the 'name' field in struct rtems_bsdnet_ifconfig to filter + drivers and device instances: + + + + either may be omitted which means that the next available + driver/hardware device is to be used. Here are a few examples: + + "" /* use first device found supported by any driver in the + * libbsdport_driver_table[]. + */ + + "le1" /* use first device supported by the 'le' driver */ + + Notes: Counting instances begins with 1 (not 0). + Consult libbsdport/README for more information. + + +KNOWN ISSUES: +- only the PCI module has been ported, so far. No ISA (yet). + This means that only the + am79900*.* + lance*.* + if_le_pci.c + files are really used. Other files are left here for reference. +- media status (SIOCGIFMEDIA) doesn't work. sc_mediastatus + is not set so the media is always reported as 0. +- 'ignore_broadcast' and 'mtu' settings from + struct rtems_bsdnet_ifconfig are ignored. I haven't seen + many drivers that honour 'ignore_broadcast' and 'mtu' can be + set using a ioctl(). I'm trying to keep changes to BSD sources + minimal... +- ring sizes are restricted to powers of 2. + +OTHER NOTES: +- you can use the 'pcn' driver for 79C971 and upwards + chips. 'pcn' supposedly uses more advanced features + of those chips. +- 'le' works with qemu's 'pcnet32' Am79C970A emulation :-) + +TESTED WITH: + Technobox 10/100-TX Ethernet PMC (AMD Am79C973 chip) + qemu 'pcnet32' emulation + +TESTED ON: + rtems-4.7 + powerpc/beatnik (motorola MVME5500 and MVME6100 VME boards) + i386/pc686 (concurrent technologies PP410 compact PCI) + qemu emulator + +T.S, 200707 diff --git a/bsd_eth_drivers/if_le/am7990.c b/bsd_eth_drivers/if_le/am7990.c new file mode 100644 index 0000000..9768dd8 --- /dev/null +++ b/bsd_eth_drivers/if_le/am7990.c @@ -0,0 +1,627 @@ +/* $NetBSD: am7990.c,v 1.68 2005/12/11 12:21:25 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/am7990.c,v 1.4 2006/12/06 02:14:31 marius Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +static void am7990_meminit(struct lance_softc *); +static void am7990_rint(struct lance_softc *); +static void am7990_tint(struct lance_softc *); +static void am7990_start_locked(struct lance_softc *sc); + +#ifdef LEDEBUG +static void am7990_recv_print(struct lance_softc *, int); +static void am7990_xmit_print(struct lance_softc *, int); +#endif + +int +am7990_config(struct am7990_softc *sc, const char* name, int unit) +{ + int error, mem; + + sc->lsc.sc_meminit = am7990_meminit; + sc->lsc.sc_start_locked = am7990_start_locked; + + error = lance_config(&sc->lsc, name, unit); + if (error != 0) + return (error); + + mem = 0; + sc->lsc.sc_initaddr = mem; + mem += sizeof(struct leinit); + sc->lsc.sc_rmdaddr = mem; + mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; + sc->lsc.sc_tmdaddr = mem; + mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; + sc->lsc.sc_rbufaddr = mem; + mem += LEBLEN * sc->lsc.sc_nrbuf; + sc->lsc.sc_tbufaddr = mem; + mem += LEBLEN * sc->lsc.sc_ntbuf; + + if (mem > sc->lsc.sc_memsize) + panic("%s: memsize", __func__); + + lance_attach(&sc->lsc); + + return (0); +} + +void +am7990_detach(struct am7990_softc *sc) +{ + + lance_detach(&sc->lsc); +} + +/* + * Set up the initialization block and the descriptor rings. + */ +static void +am7990_meminit(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct leinit init; + struct lermd rmd; + struct letmd tmd; + u_long a; + int bix; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + if (ifp->if_flags & IFF_PROMISC) + init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; + else + init.init_mode = LE_MODE_NORMAL; + + init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0]; + init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2]; + init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4]; + lance_setladrf(sc, init.init_ladrf); + + sc->sc_last_rd = 0; + sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; + + a = sc->sc_addr + LE_RMDADDR(sc, 0); + init.init_rdra = a; + init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); + + a = sc->sc_addr + LE_TMDADDR(sc, 0); + init.init_tdra = a; + init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); + + (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); + + /* + * Set up receive ring descriptors. + */ + for (bix = 0; bix < sc->sc_nrbuf; bix++) { + a = sc->sc_addr + LE_RBUFADDR(sc, bix); + rmd.rmd0 = a; + rmd.rmd1_hadr = a >> 16; + rmd.rmd1_bits = LE_R1_OWN; + rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; + rmd.rmd3 = 0; + (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), + sizeof(rmd)); + } + + /* + * Set up transmit ring descriptors. + */ + for (bix = 0; bix < sc->sc_ntbuf; bix++) { + a = sc->sc_addr + LE_TBUFADDR(sc, bix); + tmd.tmd0 = a; + tmd.tmd1_hadr = a >> 16; + tmd.tmd1_bits = 0; + tmd.tmd2 = LE_XMD2_ONES; + tmd.tmd3 = 0; + (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), + sizeof(tmd)); + } +} + +static void +am7990_rint(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m; + struct lermd rmd; + int bix, rp; +#if defined(LANCE_REVC_BUG) + struct ether_header *eh; + /* Make sure this is short-aligned, for ether_cmp(). */ + static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 }; +#endif + + bix = sc->sc_last_rd; + + /* Process all buffers with valid data. */ + for (;;) { + rp = LE_RMDADDR(sc, bix); + (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); + + if (rmd.rmd1_bits & LE_R1_OWN) + break; + + m = NULL; + if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) != + (LE_R1_STP | LE_R1_ENP)) { + if (rmd.rmd1_bits & LE_R1_ERR) { +#ifdef LEDEBUG + if (rmd.rmd1_bits & LE_R1_ENP) { + if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { + if (rmd.rmd1_bits & LE_R1_FRAM) + if_printf(ifp, + "framing error\n"); + if (rmd.rmd1_bits & LE_R1_CRC) + if_printf(ifp, + "crc mismatch\n"); + } + } else + if (rmd.rmd1_bits & LE_R1_OFLO) + if_printf(ifp, "overflow\n"); +#endif + if (rmd.rmd1_bits & LE_R1_BUFF) + if_printf(ifp, + "receive buffer error\n"); + } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != + (LE_R1_STP | LE_R1_ENP)) + if_printf(ifp, "dropping chained buffer\n"); + } else { +#ifdef LEDEBUG + if (sc->sc_flags & LE_DEBUG) + am7990_recv_print(sc, bix); +#endif + /* Pull the packet off the interface. */ + m = lance_get(sc, LE_RBUFADDR(sc, bix), + (int)rmd.rmd3 - ETHER_CRC_LEN); + } + + rmd.rmd1_bits = LE_R1_OWN; + rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; + rmd.rmd3 = 0; + (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); + + if (++bix == sc->sc_nrbuf) + bix = 0; + + if (m != NULL) { + ifp->if_ipackets++; + +#ifdef LANCE_REVC_BUG + /* + * The old LANCE (Rev. C) chips have a bug which + * causes garbage to be inserted in front of the + * received packet. The workaround is to ignore + * packets with an invalid destination address + * (garbage will usually not match). + * Of course, this precludes multicast support... + */ + eh = mtod(m, struct ether_header *); + if (ether_cmp(eh->ether_dhost, sc->sc_enaddr) && + ether_cmp(eh->ether_dhost, bcast_enaddr)) { + m_freem(m); + continue; + } +#endif + + /* Pass the packet up. */ + LE_UNLOCK(sc); + (*ifp->if_input)(ifp, m); + LE_LOCK(sc); + } else + ifp->if_ierrors++; + } + + sc->sc_last_rd = bix; +} + +static void +am7990_tint(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct letmd tmd; + int bix; + + bix = sc->sc_first_td; + + for (;;) { + if (sc->sc_no_td <= 0) + break; + + (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), + sizeof(tmd)); + +#ifdef LEDEBUG + if (sc->sc_flags & LE_DEBUG) + if_printf(ifp, "trans tmd: " + "ladr %04x, hadr %02x, flags %02x, " + "bcnt %04x, mcnt %04x\n", + tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, + tmd.tmd2, tmd.tmd3); +#endif + + if (tmd.tmd1_bits & LE_T1_OWN) + break; + + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + + if (tmd.tmd1_bits & LE_T1_ERR) { + if (tmd.tmd3 & LE_T3_BUFF) + if_printf(ifp, "transmit buffer error\n"); + else if (tmd.tmd3 & LE_T3_UFLO) + if_printf(ifp, "underflow\n"); + if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { + lance_init_locked(sc); + return; + } + if (tmd.tmd3 & LE_T3_LCAR) { + if (sc->sc_flags & LE_CARRIER) + if_link_state_change(ifp, + LINK_STATE_DOWN); + sc->sc_flags &= ~LE_CARRIER; + if (sc->sc_nocarrier) + (*sc->sc_nocarrier)(sc); + else + if_printf(ifp, "lost carrier\n"); + } + if (tmd.tmd3 & LE_T3_LCOL) + ifp->if_collisions++; + if (tmd.tmd3 & LE_T3_RTRY) { +#ifdef LEDEBUG + if_printf(ifp, "excessive collisions, tdr %d\n", + tmd.tmd3 & LE_T3_TDR_MASK); +#endif + ifp->if_collisions += 16; + } + ifp->if_oerrors++; + } else { + if (tmd.tmd1_bits & LE_T1_ONE) + ifp->if_collisions++; + else if (tmd.tmd1_bits & LE_T1_MORE) + /* Real number is unknown. */ + ifp->if_collisions += 2; + ifp->if_opackets++; + } + + if (++bix == sc->sc_ntbuf) + bix = 0; + + --sc->sc_no_td; + } + + sc->sc_first_td = bix; + + sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0; +} + +/* + * Controller interrupt + */ +void +am7990_intr(void *arg) +{ + struct lance_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; + uint16_t isr; + + LE_LOCK(sc); + + if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { + ifp->if_ierrors++; + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + + isr = (*sc->sc_rdcsr)(sc, LE_CSR0); +#if defined(LEDEBUG) && LEDEBUG > 1 + if (sc->sc_flags & LE_DEBUG) + if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); +#endif + if ((isr & LE_C0_INTR) == 0) { + LE_UNLOCK(sc); + return; + } + + /* + * Clear interrupt source flags and turn off interrupts. If we + * don't clear these flags before processing their sources we + * could completely miss some interrupt events as the NIC can + * change these flags while we're in this handler. We turn off + * interrupts so we don't get another RX interrupt while still + * processing the previous one in ifp->if_input() with the + * driver lock dropped. + */ + (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | + LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); + + if (isr & LE_C0_ERR) { + if (isr & LE_C0_BABL) { +#ifdef LEDEBUG + if_printf(ifp, "babble\n"); +#endif + ifp->if_oerrors++; + } +#if 0 + if (isr & LE_C0_CERR) { + if_printf(ifp, "collision error\n"); + ifp->if_collisions++; + } +#endif + if (isr & LE_C0_MISS) { +#ifdef LEDEBUG + if_printf(ifp, "missed packet\n"); +#endif + ifp->if_ierrors++; + } + if (isr & LE_C0_MERR) { + if_printf(ifp, "memory error\n"); + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + } + + if ((isr & LE_C0_RXON) == 0) { + if_printf(ifp, "receiver disabled\n"); + ifp->if_ierrors++; + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + if ((isr & LE_C0_TXON) == 0) { + if_printf(ifp, "transmitter disabled\n"); + ifp->if_oerrors++; + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + + /* + * Pretend we have carrier; if we don't this will be cleared shortly. + */ + if (!(sc->sc_flags & LE_CARRIER)) + if_link_state_change(ifp, LINK_STATE_UP); + sc->sc_flags |= LE_CARRIER; + + if (isr & LE_C0_RINT) + am7990_rint(sc); + if (isr & LE_C0_TINT) + am7990_tint(sc); + + /* Enable interrupts again. */ + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); + + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + am7990_start_locked(sc); + + LE_UNLOCK(sc); +} + +/* + * Set up output on interface. + * Get another datagram to send off of the interface queue, and map it to the + * interface before starting the output. + */ +static void +am7990_start_locked(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct letmd tmd; + struct mbuf *m; + int bix, enq, len, rp; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return; + + bix = sc->sc_last_td; + enq = 0; + + for (; sc->sc_no_td < sc->sc_ntbuf && + !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) { + rp = LE_TMDADDR(sc, bix); + (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); + + if (tmd.tmd1_bits & LE_T1_OWN) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + if_printf(ifp, + "missing buffer, no_td = %d, last_td = %d\n", + sc->sc_no_td, sc->sc_last_td); + } + + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + if (m == 0) + break; + + /* + * If BPF is listening on this interface, let it see the packet + * before we commit it to the wire. + */ + BPF_MTAP(ifp, m); + + /* + * Copy the mbuf chain into the transmit buffer. + */ + len = lance_put(sc, LE_TBUFADDR(sc, bix), m); + +#ifdef LEDEBUG + if (len > ETHERMTU + ETHER_HDR_LEN) + if_printf(ifp, "packet length %d\n", len); +#endif + + /* + * Init transmit registers, and set transmit start flag. + */ + tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; + tmd.tmd2 = -len | LE_XMD2_ONES; + tmd.tmd3 = 0; + + (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); + +#ifdef LEDEBUG + if (sc->sc_flags & LE_DEBUG) + am7990_xmit_print(sc, bix); +#endif + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); + enq++; + + if (++bix == sc->sc_ntbuf) + bix = 0; + + if (++sc->sc_no_td == sc->sc_ntbuf) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + break; + } + } + + sc->sc_last_td = bix; + + if (enq > 0) + sc->sc_wdog_timer = 5; +} + +#ifdef LEDEBUG +static void +am7990_recv_print(struct lance_softc *sc, int no) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ether_header eh; + struct lermd rmd; + uint16_t len; + + (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); + len = rmd.rmd3; + if_printf(ifp, "receive buffer %d, len = %d\n", no, len); + if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); + if_printf(ifp, + "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", + rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); + if (len - ETHER_CRC_LEN >= sizeof(eh)) { + (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); + if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); + printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), + ntohs(eh.ether_type)); + } +} + +static void +am7990_xmit_print(struct lance_softc *sc, int no) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ether_header eh; + struct letmd tmd; + uint16_t len; + + (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); + len = -tmd.tmd2; + if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); + if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); + if_printf(ifp, + "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", + tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); + if (len >= sizeof(eh)) { + (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); + if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); + printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), + ntohs(eh.ether_type)); + } +} +#endif /* LEDEBUG */ diff --git a/bsd_eth_drivers/if_le/if_le_cbus.c b/bsd_eth_drivers/if_le/if_le_cbus.c new file mode 100644 index 0000000..40d0e19 --- /dev/null +++ b/bsd_eth_drivers/if_le/if_le_cbus.c @@ -0,0 +1,451 @@ +/*- + * Copyright (c) 1994-2000 + * Paul Richards. All rights reserved. + * + * PC-98 port by Chiharu Shibata & FreeBSD(98) porting team. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: FreeBSD: src/sys/dev/lnc/if_lnc_cbus.c,v 1.12 2005/11/12 19:14:21 + */ + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/if_le_cbus.c,v 1.5 2007/02/23 12:18:45 piso Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#define LE_CBUS_MEMSIZE (16*1024) +#define CNET98S_IOSIZE 32 +#define CNET98S_RDP 0x10 +#define CNET98S_RAP 0x12 +#define CNET98S_RESET 0x14 +#define CNET98S_BDP 0x16 + +struct le_cbus_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + + int sc_rrid; + struct resource *sc_rres; + bus_space_tag_t sc_regt; + bus_space_handle_t sc_regh; + + int sc_irid; + struct resource *sc_ires; + void *sc_ih; + + bus_dma_tag_t sc_pdmat; + bus_dma_tag_t sc_dmat; + bus_dmamap_t sc_dmam; +}; + +static device_probe_t le_cbus_probe; +static device_attach_t le_cbus_attach; +static device_detach_t le_cbus_detach; +static device_resume_t le_cbus_resume; +static device_suspend_t le_cbus_suspend; + +static device_method_t le_cbus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, le_cbus_probe), + DEVMETHOD(device_attach, le_cbus_attach), + DEVMETHOD(device_detach, le_cbus_detach), + /* We can just use the suspend method here. */ + DEVMETHOD(device_shutdown, le_cbus_suspend), + DEVMETHOD(device_suspend, le_cbus_suspend), + DEVMETHOD(device_resume, le_cbus_resume), + + { 0, 0 } +}; + +DEFINE_CLASS_0(le, le_cbus_driver, le_cbus_methods, sizeof(struct le_cbus_softc)); +DRIVER_MODULE(le, isa, le_cbus_driver, le_devclass, 0, 0); +MODULE_DEPEND(le, ether, 1, 1, 1); + +static bus_addr_t le_ioaddr_cnet98s[CNET98S_IOSIZE] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, + 0x400, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, + 0x408, 0x409, 0x40a, 0x40b, 0x40c, 0x40d, 0x40e, 0x40f, +}; + +static void le_cbus_wrbcr(struct lance_softc *, uint16_t, uint16_t); +#ifdef LEDEBUG +static uint16_t le_cbus_rdbcr(struct lance_softc *, uint16_t); +#endif +static void le_cbus_wrcsr(struct lance_softc *, uint16_t, uint16_t); +static uint16_t le_cbus_rdcsr(struct lance_softc *, uint16_t); +static void le_cbus_hwreset(struct lance_softc *); +static bus_dmamap_callback_t le_cbus_dma_callback; + +static void +le_cbus_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_BDP, val); +} + +#ifdef LEDEBUG +static uint16_t +le_cbus_rdbcr(struct lance_softc *sc, uint16_t port) +{ + struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_BDP)); +} +#endif + +static void +le_cbus_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RDP, val); +} + +static uint16_t +le_cbus_rdcsr(struct lance_softc *sc, uint16_t port) +{ + struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RDP)); +} + +static void +le_cbus_hwreset(struct lance_softc *sc) +{ + struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; + + /* + * NB: These are Contec C-NET(98)S only. + */ + + /* Reset the chip. */ + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET, + bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET)); + DELAY(500); + + /* ISA bus configuration */ + /* ISACSR0 - set Master Mode Read Active time to 300ns. */ + le_cbus_wrbcr(sc, LE_BCR0, 0x0006); + /* ISACSR1 - set Master Mode Write Active time to 300ns. */ + le_cbus_wrbcr(sc, LE_BCR1, 0x0006); +#ifdef LEDEBUG + device_printf(dev, "ISACSR2=0x%x\n", le_cbus_rdbcr(sc, LE_BCR2)); +#endif + /* ISACSR5 - LED1 */ + le_cbus_wrbcr(sc, LE_BCR5, LE_B4_PSE | LE_B4_XMTE); + /* ISACSR6 - LED2 */ + le_cbus_wrbcr(sc, LE_BCR6, LE_B4_PSE | LE_B4_RCVE); + /* ISACSR7 - LED3 */ + le_cbus_wrbcr(sc, LE_BCR7, LE_B4_PSE | LE_B4_COLE); +} + +static void +le_cbus_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct lance_softc *sc = (struct lance_softc *)xsc; + + if (error != 0) + return; + KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); + sc->sc_addr = segs[0].ds_addr; +} + +static int +le_cbus_probe(device_t dev) +{ + struct le_cbus_softc *lesc; + struct lance_softc *sc; + int error; + + /* + * Skip PnP devices as some wedge when trying to probe them as + * C-NET(98)S. + */ + if (isa_get_vendorid(dev)) + return (ENXIO); + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + lesc->sc_rrid = 0; + lesc->sc_rres = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &lesc->sc_rrid, + le_ioaddr_cnet98s, CNET98S_IOSIZE, RF_ACTIVE); + if (lesc->sc_rres == NULL) + return (ENXIO); + isa_load_resourcev(lesc->sc_rres, le_ioaddr_cnet98s, CNET98S_IOSIZE); + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + + /* Reset the chip. */ + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET, + bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET)); + DELAY(500); + + /* Stop the chip and put it in a known state. */ + le_cbus_wrcsr(sc, LE_CSR0, LE_C0_STOP); + DELAY(100); + if (le_cbus_rdcsr(sc, LE_CSR0) != LE_C0_STOP) { + error = ENXIO; + goto fail; + } + le_cbus_wrcsr(sc, LE_CSR3, 0); + device_set_desc(dev, "C-NET(98)S"); + error = BUS_PROBE_DEFAULT; + + fail: + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + return (error); +} + +static int +le_cbus_attach(device_t dev) +{ + struct le_cbus_softc *lesc; + struct lance_softc *sc; + int error, i; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + LE_LOCK_INIT(sc, device_get_nameunit(dev)); + + lesc->sc_rrid = 0; + lesc->sc_rres = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &lesc->sc_rrid, + le_ioaddr_cnet98s, CNET98S_IOSIZE, RF_ACTIVE); + if (lesc->sc_rres == NULL) { + device_printf(dev, "cannot allocate registers\n"); + error = ENXIO; + goto fail_mtx; + } + isa_load_resourcev(lesc->sc_rres, le_ioaddr_cnet98s, CNET98S_IOSIZE); + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + + lesc->sc_irid = 0; + if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate interrupt\n"); + error = ENXIO; + goto fail_rres; + } + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ + 0, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_pdmat); + if (error != 0) { + device_printf(dev, "cannot allocate parent DMA tag\n"); + goto fail_ires; + } + + sc->sc_memsize = LE_CBUS_MEMSIZE; + /* + * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte + * aligned and the ring descriptors must be 8-byte aligned. + */ + error = bus_dma_tag_create( + lesc->sc_pdmat, /* parent */ + 8, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->sc_memsize, /* maxsize */ + 1, /* nsegments */ + sc->sc_memsize, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_dmat); + if (error != 0) { + device_printf(dev, "cannot allocate buffer DMA tag\n"); + goto fail_pdtag; + } + + error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, + BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); + if (error != 0) { + device_printf(dev, "cannot allocate DMA buffer memory\n"); + goto fail_dtag; + } + + sc->sc_addr = 0; + error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, + sc->sc_memsize, le_cbus_dma_callback, sc, 0); + if (error != 0 || sc->sc_addr == 0) { + device_printf(dev, "cannot load DMA buffer map\n"); + goto fail_dmem; + } + + sc->sc_flags = 0; + sc->sc_conf3 = 0; + + /* + * Extract the physical MAC address from the ROM. + */ + for (i = 0; i < sizeof(sc->sc_enaddr); i++) + sc->sc_enaddr[i] = bus_space_read_1(lesc->sc_regt, + lesc->sc_regh, i * 2); + + sc->sc_copytodesc = lance_copytobuf_contig; + sc->sc_copyfromdesc = lance_copyfrombuf_contig; + sc->sc_copytobuf = lance_copytobuf_contig; + sc->sc_copyfrombuf = lance_copyfrombuf_contig; + sc->sc_zerobuf = lance_zerobuf_contig; + + sc->sc_rdcsr = le_cbus_rdcsr; + sc->sc_wrcsr = le_cbus_wrcsr; + sc->sc_hwreset = le_cbus_hwreset; + sc->sc_hwinit = NULL; + sc->sc_hwintr = NULL; + sc->sc_nocarrier = NULL; + sc->sc_mediachange = NULL; + sc->sc_mediastatus = NULL; + sc->sc_supmedia = NULL; + + error = am7990_config(&lesc->sc_am7990, device_get_name(dev), + device_get_unit(dev)); + if (error != 0) { + device_printf(dev, "cannot attach Am7990\n"); + goto fail_dmap; + } + + error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, + NULL, am7990_intr, sc, &lesc->sc_ih); + if (error != 0) { + device_printf(dev, "cannot set up interrupt\n"); + goto fail_am7990; + } + + return (0); + + fail_am7990: + am7990_detach(&lesc->sc_am7990); + fail_dmap: + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + fail_dmem: + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + fail_dtag: + bus_dma_tag_destroy(lesc->sc_dmat); + fail_pdtag: + bus_dma_tag_destroy(lesc->sc_pdmat); + fail_ires: + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + fail_rres: + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + fail_mtx: + LE_LOCK_DESTROY(sc); + return (error); +} + +static int +le_cbus_detach(device_t dev) +{ + struct le_cbus_softc *lesc; + struct lance_softc *sc; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); + am7990_detach(&lesc->sc_am7990); + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + bus_dma_tag_destroy(lesc->sc_dmat); + bus_dma_tag_destroy(lesc->sc_pdmat); + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + LE_LOCK_DESTROY(sc); + + return (0); +} + +static int +le_cbus_suspend(device_t dev) +{ + struct le_cbus_softc *lesc; + + lesc = device_get_softc(dev); + + lance_suspend(&lesc->sc_am7990.lsc); + + return (0); +} + +static int +le_cbus_resume(device_t dev) +{ + struct le_cbus_softc *lesc; + + lesc = device_get_softc(dev); + + lance_resume(&lesc->sc_am7990.lsc); + + return (0); +} diff --git a/bsd_eth_drivers/if_le/if_le_isa.c b/bsd_eth_drivers/if_le/if_le_isa.c new file mode 100644 index 0000000..9299943 --- /dev/null +++ b/bsd_eth_drivers/if_le/if_le_isa.c @@ -0,0 +1,509 @@ +/* $NetBSD: if_le_isa.c,v 1.41 2005/12/24 20:27:41 perry Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/if_le_isa.c,v 1.4 2007/02/23 12:18:45 piso Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#define LE_ISA_MEMSIZE (16*1024) +#define PCNET_RDP 0x10 +#define PCNET_RAP 0x12 + +struct le_isa_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + + bus_size_t sc_rap; /* offsets to LANCE... */ + bus_size_t sc_rdp; /* ...registers */ + + int sc_rrid; + struct resource *sc_rres; + bus_space_tag_t sc_regt; + bus_space_handle_t sc_regh; + + int sc_drid; + struct resource *sc_dres; + + int sc_irid; + struct resource *sc_ires; + void *sc_ih; + + bus_dma_tag_t sc_pdmat; + bus_dma_tag_t sc_dmat; + bus_dmamap_t sc_dmam; +}; + +static device_probe_t le_isa_probe; +static device_attach_t le_isa_attach; +static device_detach_t le_isa_detach; +static device_resume_t le_isa_resume; +static device_suspend_t le_isa_suspend; + +static device_method_t le_isa_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, le_isa_probe), + DEVMETHOD(device_attach, le_isa_attach), + DEVMETHOD(device_detach, le_isa_detach), + /* We can just use the suspend method here. */ + DEVMETHOD(device_shutdown, le_isa_suspend), + DEVMETHOD(device_suspend, le_isa_suspend), + DEVMETHOD(device_resume, le_isa_resume), + + { 0, 0 } +}; + +DEFINE_CLASS_0(le, le_isa_driver, le_isa_methods, sizeof(struct le_isa_softc)); +DRIVER_MODULE(le, isa, le_isa_driver, le_devclass, 0, 0); +MODULE_DEPEND(le, ether, 1, 1, 1); + +struct le_isa_param { + const char *name; + u_long iosize; + bus_size_t rap; + bus_size_t rdp; + bus_size_t macstart; + int macstride; +} static const le_isa_params[] = { + { "BICC Isolan", 24, 0xe, 0xc, 0, 2 }, + { "Novell NE2100", 16, 0x12, 0x10, 0, 1 } +}; + +static struct isa_pnp_id le_isa_ids[] = { + { 0x0322690e, "Cabletron E2200 Single Chip" }, /* CSI2203 */ + { 0x0110490a, "Boca LANCard Combo" }, /* BRI1001 */ + { 0x0100a60a, "Melco Inc. LGY-IV" }, /* BUF0001 */ + { 0xd880d041, "Novell NE2100" }, /* PNP80D8 */ + { 0x0082d041, "Cabletron E2100 Series DNI" }, /* PNP8200 */ + { 0x3182d041, "AMD AM1500T/AM2100" }, /* PNP8231 */ + { 0x8c82d041, "AMD PCnet-ISA" }, /* PNP828C */ + { 0x8d82d041, "AMD PCnet-32" }, /* PNP828D */ + { 0xcefaedfe, "Racal InterLan EtherBlaster" }, /* _WMFACE */ + { 0, NULL } +}; + +static void le_isa_wrcsr(struct lance_softc *, uint16_t, uint16_t); +static uint16_t le_isa_rdcsr(struct lance_softc *, uint16_t); +static bus_dmamap_callback_t le_isa_dma_callback; +static int le_isa_probe_legacy(device_t, const struct le_isa_param *); + +static void +le_isa_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_isa_softc *lesc = (struct le_isa_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rdp, val); +} + +static uint16_t +le_isa_rdcsr(struct lance_softc *sc, uint16_t port) +{ + struct le_isa_softc *lesc = (struct le_isa_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rdp)); +} + +static void +le_isa_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct lance_softc *sc = (struct lance_softc *)xsc; + + if (error != 0) + return; + KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); + sc->sc_addr = segs[0].ds_addr; +} + +static int +le_isa_probe_legacy(device_t dev, const struct le_isa_param *leip) +{ + struct le_isa_softc *lesc; + struct lance_softc *sc; + int error; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + lesc->sc_rrid = 0; + lesc->sc_rres = bus_alloc_resource(dev, SYS_RES_IOPORT, &lesc->sc_rrid, + 0, ~0, leip->iosize, RF_ACTIVE); + if (lesc->sc_rres == NULL) + return (ENXIO); + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + lesc->sc_rap = leip->rap; + lesc->sc_rdp = leip->rdp; + + /* Stop the chip and put it in a known state. */ + le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP); + DELAY(100); + if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP) { + error = ENXIO; + goto fail; + } + le_isa_wrcsr(sc, LE_CSR3, 0); + error = 0; + + fail: + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + return (error); +} + +static int +le_isa_probe(device_t dev) +{ + int i; + + switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { + case 0: + return (BUS_PROBE_DEFAULT); + case ENOENT: + for (i = 0; i < sizeof(le_isa_params) / + sizeof(le_isa_params[0]); i++) { + if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { + device_set_desc(dev, le_isa_params[i].name); + return (BUS_PROBE_DEFAULT); + } + } + /* FALLTHROUGH */ + case ENXIO: + default: + return (ENXIO); + } +} + +static int +le_isa_attach(device_t dev) +{ + struct le_isa_softc *lesc; + struct lance_softc *sc; + bus_size_t macstart, rap, rdp; + int error, i, macstride; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + LE_LOCK_INIT(sc, device_get_nameunit(dev)); + + lesc->sc_rrid = 0; + switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { + case 0: + lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, + &lesc->sc_rrid, RF_ACTIVE); + rap = PCNET_RAP; + rdp = PCNET_RDP; + macstart = 0; + macstride = 1; + break; + case ENOENT: + for (i = 0; i < sizeof(le_isa_params) / + sizeof(le_isa_params[0]); i++) { + if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { + lesc->sc_rres = bus_alloc_resource(dev, + SYS_RES_IOPORT, &lesc->sc_rrid, 0, ~0, + le_isa_params[i].iosize, RF_ACTIVE); + rap = le_isa_params[i].rap; + rdp = le_isa_params[i].rdp; + macstart = le_isa_params[i].macstart; + macstride = le_isa_params[i].macstride; + goto found; + } + } + /* FALLTHROUGH */ + case ENXIO: + default: + device_printf(dev, "cannot determine chip\n"); + error = ENXIO; + goto fail_mtx; + } + + found: + if (lesc->sc_rres == NULL) { + device_printf(dev, "cannot allocate registers\n"); + error = ENXIO; + goto fail_mtx; + } + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + lesc->sc_rap = rap; + lesc->sc_rdp = rdp; + + lesc->sc_drid = 0; + if ((lesc->sc_dres = bus_alloc_resource_any(dev, SYS_RES_DRQ, + &lesc->sc_drid, RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate DMA channel\n"); + error = ENXIO; + goto fail_rres; + } + + lesc->sc_irid = 0; + if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate interrupt\n"); + error = ENXIO; + goto fail_dres; + } + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ + 0, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_pdmat); + if (error != 0) { + device_printf(dev, "cannot allocate parent DMA tag\n"); + goto fail_ires; + } + + sc->sc_memsize = LE_ISA_MEMSIZE; + /* + * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte + * aligned and the ring descriptors must be 8-byte aligned. + */ + error = bus_dma_tag_create( + lesc->sc_pdmat, /* parent */ + 8, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->sc_memsize, /* maxsize */ + 1, /* nsegments */ + sc->sc_memsize, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_dmat); + if (error != 0) { + device_printf(dev, "cannot allocate buffer DMA tag\n"); + goto fail_pdtag; + } + + error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, + BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); + if (error != 0) { + device_printf(dev, "cannot allocate DMA buffer memory\n"); + goto fail_dtag; + } + + sc->sc_addr = 0; + error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, + sc->sc_memsize, le_isa_dma_callback, sc, 0); + if (error != 0 || sc->sc_addr == 0) { + device_printf(dev, "cannot load DMA buffer map\n"); + goto fail_dmem; + } + + isa_dmacascade(rman_get_start(lesc->sc_dres)); + + sc->sc_flags = 0; + sc->sc_conf3 = 0; + + /* + * Extract the physical MAC address from the ROM. + */ + for (i = 0; i < sizeof(sc->sc_enaddr); i++) + sc->sc_enaddr[i] = bus_space_read_1(lesc->sc_regt, + lesc->sc_regh, macstart + i * macstride); + + sc->sc_copytodesc = lance_copytobuf_contig; + sc->sc_copyfromdesc = lance_copyfrombuf_contig; + sc->sc_copytobuf = lance_copytobuf_contig; + sc->sc_copyfrombuf = lance_copyfrombuf_contig; + sc->sc_zerobuf = lance_zerobuf_contig; + + sc->sc_rdcsr = le_isa_rdcsr; + sc->sc_wrcsr = le_isa_wrcsr; + sc->sc_hwreset = NULL; + sc->sc_hwinit = NULL; + sc->sc_hwintr = NULL; + sc->sc_nocarrier = NULL; + sc->sc_mediachange = NULL; + sc->sc_mediastatus = NULL; + sc->sc_supmedia = NULL; + + error = am7990_config(&lesc->sc_am7990, device_get_name(dev), + device_get_unit(dev)); + if (error != 0) { + device_printf(dev, "cannot attach Am7990\n"); + goto fail_dmap; + } + + error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, + NULL, am7990_intr, sc, &lesc->sc_ih); + if (error != 0) { + device_printf(dev, "cannot set up interrupt\n"); + goto fail_am7990; + } + + return (0); + + fail_am7990: + am7990_detach(&lesc->sc_am7990); + fail_dmap: + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + fail_dmem: + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + fail_dtag: + bus_dma_tag_destroy(lesc->sc_dmat); + fail_pdtag: + bus_dma_tag_destroy(lesc->sc_pdmat); + fail_ires: + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + fail_dres: + bus_release_resource(dev, SYS_RES_DRQ, lesc->sc_drid, lesc->sc_dres); + fail_rres: + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + fail_mtx: + LE_LOCK_DESTROY(sc); + return (error); +} + +static int +le_isa_detach(device_t dev) +{ + struct le_isa_softc *lesc; + struct lance_softc *sc; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); + am7990_detach(&lesc->sc_am7990); + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + bus_dma_tag_destroy(lesc->sc_dmat); + bus_dma_tag_destroy(lesc->sc_pdmat); + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + bus_release_resource(dev, SYS_RES_DRQ, lesc->sc_drid, lesc->sc_dres); + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + LE_LOCK_DESTROY(sc); + + return (0); +} + +static int +le_isa_suspend(device_t dev) +{ + struct le_isa_softc *lesc; + + lesc = device_get_softc(dev); + + lance_suspend(&lesc->sc_am7990.lsc); + + return (0); +} + +static int +le_isa_resume(device_t dev) +{ + struct le_isa_softc *lesc; + + lesc = device_get_softc(dev); + + lance_resume(&lesc->sc_am7990.lsc); + + return (0); +} diff --git a/bsd_eth_drivers/if_le/if_le_lebuffer.c b/bsd_eth_drivers/if_le/if_le_lebuffer.c new file mode 100644 index 0000000..5ad8d31 --- /dev/null +++ b/bsd_eth_drivers/if_le/if_le_lebuffer.c @@ -0,0 +1,408 @@ +/*- + * Copyright (c) 2006 Marius Strobl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/if_le_lebuffer.c,v 1.2 2007/02/23 12:18:45 piso Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* + * LANCE registers + */ +#define LEREG1_RDP 0 /* Register Data port */ +#define LEREG1_RAP 2 /* Register Address port */ + +struct le_lebuffer_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + + int sc_brid; + struct resource *sc_bres; + bus_space_tag_t sc_buft; + bus_space_handle_t sc_bufh; + + int sc_rrid; + struct resource *sc_rres; + bus_space_tag_t sc_regt; + bus_space_handle_t sc_regh; + + int sc_irid; + struct resource *sc_ires; + void *sc_ih; +}; + +static devclass_t le_lebuffer_devclass; + +static device_probe_t le_lebuffer_probe; +static device_attach_t le_lebuffer_attach; +static device_detach_t le_lebuffer_detach; +static device_resume_t le_buffer_resume; +static device_suspend_t le_buffer_suspend; + +static device_method_t le_lebuffer_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, le_lebuffer_probe), + DEVMETHOD(device_attach, le_lebuffer_attach), + DEVMETHOD(device_detach, le_lebuffer_detach), + /* We can just use the suspend method here. */ + DEVMETHOD(device_shutdown, le_buffer_suspend), + DEVMETHOD(device_suspend, le_buffer_suspend), + DEVMETHOD(device_resume, le_buffer_resume), + + { 0, 0 } +}; + +DEFINE_CLASS_0(le, le_lebuffer_driver, le_lebuffer_methods, + sizeof(struct le_lebuffer_softc)); +DRIVER_MODULE(le, lebuffer, le_lebuffer_driver, le_lebuffer_devclass, 0, 0); +MODULE_DEPEND(le, ether, 1, 1, 1); + +/* + * Media types supported + */ +static const int le_lebuffer_media[] = { + IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0) +}; +#define NLEMEDIA \ + (sizeof(le_lebuffer_media) / sizeof(le_lebuffer_media[0])) + +static void le_lebuffer_wrcsr(struct lance_softc *, uint16_t, uint16_t); +static uint16_t le_lebuffer_rdcsr(struct lance_softc *, uint16_t); +static void le_lebuffer_copytodesc(struct lance_softc *, void *, int, int); +static void le_lebuffer_copyfromdesc(struct lance_softc *, void *, int, int); +static void le_lebuffer_copytobuf(struct lance_softc *, void *, int, int); +static void le_lebuffer_copyfrombuf(struct lance_softc *, void *, int, int); +static void le_lebuffer_zerobuf(struct lance_softc *, int, int); + +static void +le_lebuffer_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP, val); +} + +static uint16_t +le_lebuffer_rdcsr(struct lance_softc *sc, uint16_t port) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP)); +} + +/* + * It turns out that using bus_space(9) to access the buffers and the + * descriptors yields way more throughput than accessing them via the + * KVA returned by rman_get_virtual(9). The descriptor rings can be + * accessed using 8-bit up to 64-bit operations while the buffers can + * be only accessed using 8-bit and 16-bit operations. + * NB: For whatever reason setting LE_C3_BSWP has no effect with at + * least the 501-2981 (although their 'busmaster-regval' property + * indicates to set LE_C3_BSWP also for these cards), so we need + * to manually byte swap access to the buffers, i.e. the accesses + * going through the RX/TX FIFOs. + */ + +static void +le_lebuffer_copytodesc(struct lance_softc *sc, void *fromv, int off, int len) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + caddr_t from = fromv; + + for (; len >= 8; len -= 8, off += 8, from += 8) + bus_space_write_8(lesc->sc_buft, lesc->sc_bufh, off, + be64dec(from)); + for (; len >= 4; len -= 4, off += 4, from += 4) + bus_space_write_4(lesc->sc_buft, lesc->sc_bufh, off, + be32dec(from)); + for (; len >= 2; len -= 2, off += 2, from += 2) + bus_space_write_2(lesc->sc_buft, lesc->sc_bufh, off, + be16dec(from)); + if (len == 1) + bus_space_write_1(lesc->sc_buft, lesc->sc_bufh, off, + *from); +} + +static void +le_lebuffer_copyfromdesc(struct lance_softc *sc, void *tov, int off, int len) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + caddr_t to = tov; + + for (; len >= 8; len -= 8, off += 8, to += 8) + be64enc(to, + bus_space_read_8(lesc->sc_buft, lesc->sc_bufh, off)); + for (; len >= 4; len -= 4, off += 4, to += 4) + be32enc(to, + bus_space_read_4(lesc->sc_buft, lesc->sc_bufh, off)); + for (; len >= 2; len -= 2, off += 2, to += 2) + be16enc(to, + bus_space_read_2(lesc->sc_buft, lesc->sc_bufh, off)); + if (len == 1) + *to = + bus_space_read_1(lesc->sc_buft, lesc->sc_bufh, off); +} + +static void +le_lebuffer_copytobuf(struct lance_softc *sc, void *fromv, int off, int len) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + caddr_t from = fromv; + + for (; len >= 2; len -= 2, off += 2, from += 2) + bus_space_write_2(lesc->sc_buft, lesc->sc_bufh, off, + le16dec(from)); + if (len == 1) + bus_space_write_1(lesc->sc_buft, lesc->sc_bufh, off + 1, + *from); +} + +static void +le_lebuffer_copyfrombuf(struct lance_softc *sc, void *tov, int off, int len) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + caddr_t to = tov; + + for (; len >= 2; len -= 2, off += 2, to += 2) + le16enc(to, + bus_space_read_2(lesc->sc_buft, lesc->sc_bufh, off)); + if (len == 1) + *to = + bus_space_read_1(lesc->sc_buft, lesc->sc_bufh, off + 1); +} + +static void +le_lebuffer_zerobuf(struct lance_softc *sc, int off, int len) +{ + struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; + + for (; len >= 2; len -= 2, off += 2) + bus_space_write_2(lesc->sc_buft, lesc->sc_bufh, off, 0); + if (len == 1) + bus_space_write_1(lesc->sc_buft, lesc->sc_bufh, off + 1, 0); +} + +static int +le_lebuffer_probe(device_t dev) +{ + + if (strcmp(ofw_bus_get_name(dev), "le") == 0) { + device_set_desc(dev, "LANCE Ethernet"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +le_lebuffer_attach(device_t dev) +{ + struct le_lebuffer_softc *lesc; + struct lance_softc *sc; + int error; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + LE_LOCK_INIT(sc, device_get_nameunit(dev)); + + /* + * The "register space" of the parent is just a buffer where the + * the LANCE descriptor rings and the RX/TX buffers can be stored. + */ + lesc->sc_brid = 0; + lesc->sc_bres = bus_alloc_resource_any(device_get_parent(dev), + SYS_RES_MEMORY, &lesc->sc_brid, RF_ACTIVE); + if (lesc->sc_bres == NULL) { + device_printf(dev, "cannot allocate LANCE buffer\n"); + error = ENXIO; + goto fail_mtx; + } + lesc->sc_buft = rman_get_bustag(lesc->sc_bres); + lesc->sc_bufh = rman_get_bushandle(lesc->sc_bres); + + /* Allocate LANCE registers. */ + lesc->sc_rrid = 0; + lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &lesc->sc_rrid, RF_ACTIVE); + if (lesc->sc_rres == NULL) { + device_printf(dev, "cannot allocate LANCE registers\n"); + error = ENXIO; + goto fail_bres; + } + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + + /* Allocate LANCE interrupt. */ + lesc->sc_irid = 0; + if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate interrupt\n"); + error = ENXIO; + goto fail_rres; + } + + /* + * LANCE view is offset by buffer location. + * Note that we don't use sc->sc_mem. + */ + sc->sc_addr = 0; + sc->sc_memsize = rman_get_size(lesc->sc_bres); + sc->sc_flags = 0; + + /* That old black magic... */ + if (OF_getprop(ofw_bus_get_node(dev), "busmaster-regval", + &sc->sc_conf3, sizeof(sc->sc_conf3)) == -1) + sc->sc_conf3 = LE_C3_ACON | LE_C3_BCON; + /* + * Make sure LE_C3_BSWP is cleared so that for cards where + * that flag actually works le_lebuffer_copy{from,to}buf() + * don't fail... + */ + sc->sc_conf3 &= ~LE_C3_BSWP; + + OF_getetheraddr(dev, sc->sc_enaddr); + + sc->sc_copytodesc = le_lebuffer_copytodesc; + sc->sc_copyfromdesc = le_lebuffer_copyfromdesc; + sc->sc_copytobuf = le_lebuffer_copytobuf; + sc->sc_copyfrombuf = le_lebuffer_copyfrombuf; + sc->sc_zerobuf = le_lebuffer_zerobuf; + + sc->sc_rdcsr = le_lebuffer_rdcsr; + sc->sc_wrcsr = le_lebuffer_wrcsr; + sc->sc_hwreset = NULL; + sc->sc_hwinit = NULL; + sc->sc_hwintr = NULL; + sc->sc_nocarrier = NULL; + sc->sc_mediachange = NULL; + sc->sc_mediastatus = NULL; + sc->sc_supmedia = le_lebuffer_media; + sc->sc_nsupmedia = NLEMEDIA; + sc->sc_defaultmedia = le_lebuffer_media[0]; + + error = am7990_config(&lesc->sc_am7990, device_get_name(dev), + device_get_unit(dev)); + if (error != 0) { + device_printf(dev, "cannot attach Am7990\n"); + goto fail_ires; + } + + error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, + NULL, am7990_intr, sc, &lesc->sc_ih); + if (error != 0) { + device_printf(dev, "cannot set up interrupt\n"); + goto fail_am7990; + } + + return (0); + + fail_am7990: + am7990_detach(&lesc->sc_am7990); + fail_ires: + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + fail_rres: + bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres); + fail_bres: + bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY, + lesc->sc_brid, lesc->sc_bres); + fail_mtx: + LE_LOCK_DESTROY(sc); + return (error); +} + +static int +le_lebuffer_detach(device_t dev) +{ + struct le_lebuffer_softc *lesc; + struct lance_softc *sc; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); + am7990_detach(&lesc->sc_am7990); + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres); + bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY, + lesc->sc_brid, lesc->sc_bres); + LE_LOCK_DESTROY(sc); + + return (0); +} + +static int +le_buffer_suspend(device_t dev) +{ + struct le_lebuffer_softc *lesc; + + lesc = device_get_softc(dev); + + lance_suspend(&lesc->sc_am7990.lsc); + + return (0); +} + +static int +le_buffer_resume(device_t dev) +{ + struct le_lebuffer_softc *lesc; + + lesc = device_get_softc(dev); + + lance_resume(&lesc->sc_am7990.lsc); + + return (0); +} diff --git a/bsd_eth_drivers/if_le/if_le_ledma.c b/bsd_eth_drivers/if_le/if_le_ledma.c new file mode 100644 index 0000000..248b8a0 --- /dev/null +++ b/bsd_eth_drivers/if_le/if_le_ledma.c @@ -0,0 +1,490 @@ +/* $NetBSD: if_le_ledma.c,v 1.26 2005/12/11 12:23:44 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/if_le_ledma.c,v 1.4 2007/02/23 12:18:45 piso Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define LEDMA_ALIGNMENT 8 /* ring desc. alignmet for NCR92C990 */ +#define LEDMA_BOUNDARY (16*1024*1024) /* must not cross 16MB boundary */ +#define LEDMA_MEMSIZE (16*1024) /* LANCE memory size */ +#define LEREG1_RDP 0 /* Register Data Port */ +#define LEREG1_RAP 2 /* Register Address Port */ + +struct le_dma_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + + int sc_rrid; + struct resource *sc_rres; + bus_space_tag_t sc_regt; + bus_space_handle_t sc_regh; + + int sc_irid; + struct resource *sc_ires; + void *sc_ih; + + bus_dma_tag_t sc_dmat; + bus_dmamap_t sc_dmam; + bus_addr_t sc_laddr; /* LANCE DMA address */ + + struct lsi64854_softc *sc_dma; /* pointer to DMA engine */ +}; + +static device_probe_t le_dma_probe; +static device_attach_t le_dma_attach; +static device_detach_t le_dma_detach; +static device_resume_t le_dma_resume; +static device_suspend_t le_dma_suspend; + +static device_method_t le_dma_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, le_dma_probe), + DEVMETHOD(device_attach, le_dma_attach), + DEVMETHOD(device_detach, le_dma_detach), + /* We can just use the suspend method here. */ + DEVMETHOD(device_shutdown, le_dma_suspend), + DEVMETHOD(device_suspend, le_dma_suspend), + DEVMETHOD(device_resume, le_dma_resume), + + { 0, 0 } +}; + +DEFINE_CLASS_0(le, le_dma_driver, le_dma_methods, sizeof(struct le_dma_softc)); +DRIVER_MODULE(le, dma, le_dma_driver, le_devclass, 0, 0); +MODULE_DEPEND(le, ether, 1, 1, 1); + +/* + * Media types supported + */ +static const int le_dma_supmedia[] = { + IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0) +}; + +static void le_dma_wrcsr(struct lance_softc *, uint16_t, uint16_t); +static uint16_t le_dma_rdcsr(struct lance_softc *, uint16_t); +static void le_dma_setutp(struct lance_softc *); +static void le_dma_setaui(struct lance_softc *); +static int le_dma_supmediachange(struct lance_softc *); +static void le_dma_supmediastatus(struct lance_softc *, struct ifmediareq *); +static void le_dma_hwreset(struct lance_softc *); +static int le_dma_hwintr(struct lance_softc *); +static void le_dma_nocarrier(struct lance_softc *); +static bus_dmamap_callback_t le_dma_dma_callback; + +static void +le_dma_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_dma_softc *lesc = (struct le_dma_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP, val); +} + +static uint16_t +le_dma_rdcsr(struct lance_softc *sc, uint16_t port) +{ + struct le_dma_softc *lesc = (struct le_dma_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP)); +} + +static void +le_dma_setutp(struct lance_softc *sc) +{ + struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; + + L64854_SCSR(dma, L64854_GCSR(dma) | E_TP_AUI); + DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ +} + +static void +le_dma_setaui(struct lance_softc *sc) +{ + struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; + + L64854_SCSR(dma, L64854_GCSR(dma) & ~E_TP_AUI); + DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ +} + +static int +le_dma_supmediachange(struct lance_softc *sc) +{ + struct ifmedia *ifm = &sc->sc_media; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + /* + * Switch to the selected media. If autoselect is set, we don't + * really have to do anything. We'll switch to the other media + * when we detect loss of carrier. + */ + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_10_T: + le_dma_setutp(sc); + break; + + case IFM_10_5: + le_dma_setaui(sc); + break; + + case IFM_AUTO: + break; + + default: + return (EINVAL); + } + + return (0); +} + +static void +le_dma_supmediastatus(struct lance_softc *sc, struct ifmediareq *ifmr) +{ + struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; + + /* + * Notify the world which media we're currently using. + */ + if (L64854_GCSR(dma) & E_TP_AUI) + ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0); + else + ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0); +} + +static void +le_dma_hwreset(struct lance_softc *sc) +{ + struct le_dma_softc *lesc = (struct le_dma_softc *)sc; + struct lsi64854_softc *dma = lesc->sc_dma; + uint32_t aui_bit, csr; + + /* + * Reset DMA channel. + */ + csr = L64854_GCSR(dma); + aui_bit = csr & E_TP_AUI; + DMA_RESET(dma); + + /* Write bits 24-31 of Lance address. */ + bus_space_write_4(dma->sc_regt, dma->sc_regh, L64854_REG_ENBAR, + lesc->sc_laddr & 0xff000000); + + DMA_ENINTR(dma); + + /* + * Disable E-cache invalidates on chip writes. + * Retain previous cable selection bit. + */ + csr = L64854_GCSR(dma); + csr |= (E_DSBL_WR_INVAL | aui_bit); + L64854_SCSR(dma, csr); + DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ +} + +static int +le_dma_hwintr(struct lance_softc *sc) +{ + struct le_dma_softc *lesc = (struct le_dma_softc *)sc; + struct lsi64854_softc *dma = lesc->sc_dma; + + return (DMA_INTR(dma)); +} + +static void +le_dma_nocarrier(struct lance_softc *sc) +{ + struct le_dma_softc *lesc = (struct le_dma_softc *)sc; + + /* + * Check if the user has requested a certain cable type, and + * if so, honor that request. + */ + + if (L64854_GCSR(lesc->sc_dma) & E_TP_AUI) { + switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { + case IFM_10_5: + case IFM_AUTO: + if_printf(sc->sc_ifp, "lost carrier on UTP port, " + "switching to AUI port\n"); + le_dma_setaui(sc); + } + } else { + switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { + case IFM_10_T: + case IFM_AUTO: + if_printf(sc->sc_ifp, "lost carrier on AUI port, " + "switching to UTP port\n"); + le_dma_setutp(sc); + } + } +} + +static void +le_dma_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct le_dma_softc *lesc = (struct le_dma_softc *)xsc; + + if (error != 0) + return; + KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); + lesc->sc_laddr = segs[0].ds_addr; +} + +static int +le_dma_probe(device_t dev) +{ + + if (strcmp(ofw_bus_get_name(dev), "le") == 0) { + device_set_desc(dev, "LANCE Ethernet"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +le_dma_attach(device_t dev) +{ + struct le_dma_softc *lesc; + struct lsi64854_softc *dma; + struct lance_softc *sc; + int error; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + LE_LOCK_INIT(sc, device_get_nameunit(dev)); + + /* + * Establish link to `ledma' device. + * XXX hackery. + */ + dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev)); + lesc->sc_dma = dma; + lesc->sc_dma->sc_client = lesc; + + lesc->sc_rrid = 0; + lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &lesc->sc_rrid, RF_ACTIVE); + if (lesc->sc_rres == NULL) { + device_printf(dev, "cannot allocate registers\n"); + error = ENXIO; + goto fail_mtx; + } + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + + lesc->sc_irid = 0; + if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate interrupt\n"); + error = ENXIO; + goto fail_rres; + } + + sc->sc_memsize = LEDMA_MEMSIZE; + error = bus_dma_tag_create( + dma->sc_parent_dmat, /* parent */ + LEDMA_ALIGNMENT, /* alignment */ + LEDMA_BOUNDARY, /* boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->sc_memsize, /* maxsize */ + 1, /* nsegments */ + sc->sc_memsize, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_dmat); + if (error != 0) { + device_printf(dev, "cannot allocate buffer DMA tag\n"); + goto fail_ires; + } + + error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, + BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); + if (error != 0) { + device_printf(dev, "cannot allocate DMA buffer memory\n"); + goto fail_dtag; + } + + lesc->sc_laddr = 0; + error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, + sc->sc_memsize, le_dma_dma_callback, lesc, 0); + if (error != 0 || lesc->sc_laddr == 0) { + device_printf(dev, "cannot load DMA buffer map\n"); + goto fail_dmem; + } + + sc->sc_addr = lesc->sc_laddr & 0xffffff; + sc->sc_flags = 0; + sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; + + sc->sc_mediachange = le_dma_supmediachange; + sc->sc_mediastatus = le_dma_supmediastatus; + sc->sc_supmedia = le_dma_supmedia; + sc->sc_nsupmedia = sizeof(le_dma_supmedia) / sizeof(le_dma_supmedia[0]); + sc->sc_defaultmedia = le_dma_supmedia[0]; + + OF_getetheraddr(dev, sc->sc_enaddr); + + sc->sc_copytodesc = lance_copytobuf_contig; + sc->sc_copyfromdesc = lance_copyfrombuf_contig; + sc->sc_copytobuf = lance_copytobuf_contig; + sc->sc_copyfrombuf = lance_copyfrombuf_contig; + sc->sc_zerobuf = lance_zerobuf_contig; + + sc->sc_rdcsr = le_dma_rdcsr; + sc->sc_wrcsr = le_dma_wrcsr; + sc->sc_hwreset = le_dma_hwreset; + sc->sc_hwintr = le_dma_hwintr; + sc->sc_nocarrier = le_dma_nocarrier; + + error = am7990_config(&lesc->sc_am7990, device_get_name(dev), + device_get_unit(dev)); + if (error != 0) { + device_printf(dev, "cannot attach Am7990\n"); + goto fail_dmap; + } + + error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, + NULL, am7990_intr, sc, &lesc->sc_ih); + if (error != 0) { + device_printf(dev, "cannot set up interrupt\n"); + goto fail_am7990; + } + + return (0); + + fail_am7990: + am7990_detach(&lesc->sc_am7990); + fail_dmap: + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + fail_dmem: + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + fail_dtag: + bus_dma_tag_destroy(lesc->sc_dmat); + fail_ires: + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + fail_rres: + bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres); + fail_mtx: + LE_LOCK_DESTROY(sc); + return (error); +} + +static int +le_dma_detach(device_t dev) +{ + struct le_dma_softc *lesc; + struct lance_softc *sc; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am7990.lsc; + + bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); + am7990_detach(&lesc->sc_am7990); + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + bus_dma_tag_destroy(lesc->sc_dmat); + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres); + LE_LOCK_DESTROY(sc); + + return (0); +} + +static int +le_dma_suspend(device_t dev) +{ + struct le_dma_softc *lesc; + + lesc = device_get_softc(dev); + + lance_suspend(&lesc->sc_am7990.lsc); + + return (0); +} + +static int +le_dma_resume(device_t dev) +{ + struct le_dma_softc *lesc; + + lesc = device_get_softc(dev); + + lance_resume(&lesc->sc_am7990.lsc); + + return (0); +} diff --git a/bsd_eth_drivers/if_le/lebuffer_sbus.c b/bsd_eth_drivers/if_le/lebuffer_sbus.c new file mode 100644 index 0000000..b9414f2 --- /dev/null +++ b/bsd_eth_drivers/if_le/lebuffer_sbus.c @@ -0,0 +1,300 @@ +/*- + * Copyright (c) 2006 Marius Strobl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/lebuffer_sbus.c,v 1.1 2007/01/20 12:53:30 marius Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +struct lebuffer_devinfo { + struct ofw_bus_devinfo ldi_obdinfo; + struct resource_list ldi_rl; +}; + +static devclass_t lebuffer_devclass; + +static device_probe_t lebuffer_probe; +static device_attach_t lebuffer_attach; +static device_detach_t lebuffer_detach; +static bus_print_child_t lebuffer_print_child; +static bus_probe_nomatch_t lebuffer_probe_nomatch; +static bus_get_resource_list_t lebuffer_get_resource_list; +static ofw_bus_get_devinfo_t lebuffer_get_devinfo; + +static struct lebuffer_devinfo *lebuffer_setup_dinfo(device_t, phandle_t); +static void lebuffer_destroy_dinfo(struct lebuffer_devinfo *); +static int lebuffer_print_res(struct lebuffer_devinfo *); + +static device_method_t lebuffer_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, lebuffer_probe), + DEVMETHOD(device_attach, lebuffer_attach), + DEVMETHOD(device_detach, lebuffer_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, lebuffer_print_child), + DEVMETHOD(bus_probe_nomatch, lebuffer_probe_nomatch), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_get_resource_list, lebuffer_get_resource_list), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, lebuffer_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + + { 0, 0 } +}; + +DEFINE_CLASS_0(lebuffer, lebuffer_driver, lebuffer_methods, 1); +DRIVER_MODULE(lebuffer, sbus, lebuffer_driver, lebuffer_devclass, 0, 0); + +static int +lebuffer_probe(device_t dev) +{ + const char *name; + + name = ofw_bus_get_name(dev); + if (strcmp(name, "lebuffer") == 0) { + device_set_desc_copy(dev, name); + return (0); + } + return (ENXIO); +} + +static int +lebuffer_attach(device_t dev) +{ + struct lebuffer_devinfo *ldi; + device_t cdev; + phandle_t child; + int children; + + children = 0; + for (child = OF_child(ofw_bus_get_node(dev)); child != 0; + child = OF_peer(child)) { + if ((ldi = lebuffer_setup_dinfo(dev, child)) == NULL) + continue; + if (children != 0) { + device_printf(dev, + "<%s>: only one child per buffer supported\n", + ldi->ldi_obdinfo.obd_name); + lebuffer_destroy_dinfo(ldi); + continue; + } + if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + ldi->ldi_obdinfo.obd_name); + lebuffer_destroy_dinfo(ldi); + continue; + } + device_set_ivars(cdev, ldi); + children++; + } + return (bus_generic_attach(dev)); +} + +static int +lebuffer_detach(device_t dev) +{ + device_t *children; + int i, nchildren; + + bus_generic_detach(dev); + if (device_get_children(dev, &children, &nchildren) == 0) { + for (i = 0; i < nchildren; i++) { + lebuffer_destroy_dinfo(device_get_ivars(children[i])); + device_delete_child(dev, children[i]); + } + free(children, M_TEMP); + } + return (0); +} + +static struct lebuffer_devinfo * +lebuffer_setup_dinfo(device_t dev, phandle_t node) +{ + struct lebuffer_devinfo *ldi; + struct sbus_regs *reg; + uint32_t base, iv, *intr; + int i, nreg, nintr, slot, rslot; + + ldi = malloc(sizeof(*ldi), M_DEVBUF, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&ldi->ldi_obdinfo, node) != 0) { + free(ldi, M_DEVBUF); + return (NULL); + } + resource_list_init(&ldi->ldi_rl); + slot = -1; + nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); + if (nreg == -1) { + device_printf(dev, "<%s>: incomplete\n", + ldi->ldi_obdinfo.obd_name); + goto fail; + } + for (i = 0; i < nreg; i++) { + base = reg[i].sbr_offset; + if (SBUS_ABS(base)) { + rslot = SBUS_ABS_TO_SLOT(base); + base = SBUS_ABS_TO_OFFSET(base); + } else + rslot = reg[i].sbr_slot; + if (slot != -1 && slot != rslot) { + device_printf(dev, "<%s>: multiple slots\n", + ldi->ldi_obdinfo.obd_name); + free(reg, M_OFWPROP); + goto fail; + } + slot = rslot; + + resource_list_add(&ldi->ldi_rl, SYS_RES_MEMORY, i, base, + base + reg[i].sbr_size, reg[i].sbr_size); + } + free(reg, M_OFWPROP); + if (slot != sbus_get_slot(dev)) { + device_printf(dev, "<%s>: parent and child slot do not match\n", + ldi->ldi_obdinfo.obd_name); + goto fail; + } + + /* + * The `interrupts' property contains the SBus interrupt level. + */ + nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), + (void **)&intr); + if (nintr != -1) { + for (i = 0; i < nintr; i++) { + iv = intr[i]; + /* + * SBus card devices need the slot number encoded into + * the vector as this is generally not done. + */ + if ((iv & INTMAP_OBIO_MASK) == 0) + iv |= slot << 3; + /* Set the IGN as appropriate. */ + iv |= sbus_get_ign(dev) << INTMAP_IGN_SHIFT; + resource_list_add(&ldi->ldi_rl, SYS_RES_IRQ, i, + iv, iv, 1); + } + free(intr, M_OFWPROP); + } + return (ldi); + + fail: + lebuffer_destroy_dinfo(ldi); + return (NULL); +} + +static void +lebuffer_destroy_dinfo(struct lebuffer_devinfo *dinfo) +{ + + resource_list_free(&dinfo->ldi_rl); + ofw_bus_gen_destroy_devinfo(&dinfo->ldi_obdinfo); + free(dinfo, M_DEVBUF); +} + +static int +lebuffer_print_child(device_t dev, device_t child) +{ + int rv; + + rv = bus_print_child_header(dev, child); + rv += lebuffer_print_res(device_get_ivars(child)); + rv += bus_print_child_footer(dev, child); + return (rv); +} + +static void +lebuffer_probe_nomatch(device_t dev, device_t child) +{ + const char *type; + + device_printf(dev, "<%s>", ofw_bus_get_name(child)); + lebuffer_print_res(device_get_ivars(child)); + type = ofw_bus_get_type(child); + printf(" type %s (no driver attached)\n", + type != NULL ? type : "unknown"); +} + +static struct resource_list * +lebuffer_get_resource_list(device_t dev, device_t child) +{ + struct lebuffer_devinfo *ldi; + + ldi = device_get_ivars(child); + return (&ldi->ldi_rl); +} + +static const struct ofw_bus_devinfo * +lebuffer_get_devinfo(device_t bus, device_t child) +{ + struct lebuffer_devinfo *ldi; + + ldi = device_get_ivars(child); + return (&ldi->ldi_obdinfo); +} + +static int +lebuffer_print_res(struct lebuffer_devinfo *ldi) +{ + int rv; + + rv = 0; + rv += resource_list_print_type(&ldi->ldi_rl, "mem", SYS_RES_MEMORY, + "%#lx"); + rv += resource_list_print_type(&ldi->ldi_rl, "irq", SYS_RES_IRQ, "%ld"); + return (rv); +} diff --git a/bsd_eth_drivers/if_pcn/Makefile b/bsd_eth_drivers/if_pcn/Makefile new file mode 100644 index 0000000..7e52001 --- /dev/null +++ b/bsd_eth_drivers/if_pcn/Makefile @@ -0,0 +1,143 @@ +# +# Makefile.leaf,v 1.7 2002/07/22 22:56:09 joel Exp +# +# Templates/Makefile.leaf +# Template leaf node Makefile +# +# +LIBNAME=libif_pcn.a + +LINKS=pci/if_pcnreg.h + +# C source names, if any, go here -- minus the .c +C_PIECES= + +C_PIECES+=if_pcn + +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +# C++ source names, if any, go here -- minus the .cc +CC_PIECES= +CC_FILES=$(CC_PIECES:%=%.cc) +CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .S +S_PIECES= +S_FILES=$(S_PIECES:%=%.S) +S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +# If your PGMS target has the '.exe' extension, a statically +# linked application is generated. +# If it has a '.obj' extension, a loadable module is built. +# +# +ifdef LIBNAME +LIB=${ARCH}/${LIBNAME} +else +PGMS=${ARCH}/if_pcn.obj +endif + +# List of RTEMS Classic API Managers to be included in the application +# goes here. Use: +# MANAGERS=all +# to include all RTEMS Classic API Managers in the application or +# something like this to include a specific set of managers. +# MANAGERS=io event message rate_monotonic semaphore timer +# +# UNUSED for loadable modules +MANAGERS=ALL + +ifndef RTEMS_MAKEFILE_PATH +$(error you need to set the RTEMS_MAKEFILE_PATH environment variable) +endif + +all: + +depend: ${LINKS} + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc + +include $(RTEMS_CUSTOM) +ifdef LIBNAME +include $(RTEMS_ROOT)/make/lib.cfg +else +include $(RTEMS_ROOT)/make/leaf.cfg +endif + +# +# (OPTIONAL) Add local stuff here using += +# + +#DEFINES += -DPCN_DEBUG +CPPFLAGS += -I. -I../libbsdport -I../libbsdport/dummyheaders +CFLAGS += + +# +# CFLAGS_DEBUG_V are used when the `make debug' target is built. +# To link your application with the non-optimized RTEMS routines, +# uncomment the following line: +# CFLAGS_DEBUG_V += -qrtems_debug +# + +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 += pci + +all: ${LINKS} ${ARCH} $(SRCS) $(PGMS) ${LIB} + +pci/%:% + if [ ! -d pci ]; then mkdir -p pci; fi ; ln -s ../$^ $@ + +#How to make a relocatable object +$(filter %.obj, $(PGMS)): ${OBJS} + $(make-obj) + +#How to make an executable (statically linked) +$(filter %.exe,$(PGMS)): ${LINK_FILES} + $(make-exe) +ifdef ELFEXT +ifdef XSYMS + $(XSYMS) $(@:%.exe=%.$(ELFEXT)) $(@:%.exe=%.sym) +endif +endif + +$(LIB): ${OBJS} + $(make-library) + +ifndef RTEMS_SITE_INSTALLDIR +RTEMS_SITE_INSTALLDIR = $(PROJECT_RELEASE) +endif + +${RTEMS_SITE_INSTALLDIR}/include \ +${RTEMS_SITE_INSTALLDIR}/lib \ +${RTEMS_SITE_INSTALLDIR}/bin: + test -d $@ || mkdir -p $@ +# Install the program(s), appending _g or _p as appropriate. +# for include files, just use $(INSTALL_CHANGE) +# +# - Some BSPs might generate bootable executables in yet another +# format (such as .srec) and you might need to extend the rule +# below so the essential files get installed. YMMV. +ifdef LIBNAME +install: all $(RTEMS_SITE_INSTALLDIR)/lib + $(INSTALL_VARIANT) -m 644 ${LIB} ${RTEMS_SITE_INSTALLDIR}/lib +else +install: all $(RTEMS_SITE_INSTALLDIR)/bin + $(INSTALL_VARIANT) -m 555 ${PGMS} ${PGMS:%.exe=%.bin} ${PGMS:%.exe=%.sym} ${RTEMS_SITE_INSTALLDIR}/bin +endif diff --git a/bsd_eth_drivers/if_pcn/README.rtems b/bsd_eth_drivers/if_pcn/README.rtems new file mode 100644 index 0000000..ab8ba09 --- /dev/null +++ b/bsd_eth_drivers/if_pcn/README.rtems @@ -0,0 +1,73 @@ +RTEMS PORT OF THE 'pcn' ETHERNET DRIVER +======================================= + +This is a port of the FreeBSD 'pcn' driver as of +2007/7/17 (checked out from FreeBSD/head on that date). + +SUPPORTED BSPs: +- you need 'libbsdport' which in turn needs 'libbspExt' + These work for i386/pc386 and powerpc/new-exception-processing + BSPs, i.e., the BSP must implement and . + +USAGE: +- to attach this driver: + * define a NULL terminated list with all libbsdport supported + drivers you want to include with your application: + + extern driver_t libbsdport_pcn_driver; + + driver_t *libbsdport_netdriver_table[] = { + &libbsdport_pcn_driver, + /* other drivers here or upstream of 'pcn' if they support + * the same hardware but are preferred. + */ + 0 + }; + + * specify libbsdport_netdriver_attach for the 'attach' function + pointer in struct rtems_bsdnet_ifconfig. + + * use the 'name' field in struct rtems_bsdnet_ifconfig to filter + drivers and device instances: + + + + either may be omitted which means that the next available + driver/hardware device is to be used. Here are a few examples: + + "" /* use first device found supported by any driver in the + * libbsdport_driver_table[]. + */ + + "pcn2" /* use second device supported by the 'pcn' driver */ + + Notes: Counting instances begins with 1 (not 0). + Consult libbsdport/README for more information. + +KNOWN ISSUES: +- 'ignore_broadcast' and 'mtu' settings from + struct rtems_bsdnet_ifconfig are ignored. I haven't seen + many drivers that honour 'ignore_broadcast' and 'mtu' can be + set using a ioctl(). I'm trying to keep changes to BSD sources + minimal... +- ring sizes are restricted fixed to hardcoded size. +- Only the internal phy of the 973/975 chips are supported + and will allow SIOCGIFMEDIA/SIOCSIFMEDIA to work. I don't know + what happens with other chips or external phys. + Probably, the factory-default setup should work with autonegotiation + but the ioctls wont. YMMV. + +OTHER NOTES: +- you can use the (more generic) 'le' driver for the 79C971 + and upwards chips, too, but 'pcn' supposedly uses more advanced + features of these chips. + +TESTED WITH: + Technobox 10/100-TX Ethernet PMC (AMD Am79C973 chip) + +TESTED ON: + rtems-4.7 + powerpc/beatnik (motorola MVME5500 and MVME6100 VME boards) + i386/pc686 (concurrent technologies PP410 compact PCI) + +T.S, 200707 diff --git a/bsd_eth_drivers/libbsdport/Makefile b/bsd_eth_drivers/libbsdport/Makefile new file mode 100644 index 0000000..fbf9f35 --- /dev/null +++ b/bsd_eth_drivers/libbsdport/Makefile @@ -0,0 +1,116 @@ +# +# Makefile.lib,v 1.5 2000/06/12 15:00:14 joel Exp +# +# Templates/Makefile.lib +# Template library Makefile +# + +LIBNAME=libbsdport.a +LIB=${ARCH}/${LIBNAME} + +# C and C++ source names, if any, go here -- minus the .c or .cc +C_PIECES=rtems_callout rtems_taskqueue rtems_udelay ifstuff devicet alldrv +C_PIECES+=contigmalloc sysbus malloc ifmedia +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +CC_PIECES= +CC_FILES=$(CC_PIECES:%=%.cc) +CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o) + +H_FILES=libbsdport_api.h rtems_verscheck.h + +LINKS+=sys/taskqueue.h +LINKS+=sys/bus.h +LINKS+=sys/mutex.h +LINKS+=bsp/rtems_verscheck.h + +DUMMYHEADERS+=dummyheaders/machine/bus.h +DUMMYHEADERS+=dummyheaders/machine/resource.h +DUMMYHEADERS+=dummyheaders/dev/pci/pcivar.h +DUMMYHEADERS+=dummyheaders/dev/pci/pcireg.h +DUMMYHEADERS+=dummyheaders/dev/mii/miivar.h +DUMMYHEADERS+=dummyheaders/sys/module.h +DUMMYHEADERS+=dummyheaders/sys/rman.h +DUMMYHEADERS+=dummyheaders/sys/kthread.h +DUMMYHEADERS+=dummyheaders/sys/endian.h +DUMMYHEADERS+=dummyheaders/net/if_vlan_var.h +DUMMYHEADERS+=dummyheaders/netinet/ip6.h +DUMMYHEADERS+=dummyheaders/vm/pmap.h +DUMMYHEADERS+=dummyheaders/miibus_if.h + +# Assembly source names, if any, go here -- minus the .S +S_PIECES= +S_FILES=$(S_PIECES:%=%.S) +S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +all: + +depend: ${LINKS} + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc + +include $(RTEMS_CUSTOM) +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += +CPPFLAGS += -I. +CFLAGS += + +# +# 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 += dummyheaders +CLOBBER_ADDITIONS += $(sort $(foreach n,$(LINKS),$(firstword $(subst /, ,$(n))))) + +all: ${DUMMYHEADERS} ${LINKS} ${ARCH} $(SRCS) $(LIB) + +$(LIB): ${OBJS} + $(make-library) + +dummyheaders/%: + @if [ ! -d `dirname $@` ] ; then mkdir -p `dirname $@`; fi + @touch $@ + +# for each name listed in LINKS, create parent directories (if needed) +# and a symlink to file in . +# E.g., LINKS=a/b/c.h +# creates a/b/c.h -> ../../c.h +$(LINKS): + @if [ ! -d $(dir $@) ] ; then mkdir -p $(dir $@); fi + @ln -s `echo $@ | sed -e 's%[^/]\+[/]\+%../%g'` $@ + +ifndef RTEMS_SITE_INSTALLDIR +RTEMS_SITE_INSTALLDIR = $(PROJECT_RELEASE) +endif + +ifndef RTEMS_SITE_BSP_INSTALLDIR +RTEMS_SITE_BSP_INSTALLDIR = $(RTEMS_SITE_INSTALLDIR) +endif + +${RTEMS_SITE_INSTALLDIR}/include/bsp \ +${RTEMS_SITE_INSTALLDIR}/lib \ +${RTEMS_SITE_INSTALLDIR}/bin: + test -d $@ || mkdir -p $@ + +# Install the program(s), appending _g or _p as appropriate. +# for include files, just use $(INSTALL_CHANGE) +# + +install: all $(RTEMS_SITE_INSTALLDIR)/lib $(RTEMS_SITE_INSTALLDIR)/include/bsp + $(INSTALL_VARIANT) -m 644 ${LIB} ${RTEMS_SITE_INSTALLDIR}/lib + $(INSTALL_CHANGE) -m 644 ${H_FILES} ${RTEMS_SITE_INSTALLDIR}/include/bsp + + diff --git a/bsd_eth_drivers/libbsdport/Makefile.am b/bsd_eth_drivers/libbsdport/Makefile.am index 44096b5..e6e31cd 100644 --- a/bsd_eth_drivers/libbsdport/Makefile.am +++ b/bsd_eth_drivers/libbsdport/Makefile.am @@ -38,9 +38,6 @@ DUMMYHEADERS+=dummyheaders/netinet/ip6.h DUMMYHEADERS+=dummyheaders/vm/pmap.h DUMMYHEADERS+=dummyheaders/miibus_if.h -DUMMYHEADERS+=dummyheaders/miidevs.h -DUMMYHEADERS+=dummyheaders/dev/mii/brgphyreg.h - BUILT_SOURCES= include ../links.am diff --git a/bsd_eth_drivers/libbsdport/alldrv.c b/bsd_eth_drivers/libbsdport/alldrv.c index 0738179..f81b95a 100644 --- a/bsd_eth_drivers/libbsdport/alldrv.c +++ b/bsd_eth_drivers/libbsdport/alldrv.c @@ -5,7 +5,6 @@ driver_t *libbsdport_netdriver_table_all[] = { &libbsdport_em_driver, &libbsdport_pcn_driver, &libbsdport_le_pci_driver, - &libbsdport_re_driver, 0 }; diff --git a/bsd_eth_drivers/libbsdport/bus.h b/bsd_eth_drivers/libbsdport/bus.h index 76d78a8..19cb24f 100644 --- a/bsd_eth_drivers/libbsdport/bus.h +++ b/bsd_eth_drivers/libbsdport/bus.h @@ -156,10 +156,6 @@ bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filt /* Flags currently ignored... */ #define INTR_MPSAFE 0 #define INTR_TYPE_NET 0 -/* INTR_FAST indicates that a 'handler' is actually - * a 'fast' handler which already uses taskqueues - */ -#define INTR_FAST 1 int bus_teardown_intr(device_t dev, struct resource *r, void *cookiep); @@ -196,16 +192,6 @@ rman_get_bustag(struct resource *r); #define BUS_DMA_COHERENT 0 #endif -#ifndef BUS_DMA_ZERO -/* ignored anyways */ -#define BUS_DMA_ZERO 0 -#endif - -#ifndef BUS_DMA_ALLOCNOW -/* ignored anyways */ -#define BUS_DMA_ALLOCNOW 0 -#endif - /* unused */ #ifndef BUS_SPACE_MAXADDR #define BUS_SPACE_MAXADDR 0xdeadbeef @@ -279,10 +265,10 @@ bus_get_dma_tag(device_t dev) return 0; } -typedef void bus_dmamap_callback_t (void *arg, bus_dma_segment_t *segs, int nseg, int error); +typedef void bus_dmamap_callback_t (void *, bus_dma_segment_t *, int, int); static inline int -bus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t map, caddr_t vaddr, bus_size_t size, bus_dmamap_callback_t cb, void *arg, unsigned flags) +bus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t map, caddr_t vaddr, bus_size_t size, void (*cb)(void *arg, bus_dma_segment_t *segs, int nseg, int error), void *arg, unsigned flags) { bus_dma_segment_t segs[1]; segs[0].ds_addr = CPU2BUSADDR(vaddr); @@ -291,28 +277,6 @@ bus_dma_segment_t segs[1]; return 0; } -typedef void bus_dmamap_callback2_t (void *arg, bus_dma_segment_t *segs, int nsegs, bus_size_t mapsize, int error); - -static inline int -bus_dmamap_load_mbuf(bus_dma_tag_t tag, bus_dmamap_t map, struct mbuf *m_head, bus_dmamap_callback2_t cb, void *arg, unsigned flags) -{ -/* hopefully there's enough stack ... */ -bus_dma_segment_t segs[tag->maxsegs]; -struct mbuf *m; -int n; -bus_size_t sz; - for ( m=m_head, sz=0, n=0; m; m=m->m_next, n++ ) { - if ( n >= tag->maxsegs ) { - cb(arg, segs, n, sz, EFBIG); - return EFBIG; - } - segs[n].ds_addr = CPU2BUSADDR(mtod(m, unsigned)); - sz += (segs[n].ds_len = m->m_len); - } - cb(arg, segs, n, sz, 0); - return 0; -} - #define bus_dmamap_unload(tag, map) do {} while (0) /* should we do something if we have no HW snooping ? */ diff --git a/bsd_eth_drivers/libbsdport/devicet.c b/bsd_eth_drivers/libbsdport/devicet.c index 48ddd9a..f197da4 100644 --- a/bsd_eth_drivers/libbsdport/devicet.c +++ b/bsd_eth_drivers/libbsdport/devicet.c @@ -12,7 +12,7 @@ #include #include "libbsdport_api.h" -#define DEBUG +#undef DEBUG extern void real_libc_free(void*); diff --git a/bsd_eth_drivers/libbsdport/libbsdport.h b/bsd_eth_drivers/libbsdport/libbsdport.h index 8b88784..0fdd4a4 100644 --- a/bsd_eth_drivers/libbsdport/libbsdport.h +++ b/bsd_eth_drivers/libbsdport/libbsdport.h @@ -31,10 +31,6 @@ #include -#ifndef bswap32 -#define bswap32(_x) CPU_swap_u32(_x) -#endif - #if defined(__LITTLE_ENDIAN__) || defined(__i386__) static inline uint16_t htole16(uint16_t v) { return v; } static inline uint32_t htole32(uint32_t v) { return v; } @@ -191,9 +187,6 @@ static inline void membarrier_w() { asm volatile("eieio":::"memory"); } #define PCIY_PMG 0x01 #endif -#ifndef PCI_RF_DENSE -#define PCI_RF_DENSE 0 -#endif static inline uint32_t pci_read_config(device_t dev, unsigned reg, int width) diff --git a/bsd_eth_drivers/libbsdport/libbsdport_api.h b/bsd_eth_drivers/libbsdport/libbsdport_api.h index ba3e54e..73b54b0 100644 --- a/bsd_eth_drivers/libbsdport/libbsdport_api.h +++ b/bsd_eth_drivers/libbsdport/libbsdport_api.h @@ -24,8 +24,6 @@ extern driver_t *libbsdport_netdriver_table[]; extern driver_t libbsdport_em_driver; /* AMD 79C971..976 pcnet PCI */ extern driver_t libbsdport_pcn_driver; -/* RealTek RTL8139, 8168, 8169, 8169S, 8110, 8101E, and 8111 PCI */ -extern driver_t libbsdport_re_driver; /* AMD/Lance older (and later) chips; this driver also supports what 'pcn' * does but might not be as efficient. * NOTE: The 'le_pci' driver works with the pcnet32 (79C970A) emulation diff --git a/bsd_eth_drivers/libbsdport/modini.c b/bsd_eth_drivers/libbsdport/modini.c new file mode 100644 index 0000000..3156c16 --- /dev/null +++ b/bsd_eth_drivers/libbsdport/modini.c @@ -0,0 +1,100 @@ +#include "devicet.h" +#include + +struct { + struct device dev; + struct { + char space[4096]; + } softc; +} thele = { + { + bushdr: { +/* mvme5500 { x, x, x } */ +/* qemu */ { 0, 3, 0 } + }, + type: DEV_TYPE_PCI, + name: "le", + nameunit: { 'l', 'e', '1', 0}, + unit: 1, + }, + { + { 0, } + } +}; + +void *thelesoftc = &thele.softc; + + +struct { + struct device dev; + struct { + char space[4096]; + } softc; +} theem = { + { + bushdr: { +/* mvme5500 { 2, 0xa, 0 } */ +/* cpci */ { 7, 0, 0 } + }, + type: DEV_TYPE_PCI, + name: "em", + nameunit: { 'e', 'm', '1', 0}, + unit: 1, + }, + { + { 0, } + } +}; + +void *theemsoftc = &theem.softc; + +struct { + struct device dev; + struct { + char space[4096]; + } softc; +} thepcn = { + { + bushdr: { +/* mvme5500 { x, 0xx, x } */ +/* cpci */ { 4, 6, 0 } + }, + type: DEV_TYPE_PCI, + name: "pcn", + nameunit: { 'p', 'c', 'n', '1', 0}, + unit: 1, + }, + { + { 0, } + } +}; + +void *thepcnsoftc = &thepcn.softc; + +extern driver_t rtems_em_driver; +extern driver_t rtems_le_pci_driver; +extern driver_t rtems_pcn_driver; + +driver_t *rtems_netdriver_table[] = { + &rtems_em_driver, + &rtems_le_pci_driver, + &rtems_pcn_driver, + 0 +}; + +struct rtems_bsdnet_ifconfig pcncfg = { + name: "pcn", + rbuf_count:20, + xbuf_count:3, +}; + +#ifdef DEBUG_MODULAR +void +_cexpModuleInitialize(void *unused) +{ +extern void * rtems_callout_initialize(); +extern void * rtems_taskqueue_initialize(); + rtems_callout_initialize(); + rtems_taskqueue_initialize(); +} +#endif diff --git a/bsd_eth_drivers/libbsdport/sysbus.c b/bsd_eth_drivers/libbsdport/sysbus.c index fc0ae0b..fcd3aac 100644 --- a/bsd_eth_drivers/libbsdport/sysbus.c +++ b/bsd_eth_drivers/libbsdport/sysbus.c @@ -143,17 +143,12 @@ bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filt int rval; struct irq_cookie *info = 0; + + if ( filter && handler ) { rtems_panic("bus_setup_intr for both: filter & handler not implemented\n"); } - if ( (flags & INTR_FAST) && filter ) { - rtems_panic("bus_setup_intr for both: filter & INTR_FAST not implemented\n"); - /* handler is a fast handler already */ - filter = (driver_filter_t) handler; - handler = 0; - } - if ( handler ) { if ( !dev->drv ) { device_printf(dev, "bus_setup_intr: device has no driver attached\n"); @@ -192,8 +187,7 @@ struct irq_cookie *info = 0; return rval; } - if ( cookiep ) - *cookiep = info; + *cookiep = info; return rval; } diff --git a/bsd_eth_drivers/libbsdport/taskqueue.h b/bsd_eth_drivers/libbsdport/taskqueue.h index d700edf..a341ec1 100644 --- a/bsd_eth_drivers/libbsdport/taskqueue.h +++ b/bsd_eth_drivers/libbsdport/taskqueue.h @@ -31,8 +31,6 @@ taskqueue_create_fast(const char *name, int mflags, tq_enq_fn, void *ctxt); int taskqueue_enqueue(struct taskqueue *tq, struct task *ta); -#define taskqueue_enqueue_fast(_q,_t) taskqueue_enqueue(_q,_t) - void taskqueue_thread_enqueue(void *ctxt); -- cgit v1.2.3