1 This file provides a simple description of how to write a low-level,
2 hardware dependent ethernet driver.
4 The basic idea is that there is a high-level driver (which is only
5 code/functions) that is part of the stack. There will be one or more
6 low-level driver tied to the actual network hardware. Each of these
7 drivers contains one or more driver instances. The principal idea is
8 that the low-level drivers know nothing of the details of the stack that
9 will be using them. Thus, the same driver can be used by the eCos
10 supported TCP/IP stack, or any other, with no changes.
12 A driver instance is contained within a "struct eth_drv_sc".
15 // Initialize hardware (including startup)
16 void (*start)(struct eth_drv_sc *sc,
17 unsigned char *enaddr);
19 void (*stop)(struct eth_drv_sc *sc);
21 int (*control)(struct eth_drv_sc *sc,
25 // Query interface - can a packet be sent?
26 int (*can_send)(struct eth_drv_sc *sc);
27 // Send a packet of data
28 void (*send)(struct eth_drv_sc *sc,
29 struct eth_drv_sg *sg_list,
33 // Receive [unload] a packet of data
34 void (*recv)(struct eth_drv_sc *sc,
35 struct eth_drv_sg *sg_list,
37 // Deliver data to/from device from/to stack memory space
38 // (moves lots of memcpy()s out of DSRs into thread)
39 void (*deliver)(struct eth_drv_sc *sc);
40 // Poll for interrupts/device service
41 void (*poll)(struct eth_drv_sc *sc);
42 // Get interrupt information from hardware driver
43 int (*int_vector)(struct eth_drv_sc *sc);
44 // Logical driver interface
45 struct eth_drv_funs *eth_drv, *eth_drv_old;
49 struct eth_hwr_funs *funs;
52 struct arpcom sc_arpcom; /* ethernet common */
55 You create one of these instances using the "ETH_DRV_SC()" macro which
56 sets up the structure, including the prototypes for the functions, etc.
57 By doing things this way, if the internal design of the ethernet drivers
58 changes (e.g. we need to add a new low-level implementation function),
59 existing drivers will no longer compile until updated. This is much
60 better than to have all of the definitions in the low-level drivers
61 themselves and have them be [quietly] broken if the interfaces change.
63 The "magic" which gets the drivers started [and indeed, linked] is
64 similar to what is used for the I/O subsystem. [Note: I may try and
65 make it part of the I/O subsystem later.] This is done using the
66 "NETDEVTAB_ENTRY()" macro, which defines an initialization function
67 and the basic data structures for the low-level driver.
69 typedef struct cyg_netdevtab_entry {
71 bool (*init)(struct cyg_netdevtab_entry *tab);
72 void *device_instance;
74 } cyg_netdevtab_entry_t;
76 The "device_instance" entry here would point to the "struct
77 eth_drv_sc" entry previously defined. This allows the network driver
78 setup to work with any class of driver, not just ethernet drivers. In
79 the future, there will surely be serial PPP drivers, etc. These will
80 use the "NETDEVTAB" setup to create the basic driver, but they will
81 most likely be built on top of other high-level device driver layers.
83 So, the bottom line is that a hardware driver will have a template
84 (boilerplate) which looks like this:
86 #include <cyg/infra/cyg_type.h>
87 #include <cyg/hal/hal_arch.h>
88 #include <cyg/infra/diag.h>
89 #include <cyg/hal/drv_api.h>
90 #include <cyg/io/eth/netdev.h>
91 #include <cyg/io/eth/eth_drv.h>
94 0, // No driver specific data needed
95 "eth0", // Name for this interface
103 NETDEVTAB_ENTRY(DRV_netdev,
108 This, along with the referenced functions, completely define the driver.
109 Extensibility note: if one needed the same low-level driver to handle
110 multiple similar hardware interfaces, you would need multiple invocations
111 of the "ETH_DRV_SC()/NETDEVTAB_ENTRY()" macros. You would add a pointer
112 to some instance specific data, e.g. containing base addresses, interrupt
113 numbers, etc, where the "0, // No driver specific data" is currently.
115 Now a quick waltz through the functions. This discussion will use the
116 generic names from above.
118 static bool DRV_HDWR_init(struct cyg_netdevtab_entry *tab)
119 ==========================================================
121 This function is called as part of system initialization. Its primary
122 function is to decide if the hardware [as indicated via
123 tab->device_instance] is working and if the interface needs to be made
124 available in the system. If this is the case, this function needs to
125 finish with a call to the ethernet driver function:
127 eth_drv_init((struct eth_drv_sc *)tab->device_instance,
128 unsigned char *enaddr);
130 where 'enaddr' is a pointer to the ethernet station address for this
131 unit. Note: the ethernet station address is supposed to be a
132 world-unique, 48 bit address for this particular ethernet interface.
133 Typically it is provided by the board/hardware manufacturer in ROM.
135 In many packages it is possible for the ESA to be set from RedBoot,
136 (perhaps from 'fconfig' data), hard-coded from CDL, or from an EPROM.
137 A driver should choose a run-time specified ESA (e.g. from RedBoot)
138 preferentially, otherwise (in order) it should use a CDL specified
139 ESA if one has been set, otherwise an EPROM set ESA, or otherwise
140 fail. See the cl/cs8900a eth driver for an example.
143 HRDWR_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
144 ====================================================================
146 This function is called, perhaps much later than system initialization
147 time, when the system (an application) is ready for the interface to
148 become active. The purpose of this function is to set up the hardware
149 interface to start accepting packets from the network and be able to
150 send packets out. Note: this function will be called whenever the
151 up/down state of the logical interface changes, e.g. when the IP address
152 changes. This may occur more than one time, so this function needs to
153 be prepared for that case.
155 FUTURE: the "flags" field (currently unused) may be used to tell the
156 function how to start up, e.g. whether interrupts will be used,
157 selection of "promiscuous" mode etc.
159 static void HRDWR_stop(struct eth_drv_sc *sc)
160 =============================================
162 This function is the inverse of "start". It should shut down the
163 hardware and keep it from interacting with the physical network.
166 HRDWR_control(struct eth_drv_sc *sc, unsigned long key, void *data, int len)
167 ============================================================================
169 This function is used to perform low-level "control" operations on the
170 interface. These operations would be initiated via 'ioctl()' in the BSD
171 stack, and would be anything that would require the hardware setup to
172 possibly change (i.e. cannot be performed totally by the
173 platform-independent layers).
177 ETH_DRV_SET_MAC_ADDRESS:
178 This function sets the ethernet station address (ESA or MAC) for the
179 device. Normally this address is kept in non-volatile memory and is
180 unique in the world. This function must at least set the interface to
181 use the new address. It may also update the NVM as appropriate.
183 This function should return zero if the specified operation was
184 completed successfully. It should return non-zero if the operation
185 could not be performed, for any reason.
187 static int HRDWR_can_send(struct eth_drv_sc *sc)
188 ================================================
190 This function is called to determine if it is possible to start the
191 transmission of a packet on the interface. Some interfaces will allow
192 multiple packets to be "queued" and this function allows for the highest
193 possible utilization of that mode.
195 Return the number of packets which could be accepted at this time, zero
196 implies that the interface is saturated/busy.
199 HRDWR_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
200 int total_len, unsigned long key)
201 =========================================================================
203 This function is used to send a packet of data to the network. It is
204 the responsibility of this function to somehow hand the data over to the
205 hardware interface. This will most likely require copying, but just the
206 address/length values could be used by smart hardware.
208 NOTE: All data in/out of the driver is specified via a "scatter-gather"
209 list. This is just an array of address/length pairs which describe
210 sections of data to move (in the order given by the array).
212 Once the data has been successfully sent by the interface (or if an
213 error occurs), the driver should call 'eth_drv_tx_done()' using the
214 specified 'key'. Only then will the upper layers release the resources
215 for that packet and start another transmission.
217 FUTURE: This function may be extended so that the data need not be
218 copied by having the function return a "disposition" code (done, send
219 pending, etc). At this point, you should move the data to some "safe"
220 location before returning.
223 HRDWR_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
224 =========================================================================
226 This function is actually a call back, only invoked after the
228 eth_drv_recv(struct eth_drv_sc *sc, int total_len)
229 has been called. This upper level function is called by the hardware
230 driver when it knows that a packet of data is available on the
231 interface. The 'eth_drv_recv()' function then arranges network buffers
232 and structures for the data and then calls "HRDWR_recv()" to actually
233 move the data from the interface.
236 HRDWR_deliver(struct eth_drv_sc *sc)
237 =========================================================================
239 This function is actually a call back, and notifies the driver that delivery
240 is happening. This allows it to actually do the copy of packet data to/from
241 the hardware from/to the packet buffer. And once that's done, then do things
242 like unmask its interrupts, and free any relevant resources so it can process
245 In general it will be called from the user thread responsible for delivering
249 HRDWR_poll(struct eth_drv_sc *sc)
250 =========================================================================
252 This function is used when in a non-interrupt driven system, e.g. when
253 interrupts are completely disabled. This allows the driver time to check
254 whether anything needs doing either for transmission, or to check if
255 anything has been received, or if any other processing needs doing..
258 HRDWR_int_vector(struct eth_drv_sc *sc)
259 =========================================================================
261 This function returns the interrupt vector number used for RX interrupts.
262 This is so the common GDB stubs infrastructure can detect when to check
263 for incoming ctrl-c's when doing debugging over ethernet.
265 Upper layer functions - called by drivers
266 =========================================
268 These functions are defined by the upper layers (machine independent) of
269 the networking driver support. They are present to hide the interfaces
270 to the actual networking stack so that the hardware drivers may possibly
271 be used by any network stack implementation.
273 These functions require a pointer to a "struct eth_drv_sc" table which
274 describes the interface at a logical level. It is assumed that the
275 driver [lowest level hardware support] will keep track of this pointer
276 so it may be passed "up" as appropriate.
279 struct eth_drv_funs *funs; // Pointer to hardware functions (see above)
280 void *driver_private; // Device specific data
281 const char *dev_name;
282 struct arpcom sc_arpcom; // ethernet common
285 This structure is created, one per logical interface, via ETH_DRV_SC macro.
287 void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr)
288 ===============================================================
290 This function establishes the device at initialization time. The
291 hardware should be totally intialized (not "started") when this function
294 void eth_drv_tx_done(struct eth_drv_sc *sc, unsigned long key, int status)
295 ==========================================================================
297 This function is called when a packet completes transmission on the
298 interface. The 'key' value must be one of the keys provided to
299 "HRDWR_send()" above. The value 'status' should be non-zero (currently
300 undefined) to indicate that an error occurred during the transmission.
302 void eth_drv_recv(struct eth_drv_sc *sc, int len)
303 =================================================
305 This function is called to indicate that a packet of length 'len' has
306 arrived at the interface. The callback "HRDWR_recv()" function
307 described above will be used to actually unload the data from the
308 interface into buffers used by the machine independent layers.
312 Calling graph for Transmit and Receive
313 --------------------------------------
315 It may be worth clarifying further the flow of control in the transmit
316 and receive cases, where the hardware driver does use interrupts and so
317 DSRs to tell the "foreground" when something asynchronous has occurred.
320 Foreground task calls into network stack to send a packet (or the
321 stack decides to send a packet in response to incoming traffic).
322 The driver calls the HRDWR_can_send() function in the hardware driver.
323 HRDWR_can_send() returns the number of available "slots" in which it
324 can store a pending transmit packet.
325 If it cannot send at this time, the packet is queued outside the
326 hardware driver for later; in this case, the hardware is already busy
327 transmitting, so expect an interrupt as described below for completion
328 of the packet currently outgoing.
329 If it can send right now, HRDWR_send() is called.
330 HRDWR_send() copies the data into special hardware buffers, or
331 instructs the hardware to "send that".
332 It also remembers the key that is associated with this tx request.
336 Asynchronously, the hardware makes an interrupt to say "transmit is
337 done"; the ISR quietens the interrupt source in the hardware and
338 requests that the associated DSR be run.
339 The DSR realizes that a transmit request has completed, and calls
340 eth_drv_tx_done() with the same key that it remembered for this tx.
341 eth_drv_tx_done() uses the key to find the resources associated with
342 this transmit request; thus the stack knows that the transmit has
343 completed and its resources can be freed.
344 eth_drv_tx_done() also enquires whether HRDWR_can_send() now says
345 "yes, we can send" and if so, dequeues a further transmit request
346 which may have been queued as described above. If so:
347 HRDWR_send() copies the data into the hardware buffers, or
348 instructs the hardware to "send that" and remembers the new key.
349 these calls return to the DSR and thus to the foreground.
356 Asynchronously, the hardware makes an interrupt to say "there is ready
357 data in a receive buffer"; the ISR quietens the interrupt source in
358 the hardware and requests that the associated DSR be run.
359 The DSR realizes that there is data ready and calls eth_drv_recv()
360 with the length of the data that is available.
361 eth_drv_recv() prepares a set of scatter-gather buffers that can
362 accommodate that data.
363 It then calls back into the hardware driver routine HRDWR_recv().
364 HRDWR_recv() must copy the data from the hardware's buffers into
365 the scatter-gather buffers provided, and return.
366 eth_drv_recv() sends the new packet up the network stack and returns.
367 Back in the DSR now, the driver cleans the receive buffer and returns
368 it to the hardware's control, available to receive another packet from
370 The DSR returns to the foreground.