|
|
|
|
|
|
|
|
|
|
The development page at: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
REDD is an Open Source
project consisting on a set of Ethernet
card drivers for RTLinux-GPL. This
drivers provide the standard POSIX API
(open,
close,
read,
write and
ioctl calls) and
can be accessed by RT-tasks to send and
receive messages through an Ethernet
network.
Two kind of drivers are
distinguised:
Native drivers are
interrupt-driven drivers that use the
Linux PCI subsystem to access the PCI
bus. This drivers were included in the
RTL-lwIP
distribution until version 0.5.
Etherboot drivers
are the porting of the Etherboot
project's Ethernet drivers to
RTLinux-GPL. This drivers are accessed by
means of polling and they've been
modified to provide the POSIX API and to
make abstract the polling access to the
final user (normally an RT-task). This
porting is handled in another web page by
now: RTL-EtherbootD
project . The RTL-EtherbootD web page
will be merged into this one in
short.
NOTE: the
drivers only provide access to the
network, they don't implement no protocol
(such as ARP or RARP) and also they don't
add Ethernet headers to your data
(Etherboot drivers can do it, that's
called the raw API). Your application
must add the proper headers. Take this
into account.
NOTE FOR
DRIVER DEVELOPERS: The RTLinux code
needed to develop a new REDD driver is
gathered together in the file
src/include/drivers/rtl_posix_if.h. This
simplifies a lot the work of developing a
new driver. The rest of work deals with
modifying the Linux driver sources to
make them not to call some Linux kernel
calls and substitute them for the proper
calls. The file rtl_posix_if.h not only
gathers together the RTLinux code but
specifies which functions have to be
provided by any driver and standarizes
the structure of a REDD driver.
If you're interested in developing a new
driver contact me at
(serpeal_AT_upvnet_DOT_upv_DOT_es).
NOTE FOR
PROTOCOL DEVELOPERS: REDD provides a
mechanism that allows developers to
substitute the open, read, write, close
and ioctl (hereafter the POSIX calls)
with your own calls without modifying the
driver's code. This mechanism is provided
in the file
src/include/posix_fake/rtl_posixio_fake.h.
That file allows your code to get a
pointer to each of the POSIX calls
functions declared in the driver and use
them (if you want) inside your calls
(that will substitute the driver's ones).
This allows you to add code before and
after the POSIX calls transparently (the
final user will call read, write, etc..
in the same way, but your code will be
executed instead of the driver's code),
being a powerful mechanism to develop
protocols that use the network (in fact
we're developing a real-time protocol
over Ethernet using that structure :)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Native drivers - two
drivers ported by now:
-
3c59x driver: ported to RTLinux by
Sergio Pérez
(serpeal_at_upvnet_dot_upv_dot_es).
-
8139too driver: ported to RTLinux
by ByungGi Baek
(gi_at_realtimewave_dot_com).
-
e100 driver: ported to RTLinux by
De Yu Liu
(bullleo2003_at_yahoo_dot_com).
Since the RTLinux native
drivers are ported from the Linux
drivers, each driver should support the
same adaptors than the Linux driver. This
lines are from the original drivers:
-
3c59x: this
driver is for the 3Com "Vortex" and
"Boomerang" series ethercards.
Members of the series include Fast
EtherLink 3c590/3c592/3c595/3c597 and
the EtherLink XL 3c900 and 3c905
cards.
-
8139too:
this driver is for boards based on
the RTL8129 and RTL8139 PCI ethernet
chips. It also supports RTL8139C+ PCI
ethernet chips.
-
e100: the
following Intel network adapters are
compatible with the drivers in this
release.
Controller |
Adapter
Name |
Board
IDs |
82558 |
PRO/100+ PCI
Adapter |
668081-xxx,
689661-xxx |
82558 |
PRO/100+
Management Adapter |
691334-xxx,
701738-xxx, 721383-xxx |
82558 |
PRO/100+
Dual Port Server Adapter |
714303-xxx,
711269-xxx, A28276-xxx |
82558 |
PRO/100+ PCI
Server Adapter |
710550-xxx |
82550
82559 |
PRO/100 S
Server Adapter |
752438-xxx
(82550)
A56831-xxx, A10563-xxx,
A12171-xxx, A12321-xxx,
A12320-xxx, A12170-xxx
748568-xxx (82559)
748565-xxx (82559) |
82550
82559 |
PRO/100 S
Desktop Adapter |
751767-xxx
(82550)
748592-xxx, A12167-xxx,
A12318-xxx, A12317-xxx,
A12165-xxx
748569-xxx (82559) |
82559 |
PRO/100+
Server Adapter |
729757-xxx |
82559 |
PRO/100 S
Management Adapter |
748566-xxx,
748564-xxx |
82550 |
PRO/100 S
Dual Port Server Adapter |
A56831-xxx |
82551 |
PRO/100 M
Desktop Adapter
PRO/100 S Advanced Management
Adapter |
A80897-xxx
747842-xxx, 745171-xxx |
CNR |
PRO/100 VE
Desktop Adapter
PRO/100 VM Desktop Adapter |
A10386-xxx,
A10725-xxx, A23801-xxx,
A19716-xxx
A14323-xxx, A19725-xxx,
A23801-xxx, A22220-xxx,
A23796-xxx |
Etherboot drivers -
this porting is handled in another web
page by now. The detailed list of
supported drivers is listed
here. Please visit the RTL-EtherbootD
project web site for more
information.
|
|
|
|
|
|
|
|
|
|
The API: Special
Features [top]
|
|
|
|
|
|
|
This drivers, despite the
usual API, provide the standard POSIX
API, i.e., the standard open(), close(), read(), write() and ioctl() calls. Except for the
read() call, the
other calls are used as usual.
The read() call has been
implemented to provide the standard
interface, although the way of using that
interface by default is not the usual
(the drivers can provide the usual way of
interfacing them by modifying a macro...
go on reading :): it implements the
ZERO COPY technique. A normal
read() call would
need the user to pass a pointer to a
previously reserved memory area and the
driver would fill that area with data
(this way of interfacing the read can be achieved by
uncommenting the macro _NO_ZERO_COPY_API_
in the reddopts.h file) call. That means
that the driver would have to perform a
copy for each packet. In the
implementation we provide, the driver
saves the expense of that copy just by
returning a pointer to the packet being
hold in the internal buffers of the
driver; this technique is usually named
zero copy.
Now a description of the
API of each call and an example using it
will be shown. The examples are taken
from the test program provided with REDD,
which is a ping server. You can see the
whole code here.
Pay special attention to the read() call.
SYNOPSIS: int open(const
char *pathname, int flags);
Next, an example of how to
use the open()
call with RTLinux drivers. In RTLinux,
the open call
MUST be called inside the
init_module()
function. Each driver will be located in
a virtual location, such as /dev/, and will have a name,
such as eth0, or
rtl0 or whatever
name. In the next example we'll open
/dev/eth0 in
blocking mode (0 does not mean blocking
mode, blocking mode is set by default).
The returned value, fd, is used to identify the
device. A reference to fd will be used in the next
examples.
if((fd=open("/dev/eth0",0)) == -1){
rtl_printf("ERROR OPENING /dev/eth0 in blocking mode\n");
return -1;
}
The driver can be opened in
non-blocking mode by using the flag
O_NONBLOCK as follows:
if((fd=open("/dev/eth0",O_NONBLOCK)) == -1){
rtl_printf("ERROR OPENING /dev/eth0 in non-blocking mode\n");
return -1;
}
SYNOPSIS: int close(int
fd);
Next, an example of how
to use the close() call with RTLinux
drivers. If fd
is the device we want to close, then
this code closes the device referenced
by fd.
SYNOPSIS: int ioctl(int
d, int request, ...);
The ioctl() call is used to set
or to get parameters of the device. In
the next example we'll show how to get
the Ethernet card's MAC address by
means of ioctl().
unsigned char MAC[6];
ioctl(fd, 2, (unsigned long) MAC);
SYNOPSIS: ssize_t
read(int fd, void *buf, size_t
count);
As said before, by
default the read() call uses the ZERO
COPY technique. Although the
read()'s
interface is standard, the way of using
that interface has to be modified to
implement the zero copy technique.
Using the zero copy technique, in order
to get a pointer to the driver's
internal buffer, an indirection level
is needed. To achieve this, a structure
encapsulating a memory pointer is
needed. The next structure is the one
used in REDD:
struct memory{
void *mem;
}
The next code shows how
to interface the read call using the
previous structure:
struct memory receive_buffer;
unsigned char *in_buf;
int len;
len = read(fd,(void *) &receive_buffer,1536);
in_buf = (char *) receive_buffer.mem;
Programming this way the
driver's interface, after performing
the read()
call, receive_buffer.mem will contain a
pointer to the driver's internal
buffer.
If you want to interface
read() as usual and not to use the ZERO
COPY API uncomment the define
_NO_ZERO_COPY_API_ in the reddopts.h
file. That will allow you to use the
read() call as usual. Nex a code
showing how to use the read() call in
this mode (it is supposed that the
driver has been opened in blocking
mode):
unsigned char in_buf[1536];
int len;
len = read(fd,(void *) &in_buf,1536);
If the driver is opened
in non-blocking mode (using the
O_NONBLOCK flag), then the application
must poll the driver to see if a packet
has arrived. The next code shows how to
use the read() call if the driver is
opened in non-blocking mode:
unsigned char in_buf[1536];
int len;
do{
len = read(fd,(void *) &in_buf,1536);
usleep(10);
}while(!len);
The usleep() call is
necessary (although the time to sleep
can vary). If not called, your machine
will be blocked in the do-while loop
until a packet arrives, and that can
hang your machine.
For more information
about the implementation of the
drivers, please read the paper
"Building Ethernet Drivers on
RTLinux-GPL", downloadable in the
download
section.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In order to correctly
compile and run REDD you need:
- TLSF - Real-Time Dynamic Memory
Allocator: this is the first
real-time dynamic memory allocator in
the world. It has it's own web
page, however the latest version is
not prepared to run in RTLinux, so
we've prepared our own tarball where
we've modified TLSF to run in RTLinux
and to use the memory provided by
bigphysarea. It is used to handle the
drivers' buffers. TLSF-1.3.1 is
included in the REDD-0.3 tarball,
however we've prepared a separate
tarball for those that are interested
in using it in RTLinux. Go to the
download
section.
- Bigphysarea: this is a
driver which allocates a big piece of
memory during boottime and returns the
entire piece or parts of it to a
requesting driver (download it
here).
|
|
|
|
|
|
|
|
|
|
|
|
|
Here you can download the
native drivers and a tool for both native
and Etherboot drivers. If you want to
download the Etherboot drivers, please
visit the RTL-EtherbootD
web page.
Name
|
Description
|
Size
|
Download
|
REDD-0.4
|
RTLinux Ethernet Device Drivers
version 0.4 (Native drivers). View
the changelog. |
400 kb
|
|
REDD-0.3
|
RTLinux Ethernet Device Drivers
version 0.3 (Native drivers). View
the changelog. |
404 kb
|
|
REDD-0.2
|
RTLinux Ethernet Device Drivers
version 0.2 (Native drivers). View
the changelog. |
404 kb
|
|
REDD-0.1.1
|
RTLinux Ethernet Device Drivers
version 0.1.1 (Native drivers). View
the changelog. |
360 kb
|
|
REDD-0.1
|
RTLinux Ethernet Device Drivers
version 0.1 (Native drivers) |
368 kb
|
|
TLSF-1.3.1
|
Real-Time Dynamic Memory
Allocator for RTLinux (included in
REDD-0.3) |
308 kb
|
|
Building Ethernet Drivers
on RTLinux-GPL
|
Paper describing the main
features of this drivers and how to
build new drivers. |
360 kb
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
You can test any REDD
driver by inserting the ping server
examples provided in src/test. If you've
uncommented the _NO_ZERO_COPY_API_
defined in src/reddopts.h then you can
use the ping_posix.o module to test the
drivers (ping_posix.o uses the read()
call as the standard defines). If you
haven't uncommented that option then you
can test the drivers by means of the
ping_zc.o module, which is a ping server
that uses the read() function applying
the ZERO COPY technique.
In both cases you may want
to modify the sources (in src/test) to
open the devices in nonblocking mode (by
modifying the line: open(DEVICE_NAME,0)
with open(DEVICE_NAME,O_NONBLOCK)).
Depending on the driver
that you want to test you must configure
the source files in order to test the
driver you need. For example: by default,
ping_zc.c opens "/dev/eth0", which is
assigned to the 3c59x driver. If you want
to test the realtek driver you must
change "/dev/eth0" by "/dev/rtl0" or the
e100 driver by using "/dev/rtle0".
Both ping_zc.o and
ping_posix.o modules have parameters. You
must give the IP address of your machine
to the ping server in order to serve echo
replies. Usage (it is the same for
both):
This module requires parameters.
Usage:
insmod ping_{zc,posix}.o IP=ip_address;
Example:
insmod ping_{zc,posix}.o IP="162.58.0.1";
For more information type as root:
modinfo ping_{zc,posix}.o;
Here you can visit the
ping_zc.c
code.
|
|
|
|
|
|
|
|
|
|
|
|
|
The logo is a mixture
between a drawing of the first Ethernet
system by Bob Metcalfe (taken from
here) and the RT-Tux of the
Real Time Linux Foundation.
This mixture represents the
essence of the REDD project, doesn't it?
|
|
|
|
|
|
|
Frequently Asked
Questions [top]
|
|
|
|
|
|
|
Can I have two drivers for
the same card, the Linux one and the
RTLinux one?
You can, but they can't
work at the same time. The RTLinux driver
must control the card, so the Linux
driver must not interfere. In fact,
before inserting the RTLinux driver you
must turn down the Linux one (lets call
it eth0) by means of the command:
$ifconfig eth0 down
If you don't do this you may hang your
machine.
After removing the RTLinux driver you can
turn up your linux driver by typing:
$ifconfig eth0 up
Your Linux driver will start working as
it always did.
Can Linux access the
RTLinux driver?
Not yet. I'm working in a
layer that will allow Linux to share any
RTLinux driver in a prioritised way. As
soon as I finish this layer I will
release a new REDD version.
Does the RTLinux driver
handle more than one Ethernet card at the
same time?
No, an RTLinux driver
handles only one Ethernet card, the one
located nearer in the PCI bus.
I have two Ethernet cards
of the same model: eth0 and eth1. Can I
use the Linux driver for eth0 and the
RTLinux one for eth1 or viceversa?
You cannot assign eth0 to
Linux and eth1 to RTLinux, becase the
RTLinux driver will try to manage the
eth0 Ethernet card and your machine will
be hanged. Assigning eth0 to RTLinux and
eth1 to Linux may work, but I've never
tested it. Let me know if it works.
When inserting the RTLinux
driver the kernel shouts "Unresolved
symbols" and something about "rtl_malloc"
or whatever. What's happening?
The REDD project depends on
a real-time dynamic memory allocator
called TLSF to manage the drivers'
buffers. Go to the requirements
section to know more about it.
How do I install TLSF in
RTLinux?
The TLSF tarball provided
in the download
section is the latest version of TLSF
ready to run in RTLinux. Compile the
sources and a module called
"rtl_malloc.o" will be generated. This
module is ready to be inserted in the
kernel by means of insmod. Nothing else
has to be done.
About bigphysarea... I
have to apply two patches to the Linux
kernel: the bigphysarea patch and the
RTLinux one. Which one do I apply
first?
Apply the bigphysarea patch
and then the RTLinux one. Remember to
check the "Support for big physical area
reservation" option in the "Processor
type and features" menu when compiling
the Linux kernel.
After patching the kernel and
compiling, users must add a line in the
lilo.conf file like the next:
image=/boot/vmlinuz-2.4.21
label=linux-2.4.21
read-only
append="bigphysarea=4096"
<----------------------------
How do I know if
bigphysarea is installed properly?
After adding this line and rebooting,
to see if bigphysarea is properly
installed run:
$cat /proc/bigphysarea
You should see something like
this:
Big physical area, size
16384 kB
free list: used list:
number of blocks: 1 0
size of largest block: 16384 kB 0 kB
total: 16384 kB 0 kB
Or executing:
$cat /proc/ksysms | grep
bigphys
You'll see something like:
c012e8c8
bigphysarea_alloc
c012e8e8 bigphysarea_free
c012e698 bigphysarea_alloc_pages
c012e814 bigphysarea_free_pages
How do I access the
driver? I mean, what's the interface it
provides?
The API provided by the
drivers is described in the section
called The
API: Special Features.
|
|
|
|
|
|
|
|
|
|
Last updated: 2004/12/03 11:20 $
(GMT+1)
|
|
|
|