This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Re: RealTek 8139 driver, 4. revision
- From: Gary Thomas <gary at mlbassoc dot com>
- To: Eric Doenges <Eric dot Doenges at DynaPel dot com>
- Cc: eCos patches <ecos-patches at sources dot redhat dot com>
- Date: 13 Nov 2003 06:41:13 -0700
- Subject: Re: RealTek 8139 driver, 4. revision
- Organization: MLB Associates
- References: <3FB10769.20204@DynaPel.com>
On Tue, 2003-11-11 at 08:59, Eric Doenges wrote:
> Hi,
>
>
> this is the fourth (and hopefully final =8^) revision of my RealTek
> 8139 driver. Compared to the 3. revision released way back in August,
> the only changes are in the documentation and the PC-specific
> .inl file, which now tells the driver to handle cache coherency in
> software. The same limitations that existed in August still apply:
>
> a) The driver assumes the MAC address, media selection, etc. is
> configured via an EEPROM; these settings cannot be changed by the
> driver.
>
> b) The 'twister' cannot be tuned.
>
> c) Interrupt muxing like the Intel 82559 driver has is not supported.
> If multiple 8139s share one interrupt, chained interrupts have to
> be enabled for the HAL.
>
> d) The multicast acceptance filter code is completely untested, since
> I have no multicast test bed. A kind soul recommended testing with
> an IPv6 network; however, I don't have that either.
>
> e) All testing has been done on a custom architecture (Equator BSP),
> not on a i386 PC like the included (sample) .inl file might suggest.
> (This is because I totally failed to get eCos to boot on my PC at
> home). As a result, it may not work as expected on other platforms.
>
> f) It's slow. The 8139 is a low-cost chip that makes heavy demands on
> the CPU. You need a fast target to get anywhere near 100MBit/s
> performance with this chip (this is not really a driver problem -
> Linux on the same hardware is only marginally faster).
>
> One more thing - RedHat has now confirmed my copyright assignment, so
> the driver can now go into the CVS repository.
>
> Enjoy,
Commited, along with ChangeLog entries (**PLEASE folks, don't forget
these!) I also had to make up the ecos.db entries :-(
--
Gary Thomas <gary@mlbassoc.com>
MLB Associates
Index: ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/ChangeLog,v
retrieving revision 1.127
diff -u -5 -p -r1.127 ChangeLog
--- ChangeLog 9 Nov 2003 23:09:50 -0000 1.127
+++ ChangeLog 13 Nov 2003 13:35:32 -0000
@@ -72,10 +72,14 @@
* ecos.db: Added new packages CYGPKG_DEVS_FLASH_SST_39VF400 and
CYGPKG_DEVS_FLASH_ARM_E7T. Updated e7t target to include FLASH
drivers.
+2003-07-09 Eric Doenges <Eric.Doenges@DynaPel.com>
+
+ * ecos.db: Add Realtek 8139 (PCI) ethernet driver.
+
2003-06-12 John Dallaway <jld@ecoscentric.com>
* ecosadmin.tcl: Add repository merge capability (undocumented and
unsupported at present).
Index: ecos.db
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/ecos.db,v
retrieving revision 1.111
diff -u -5 -p -r1.111 ecos.db
--- ecos.db 9 Nov 2003 23:09:50 -0000 1.111
+++ ecos.db 12 Nov 2003 16:38:18 -0000
@@ -5258,10 +5258,48 @@ target moab {
}
##-------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------
+# Realtek 8139 (PCI) Ethernet driver
+package CYGPKG_DEVS_ETH_RLTK_8139 {
+ alias { "Realtek 8139 ethernet driver" rltk8139_eth_driver }
+ hardware
+ directory devs/eth/rltk/8139
+ script rltk_8139_eth_drivers.cdl
+ description "Ethernet driver for Realtek 8139 (PCI) card."
+}
+
+package CYGPKG_DEVS_ETH_I386_PC_RLTK8139 {
+ alias { "Intel PC with Realtek 8139 ethernet driver" pc_rltk8139_eth_driver }
+ hardware
+ directory devs/eth/i386/pc/rltk8139
+ script i386_pc_rltk8139_eth_drivers.cdl
+ description "Intel PC using Realtek 8139 (PCI) card."
+}
+
+target pc_rltk8139 {
+ alias { "i386 PC target using Realtek 8139 networking" }
+ packages { CYGPKG_HAL_I386
+ CYGPKG_HAL_I386_GENERIC
+ CYGPKG_HAL_I386_PC
+ CYGPKG_HAL_I386_PCMB
+ CYGPKG_IO_PCI
+ CYGPKG_IO_SERIAL_GENERIC_16X5X
+ CYGPKG_IO_SERIAL_I386_PC
+ CYGPKG_DEVS_ETH_RLTK_8139
+ CYGPKG_DEVS_ETH_I386_PC_RLTK8139
+ CYGPKG_DEVICES_WALLCLOCK_DALLAS_DS12887
+ CYGPKG_DEVICES_WALLCLOCK_I386_PC
+ }
+ description "
+ The pc target provides the packages needed to run eCos binaries
+ on a standard i386 PC motherboard, using a Realtek 8139 network card."
+}
+
+# --------------------------------------------------------------------------
+
package CYGPKG_VNC_SERVER {
alias { "VNC server" vnc_server }
directory net/vnc_server
script vnc-server.cdl
description "VNC server."
Index: devs/eth/rltk/8139/current/ChangeLog
===================================================================
RCS file: devs/eth/rltk/8139/current/ChangeLog
diff -N devs/eth/rltk/8139/current/ChangeLog
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/rltk/8139/current/ChangeLog 13 Nov 2003 13:36:29 -0000
@@ -0,0 +1,43 @@
+2003-07-09 Eric Doenges <Eric.Doenges@DynaPel.com>
+
+ * src/if_8139.h:
+ * src/if_8139.c:
+ * doc/README:
+ * cdl/rltk_8139_eth_drivers.cdl:
+ New package - PCI ethernet driver for RTL8139 cards,
+ (using the Intel 82259 driver as inspiration).
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
Index: devs/eth/rltk/8139/current/cdl/rltk_8139_eth_drivers.cdl
===================================================================
RCS file: devs/eth/rltk/8139/current/cdl/rltk_8139_eth_drivers.cdl
diff -N devs/eth/rltk/8139/current/cdl/rltk_8139_eth_drivers.cdl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/rltk/8139/current/cdl/rltk_8139_eth_drivers.cdl 6 Aug 2003 14:24:07 -0000
@@ -0,0 +1,171 @@
+# ====================================================================
+#
+# rltk_8139_eth_drivers.cdl
+#
+# RealTek 8139 ethernet driver
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Eric Doenges
+# Original data:
+# Contributors:
+# Date: 2003-07-16
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_ETH_RLTK_8139 {
+ display "RealTek 8139 ethernet driver"
+ description "Ethernet driver for RealTek 8139 controller."
+
+ parent CYGPKG_IO_ETH_DRIVERS
+ active_if CYGPKG_IO_ETH_DRIVERS
+ active_if CYGINT_DEVS_ETH_RLTK_8139_REQUIRED
+
+ implements CYGINT_IO_ETH_MULTICAST
+
+ include_dir cyg/devs/eth
+
+ # SNMP demands to know stuff; this sadly makes us break the neat
+ # abstraction of the device having nothing exported.
+ # include_files include/8139_info.h
+ # and tell them that it is available
+ define_proc {
+ puts $::cdl_system_header \
+ "#define CYGBLD_DEVS_ETH_DEVICE_H <pkgconf/devs_eth_rltk_8139.h>"
+
+ puts $::cdl_header "#include CYGDAT_DEVS_ETH_RLTK_8139_CFG";
+ }
+
+ compile -library=libextras.a if_8139.c
+
+ cdl_component CYGPKG_DEVS_ETH_RLTK_8139_SHARE_INTERRUPTS {
+ display "Share interrupt with other devices"
+ default_value 1
+ description "
+ If this option is enabled, the driver does not assume that it is
+ in sole possession of the interrupt pin used by the 8139."
+
+ cdl_option CYGPKG_DEVS_ETH_RLTK_8139_MASK_INTERRUPTS_IN_8139 {
+ display "Mask 8139 interrupts on chip"
+ default_value 1
+ description "
+ If this option is enabled, the driver masks interrupts in the 8139's
+ status register, and does not mask the interrupt vector. This is
+ only useful if the 8139 must share it's interrupt line with other
+ devices."
+ }
+ }
+
+ cdl_option CYGDBG_DEVS_ETH_RLTK_8139_CHATTER {
+ display "Print debugging messages"
+ default_value 0
+ description "
+ If this option is set, a lot of debugging messages are printed
+ to the console to help debug the driver."
+ }
+
+# cdl_component CYGDBG_DEVS_ETH_RLTK_8139_KEEP_STATISTICS {
+# display "Keep Ethernet statistics"
+# default_value 1
+# description "
+# The ethernet device can maintain statistics about the network,
+# specifically a great variety of error rates which are useful
+# for network management. SNMP for example uses this
+# information. There is some performance cost in maintaining
+# this information; disable this option to recoup that."
+
+# cdl_option CYGDBG_DEVS_ETH_RLTK_8139_KEEP_8139_STATISTICS {
+# display "Keep RealTek 8139 internal statistics"
+# default_value 1
+# description "
+# The i82559 keeps internal counters, and it is possible to
+# acquire these. But the i82559 (reputedly) does not service
+# the network whilst uploading the data to RAM from its
+# internal registers. If throughput is a problem, disable
+# this option to acquire only those statistics gathered by
+# software, so that the i82559 never sleeps."
+# }
+# }
+
+# cdl_component CYGPKG_DEVS_ETH_RLTK_8139_WRITE_EEPROM {
+# display "SIOCSIFHWADDR records MAC address in EEPROM"
+# default_value 0
+# description "
+# The ioctl() socket call with operand SIOCSIFHWADDR sets the
+# interface hardware address - the MAC address or ethernet
+# address. This option causes the new MAC address to be written
+# into the EEPROM associated with the interface, so that the new
+# MAC address is permanently recorded. Doing this should be a
+# carefully chosen decision, hence this option."
+# }
+
+ cdl_option CYGNUM_DEVS_ETH_RLTK_8139_RX_BUF_LEN_IDX {
+ display "Size of the receive ring"
+ flavor data
+ legal_values 0 to 2
+ default_value { CYGPKG_REDBOOT ? 0 : 2 }
+ define RX_BUF_LEN_IDX
+ description "
+ The 8139 stores all received packets in a single 'rx ring'
+ located somewhere in physical memory. The size of this ring
+ can be varied from ~8k to ~64k; however the driver currently
+ supports a maximum buffer size of only ~32k (so we can use
+ the 8139's WRAP mode). The actual buffer size is
+ 8192<<x + 16 + 1536 bytes, with x being the value of this
+ option."
+ }
+
+ cdl_component CYGPKG_DEVS_ETH_RLTK_8139_OPTIONS {
+ display "RealTek 8139 ethernet driver build options"
+ flavor none
+ no_define
+
+ cdl_option CYGPKG_DEVS_ETH_RLTK_8139_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "-D_KERNEL -D__ECOS" }
+ description "
+ This option modifies the set of compiler flags for
+ building the RealTek 8139 ethernet driver package. These
+ flags are used in addition to the set of global flags."
+ }
+ }
+}
+# EOF rltk_8139_eth_drivers.cdl
Index: devs/eth/rltk/8139/current/doc/README
===================================================================
RCS file: devs/eth/rltk/8139/current/doc/README
diff -N devs/eth/rltk/8139/current/doc/README
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/rltk/8139/current/doc/README 11 Nov 2003 15:13:10 -0000
@@ -0,0 +1,164 @@
+Some notes on the RealTek 8139 driver
+
+
+1. Using the driver
+
+This driver follows the customization model used by many other drivers
+to separate those parts of the code that are device specific from those
+that are platform specific by requiring two packages to actually use the
+driver -- the driver itself and a platform glue package that contains
+only a .cdl and an .inl file (see the devs/i386/pc/rltk8139 package for
+an example).
+
+Both the driver and the glue packages must be added to the package
+database before you can use them. My entries look like this:
+
+package CYGPKG_DEVS_ETH_RLTK_8139 {
+ alias { "RealTek 8139 ethernet driver"
+ devs_eth_rltk_8139 8139_eth_driver }
+ hardware
+ directory devs/eth/rltk/8139
+ script rltk_8139_eth_drivers.cdl
+ description "Ethernet driver for RealTek 8139 NIC."
+}
+
+and
+
+package CYGPKG_DEVS_ETH_I386_RLTK8139 {
+ alias { "Standard PC with RealTek 8139 ethernet device"
+ devs_eth_i386_pc_rltk8139 }
+ hardware
+ directory devs/eth/i386/pc/rltk8139
+ script i386_pc_rltk8139_eth_drivers.cdl
+ description "Ethernet driver for the RealTek 8139 family of chips."
+}
+
+Finally, you will need to create a new target that includes the RealTek
+driver. The easiest way to this is copy an existing target and add the
+two packages defined above (and removing the Intel 82259 packages in case
+of an i386 pc target).
+
+
+2. Cache Coherency
+
+Since the 8139 reads data directly from memory via the PCI bus, you may
+have to worry about data cache coherency. For eCos, there are basically
+three cases (turning the data cache off is not considered a serious solution):
+
+a. Either the CPU has no data cache, or the CPU has cache snooping logic
+that will detect memory accesses by PCI bus master devices and flush the cache
+when necessary. In this case, nothing special needs to be done.
+
+b. The MMU is configured to access memory uncached in a certain address space.
+In this case, the macro CYGARC_UNCACHED_ADDRESS() can be used to convert
+normal (cached) into uncached accesses. The driver always uses this macro for
+accessing the transmit and receive buffers, since if the HAL doesn't
+support this mechanism, the macro does nothing and no harm is done.
+
+c. The data cache needs to be flushed/invalidated by the driver. In this case,
+you must define CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY in the
+platform specific .inl file. Furthermore, the HAL macros HAL_DCACHE_INVALIDATE
+and HAL_DCACHE_FLUSH must be defined. Next, you must ensure that the buffers
+are aligned to cache line boundaries; otherwise, the code could fail in
+mysterious ways.
+
+One way to do this is to define the following in the .inl file:
+
+#define CACHE_ALIGNED __attribute__ ((aligned (HAL_DCACHE_LINE_SIZE)))
+
+Then, use this attribute on the transmit and receive buffer definitions:
+
+static cyg_uint8 rltk8139_eth0_rx_ring[RX_BUF_TOT_LEN] CACHE_ALIGNED;
+
+Note that this may fail for long cache lines, since the 'aligned' attribute
+does not allow arbitrarily large alignment parameters. Unfortunately, the gcc
+documentation does not say what the maximum alignment that can be specified
+is. Additionally, the linker may also be limited in the maximum alignment that
+can be used. In such cases, you'll have to bite the bullet and define more
+space than would be strictly necessary, and ensure the necessary alignment
+like this:
+
+static cyg_uint8 rltk8139_eth0_rx_ring[RX_BUF_TOT_LEN + HAL_DCACHE_LINE_SIZE];
+
+Then, reference the buffers in the Rltk8139 definition like this:
+
+(cyg_uint8 *)((int)(&rltk8139_eth0_rx_ring[0] + HAL_DCACHE_LINE_SIZE)
+ & ~(HAL_DCACHE_LINE_SIZE - 1))
+
+This assumes the cache line size is a power of 2; this is the case for all
+CPUs I know of. It also assumes an int can hold a pointer; if this is
+not true for your platform, use an integral type that can.
+
+Another thing to watch out for is that the buffers should also end on
+a cache line boundary. If your linker places the buffers sequentially in
+memory, you will only have to do this for the last buffer defined (since
+all buffers will start on cache line boundaries):
+
+static cyg_uint8
+rltk8139_eth0_tx_buffer[(TX_BUF_TOT_LEN + HAL_DCACHE_LINE_SIZE - 1)
+ & ~(HAL_DCACHE_LINE_SIZE - 1)] CACHE_ALIGNED;
+
+
+3. Interrupt sharing
+
+If the 8139 must share it's interrupt request line with other devices, the
+HAL option 'chained interrupts' must be enabled. The 8139 driver does not
+support IRQ muxing like the Intel 82559 driver does (see also *Limitations*).
+
+The driver's ISR does not clear the interrupt status bits since I believe this
+should only be done after the conditions that caused those bits to be set
+have been handled by the '_deliver' routine. Instead, the interrupt is masked.
+There are two ways to do this (configurable with a CDL option):
+
+a. The interrupt vector is masked. Personally I think this is a bad idea
+ because this will also block interrupts from all other devices sharing
+ this interrupt until the network thread gets around to calling the
+ '_deliver' routine.
+
+b. Mask the interrupt request using the 8139's interrupt mask register. This
+ way, other devices' interrupt requests can still be serviced. Enable the
+ CYGPKG_DEVS_ETH_RLTK_8139_MASK_INTERRUPTS_IN_8139 option to use this.
+
+
+4. Limitations
+
+There are a number of limitations associated with this driver:
+
+a. The configuration of the NIC (MAC address, media selection, etc.) is
+ loaded from the serial EEPROM (which is assumed to exist) and cannot be
+ changed either at compile or run time.
+
+b. The 'twister' cannot be tuned. As far as I can make out, the 'twister'
+ can be tuned to improve signal quality over long lines. The RealTek
+ data sheet does not document the twister; and the code in the Linux
+ driver that does this is totally incomprehensible to me.
+
+c. If multiple 8139s share the same interrupt, chained interrupts have to
+ be used. No IRQ MUXing (like the Intel 82559 driver has) is supported.
+
+d. Programming the multicast acceptance filter is now implemented, but not
+ tested because eCos doesn't have such a test program (or at least I
+ couldn't find any). Since I have never used multicasting myself, I don't
+ feel competent to write one. Someone suggested setting up an IPv6 network
+ for testing, since it seems IPv6 makes use of multicasting in normal
+ operation, but I haven't got around to doing that.
+
+e. It's fairly slow. This is not really the driver's fault - the 8139 requires
+ a fast CPU to get anything approaching decent speed because all messages
+ have to be copied around in memory.
+
+
+5. Credits
+
+The 8139's data sheet is not really all that helpful, since it contains
+a lot of omissions and some data that is simply incorrect. As such, I am
+indebted to Bill Paul for his well-documented OpenBSD driver, which was
+invaluable for figuring out how the chip is supposed to work. The idea of
+using 'enum' instead of '#define' came from the Linux 8139 driver, which I
+initially wanted to port to eCos, but didn't because I found it extremely
+hard to read and understand. (Note that I didn't copy any code from those
+drivers to avoid tainting eCos' license). The basic structure of the driver
+and .cdl files was taken from the eCos i82559 driver.
+
+I'd also like all the people who have downloaded and tested the driver, and
+contributed bug reports and fixes.
Index: devs/eth/rltk/8139/current/src/if_8139.c
===================================================================
RCS file: devs/eth/rltk/8139/current/src/if_8139.c
diff -N devs/eth/rltk/8139/current/src/if_8139.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/rltk/8139/current/src/if_8139.c 18 Sep 2003 08:57:38 -0000
@@ -0,0 +1,1325 @@
+//==========================================================================
+//
+// if_8139.c
+//
+// RealTek 8139 ethernet driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or
+// other sources, and are covered by the appropriate copyright
+// disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Eric Doenges
+// Contributors: Chris Nimmers, Gary Thomas, Andy Dyer
+// Date: 2003-07-09
+// Purpose:
+// Description: hardware driver for RealTek 8139 ethernet
+// Notes: This is a very basic driver that will send and receive
+// packets and not much else. A lot of features of the 8139
+// are not supported (power management, MII interface,
+// access to the serial eeprom, 'twister tuning', etc.).
+//
+// Many of the configuration options (like media type and
+// speed) the 8139 has are taken directly from the serial
+// eeprom and are not currently configurable from this driver.
+//
+// I've tentatively added some code to handle cache coherency
+// issues for platforms that do not have a separate address
+// space for uncached memory access and do not do cache
+// snooping for PCI bus masters. This code can be activated by
+// defining CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY
+// in the platform specific .inl file. Note that if
+// CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY is
+// defined, the .inl file is also responsible for making sure
+// the receive and transmit buffers are located in memory in
+// such a way that flushing or invalidating cache lines for
+// these buffers will not affect any other buffers. See the
+// README in the doc directory for some suggestions on how
+// to do this.
+//
+// Since the official data sheet for this chip is a bit
+// vague, I had to look at the Linux and OpenBSD drivers to
+// understand the basic workings of the chip; however, I have
+// not copied any code from those drivers to avoid tainting
+// eCos' license.
+//
+// FIXME:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+#include <pkgconf/system.h>
+#ifdef CYGPKG_IO_ETH_DRIVERS
+#include <pkgconf/io_eth_drivers.h>
+#endif
+#include <pkgconf/devs_eth_rltk_8139.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/hal/hal_cache.h>
+#include <cyg/io/eth/netdev.h>
+#include <cyg/io/eth/eth_drv.h>
+
+#include <string.h> /* for memset */
+
+#ifdef CYGPKG_IO_PCI
+#include <cyg/io/pci.h>
+#else
+#error "This driver requires the PCI package (CYGPKG_IO_PCI)"
+#endif
+
+#include <cyg/io/pci.h>
+
+/* Necessary for memory mapping macros */
+#include CYGHWR_MEMORY_LAYOUT_H
+
+/* Check if we should be dumping debug information or not */
+#if defined CYGDBG_DEVS_ETH_RLTK_8139_CHATTER \
+ && (CYGDBG_DEVS_ETH_RLTK_8139_CHATTER > 0)
+#define DEBUG_RLTK8139_DRIVER
+#endif
+
+#include "if_8139.h"
+
+/* Which interrupts we will handle */
+#define RLTK8139_IRQ (IR_SERR|IR_FOVW|IR_RXOVW|IR_TER|IR_TOK|IR_RER|IR_ROK)
+
+/* Allow platform-specific configuration of the driver */
+#ifndef CYGDAT_DEVS_ETH_RLTK_8139_INL
+#error "CYGDAT_DEVS_ETH_RLTK_8139_INL not defined"
+#else
+#include CYGDAT_DEVS_ETH_RLTK_8139_INL
+#endif
+
+/*
+ * If software cache coherency is required, the HAL_DCACHE_INVALIDATE
+ * hal macro must be defined as well.
+ */
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY
+#if !defined HAL_DCACHE_INVALIDATE || !defined HAL_DCACHE_FLUSH
+#error "HAL_DCACHE_INVALIDATE/HAL_DCACHE_FLUSH not defined for this platform but CYGPKG_DEVS_ETH_RLTK_8139_CACHE_COHERENCY was defined."
+#endif
+#endif
+
+/* Local driver function declarations */
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+static cyg_uint32 rltk8139_isr(cyg_vector_t vector, cyg_addrword_t data);
+#endif
+
+#ifdef ETH_DRV_SET_MC_LIST
+static cyg_uint32 ether_crc(cyg_uint8 *data, int length);
+static void rltk8139_set_multicast_list(Rltk8139_t *rltk8139_info,
+ struct eth_drv_mc_list *mc_list);
+#endif
+
+static void rltk8139_reset(struct eth_drv_sc *sc);
+static bool rltk8139_init(struct cyg_netdevtab_entry *tab);
+static void rltk8139_start(struct eth_drv_sc *sc, unsigned char *enaddr,
+ int flags);
+static void rltk8139_stop(struct eth_drv_sc *sc);
+static int rltk8139_control(struct eth_drv_sc *sc, unsigned long key,
+ void *data, int data_length);
+static int rltk8139_can_send(struct eth_drv_sc *sc);
+static void rltk8139_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,
+ int sg_len, int total_len, unsigned long key);
+static void rltk8139_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,
+ int sg_len);
+static void rltk8139_deliver(struct eth_drv_sc *sc);
+static void rltk8139_poll(struct eth_drv_sc *sc);
+static int rltk8139_int_vector(struct eth_drv_sc *sc);
+
+#ifdef DEBUG_RLTK8139_DRIVER
+void rltk8139_print_state(struct eth_drv_sc *sc);
+#endif
+
+/*
+ * Define inline functions to access the card. This will also handle
+ * endianess issues in one place. This code was lifted from the eCos
+ * i82559 driver.
+ */
+#if (CYG_BYTEORDER == CYG_MSBFIRST)
+#define HAL_CTOLE32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24) & 0xff))
+#define HAL_LE32TOC(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24) & 0xff))
+
+#define HAL_CTOLE16(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define HAL_LE16TOC(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+
+static inline void
+OUTB(cyg_uint8 value,
+ cyg_uint32 io_address)
+{
+ HAL_WRITE_UINT8( io_address, value);
+}
+
+static inline void
+OUTW(cyg_uint16 value, cyg_uint32 io_address)
+{
+ HAL_WRITE_UINT16(io_address,
+ (((value & 0xff) << 8) | ((value & 0xff00) >> 8)) );
+}
+
+static inline void
+OUTL(cyg_uint32 value, cyg_uint32 io_address)
+{
+ HAL_WRITE_UINT32(io_address,
+ ((((value) & 0xff) << 24) | (((value) & 0xff00) << 8)
+ | (((value) & 0xff0000) >> 8)
+ | (((value) >> 24) & 0xff)) );
+}
+
+static inline cyg_uint8
+INB(cyg_uint32 io_address)
+{
+ cyg_uint8 d;
+ HAL_READ_UINT8(io_address, d);
+ return d;
+}
+
+static inline cyg_uint16
+INW(cyg_uint32 io_address)
+{
+ cyg_uint16 d;
+ HAL_READ_UINT16( io_address, d );
+ return (((d & 0xff) << 8) | ((d & 0xff00) >> 8));
+}
+
+static inline cyg_uint32
+INL(cyg_uint32 io_address)
+{
+ cyg_uint32 d;
+ HAL_READ_UINT32(io_address, d);
+ return ((((d) & 0xff) << 24) | (((d) & 0xff00) << 8)
+ | (((d) & 0xff0000) >> 8) | (((d) >> 24) & 0xff));
+}
+#else
+
+// Maintaining the same styleee as above...
+#define HAL_CTOLE32(x) ((((x))))
+#define HAL_LE32TOC(x) ((((x))))
+
+#define HAL_CTOLE16(x) ((((x))))
+#define HAL_LE16TOC(x) ((((x))))
+
+static inline void OUTB(cyg_uint8 value, cyg_uint32 io_address)
+{ HAL_WRITE_UINT8( io_address, value ); }
+
+static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address)
+{ HAL_WRITE_UINT16( io_address, value ); }
+
+static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address)
+{ HAL_WRITE_UINT32( io_address, value ); }
+
+static inline cyg_uint8 INB(cyg_uint32 io_address)
+{ cyg_uint8 _t_; HAL_READ_UINT8( io_address, _t_ ); return _t_; }
+
+static inline cyg_uint16 INW(cyg_uint32 io_address)
+{ cyg_uint16 _t_; HAL_READ_UINT16( io_address, _t_ ); return _t_; }
+
+static inline cyg_uint32 INL(cyg_uint32 io_address)
+{ cyg_uint32 _t_; HAL_READ_UINT32( io_address, _t_ ); return _t_; }
+
+#endif // byteorder
+
+
+/*
+ * Table of all known PCI device/vendor ID combinations for the RealTek 8139.
+ * Add them as you get to know them.
+ */
+#define CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES 1
+static pci_identifier_t
+known_8139_aliases[CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES] = {
+ { 0x10ec, 0x8139, NULL } /* This is the offical RealTek vendor/device code */
+};
+
+
+/*
+ * Check if the device description matches a known 8139 alias.
+ */
+static cyg_bool
+rltk8139_find_match_func(cyg_uint16 vendor_id, cyg_uint16 device_id,
+ cyg_uint32 class_id, void *p)
+{
+ int i;
+
+
+ for (i = 0; i < CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES; ++i) {
+ if (((known_8139_aliases[i].vendor_id == PCI_ANY_ID) ||
+ (known_8139_aliases[i].vendor_id == vendor_id)) &&
+ ((known_8139_aliases[i].device_id == PCI_ANY_ID) ||
+ (known_8139_aliases[i].device_id == device_id)))
+ return true;
+ }
+
+ return false;
+}
+
+
+/*
+ * Find the Nth 8139 device on all attached PCI busses and do some initial
+ * PCI-type initialization. Also setup the interrupt for use in eCos.
+ */
+static bool
+rltk8139_find(int n_th, struct eth_drv_sc *sc)
+{
+ Rltk8139_t *rltk8139_info;
+ cyg_pci_device_id pci_device_id;
+ cyg_pci_device pci_device_info;
+ cyg_uint16 command;
+ int found = -1;
+
+
+ /* Go through all PCI devices until we find the Nth 8139 chip */
+ do {
+ pci_device_id = CYG_PCI_NULL_DEVID;
+ if (!cyg_pci_find_matching(&rltk8139_find_match_func, NULL,
+ &pci_device_id))
+ return false;
+ else
+ found += 1;
+ } while (found != n_th);
+
+ /* Save device ID in driver private data in case we ever need it again */
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+ rltk8139_info->pci_device_id = pci_device_id;
+
+ /* Now that we have found the device, we can extract some data about it */
+ cyg_pci_get_device_info(pci_device_id, &pci_device_info);
+
+ /* Get the assigned interrupt and set up ISR and DSR for it. */
+ if (cyg_pci_translate_interrupt(&pci_device_info, &rltk8139_info->vector)) {
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf(" Wired to HAL interrupt vector %d\n", rltk8139_info->vector);
+#endif
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ /*
+ * Note that we use the generic eth_drv_dsr routine instead of
+ * our own.
+ */
+ cyg_drv_interrupt_create(rltk8139_info->vector, 0,
+ (CYG_ADDRWORD)sc,
+ rltk8139_isr,
+ eth_drv_dsr,
+ &rltk8139_info->interrupt_handle,
+ &rltk8139_info->interrupt);
+ cyg_drv_interrupt_attach(rltk8139_info->interrupt_handle);
+#endif
+ }
+ else {
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf(" Does not generate interrupts.\n");
+#endif
+ }
+
+ /*
+ * Call 'cyg_pci_configure_device' for those platforms that do not
+ * configure the PCI bus during HAL initialization. According to Nick
+ * Garnett, there are good reasons to not configure PCI devices during HAL
+ * initialization. Also according to Nick, calling
+ * 'cyg_pci_configure_device' for devices already configured should have no
+ * effect and thus is safe to do.
+ */
+ if (cyg_pci_configure_device(&pci_device_info)) {
+#ifdef DEBUG_RLTK8139_DRIVER
+ int i;
+ diag_printf("Found device #%d on bus %d, devfn 0x%02x:\n", n_th,
+ CYG_PCI_DEV_GET_BUS(pci_device_id),
+ CYG_PCI_DEV_GET_DEVFN(pci_device_id));
+
+ if (pci_device_info.command & CYG_PCI_CFG_COMMAND_ACTIVE)
+ diag_printf(" Note that board is active. Probed"
+ " sizes and CPU addresses are invalid!\n");
+
+ diag_printf(" Vendor 0x%04x", pci_device_info.vendor);
+ diag_printf("\n Device 0x%04x", pci_device_info.device);
+ diag_printf("\n Command 0x%04x, Status 0x%04x\n",
+ pci_device_info.command, pci_device_info.status)
+ ;
+
+ diag_printf(" Class/Rev 0x%08x", pci_device_info.class_rev);
+ diag_printf("\n Header 0x%02x\n", pci_device_info.header_type);
+
+ diag_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
+ pci_device_info.header.normal.sub_vendor,
+ pci_device_info.header.normal.sub_id);
+
+ for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
+ diag_printf(" BAR[%d] 0x%08x /", i, pci_device_info.base_address[i]);
+ diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
+ pci_device_info.base_size[i], pci_device_info.base_map[i]);
+ }
+#endif
+ }
+ else {
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("Failed to configure 8139 device #%d\n", n_th);
+#endif
+ return false;
+ }
+
+ /*
+ * Enable memory mapped and port based I/O and busmastering. We currently
+ * only support IO space accesses; memory mapping is enabled so that bit
+ * DVRLOAD in CONFIG1 is cleared automatically.
+ *
+ * NOTE: it seems that for some configurations/HALs, the device is already
+ * activated at this point, even though eCos' documentation suggests
+ * it shouldn't be. At least in my case, this is not a problem.
+ */
+ cyg_pci_read_config_uint16(pci_device_info.devid, CYG_PCI_CFG_COMMAND,
+ &command);
+ command |= (CYG_PCI_CFG_COMMAND_IO | CYG_PCI_CFG_COMMAND_MEMORY
+ | CYG_PCI_CFG_COMMAND_MASTER);
+ cyg_pci_write_config_uint16(pci_device_info.devid, CYG_PCI_CFG_COMMAND,
+ command);
+
+ /*
+ * This is the base address used to talk to the device. The 8139's IOAR
+ * and MEMAR registers are BAR0 and BAR1, respectively.
+ */
+ rltk8139_info->base_address = pci_device_info.base_map[0];
+
+ /*
+ * Read the MAC address. The RealTek data sheet seems to claim this should
+ * only be read in 4 byte accesses, but the code below works just fine.
+ */
+ for (found = 0; found < 6; ++found)
+ rltk8139_info->mac[found] = INB(rltk8139_info->base_address + IDR0 + found);
+
+ /*
+ * This is the indicator for "uses an interrupt". The code was lifted
+ * from the eCos Intel 82559 driver.
+ */
+ if (rltk8139_info->interrupt_handle != 0) {
+ cyg_drv_interrupt_acknowledge(rltk8139_info->vector);
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_drv_interrupt_unmask(rltk8139_info->vector);
+#endif
+ }
+
+ return true;
+}
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+/*
+ * Interrupt service routine. We do not clear the interrupt status bits
+ * (since this should really only be done after handling whatever caused
+ * the interrupt, and that is done in the '_deliver' routine), but instead
+ * clear the interrupt mask.
+ *
+ * If we are sharing interrupts with other devices, we have two options
+ * (configurable):
+ *
+ * 1. Mask the interrupt vector completly. Personally I think this is a bad
+ * idea because the other devices sharing this interrupt are also masked
+ * until the network thread gets around to calling the '_deliver' routine.
+ *
+ * 2. Use the interrupt mask register in the 8139 to mask just the interrupt
+ * request coming from the 8139. This way, the other devices' requests
+ * can still be serviced.
+ */
+static cyg_uint32
+rltk8139_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+ Rltk8139_t *rltk8139_info;
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SHARE_INTERRUPTS
+ cyg_uint16 isr;
+#endif
+
+ rltk8139_info = (Rltk8139_t *)(((struct eth_drv_sc *)data)->driver_private);
+
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SHARE_INTERRUPTS
+ /*
+ * If interrupt sharing is enabled, check if the interrupt is really
+ * intended for us. Note that while the RealTek data sheet claims that
+ * reading the interrupt status register will clear all it's bits,
+ * this is not true, so we can read it without problems.
+ */
+ if (!(isr = INW(rltk8139_info->base_address + ISR)))
+ return 0;
+#endif
+
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_MASK_INTERRUPTS_IN_8139
+ /* Clear the interrupt mask to stop the current request. */
+ OUTW(0, rltk8139_info->base_address + IMR);
+#else
+ /* Mask the interrupt */
+ cyg_interrupt_mask(vector);
+#endif
+
+ /* Acknowledge the interrupt for those platforms were this is necessary */
+ cyg_interrupt_acknowledge(vector);
+
+ return (CYG_ISR_HANDLED | CYG_ISR_CALL_DSR);
+}
+#endif /* ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE */
+
+/*
+ * Reset the chip. This function is not exported to higher level software.
+ */
+static void
+rltk8139_reset(struct eth_drv_sc *sc)
+{
+ rltk8139_stop(sc);
+ rltk8139_start(sc, NULL, 0);
+}
+
+#ifdef ETH_DRV_SET_MC_LIST
+/*
+ * I assume (hope !) that this is identical to Ethernet's CRC algorithm
+ * specified in IEEE 802.3. It does seem to calculate the same CRC that
+ * the 8139 itself does, so I think it is correct.
+ * Note that while Ethernet's polynomial is usually specified as 04C11DB7,
+ * we must use EDB88320 because we shift the bits to the left, not the right.
+ * (See ftp://ftp.rocksoft.com/papers/crc_v3.txt for a good description of
+ * CRC algorithms).
+ */
+static cyg_uint32
+ether_crc(cyg_uint8 *data, int length)
+{
+ int bit;
+ cyg_uint32 crc = 0xFFFFFFFFU;
+
+ while (length-- > 0) {
+ crc ^= *data++;
+ for (bit = 0; bit < 8; ++bit) {
+ if (crc & 1)
+ crc = (crc >> 1) ^ 0xEDB88320U;
+ else
+ crc = (crc >> 1);
+ }
+ }
+
+ return crc ^ 0xFFFFFFFFU;
+}
+
+
+/*
+ * Set up multicast filtering. The way I understand existing driver code
+ * (Linux and OpenBSD), the 8139 calculates the ethernet CRC of
+ * incoming addresses and uses the top 6 bits as an index into a hash
+ * table. If the corresponding bit is set in MAR0..7, the address is
+ * accepted.
+ */
+static void
+rltk8139_set_multicast_list(Rltk8139_t *rltk8139_info,
+ struct eth_drv_mc_list *mc_list)
+{
+ cyg_uint32 mar[2], hash;
+ int i;
+
+ /* If 'mc_list' is NULL, accept all multicast packets. */
+ if (!mc_list) {
+ mar[0] = 0xFFFFFFFFU;
+ mar[1] = 0xFFFFFFFFU;
+ }
+ else {
+ mar[0] = 0;
+ mar[1] = 0;
+
+ for (i = 0; i < mc_list->len; ++i) {
+ hash = ether_crc(&mc_list->addrs[i][0], ETHER_ADDR_LEN) >> 26;
+ mar[hash >> 5] |= (1 << (hash & 0x1F));
+ }
+ }
+
+ /* Program the new filter values */
+ OUTL(mar[0], rltk8139_info->base_address + MAR0);
+ OUTL(mar[1], rltk8139_info->base_address + MAR4);
+}
+#endif /* ifdef ETH_DRV_SET_MC_LIST */
+
+
+/*
+ * Initialize the network interface. Since the chips is reset by calling
+ * _stop() and _start(), any code that will never need to be executed more
+ * than once after system startup should go here.
+ */
+static bool
+rltk8139_init(struct cyg_netdevtab_entry *tab)
+{
+ struct eth_drv_sc *sc;
+ Rltk8139_t *rltk8139_info;
+
+
+ sc = (struct eth_drv_sc *)(tab->device_instance);
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ /*
+ * Initialize the eCos PCI library. According to the documentation, it
+ * is safe to call this function multiple times, so we call it just to
+ * be sure it has been done.
+ */
+ cyg_pci_init();
+
+ /*
+ * Scan the PCI bus for the specified chip. The '_find' function will also
+ * do some basic PCI initialization.
+ */
+ if (!rltk8139_find(rltk8139_info->device_num, sc)) {
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_init: could not find RealTek 8139 chip #%d.\n",
+ rltk8139_info->device_num);
+#endif
+ return false;
+ }
+
+ /*
+ * The initial tx threshold is set here to prevent it from being reset
+ * with every _start().
+ */
+ rltk8139_info->tx_threshold = 3;
+
+ /* Initialize upper level driver */
+ (sc->funs->eth_drv->init)(sc, rltk8139_info->mac);
+
+ return true;
+}
+
+
+/*
+ * (Re)Start the chip, initializing data structures and enabling the
+ * transmitter and receiver. Currently, 'flags' is unused by eCos.
+ */
+static void
+rltk8139_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
+{
+ Rltk8139_t *rltk8139_info;
+ int i;
+
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_start(%s)\n", sc->dev_name);
+#endif
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ /*
+ * Reset the chip. Existing driver code implies that this may take up
+ * to 10ms; since I don't know under what exact circumstances this code may
+ * be called I busy wait here regardless.
+ */
+ OUTB(RST, rltk8139_info->base_address + CR);
+ while (INB(rltk8139_info->base_address + CR) & RST);
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_start(%s): 8139 was successfully reset.\n",
+ sc->dev_name);
+#endif
+
+ /*
+ * Clear the key storage area. These keys are used by the eCos networking
+ * support code to keep track of individual packets.
+ */
+ for (i = 0; i < NUM_TX_DESC; ++i)
+ rltk8139_info->tx_desc_key[i] = 0;
+
+ /* Initialize transmission buffer control */
+ rltk8139_info->tx_free_desc = 0;
+ rltk8139_info->tx_num_free_desc = NUM_TX_DESC;
+
+ /*
+ * Set the requested MAC address if enaddr != NULL. This is a special
+ * feature of my '_start' function since it's used to reset the chip after
+ * errors as well.
+ */
+ if (enaddr != NULL) {
+ for (i = 0; i < 6; ++i) {
+ rltk8139_info->mac[i] = enaddr[i];
+ OUTB(enaddr[i], rltk8139_info->base_address + IDR0 + i);
+ }
+ }
+
+ /*
+ * Now setup the transmission and reception buffers. These could be done
+ * in _init() and kept around, but putting them here fits better logically.
+ */
+ OUTL(CYGARC_PCI_DMA_ADDRESS((cyg_uint32)(rltk8139_info->tx_buffer
+ + 0 * TX_BUF_SIZE)),
+ rltk8139_info->base_address + TSAD0);
+ OUTL(CYGARC_PCI_DMA_ADDRESS((cyg_uint32)(rltk8139_info->tx_buffer
+ + 1 * TX_BUF_SIZE)),
+ rltk8139_info->base_address + TSAD1);
+ OUTL(CYGARC_PCI_DMA_ADDRESS((cyg_uint32)(rltk8139_info->tx_buffer
+ + 2 * TX_BUF_SIZE)),
+ rltk8139_info->base_address + TSAD2);
+ OUTL(CYGARC_PCI_DMA_ADDRESS((cyg_uint32)(rltk8139_info->tx_buffer
+ + 3 * TX_BUF_SIZE)),
+ rltk8139_info->base_address + TSAD3);
+ OUTL(CYGARC_PCI_DMA_ADDRESS((cyg_uint32)rltk8139_info->rx_ring),
+ rltk8139_info->base_address + RBSTART);
+
+ /*
+ * Enable the transmitter and receiver, then clear the missed packet
+ * counter.
+ */
+ OUTB(INB(rltk8139_info->base_address + CR) | (TE|RE),
+ rltk8139_info->base_address + CR);
+ OUTL(0, rltk8139_info->base_address + MPC);
+
+ /*
+ * It seems the receiver and transmitter configuration can only
+ * be set after the transmitter/receiver have been enabled.
+ */
+ OUTL(TXCFG, rltk8139_info->base_address + TCR);
+ OUTL(RXCFG | AM, rltk8139_info->base_address + RCR);
+
+ /*
+ * Enable the transmitter and receiver again. I'm not sure why this is
+ * necessary; the Linux driver does it so we do it here just to be on
+ * the safe side.
+ */
+ OUTB(INB(rltk8139_info->base_address + CR) | (TE|RE),
+ rltk8139_info->base_address + CR);
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ /*
+ * If this driver was not compiled in stand alone (without interrupts)
+ * mode, enable interrupts.
+ */
+ OUTW(RLTK8139_IRQ, rltk8139_info->base_address + IMR);
+#endif
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ rltk8139_print_state(sc);
+#endif
+}
+
+
+/*
+ * Stop the chip, disabling the transmitter and receiver.
+ */
+static void
+rltk8139_stop(struct eth_drv_sc *sc)
+{
+ Rltk8139_t *rltk8139_info;
+
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_stop(%s)\n", sc->dev_name);
+#endif
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ /* Disable receiver and transmitter */
+ OUTB(INB(rltk8139_info->base_address + CR) & ~(TE|RE),
+ rltk8139_info->base_address + CR);
+
+ /* Mask all interrupts */
+ OUTW(0, rltk8139_info->base_address + IMR);
+}
+
+
+/*
+ * 8139 control function. Unlike a 'real' ioctl function, this function is
+ * not required to tell the caller why a request failed, only that it did
+ * (see the eCos documentation).
+ */
+static int
+rltk8139_control(struct eth_drv_sc *sc, unsigned long key, void *data,
+ int data_length)
+{
+ int i;
+ Rltk8139_t *rltk8139_info;
+
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_control(%08x, %lx)\n", sc, key);
+#endif
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ switch (key) {
+#ifdef ETH_DRV_SET_MAC_ADDRESS
+ case ETH_DRV_SET_MAC_ADDRESS:
+ if ( 6 != data_length )
+ return 1;
+
+ /* Set the mac address */
+ for (i = 0; i < 6; ++i) {
+ rltk8139_info->mac[i] = *(((cyg_uint8 *)data) + i);
+ OUTB(rltk8139_info->mac[i], rltk8139_info->base_address + IDR0 + i);
+ }
+ return 0;
+#endif
+
+#ifdef ETH_DRV_GET_MAC_ADDRESS
+ case ETH_DRV_GET_MAC_ADDRESS:
+ if (6 != data_length)
+ return 1;
+
+ memcpy(data, rltk8139_info->mac, 6);
+ return 0;
+#endif
+
+#ifdef ETH_DRV_GET_IF_STATS_UD
+ case ETH_DRV_GET_IF_STATS_UD: // UD == UPDATE
+ //ETH_STATS_INIT( sc ); // so UPDATE the statistics structure
+#endif
+ // drop through
+#ifdef ETH_DRV_GET_IF_STATS
+ case ETH_DRV_GET_IF_STATS:
+#endif
+#if defined(ETH_DRV_GET_IF_STATS) || defined (ETH_DRV_GET_IF_STATS_UD)
+ break;
+#endif
+
+#ifdef ETH_DRV_SET_MC_LIST
+ case ETH_DRV_SET_MC_LIST:
+ /*
+ * Program the 8139's multicast filter register. If the eth_drv_mc_list
+ * contains at least one element, set the accept multicast bit in the
+ * receive config register.
+ */
+ rltk8139_set_multicast_list(rltk8139_info, (struct eth_drv_mc_list *)data);
+ if (((struct eth_drv_mc_list *)data)->len > 0)
+ OUTL(INL(rltk8139_info->base_address + RCR) | AM,
+ rltk8139_info->base_address + RCR);
+ else
+ OUTL(INL(rltk8139_info->base_address + RCR) & ~AM,
+ rltk8139_info->base_address + RCR);
+
+ return 0;
+#endif // ETH_DRV_SET_MC_LIST
+
+#ifdef ETH_DRV_SET_MC_ALL
+ case ETH_DRV_SET_MC_ALL:
+ /*
+ * Set the accept multicast bit in the receive config register and
+ * program the multicast filter to accept all addresses.
+ */
+ rltk8139_set_multicast_list(rltk8139_info, NULL);
+ OUTL(INL(rltk8139_info->base_address + RCR) | AM,
+ rltk8139_info->base_address + RCR);
+ return 0;
+#endif // ETH_DRV_SET_MC_ALL
+
+ default:
+ return 1;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Check if a new packet can be sent.
+ */
+static int
+rltk8139_can_send(struct eth_drv_sc *sc)
+{
+ return ((Rltk8139_t *)(sc->driver_private))->tx_num_free_desc;
+}
+
+
+/*
+ * Send a packet over the wire.
+ */
+static void
+rltk8139_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
+ int total_len, unsigned long key)
+{
+ Rltk8139_t *rltk8139_info;
+ cyg_uint8 *tx_buffer;
+ struct eth_drv_sg *last_sg;
+ int desc;
+
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_send(%s, %08x, %d, %d, %08lx)\n",
+ sc->dev_name, sg_list, sg_len, total_len, key);
+#endif
+
+ CYG_ASSERT(total_len <= TX_BUF_SIZE, "packet too long");
+
+ /*
+ * Get the next free descriptor to send. We lock out all interrupts
+ * and scheduling because we really, really do not want to be interrupted
+ * at this point.
+ *
+ * IMPORTANT NOTE: the RealTek data sheet does not really make this clear,
+ * but when they talk about a 'ring' of transmit descriptors, they
+ * _really_ mean it, i.e. you _must_ use descriptor #1 after descriptor
+ * #0 even if transmission of descriptor #0 has already completed.
+ */
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_disable();
+#endif
+
+ /*
+ * Sanity check to see if '_send' was called even though there is no free
+ * descriptor. This is probably unnecessary.
+ */
+ if (rltk8139_info->tx_num_free_desc == 0) {
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_enable();
+#endif
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_send(%s): no free descriptor available\n",
+ sc->dev_name);
+#endif
+ return;
+ }
+
+ /*
+ * Get the free descriptor and advance the descriptor counter modulo
+ * TX_NUM_DESC. We assume that TX_NUM_DESC will always be a power of 2.
+ */
+ desc = rltk8139_info->tx_free_desc;
+ rltk8139_info->tx_free_desc = (rltk8139_info->tx_free_desc + 1)
+ & (NUM_TX_DESC - 1);
+
+ /* Decrement the number of free descriptors */
+ rltk8139_info->tx_num_free_desc -= 1;
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ /* Reenable interrupts at this point */
+ cyg_interrupt_enable();
+#endif
+
+ /*
+ * Determine the buffer memory to use and tell the hardware about it.
+ * Since we use fixed buffer addresses, we do not need to set up TSADx.
+ * Memorize the key so we can call the tx_done callback correctly.
+ *
+ * While it would be possible to set TSADx to the packet directly if
+ * it is stored in a linear memory area with 32 bit alignment, it seems
+ * this happens so seldomly that it's simply not worth the extra
+ * runtime check.
+ */
+ tx_buffer = CYGARC_UNCACHED_ADDRESS(rltk8139_info->tx_buffer
+ + TX_BUF_SIZE * desc);
+ rltk8139_info->tx_desc_key[desc] = key;
+
+ /*
+ * Copy the data to the designated position. Note that unlike the eCos
+ * Intel 82559 driver, we simply assume that all the scatter/gather list
+ * elements' lengths will add up to total_len exactly, and don't check
+ * to make sure.
+ */
+ for (last_sg = &sg_list[sg_len]; sg_list < last_sg; ++sg_list) {
+ memcpy(tx_buffer, (void *)(sg_list->buf), sg_list->len);
+ tx_buffer += sg_list->len;
+ }
+
+ /*
+ * Make sure the packet has the minimum ethernet packet size, padding
+ * with zeros if necessary.
+ */
+ if (total_len < MIN_ETH_FRAME_SIZE) {
+ memset(tx_buffer, 0, MIN_ETH_FRAME_SIZE - total_len);
+ total_len = MIN_ETH_FRAME_SIZE;
+ }
+
+ /*
+ * Flush the data cache here if necessary. This ensures the 8139 can
+ * read the correct data from the transmit buffer.
+ */
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY
+ HAL_DCACHE_FLUSH(rltk8139_info->tx_buffer + TX_BUF_SIZE * desc, total_len);
+#endif
+
+ /*
+ * Now setup the correct transmit descriptor to actually send the data.
+ * The early TX threshold is incremented by the driver until we reach a
+ * size that prevents transmit underruns. (An earlier attempt to calculate
+ * this parameter from the packet size didn't work).
+ */
+ OUTL((rltk8139_info->tx_threshold << ERTXTH_SHIFT) | (total_len & SIZE),
+ rltk8139_info->base_address + TSD0 + (desc<<2));
+}
+
+
+/*
+ * This routine actually retrieves data from the receive ring by
+ * copying it into the specified scatter/gather buffers. Again,
+ * we assume the scatter/gather list is OK and don't check against
+ * total length.
+ */
+static void
+rltk8139_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,
+ int sg_len)
+{
+ Rltk8139_t *rltk8139_info;
+ struct eth_drv_sg *last_sg;
+ cyg_uint8 *rx_buffer;
+
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+ rx_buffer = rltk8139_info->rx_current;
+
+ /*
+ * Invalidate the cache line(s) mapped to the receive buffer
+ * if necessary.
+ */
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY
+ HAL_DCACHE_INVALIDATE(rx_buffer, rltk8139_info->rx_size);
+#endif
+
+ for (last_sg = &sg_list[sg_len]; sg_list < last_sg; ++sg_list) {
+ memcpy((void *)(sg_list->buf), rx_buffer, sg_list->len);
+ rx_buffer += sg_list->len;
+ }
+}
+
+
+/*
+ * This function does all the heavy lifting associated with interrupts.
+ */
+static void
+rltk8139_deliver(struct eth_drv_sc *sc)
+{
+ Rltk8139_t *rltk8139_info;
+ cyg_uint16 status, pci_status;
+ cyg_uint32 tsd;
+ int desc;
+
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ /*
+ * The RealTek data sheet claims that reading the ISR will clear
+ * it. This is incorrect; to clear a bit in the ISR, a '1' must be
+ * written to the ISR instead. We immediately clear the interrupt
+ * bits at this point.
+ */
+ status = INW(rltk8139_info->base_address + ISR);
+ OUTW(status, rltk8139_info->base_address + ISR);
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_deliver(%s): %04x\n", sc->dev_name, status);
+#endif
+
+ /*
+ * Check for a PCI error. This seems like a very serious error to
+ * me, so we will reset the chip and hope for the best.
+ */
+ if (status & IR_SERR) {
+ cyg_pci_read_config_uint16(rltk8139_info->pci_device_id,
+ CYG_PCI_CFG_STATUS, &pci_status);
+ cyg_pci_write_config_uint16(rltk8139_info->pci_device_id,
+ CYG_PCI_CFG_STATUS, pci_status);
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_deliver(%s): PCI error %04x\n",
+ sc->dev_name, pci_status);
+#endif
+
+ rltk8139_reset(sc);
+ return;
+ }
+
+ /* Check for transmission complete (with errors or not) */
+ if ((status & IR_TER) || (status & IR_TOK)) {
+ /*
+ * Figure out which descriptors' status must be checked. We lock out
+ * interrupts while manipulating the descriptor list because we do not
+ * want to be interrupted at this point.
+ */
+ while (1) {
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_disable();
+#endif
+
+ /* Check if all descriptors are ready, in which case we are done. */
+ if (rltk8139_info->tx_num_free_desc >= NUM_TX_DESC) {
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_enable();
+#endif
+ break;
+ }
+
+ desc = (rltk8139_info->tx_free_desc
+ - (NUM_TX_DESC - rltk8139_info->tx_num_free_desc))
+ & (NUM_TX_DESC - 1);
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_enable();
+#endif
+ /* Get the current status of the descriptor */
+ tsd = INL(rltk8139_info->base_address + TSD0 + (desc<<2));
+
+ /*
+ * If a transmit FIFO underrun occurred, increment the threshold
+ * value.
+ */
+ if ((tsd & TUN) && (rltk8139_info->tx_threshold < 64))
+ rltk8139_info->tx_threshold += 1;
+
+ /*
+ * Check if a transmission completed OK. RealTek's data sheet implies
+ * that a successful transmission that experiences underrun will only
+ * set TUN. This is not true; TOK is set for all successful
+ * transmissions.
+ */
+ if (tsd & TOK) {
+ (sc->funs->eth_drv->tx_done)(sc, rltk8139_info->tx_desc_key[desc], 0);
+ }
+ else if (tsd & TABT) {
+ /*
+ * Set the CLRABT bit in TCR. Since I haven't encountered any
+ * transmission aborts so far, I don't really know if this code
+ * will work or not.
+ */
+ OUTL(INL(rltk8139_info->base_address + TCR) & CLRABT,
+ rltk8139_info->base_address + TCR);
+ (sc->funs->eth_drv->tx_done)(sc, rltk8139_info->tx_desc_key[desc], -1);
+ }
+ else {
+ /*
+ * This descriptor is not ready. Since the descriptors are used
+ * in a ring, this means that no more descriptors are ready.
+ */
+ break;
+ }
+
+ /*
+ * Clear the saved key value. This is not really necessary, since
+ * the key value is never used to determine if a descriptor is
+ * valid or not. However, clearing it is a tidier IMO.
+ */
+ rltk8139_info->tx_desc_key[desc] = 0;
+
+ /*
+ * Increment the free descriptor count and go through the loop again
+ * to see if more descriptors are ready.
+ */
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_disable();
+#endif
+ rltk8139_info->tx_num_free_desc += 1;
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ cyg_interrupt_enable();
+#endif
+ }
+ }
+
+ if (status & IR_ROK) {
+ /*
+ * Received a frame. Note that '_deliver' does not actually copy any
+ * data; it just determines how many bytes are available and tells
+ * the generic ethernet driver about it, which then calls into
+ * the '_recv' function to copy the data.
+ */
+ cyg_uint16 rx_pos;
+ cyg_uint32 header, length;
+
+ /*
+ * CAPR contains the index into the receive buffer. It is controlled
+ * completely in software. For some reason, CAPR points 16 bytes
+ * before the actual start of the packet.
+ */
+ rx_pos = (INW(rltk8139_info->base_address + CAPR) + 16) % RX_BUF_LEN;
+
+ /*
+ * Loop until the rx buffer is empty. I have no idea how the 8139
+ * determines if the buffer still contains a packet; it may check
+ * that CAPR points 16 bytes before CBR.
+ */
+ while (!(INB(rltk8139_info->base_address + CR) & BUFE)) {
+ /*
+ * Invalidate the data cache for the cache line containing the header
+ * if necessary.
+ */
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY
+ HAL_DCACHE_INVALIDATE(&rltk8139_info->rx_ring[rx_pos],
+ sizeof(cyg_uint32));
+#endif
+
+ /*
+ * The 8139 prepends each packet with a 32 bit packet header that
+ * contains a 16 bit length and 16 bit status field, in little-endian
+ * byte order.
+ */
+ header = HAL_LE32TOC(*((volatile cyg_uint32 *)CYGARC_UNCACHED_ADDRESS(&rltk8139_info->rx_ring[rx_pos])));
+
+ /*
+ * If the 8139 is still copying data for this packet into the
+ * receive ring, it will set packet length to 0xfff0. This shouldn't
+ * ever happen because we do not use early receive.
+ */
+ if ((header >> 16) == 0xFFF0)
+ break;
+
+ /*
+ * Since the 8139 appends the ethernet CRC to every packet, we
+ * must subtract 4 from the length to get the true packet length.
+ */
+ length = (header >> 16) - 4;
+
+ /*
+ * Check if the packet was received correctly. The OpenBSD driver
+ * resets the chip if this is not the case; we attempt to salvage
+ * following packets by doing nothing.
+ */
+ if (!(header & HDR_ROK)) {
+ }
+ else {
+ /*
+ * Packet was received OK. Determine from where to start copying
+ * bytes. This is saved in the driver private area so rlt8139_recv
+ * doesn't have to redetermine this information. Then, inform
+ * the generic ethernet driver about the packet.
+ */
+ rltk8139_info->rx_current = CYGARC_UNCACHED_ADDRESS(rltk8139_info->rx_ring + rx_pos + 4);
+ rltk8139_info->rx_size = length;
+
+ /* Tell eCos about the packet */
+ (sc->funs->eth_drv->recv)(sc, length);
+ }
+
+ /*
+ * Update CAPR. CAPR must be aligned to a 32 bit boundary, and should
+ * point 16 bytes before it's actual position.
+ */
+ rx_pos = ((rx_pos + length + 8 + 3) & ~3) % RX_BUF_LEN;
+ OUTW((rx_pos - 16) % RX_BUF_LEN, rltk8139_info->base_address + CAPR);
+ }
+ }
+
+ if (status & IR_RXOVW) {
+ /*
+ * In case of a receive buffer overflow, the RealTek data sheet claims we
+ * should update CAPR and then write a '1'?to ROK in ISR. However, none of
+ * the other 8139 drivers I have looked at do this, so we will just reset
+ * the chip instead.
+ */
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_deliver(%s): receive buffer overflow\n",
+ sc->dev_name);
+#endif
+ rltk8139_reset(sc);
+ return;
+ }
+
+ if (status & IR_FOVW) {
+ /*
+ * Rx FIFO overflow. According to RealTek's data sheet, this is cleared
+ * by writing a '1' to RXOVW. Again, none of the 8139 drivers I have
+ * seen actually do this, so we reset the chip instead.
+ */
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_deliver(%s): receive FIFO overflow\n",
+ sc->dev_name);
+#endif
+ rltk8139_reset(sc);
+ return;
+ }
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
+ /* Finally, reenable interrupts */
+#ifdef CYGPKG_DEVS_ETH_RLTK_8139_MASK_INTERRUPTS_IN_8139
+ OUTW(RLTK8139_IRQ, rltk8139_info->base_address + IMR);
+#else
+ cyg_interrupt_unmask(rltk8139_info->vector);
+#endif
+#endif
+}
+
+
+/*
+ * '_poll' does the same thing as '_deliver'. It is called periodically when
+ * the ethernet driver is operated in non-interrupt mode, for instance by
+ * RedBoot.
+ */
+static void
+rltk8139_poll(struct eth_drv_sc *sc)
+{
+ Rltk8139_t *rltk8139_info;
+ cyg_uint16 isr;
+
+
+#ifdef DEBUG_RLTK8139_DRIVER
+ diag_printf("rltk8139_poll(%s)\n", sc->dev_name);
+#endif
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ /*
+ * Get the current interrupt status. If anything changed, call
+ * _deliver.
+ */
+ if ((isr = INW(rltk8139_info->base_address + ISR)))
+ rltk8139_deliver(sc);
+}
+
+
+/*
+ * Return the interrupt vector used by this device.
+ */
+static int
+rltk8139_int_vector(struct eth_drv_sc *sc)
+{
+ return ((Rltk8139_t *)(sc->driver_private))->vector;
+}
+
+
+/*
+ * Quick and dirty register dump. This is somewhat dangerous, since
+ * we read the register space 32 bits at a time, regardless of actual
+ * register sizes.
+ */
+#ifdef DEBUG_RLTK8139_DRIVER
+void
+rltk8139_print_state(struct eth_drv_sc *sc) {
+ int i;
+ Rltk8139_t *rltk8139_info;
+
+
+ rltk8139_info = (Rltk8139_t *)(sc->driver_private);
+
+ for (i = IDR0; i < FFER; i += 16) {
+ diag_printf("8139 reg address 0x%02x = 0x%08x", i,
+ INL(rltk8139_info->base_address + i));
+ diag_printf(" 0x%08x", INL(rltk8139_info->base_address + i + 4));
+ diag_printf(" 0x%08x", INL(rltk8139_info->base_address + i + 8));
+ diag_printf(" 0x%08x\n", INL(rltk8139_info->base_address + i + 12));
+ }
+}
+#endif
Index: devs/eth/rltk/8139/current/src/if_8139.h
===================================================================
RCS file: devs/eth/rltk/8139/current/src/if_8139.h
diff -N devs/eth/rltk/8139/current/src/if_8139.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/rltk/8139/current/src/if_8139.h 1 Sep 2003 09:16:40 -0000
@@ -0,0 +1,366 @@
+#ifndef CYGONCE_DEVS_ETH_REALTEK_8139_INFO_H
+#define CYGONCE_DEVS_ETH_REALTEK_8139_INFO_H
+/*==========================================================================
+//
+// 8139_info.h
+//
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Eric Doenges
+// Contributors: Chris Nimmers, Gary Thomas, Andy Dyer
+// Date: 2003-07-09
+// Description:
+//
+//####DESCRIPTIONEND####
+*/
+#include <pkgconf/devs_eth_rltk_8139.h>
+
+
+/*
+ * Used to define all vendor/device ID combinations we know about to find
+ * the chip.
+ */
+typedef struct {
+ cyg_uint16 vendor_id;
+ cyg_uint16 device_id;
+ void *data;
+} pci_identifier_t;
+
+#define PCI_ANY_ID (0xFFFF)
+
+/*
+ * Valid receive buffer sizes are 8k+16, 16k+16, 32k+16, or 64k+16.
+ * For the last case, WRAP mode should not be enabled. Since we do not
+ * currently want to support unwrapped mode, do not use 64k+16 at this
+ * point. The buffer length is set via the configuration mechanism.
+ */
+#if (CYGNUM_DEVS_ETH_RLTK_8139_RX_BUF_LEN_IDX < 0) |\
+ (CYGNUM_DEVS_ETH_RLTK_8139_RX_BUF_LEN_IDX > 2)
+#error "The receive ring size index must be in the range of 0 to 2"
+#endif
+#define RX_BUF_LEN (8192 << (CYGNUM_DEVS_ETH_RLTK_8139_RX_BUF_LEN_IDX))
+#define RX_BUF_PAD 16
+#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
+#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
+
+/* Number of Tx descriptor registers. */
+#define NUM_TX_DESC 4
+
+/*
+ * Max supported ethernet frame size. The 8139 cannot transmit packets more
+ * than 1792 bytes long. Also, since transmit buffers must be 32-bit
+ * aligned, MAX_ETH_FRAME_SIZE should always be a multiple of 4.
+ */
+#define MIN_ETH_FRAME_SIZE 60 /* without FCS */
+#define MAX_ETH_FRAME_SIZE 1536 /* is this with/without FCS ? */
+
+/* Size of the Tx buffers. */
+#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE
+#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)
+
+/* Rx buffer level before first PCI transfer ('5' is 512 bytes) */
+#define RX_FIFO_THRESH 5
+
+/*
+ * Maximum PCI rx and tx bursts. This value ranges from '0' (16 bytes)
+ * to '7' (unlimited), with MXDMA = 2^(4 + 'value').
+ */
+#define RX_DMA_BURST 6
+#define TX_DMA_BURST 6
+
+/*
+ * Device driver private data
+ */
+typedef struct {
+ /* Device number. Used for actually finding the device */
+ cyg_uint32 device_num;
+
+ /* Receive buffer ring area */
+ cyg_uint8 *rx_ring;
+
+ /* Transmit buffer area */
+ cyg_uint8 *tx_buffer;
+
+ /* PCI device ID */
+ cyg_pci_device_id pci_device_id;
+
+ /* Address for memory mapped I/O */
+ cyg_uint32 base_address;
+
+ /* Our current MAC address */
+ unsigned char mac[6];
+
+ /* tx FIFO threshold. */
+ cyg_uint8 tx_threshold;
+
+ /* This is the first free descriptor. */
+ int tx_free_desc;
+
+ /* This is the number of currently free descriptors */
+ int tx_num_free_desc;
+
+ /* Keys to match _send calls with the tx_done callback */
+ unsigned long tx_desc_key[NUM_TX_DESC];
+
+ /*
+ * This is used to (temporarily) store the address of the current
+ * received packet. We save it here to avoid having to calculate it
+ * several times.
+ */
+ cyg_uint8 *rx_current;
+ cyg_uint32 rx_size;
+
+ /* Interrupt handling stuff */
+ cyg_vector_t vector;
+ cyg_handle_t interrupt_handle;
+ cyg_interrupt interrupt;
+} Rltk8139_t;
+
+
+/*
+ * Register offsets and bit definitions. These use the names in the 8139
+ * data sheet, not those found e.g. in the Linux driver for the 8139.
+ */
+enum {
+ IDR0 = 0x0, /* mac address, seemingly in big-endian order */
+ IDR1 = 0x1,
+ IDR2 = 0x2,
+ IDR3 = 0x3,
+ IDR4 = 0x4,
+ IDR5 = 0x5,
+ MAR0 = 0x8, /* multicast registers (0-7) */
+ MAR1 = 0x9,
+ MAR2 = 0xA,
+ MAR3 = 0xB,
+ MAR4 = 0xC,
+ MAR5 = 0xD,
+ MAR6 = 0xE,
+ MAR7 = 0xF,
+ TSD0 = 0x10, /* L, transmit status of descriptor 0 */
+ TSD1 = 0x14,
+ TSD2 = 0x18,
+ TSD3 = 0x1C,
+ TSAD0 = 0x20, /* L, transmit start address of descriptor 0 */
+ TSAD1 = 0x24,
+ TSAD2 = 0x28,
+ TSAD3 = 0x2C,
+ RBSTART = 0x30, /* L, receive buffer start address */
+ ERBCR = 0x34, /* W, early receive byte count register */
+ ERSR = 0x36, /* B, early receive status register */
+ CR = 0x37, /* B, command register */
+ CAPR = 0x38, /* W, current address of packet read */
+ CBR = 0x3A, /* W, current buffer address */
+ IMR = 0x3C, /* W, interrupt mask register */
+ ISR = 0x3E, /* W, interrupt status register */
+ TCR = 0x40, /* L, transmit configuration register */
+ RCR = 0x44, /* L, receive configuration register */
+ TCTR = 0x48, /* L, timer count register */
+ MPC = 0x4C, /* L, missed packet counter */
+ CR9346 = 0x50, /* B, 93C46 (serial eeprom) command register */
+ CONFIG0 = 0x51, /* B, configuration register 0 */
+ CONFIG1 = 0x52, /* B, configuration register 1 */
+ TIMERINT= 0x54, /* L, timer interrupt register */
+ MSR = 0x58, /* B, media status register */
+ CONFIG3 = 0x59, /* B, configuration register 0 */
+ CONFIG4 = 0x5A, /* B, configuration register 1 */
+ MULINT = 0x5C, /* W, multiple interrupt select */
+ RERID = 0x5E, /* B, PCI revision ID; should be 0x10 */
+ TSAD = 0x60, /* W, transmit status of all descriptors */
+ BMCR = 0x62, /* W, basic mode control register */
+ BMSR = 0x64, /* W, basic mode status register */
+ ANAR = 0x66, /* W, auto-negotiation advertisement register */
+ ANLPAR = 0x68, /* W, auto-negotiation link partner register */
+ ANER = 0x6A, /* W, auto-negotiation expansion register */
+ DIS = 0x6C, /* W, disconnect counter */
+ FCSC = 0x6E, /* W, false carrier sense counter */
+ NWAYTR = 0x70, /* W, N-way test register */
+ REC = 0x72, /* W, RX_ER counter */
+ CSCR = 0x74, /* W, CS configuration register */
+ PHY1_PARM = 0x78, /* L, PHY parameter 1 */
+ TW_PARM = 0x7C, /* L, twister parameter */
+ PHY2_PARM = 0x80, /* B, PHY parameter 2 */
+ CRC0 = 0x84, /* B, power management CRC register for wakeup frame 0 */
+ CRC1 = 0x85, /* B, power management CRC register for wakeup frame 1 */
+ CRC2 = 0x86, /* B, power management CRC register for wakeup frame 2 */
+ CRC3 = 0x87, /* B, power management CRC register for wakeup frame 3 */
+ CRC4 = 0x88, /* B, power management CRC register for wakeup frame 4 */
+ CRC5 = 0x89, /* B, power management CRC register for wakeup frame 5 */
+ CRC6 = 0x8A, /* B, power management CRC register for wakeup frame 6 */
+ CRC7 = 0x8B, /* B, power management CRC register for wakeup frame 7 */
+ WAKEUP0 = 0x8C, /* Q, power management wakeup frame 0 (64 bits) */
+ WAKEUP1 = 0x94, /* Q, power management wakeup frame 1 (64 bits) */
+ WAKEUP2 = 0x9C, /* Q, power management wakeup frame 2 (64 bits) */
+ WAKEUP3 = 0xA4, /* Q, power management wakeup frame 3 (64 bits) */
+ WAKEUP4 = 0xAC, /* Q, power management wakeup frame 4 (64 bits) */
+ WAKEUP5 = 0xB4, /* Q, power management wakeup frame 5 (64 bits) */
+ WAKEUP6 = 0xBC, /* Q, power management wakeup frame 6 (64 bits) */
+ WAKEUP7 = 0xC4, /* Q, power management wakeup frame 7 (64 bits) */
+ LSBCRC0 = 0xCC, /* B, LSB of mask byte of wakeup frame 0 offset 12 to 75 */
+ LSBCRC1 = 0xCD, /* B, LSB of mask byte of wakeup frame 1 offset 12 to 75 */
+ LSBCRC2 = 0xCE, /* B, LSB of mask byte of wakeup frame 2 offset 12 to 75 */
+ LSBCRC3 = 0xCF, /* B, LSB of mask byte of wakeup frame 3 offset 12 to 75 */
+ LSBCRC4 = 0xD0, /* B, LSB of mask byte of wakeup frame 4 offset 12 to 75 */
+ LSBCRC5 = 0xD1, /* B, LSB of mask byte of wakeup frame 5 offset 12 to 75 */
+ LSBCRC6 = 0xD2, /* B, LSB of mask byte of wakeup frame 6 offset 12 to 75 */
+ LSBCRC7 = 0xD3, /* B, LSB of mask byte of wakeup frame 7 offset 12 to 75 */
+ FLASH = 0xD4, /* L, flash memory read/write register */
+ CONFIG5 = 0xD8, /* B, configuration register #5 */
+ FER = 0xF0, /* L, function event register (CardBus only) */
+ FEMR = 0xF4, /* L, function event mask register (CardBus only) */
+ FPSR = 0xF8, /* L, function present state register (CardBus only) */
+ FFER = 0xFC /* L, function force event register (CardBus only) */
+};
+
+/* Receive status register in Rx packet header */
+enum {
+ MAR = (1<<15), /* multicast address received */
+ PAM = (1<<14), /* physical address matched */
+ BAR = (1<<13), /* broadcast address received */
+ ISE = (1<<5), /* invalid symbol error */
+ RUNT = (1<<4), /* runt packet (<64 bytes) received */
+ LONG = (1<<3), /* long packet (>4K bytes) received */
+ CRC = (1<<2), /* CRC error */
+ FAE = (1<<1), /* frame alignment error */
+ ROK = (1<<0) /* receive OK */
+};
+
+/* Transmit status register */
+enum {
+ CRS = (1<<31), /* carrier sense lost */
+ TABT = (1<<30), /* transmit abort */
+ OWC = (1<<29), /* out of window collision */
+ CDH = (1<<28), /* CD heart beat */
+ NCC_SHIFT = 24,
+ NCC = (0xF<<24), /* number of collision count */
+ ERTXTH_SHIFT = 16,
+ ERTXTH = (0x1F<<16), /* early tx threshold, in multiples of 32 bytes */
+ TOK = (1<<15), /* transmission OK */
+ TUN = (1<<14), /* transmit FIFO underrun */
+ OWN = (1<<13), /* own */
+ SIZE = 0xFFF /* descriptor size */
+};
+
+/* Command register */
+enum {
+ RST = (1<<4), /* reset */
+ RE = (1<<3), /* receiver enable */
+ TE = (1<<2), /* transmitter enable */
+ BUFE = (1<<0) /* buffer empty */
+};
+
+/* Transmit configuration register */
+enum {
+ CLRABT = (1<<0) /* clear abort */
+};
+
+/* Receive configuration register */
+enum {
+ ERTH_SHIFT = 24, /* Early Rx threshold bits (4) */
+ MULERINT = (1<<17), /* multiple early interrupt */
+ RER8 = (1<<16), /* ? */
+ RXFTH_SHIFT= 13, /* Rx FIFO threshold */
+ RBLEN_SHIFT= 11, /* Rx buffer length */
+ MXDMA_SHIFT= 8, /* max DMA burst size per Rx DMA burst */
+ WRAP = (1<<7), /* WRAP mode */
+ SEL9356 = (1<<6), /* EEPROM select */
+ AER = (1<<5), /* accept error packets */
+ AR = (1<<4), /* accept runt packets */
+ AB = (1<<3), /* accept broadcast packets */
+ AM = (1<<2), /* accept multicast packets */
+ APM = (1<<1), /* accept physical match packets (our MAC) */
+ AAP = (1<<0), /* accept physical address packets (any MAC) */
+};
+
+/* TSAD (transmit status of all descriptors */
+enum {
+ TOK3 = (1<<15),
+ TOK2 = (1<<14),
+ TOK1 = (1<<13),
+ TOK0 = (1<<12),
+ TUN3 = (1<<11),
+ TUN2 = (1<<10),
+ TUN1 = (1<<9),
+ TUN0 = (1<<8),
+ TABT3 = (1<<7),
+ TABT2 = (1<<6),
+ TABT1 = (1<<5),
+ TABT0 = (1<<4),
+ OWN3 = (1<<3),
+ OWN2 = (1<<2),
+ OWN1 = (1<<1),
+ OWN0 = (1<<0)
+};
+
+/* Interrupt mask/status register */
+enum {
+ IR_SERR = (1<<15), /* system error interrupt */
+ IR_TIMEOUT = (1<<14), /* time out interrupt */
+ IR_LENCHG = (1<<13), /* cable length change interrupt */
+ IR_FOVW = (1<<6), /* Rx FIFO overflow */
+ IR_FUN = (1<<5), /* Packet underrun or link change interrupt */
+ IR_RXOVW = (1<<4), /* Rx buffer overflow */
+ IR_TER = (1<<3), /* transmit error interrupt */
+ IR_TOK = (1<<2), /* transmit OK interrupt */
+ IR_RER = (1<<1), /* receive error interrupt */
+ IR_ROK = (1<<0) /* receive OK interrupt */
+};
+
+/* Packet header bits */
+enum {
+ HDR_MAR = (1<<15), /* multicast address received */
+ HDR_PAM = (1<<14), /* physical address matched */
+ HDR_BAR = (1<<13), /* broadcast address matched */
+ HDR_ISE = (1<<5), /* invalid symbol error */
+ HDR_RUNT = (1<<4), /* runt packet received (packet < 64 bytes) */
+ HDR_LONG = (1<<3), /* long packet (>4k) */
+ HDR_CRC = (1<<2), /* CRC error */
+ HDR_FAE = (1<<1), /* frame alignment error */
+ HDR_ROK = (1<<0) /* receive OK */
+};
+
+
+/*
+ * Define some options to use
+ */
+#define TXCFG ((0x3 << 24) | (TX_DMA_BURST << MXDMA_SHIFT))
+#define RXCFG ((RX_FIFO_THRESH << RXFTH_SHIFT) |\
+ (RX_BUF_LEN_IDX << RBLEN_SHIFT) |\
+ (RX_DMA_BURST << MXDMA_SHIFT) |\
+ WRAP | AB | APM)
+
+#endif /* ifndef CYGONCE_DEVS_ETH_REALTEK_8139_INFO_H */
Index: devs/eth/i386/pc/rltk8139/current/ChangeLog
===================================================================
RCS file: devs/eth/i386/pc/rltk8139/current/ChangeLog
diff -N devs/eth/i386/pc/rltk8139/current/ChangeLog
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/i386/pc/rltk8139/current/ChangeLog 12 Nov 2003 16:22:11 -0000
@@ -0,0 +1,40 @@
+2003-07-09 Eric Doenges <Eric.Doenges@DynaPel.com>
+
+ * include/devs_eth_i386_pc_rltk8139.inl:
+ * cdl/i386_pc_rltk8139_eth_drivers.cdl:
+ New package - RTL8139 PCI ethernet card driver
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
Index: devs/eth/i386/pc/rltk8139/current/cdl/i386_pc_rltk8139_eth_drivers.cdl
===================================================================
RCS file: devs/eth/i386/pc/rltk8139/current/cdl/i386_pc_rltk8139_eth_drivers.cdl
diff -N devs/eth/i386/pc/rltk8139/current/cdl/i386_pc_rltk8139_eth_drivers.cdl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/i386/pc/rltk8139/current/cdl/i386_pc_rltk8139_eth_drivers.cdl 19 Jul 2003 10:25:22 -0000
@@ -0,0 +1,92 @@
+# ====================================================================
+#
+# i386_pc_rltk8139_eth_drivers.cdl
+#
+# Ethernet drivers - support for RealTek 8139 ethernet controller
+# on i386 PC target
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Eric Doenges
+# Contributors:
+# Date: 2003-07-16
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_ETH_I386_PC_RLTK8139 {
+ display "PC RealTek 8139 ethernet driver"
+ description "Ethernet driver for standard PC's."
+
+ parent CYGPKG_IO_ETH_DRIVERS
+ active_if CYGPKG_IO_ETH_DRIVERS
+ active_if CYGPKG_HAL_I386_PC
+
+ include_dir cyg/io
+
+ # FIXME: This really belongs in the RealTek_8139 package ?
+ cdl_interface CYGINT_DEVS_ETH_RLTK_8139_REQUIRED {
+ display "RealTek 8139 ethernet driver required"
+ }
+
+ define_proc {
+ puts $::cdl_system_header "/***** ethernet driver proc output start *****/"
+ puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_RLTK_8139_INL <cyg/io/devs_eth_i386_pc_rltk8139.inl>"
+ puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_RLTK_8139_CFG <pkgconf/devs_eth_i386_pc_rltk8139.h>"
+ puts $::cdl_system_header "/***** ethernet driver proc output end *****/"
+ }
+
+ cdl_component CYGPKG_DEVS_ETH_I386_PC_RLTK8139_ETH0 {
+ display "Ethernet port 0 driver"
+ flavor bool
+ default_value 1
+
+ implements CYGHWR_NET_DRIVERS
+ implements CYGHWR_NET_DRIVER_ETH0
+ implements CYGINT_DEVS_ETH_RLTK_8139_REQUIRED
+
+ cdl_option CYGDAT_DEVS_ETH_I386_PC_RLTK8139_ETH0_NAME {
+ display "Device name for the ETH0 ethernet port 0 driver"
+ flavor data
+ default_value {"\"eth0\""}
+ description "
+ This option sets the name of the ethernet device for the
+ RealTek 8139 ethernet port 0."
+ }
+ }
+}
Index: devs/eth/i386/pc/rltk8139/current/include/devs_eth_i386_pc_rltk8139.inl
===================================================================
RCS file: devs/eth/i386/pc/rltk8139/current/include/devs_eth_i386_pc_rltk8139.inl
diff -N devs/eth/i386/pc/rltk8139/current/include/devs_eth_i386_pc_rltk8139.inl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devs/eth/i386/pc/rltk8139/current/include/devs_eth_i386_pc_rltk8139.inl 13 Nov 2003 13:32:43 -0000
@@ -0,0 +1,90 @@
+//==========================================================================
+//
+// devs/eth/i386/pc/rltk8139/include/devs_eth_i386_pc_rltk8139.inl
+//
+// i386 PC RealTek 8139 ethernet I/O definitions.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Eric Doenges
+// Contributors:
+// Date: 2003-07-16
+// Purpose: i386 PC RealTek 8139 ethernet definitions
+//####DESCRIPTIONEND####
+//==========================================================================
+
+//
+// CAUTION! This driver has *not* been tested on PC hardware. It may work
+// or not :-) If there are problems, they are probably cache related.
+// If you find such, please let us know.
+//
+//#define CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY
+
+#define CACHE_ALIGNED __attribute__ ((aligned (HAL_DCACHE_LINE_SIZE)))
+
+#ifdef CYGPKG_DEVS_ETH_I386_PC_RLTK8139_ETH0
+
+static cyg_uint8 rltk8139_eth0_rx_ring[RX_BUF_TOT_LEN] CACHE_ALIGNED;
+static cyg_uint8
+rltk8139_eth0_tx_buffer[(TX_BUF_TOT_LEN + HAL_DCACHE_LINE_SIZE - 1)
+ & ~(HAL_DCACHE_LINE_SIZE - 1)] CACHE_ALIGNED;
+static Rltk8139_t rltk8139_eth0_priv_data = {
+ 0, rltk8139_eth0_rx_ring, rltk8139_eth0_tx_buffer
+};
+
+ETH_DRV_SC(rltk8139_sc0,
+ &rltk8139_eth0_priv_data,
+ CYGDAT_DEVS_ETH_I386_PC_RLTK8139_ETH0_NAME,
+ rltk8139_start,
+ rltk8139_stop,
+ rltk8139_control,
+ rltk8139_can_send,
+ rltk8139_send,
+ rltk8139_recv,
+ rltk8139_deliver,
+ rltk8139_poll,
+ rltk8139_int_vector
+ );
+
+NETDEVTAB_ENTRY(rltk8139_netdev0,
+ "rltk8139_" CYGDAT_DEVS_ETH_I386_PC_RLTK8139_ETH0_NAME,
+ rltk8139_init,
+ &rltk8139_sc0);
+
+#endif // CYGPKG_DEVS_ETH_I386_PC_RLTK8139_ETH0
+
+// EOF devs_eth_i386_pc_rltk8139.inl