mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
This file is linked in
This commit is contained in:
@@ -1,284 +0,0 @@
|
||||
@c
|
||||
@c Written by Eric Norum
|
||||
@c
|
||||
@c COPYRIGHT (c) 1988-1998.
|
||||
@c On-Line Applications Research Corporation (OAR).
|
||||
@c All rights reserved.
|
||||
@c
|
||||
@c $Id$
|
||||
@c
|
||||
|
||||
@chapter Networking Driver
|
||||
|
||||
@section Introduction
|
||||
|
||||
This chapter is intended to provide an introduction to the
|
||||
procedure for writing RTEMS network device drivers.
|
||||
The example code is taken from the `Generic 68360' network device
|
||||
driver. The source code for this driver is located in the
|
||||
@code{c/src/lib/libbsp/m68k/gen68360/network} directory in the RTEMS
|
||||
source code distribution. You should have a copy of this driver at
|
||||
hand when reading the following notes.
|
||||
|
||||
@section Learn about the network device
|
||||
|
||||
Before starting to write the network driver you need to be completely
|
||||
familiar with the programmer's view of the device.
|
||||
The following points list some of the details of the
|
||||
device that must be understood before a driver can be written.
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item Does the device use DMA to transfer packets to and from
|
||||
memory or does the processor have to
|
||||
copy packets to and from memory on the device?
|
||||
|
||||
@item If the device uses DMA, is it capable of forming a single
|
||||
outtoing packet from multiple fragments scattered in separate
|
||||
memory buffers?
|
||||
|
||||
@item If the device uses DMA, is it capable of chaining multiple
|
||||
outgoing packets, or does each outgoing packet require
|
||||
intervention by the driver?
|
||||
|
||||
@item Does the device automatically pad short frames to the minimum
|
||||
64 bytes or does the driver have to supply the padding?
|
||||
|
||||
@item Does the device automatically retry a transmission on detection
|
||||
of a collision?
|
||||
|
||||
@item If the device uses DMA, is it capable of buffering multiple
|
||||
packets to memory, or does the receiver have to be restarted
|
||||
after the arrival of each packet?
|
||||
|
||||
@item How are packets that are too short, too long, or received with
|
||||
CRC errors handled? Does the device automatically continue
|
||||
reception or does the driver have to intervene?
|
||||
|
||||
@item How is the device Ethernet address set? How is the device
|
||||
programmed to accept or reject broadcast and multicast packets?
|
||||
|
||||
@item What interrupts does the device generate? Does it generate an
|
||||
interrupt for each incoming packet, or only for packets received
|
||||
without error? Does it generate an interrupt for each packet
|
||||
transmitted, or only when the transmit queue is empty? What
|
||||
happens when a transmit error is detected?
|
||||
|
||||
@end itemize
|
||||
|
||||
In addition, some controllers have specific questions regarding
|
||||
board specific configuration. For example, the SONIC Ethernet
|
||||
controller has a very configurable data bus interface. It can
|
||||
even be configured for sixteen and thirty-two bit data buses. This
|
||||
type of information should be obtained from the board vendor.
|
||||
|
||||
@section Understand the network scheduling conventions
|
||||
|
||||
When writing code for your driver transmit and receive tasks you must
|
||||
take care to follow the network scheduling conventions. All tasks
|
||||
which are associated with networking share various
|
||||
data structures and resources. To ensure the consistency
|
||||
of these structures the tasks
|
||||
execute only when they hold the network semaphore (@code{rtems_bsdnet_semaphore}).
|
||||
Your transmit and receive tasks must abide by this protocol which means you must
|
||||
be careful to avoid `deadly embraces' with the other network tasks.
|
||||
A number of routines are provided to make it easier for your code
|
||||
to conform to the network task scheduling conventions.
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item @code{void rtems_bsdnet_semaphore_release(void)}
|
||||
|
||||
This function releases the network semaphore.
|
||||
Your task must call this function immediately before
|
||||
making any blocking RTEMS request.
|
||||
|
||||
@item @code{void rtems_bsdnet_semaphore_obtain(void)}
|
||||
|
||||
This function obtains the network semaphore.
|
||||
If your task has released the network semaphore to allow other
|
||||
network-related tasks to run while your task blocks you must call this
|
||||
function to reobtain the semaphore immediately after the return from the
|
||||
blocking RTEMS request.
|
||||
|
||||
@item @code{rtems_bsdnet_event_receive(rtems_event_set, rtems_option, rtems_interval, rtems_event_set *)}
|
||||
Your task should call this function when it wishes to wait for an event.
|
||||
This function releases the network semaphore,
|
||||
calls @code{rtems_event_receive} to wait for the specified event
|
||||
or events and reobtains the semaphore.
|
||||
The value returned is the value returned by the @code{rtems_event_receive}.
|
||||
|
||||
@end itemize
|
||||
|
||||
@section Write your driver attach function
|
||||
The driver attach function is responsible for configuring the driver
|
||||
and making the connection between the network stack
|
||||
and the driver.
|
||||
|
||||
Driver attach functions take a pointer to an
|
||||
@code{rtems_bsdnet_ifconfig} structure as their only argument.
|
||||
and set the driver parameters based on the
|
||||
values in this structure. If an entry in the configuration
|
||||
structure is zero the attach function chooses an
|
||||
appropriate default value for that parameter.
|
||||
|
||||
|
||||
The driver should then set up several fields in the ifnet structure
|
||||
in the device-dependent data structure supplied and maintained by the driver:
|
||||
|
||||
@table @code
|
||||
@item ifp->if_softc
|
||||
Pointer to the device-dependent data. The first entry
|
||||
in the device-dependent data structure must be an @code{arpcom}
|
||||
structure.
|
||||
|
||||
@item ifp->if_name
|
||||
The name of the device. The network stack uses this string
|
||||
and the device number for device name lookups. The name should not
|
||||
contain digits as these will be assumed to be part of the unit number
|
||||
and not part of the device name.
|
||||
|
||||
|
||||
@item ifp->if_unit
|
||||
The device number. The network stack uses this number and the
|
||||
device name for device name lookups. For example, if
|
||||
@code{ifp->if_name} is @samp{scc}, and @code{ifp->if_unit} is @samp{1},
|
||||
the full device name would be @samp{scc1}.
|
||||
|
||||
@item ifp->if_mtu
|
||||
The maximum transmission unit for the device. For Ethernet
|
||||
devices this value should almost always be 1500.
|
||||
|
||||
@item ifp->if_flags
|
||||
The device flags. Ethernet devices should set the flags
|
||||
to @code{IFF_BROADCAST|IFF_SIMPLEX}, indicating that the
|
||||
device can broadcast packets to multiple destinations
|
||||
and does not receive and transmit at the same time.
|
||||
|
||||
@item ifp->if_snd.ifq_maxlen
|
||||
The maximum length of the queue of packets waiting to be
|
||||
sent to the driver. This is normally set to @code{ifqmaxlen}.
|
||||
|
||||
@item ifp->if_init
|
||||
The address of the driver initialization function.
|
||||
|
||||
@item ifp->if_start
|
||||
The address of the driver start function.
|
||||
|
||||
@item ifp->if_ioctl
|
||||
The address of the driver ioctl function.
|
||||
|
||||
@item ifp->if_output
|
||||
The address of the output function. Ethernet devices
|
||||
should set this to @code{ether_output}.
|
||||
@end table
|
||||
|
||||
Once the attach function has set up the above entries it must link the
|
||||
driver data structure onto the list of devices by
|
||||
calling @code{if_attach}. Ethernet devices should then
|
||||
call @code{ether_ifattach}. Both functions take a pointer to the
|
||||
device's @code{ifnet} structure as their only argument.
|
||||
|
||||
The attach function should return a non-zero value to indicate that
|
||||
the driver has been successfully configured and attached.
|
||||
|
||||
|
||||
|
||||
|
||||
@section Write your driver start function.
|
||||
This function is called each time the network stack wants to start the
|
||||
transmitter. This occures whenever the network stack adds a packet
|
||||
to a device's send queue and the @code{IFF_OACTIVE} bit in the
|
||||
device's @code{if_flags} is not set.
|
||||
|
||||
For many devices this function need only set the @code{IFF_OACTIVE} bit in the
|
||||
@code{if_flags} and send an event to the transmit task
|
||||
indicating that a packet is in the driver transmit queue.
|
||||
|
||||
|
||||
@section Write your driver initialization function.
|
||||
This function should initialize the device, attach to interrupt handler,
|
||||
and start the driver transmit and receive tasks. The function
|
||||
|
||||
@example
|
||||
rtems_id
|
||||
rtems_bsdnet_newproc (char *name,
|
||||
int stacksize,
|
||||
void(*entry)(void *),
|
||||
void *arg);
|
||||
@end example
|
||||
|
||||
should be used to start the driver tasks.
|
||||
|
||||
Note that the network stack may call the driver initialization function more
|
||||
than once.
|
||||
Make sure you don't start multiple versions of the receive and transmit tasks.
|
||||
|
||||
|
||||
|
||||
@section Write your driver transmit task.
|
||||
This task is reponsible for removing packets from the driver send queue and sending them to the device. The task should block waiting for an event from the
|
||||
driver start function indicating that packets are waiting to be transmitted.
|
||||
When the transmit task has drained the driver send queue the task should clear
|
||||
the @code{IFF_OACTIVE} bit in @code{if_flags} and block until another outgoing
|
||||
packet is queued.
|
||||
|
||||
|
||||
@section Write your driver receive task.
|
||||
This task should block until a packet arrives from the device. If the
|
||||
device is an Ethernet interface the function @code{ether_input} should be called
|
||||
to forward the packet to the network stack. The arguments to @code{ether_input}
|
||||
are a pointer to the interface data structure, a pointer to the ethernet
|
||||
header and a pointer to an mbuf containing the packet itself.
|
||||
|
||||
|
||||
|
||||
|
||||
@section Write your driver interrupt handler.
|
||||
A typical interrupt handler will do nothing more than the hardware
|
||||
manipulation required to acknowledge the interrupt and send an RTEMS event
|
||||
to wake up the driver receive or transmit task waiting for the event.
|
||||
Network interface interrupt handlers must not make any calls to other
|
||||
network routines.
|
||||
|
||||
|
||||
|
||||
@section Write your driver ioctl function.
|
||||
This function handles ioctl requests directed at the device. The ioctl
|
||||
commands which must be handled are:
|
||||
|
||||
@table @code
|
||||
@item SIOCGIFADDR
|
||||
@item SIOCSIFADDR
|
||||
If the device is an Ethernet interface these
|
||||
commands should be passed on to @code{ether_ioctl}.
|
||||
|
||||
@item SIOCSIFFLAGS
|
||||
This command should be used to start or stop the device,
|
||||
depending on the state of the interface @code{IFF_UP} and
|
||||
@code{IFF_RUNNING} bits in @code{if_flags}:
|
||||
@table @code
|
||||
@item IFF_RUNNING
|
||||
Stop the device.
|
||||
|
||||
@item IFF_UP
|
||||
Start the device.
|
||||
|
||||
@item IFF_UP|IFF_RUNNING
|
||||
Stop then start the device.
|
||||
|
||||
@item 0
|
||||
Do nothing.
|
||||
|
||||
@end table
|
||||
@end table
|
||||
|
||||
|
||||
|
||||
@section Write Your Driver Statistic-Printing Function
|
||||
This function should print the values of any statistic/diagnostic
|
||||
counters your driver may use. The driver ioctl function should call
|
||||
the statistic-printing function when the ioctl command is
|
||||
@code{SIO_RTEMS_SHOW_STATS}.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user