1 | Networking Driver |
---|
2 | ################# |
---|
3 | |
---|
4 | Introduction |
---|
5 | ============ |
---|
6 | |
---|
7 | This chapter is intended to provide an introduction to the |
---|
8 | procedure for writing RTEMS network device drivers. |
---|
9 | The example code is taken from the âGeneric 68360â network device |
---|
10 | driver. The source code for this driver is located in the``c/src/lib/libbsp/m68k/gen68360/network`` directory in the RTEMS |
---|
11 | source code distribution. Having a copy of this driver at |
---|
12 | hand when reading the following notes will help significantly. |
---|
13 | |
---|
14 | Learn about the network device |
---|
15 | ============================== |
---|
16 | |
---|
17 | Before starting to write the network driver become completely |
---|
18 | familiar with the programmerâs view of the device. |
---|
19 | The following points list some of the details of the |
---|
20 | device that must be understood before a driver can be written. |
---|
21 | |
---|
22 | - Does the device use DMA to transfer packets to and from |
---|
23 | memory or does the processor have to |
---|
24 | copy packets to and from memory on the device? |
---|
25 | |
---|
26 | - If the device uses DMA, is it capable of forming a single |
---|
27 | outgoing packet from multiple fragments scattered in separate |
---|
28 | memory buffers? |
---|
29 | |
---|
30 | - If the device uses DMA, is it capable of chaining multiple |
---|
31 | outgoing packets, or does each outgoing packet require |
---|
32 | intervention by the driver? |
---|
33 | |
---|
34 | - Does the device automatically pad short frames to the minimum |
---|
35 | 64 bytes or does the driver have to supply the padding? |
---|
36 | |
---|
37 | - Does the device automatically retry a transmission on detection |
---|
38 | of a collision? |
---|
39 | |
---|
40 | - If the device uses DMA, is it capable of buffering multiple |
---|
41 | packets to memory, or does the receiver have to be restarted |
---|
42 | after the arrival of each packet? |
---|
43 | |
---|
44 | - How are packets that are too short, too long, or received with |
---|
45 | CRC errors handled? Does the device automatically continue |
---|
46 | reception or does the driver have to intervene? |
---|
47 | |
---|
48 | - How is the device Ethernet address set? How is the device |
---|
49 | programmed to accept or reject broadcast and multicast packets? |
---|
50 | |
---|
51 | - What interrupts does the device generate? Does it generate an |
---|
52 | interrupt for each incoming packet, or only for packets received |
---|
53 | without error? Does it generate an interrupt for each packet |
---|
54 | transmitted, or only when the transmit queue is empty? What |
---|
55 | happens when a transmit error is detected? |
---|
56 | |
---|
57 | In addition, some controllers have specific questions regarding |
---|
58 | board specific configuration. For example, the SONIC Ethernet |
---|
59 | controller has a very configurable data bus interface. It can |
---|
60 | even be configured for sixteen and thirty-two bit data buses. This |
---|
61 | type of information should be obtained from the board vendor. |
---|
62 | |
---|
63 | Understand the network scheduling conventions |
---|
64 | ============================================= |
---|
65 | |
---|
66 | When writing code for the driver transmit and receive tasks, |
---|
67 | take care to follow the network scheduling conventions. All tasks |
---|
68 | which are associated with networking share various |
---|
69 | data structures and resources. To ensure the consistency |
---|
70 | of these structures the tasks |
---|
71 | execute only when they hold the network semaphore (``rtems_bsdnet_semaphore``). |
---|
72 | The transmit and receive tasks must abide by this protocol. Be very |
---|
73 | careful to avoid âdeadly embracesâ with the other network tasks. |
---|
74 | A number of routines are provided to make it easier for the network |
---|
75 | driver code to conform to the network task scheduling conventions. |
---|
76 | |
---|
77 | - ``void rtems_bsdnet_semaphore_release(void)`` |
---|
78 | This function releases the network semaphore. |
---|
79 | The network driver tasks must call this function immediately before |
---|
80 | making any blocking RTEMS request. |
---|
81 | |
---|
82 | - ``void rtems_bsdnet_semaphore_obtain(void)`` |
---|
83 | This function obtains the network semaphore. |
---|
84 | If a network driver task has released the network semaphore to allow other |
---|
85 | network-related tasks to run while the task blocks, then this function must |
---|
86 | be called to reobtain the semaphore immediately after the return from the |
---|
87 | blocking RTEMS request. |
---|
88 | |
---|
89 | - ``rtems_bsdnet_event_receive(rtems_event_set, rtems_option, rtems_interval, rtems_event_set \*)`` |
---|
90 | The network driver task should call this function when it wishes to wait |
---|
91 | for an event. This function releases the network semaphore, |
---|
92 | calls ``rtems_event_receive`` to wait for the specified event |
---|
93 | or events and reobtains the semaphore. |
---|
94 | The value returned is the value returned by the ``rtems_event_receive``. |
---|
95 | |
---|
96 | Network Driver Makefile |
---|
97 | ======================= |
---|
98 | |
---|
99 | Network drivers are considered part of the BSD network package and as such |
---|
100 | are to be compiled with the appropriate flags. This can be accomplished by |
---|
101 | adding ``-D__INSIDE_RTEMS_BSD_TCPIP_STACK__`` to the ``command line``. |
---|
102 | If the driver is inside the RTEMS source tree or is built using the |
---|
103 | RTEMS application Makefiles, then adding the following line accomplishes |
---|
104 | this: |
---|
105 | .. code:: c |
---|
106 | |
---|
107 | DEFINES += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ |
---|
108 | |
---|
109 | This is equivalent to the following list of definitions. Early versions |
---|
110 | of the RTEMS BSD network stack required that all of these be defined. |
---|
111 | |
---|
112 | .. code:: c |
---|
113 | |
---|
114 | -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \\ |
---|
115 | -DDIAGNOSTIC -DBOOTP_COMPAT |
---|
116 | |
---|
117 | Defining these macros tells the network header files that the driver |
---|
118 | is to be compiled with extended visibility into the network stack. This |
---|
119 | is in sharp contrast to applications that simply use the network stack. |
---|
120 | Applications do not require this level of visibility and should stick |
---|
121 | to the portable application level API. |
---|
122 | |
---|
123 | As a direct result of being logically internal to the network stack, |
---|
124 | network drivers use the BSD memory allocation routines This means, |
---|
125 | for example, that malloc takes three arguments. See the SONIC |
---|
126 | device driver (``c/src/lib/libchip/network/sonic.c``) for an example |
---|
127 | of this. Because of this, network drivers should not include``<stdlib.h>``. Doing so will result in conflicting definitions |
---|
128 | of ``malloc()``. |
---|
129 | |
---|
130 | *Application level* code including network servers such as the FTP |
---|
131 | daemon are *not* part of the BSD kernel network code and should not be |
---|
132 | compiled with the BSD network flags. They should include``<stdlib.h>`` and not define the network stack visibility |
---|
133 | macros. |
---|
134 | |
---|
135 | Write the Driver Attach Function |
---|
136 | ================================ |
---|
137 | |
---|
138 | The driver attach function is responsible for configuring the driver |
---|
139 | and making the connection between the network stack |
---|
140 | and the driver. |
---|
141 | |
---|
142 | Driver attach functions take a pointer to an``rtems_bsdnet_ifconfig`` structure as their only argument. |
---|
143 | and set the driver parameters based on the |
---|
144 | values in this structure. If an entry in the configuration |
---|
145 | structure is zero the attach function chooses an |
---|
146 | appropriate default value for that parameter. |
---|
147 | |
---|
148 | The driver should then set up several fields in the ifnet structure |
---|
149 | in the device-dependent data structure supplied and maintained by the driver: |
---|
150 | |
---|
151 | ``ifp->if_softc`` |
---|
152 | Pointer to the device-dependent data. The first entry |
---|
153 | in the device-dependent data structure must be an ``arpcom`` |
---|
154 | structure. |
---|
155 | |
---|
156 | ``ifp->if_name`` |
---|
157 | The name of the device. The network stack uses this string |
---|
158 | and the device number for device name lookups. The device name should |
---|
159 | be obtained from the ``name`` entry in the configuration structure. |
---|
160 | |
---|
161 | ``ifp->if_unit`` |
---|
162 | The device number. The network stack uses this number and the |
---|
163 | device name for device name lookups. For example, if``ifp->if_name`` is â``scc``â and ``ifp->if_unit`` is â``1``â, |
---|
164 | the full device name would be â``scc1``â. The unit number should be |
---|
165 | obtained from the ânameâ entry in the configuration structure. |
---|
166 | |
---|
167 | ``ifp->if_mtu`` |
---|
168 | The maximum transmission unit for the device. For Ethernet |
---|
169 | devices this value should almost always be 1500. |
---|
170 | |
---|
171 | ``ifp->if_flags`` |
---|
172 | The device flags. Ethernet devices should set the flags |
---|
173 | to ``IFF_BROADCAST|IFF_SIMPLEX``, indicating that the |
---|
174 | device can broadcast packets to multiple destinations |
---|
175 | and does not receive and transmit at the same time. |
---|
176 | |
---|
177 | ``ifp->if_snd.ifq_maxlen`` |
---|
178 | The maximum length of the queue of packets waiting to be |
---|
179 | sent to the driver. This is normally set to ``ifqmaxlen``. |
---|
180 | |
---|
181 | ``ifp->if_init`` |
---|
182 | The address of the driver initialization function. |
---|
183 | |
---|
184 | ``ifp->if_start`` |
---|
185 | The address of the driver start function. |
---|
186 | |
---|
187 | ``ifp->if_ioctl`` |
---|
188 | The address of the driver ioctl function. |
---|
189 | |
---|
190 | ``ifp->if_output`` |
---|
191 | The address of the output function. Ethernet devices |
---|
192 | should set this to ``ether_output``. |
---|
193 | |
---|
194 | RTEMS provides a function to parse the driver name in the |
---|
195 | configuration structure into a device name and unit number. |
---|
196 | .. code:: c |
---|
197 | |
---|
198 | int rtems_bsdnet_parse_driver_name ( |
---|
199 | const struct rtems_bsdnet_ifconfig \*config, |
---|
200 | char \**namep |
---|
201 | ); |
---|
202 | |
---|
203 | The function takes two arguments; a pointer to the configuration |
---|
204 | structure and a pointer to a pointer to a character. The function |
---|
205 | parses the configuration name entry, allocates memory for the driver |
---|
206 | name, places the driver name in this memory, sets the second argument |
---|
207 | to point to the name and returns the unit number. |
---|
208 | On error, a message is printed and -1 is returned. |
---|
209 | |
---|
210 | Once the attach function has set up the above entries it must link the |
---|
211 | driver data structure onto the list of devices by |
---|
212 | calling ``if_attach``. Ethernet devices should then |
---|
213 | call ``ether_ifattach``. Both functions take a pointer to the |
---|
214 | deviceâs ``ifnet`` structure as their only argument. |
---|
215 | |
---|
216 | The attach function should return a non-zero value to indicate that |
---|
217 | the driver has been successfully configured and attached. |
---|
218 | |
---|
219 | Write the Driver Start Function. |
---|
220 | ================================ |
---|
221 | |
---|
222 | This function is called each time the network stack wants to start the |
---|
223 | transmitter. This occures whenever the network stack adds a packet |
---|
224 | to a deviceâs send queue and the ``IFF_OACTIVE`` bit in the |
---|
225 | deviceâs ``if_flags`` is not set. |
---|
226 | |
---|
227 | For many devices this function need only set the ``IFF_OACTIVE`` bit in the``if_flags`` and send an event to the transmit task |
---|
228 | indicating that a packet is in the driver transmit queue. |
---|
229 | |
---|
230 | Write the Driver Initialization Function. |
---|
231 | ========================================= |
---|
232 | |
---|
233 | This function should initialize the device, attach to interrupt handler, |
---|
234 | and start the driver transmit and receive tasks. The function |
---|
235 | .. code:: c |
---|
236 | |
---|
237 | rtems_id |
---|
238 | rtems_bsdnet_newproc (char \*name, |
---|
239 | int stacksize, |
---|
240 | void(\*entry)(void \*), |
---|
241 | void \*arg); |
---|
242 | |
---|
243 | should be used to start the driver tasks. |
---|
244 | |
---|
245 | Note that the network stack may call the driver initialization function more |
---|
246 | than once. |
---|
247 | Make sure multiple versions of the receive and transmit tasks are not accidentally |
---|
248 | started. |
---|
249 | |
---|
250 | Write the Driver Transmit Task |
---|
251 | ============================== |
---|
252 | |
---|
253 | 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 |
---|
254 | driver start function indicating that packets are waiting to be transmitted. |
---|
255 | When the transmit task has drained the driver send queue the task should clear |
---|
256 | the ``IFF_OACTIVE`` bit in ``if_flags`` and block until another outgoing |
---|
257 | packet is queued. |
---|
258 | |
---|
259 | Write the Driver Receive Task |
---|
260 | ============================= |
---|
261 | |
---|
262 | This task should block until a packet arrives from the device. If the |
---|
263 | device is an Ethernet interface the function ``ether_input`` should be called |
---|
264 | to forward the packet to the network stack. The arguments to ``ether_input`` |
---|
265 | are a pointer to the interface data structure, a pointer to the ethernet |
---|
266 | header and a pointer to an mbuf containing the packet itself. |
---|
267 | |
---|
268 | Write the Driver Interrupt Handler |
---|
269 | ================================== |
---|
270 | |
---|
271 | A typical interrupt handler will do nothing more than the hardware |
---|
272 | manipulation required to acknowledge the interrupt and send an RTEMS event |
---|
273 | to wake up the driver receive or transmit task waiting for the event. |
---|
274 | Network interface interrupt handlers must not make any calls to other |
---|
275 | network routines. |
---|
276 | |
---|
277 | Write the Driver IOCTL Function |
---|
278 | =============================== |
---|
279 | |
---|
280 | This function handles ioctl requests directed at the device. The ioctl |
---|
281 | commands which must be handled are: |
---|
282 | |
---|
283 | ``SIOCGIFADDR`` |
---|
284 | |
---|
285 | ``SIOCSIFADDR`` |
---|
286 | |
---|
287 | If the device is an Ethernet interface these |
---|
288 | commands should be passed on to ``ether_ioctl``. |
---|
289 | |
---|
290 | ``SIOCSIFFLAGS`` |
---|
291 | |
---|
292 | This command should be used to start or stop the device, |
---|
293 | depending on the state of the interface ``IFF_UP`` and``IFF_RUNNING`` bits in ``if_flags``: |
---|
294 | |
---|
295 | ``IFF_RUNNING`` |
---|
296 | |
---|
297 | Stop the device. |
---|
298 | |
---|
299 | ``IFF_UP`` |
---|
300 | |
---|
301 | Start the device. |
---|
302 | |
---|
303 | ``IFF_UP|IFF_RUNNING`` |
---|
304 | |
---|
305 | Stop then start the device. |
---|
306 | |
---|
307 | ``0`` |
---|
308 | |
---|
309 | Do nothing. |
---|
310 | |
---|
311 | Write the Driver Statistic-Printing Function |
---|
312 | ============================================ |
---|
313 | |
---|
314 | This function should print the values of any statistic/diagnostic |
---|
315 | counters the network driver may use. The driver ioctl function should call |
---|
316 | the statistic-printing function when the ioctl command is``SIO_RTEMS_SHOW_STATS``. |
---|
317 | |
---|
318 | .. COMMENT: Written by Eric Norum |
---|
319 | |
---|
320 | .. COMMENT: COPYRIGHT (c) 1988-2002. |
---|
321 | |
---|
322 | .. COMMENT: On-Line Applications Research Corporation (OAR). |
---|
323 | |
---|
324 | .. COMMENT: All rights reserved. |
---|
325 | |
---|