[ab0c689] | 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 | |
---|