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