1 <!-- Copyright (C) 2003 Red Hat, Inc. -->
2 <!-- This material may be distributed only subject to the terms -->
3 <!-- and conditions set forth in the Open Publication License, v1.0 -->
4 <!-- or later (the latest version is presently available at -->
5 <!-- http://www.opencontent.org/openpub/). -->
6 <!-- Distribution of the work or derivative of the work in any -->
7 <!-- standard (paper) book form is prohibited unless prior -->
8 <!-- permission is obtained from the copyright holder. -->
12 >Generic Ethernet Device Driver</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
22 TITLE="Ethernet Device Drivers"
23 HREF="io-eth-drv-generic.html"><LINK
25 TITLE="Ethernet Device Drivers"
26 HREF="io-eth-drv-generic.html"><LINK
28 TITLE="Review of the functions"
29 HREF="io-eth-drv-api-funcs.html"></HEAD
40 SUMMARY="Header navigation table"
49 >eCos Reference Manual</TH
57 HREF="io-eth-drv-generic.html"
71 HREF="io-eth-drv-api-funcs.html"
84 NAME="IO-ETH-DRV-GENERIC1">Chapter 46. Generic Ethernet Device Driver</H1
94 HREF="io-eth-drv-generic1.html#IO-ETH-DRV-API"
95 >Generic Ethernet API</A
99 HREF="io-eth-drv-api-funcs.html"
100 >Review of the functions</A
104 HREF="io-eth-drv-upper-api.html"
105 >Upper Layer Functions</A
109 HREF="io-eth-call-graph.html"
110 >Calling graph for Transmission and Reception</A
119 NAME="IO-ETH-DRV-API">Generic Ethernet API</H1
121 >This file provides a simple description of how to write a low-level,
122 hardware dependent ethernet driver.</P
124 >There is a high-level driver (which is only code — with no state of
125 its own) that is part of the stack. There will be one or more low-level
126 drivers tied to the actual network hardware. Each of these drivers
127 contains one or more driver instances. The intent is that the
128 low-level drivers know nothing of the details of the stack that will be
129 using them. Thus, the same driver can be used by the
144 or any other, with no changes.</P
146 >A driver instance is contained within a
149 >struct eth_drv_sc</SPAN
158 CLASS="PROGRAMLISTING"
159 >struct eth_hwr_funs {
160 // Initialize hardware (including startup)
161 void (*start)(struct eth_drv_sc *sc,
162 unsigned char *enaddr,
164 // Shut down hardware
165 void (*stop)(struct eth_drv_sc *sc);
166 // Device control (ioctl pass-thru)
167 int (*control)(struct eth_drv_sc *sc,
171 // Query - can a packet be sent?
172 int (*can_send)(struct eth_drv_sc *sc);
173 // Send a packet of data
174 void (*send)(struct eth_drv_sc *sc,
175 struct eth_drv_sg *sg_list,
179 // Receive [unload] a packet of data
180 void (*recv)(struct eth_drv_sc *sc,
181 struct eth_drv_sg *sg_list,
183 // Deliver data to/from device from/to stack memory space
184 // (moves lots of memcpy()s out of DSRs into thread)
185 void (*deliver)(struct eth_drv_sc *sc);
186 // Poll for interrupts/device service
187 void (*poll)(struct eth_drv_sc *sc);
188 // Get interrupt information from hardware driver
189 int (*int_vector)(struct eth_drv_sc *sc);
190 // Logical driver interface
191 struct eth_drv_funs *eth_drv, *eth_drv_old;
195 struct eth_hwr_funs *funs;
196 void *driver_private;
197 const char *dev_name;
199 struct arpcom sc_arpcom; /* ethernet common */
212 >If you have two instances of the same hardware, you only need one
215 >struct eth_hwr_funs</SPAN
216 > shared between them.</P
220 >There is another structure which is used to communicate with the rest of
229 CLASS="PROGRAMLISTING"
230 >struct eth_drv_funs {
231 // Logical driver - initialization
232 void (*init)(struct eth_drv_sc *sc,
233 unsigned char *enaddr);
234 // Logical driver - incoming packet notifier
235 void (*recv)(struct eth_drv_sc *sc,
237 // Logical driver - outgoing packet notifier
238 void (*tx_done)(struct eth_drv_sc *sc,
246 Your driver does <SPAN
252 > create an instance of this
253 structure. It is provided for driver code to use in the
257 > member of the function record.
258 Its usage is described below in <A
259 HREF="io-eth-drv-upper-api.html"
260 >the Section called <I
261 >Upper Layer Functions</I
265 >One more function completes the API with which your driver communicates
266 with the rest of the stack:
274 CLASS="PROGRAMLISTING"
275 >extern void eth_drv_dsr(cyg_vector_t vector,
277 cyg_addrword_t data);</PRE
283 >This function is designed so that it can be registered as the DSR for your
284 interrupt handler. It will awaken the
285 “Network Delivery Thread”
286 to call your deliver routine. See <A
287 HREF="io-eth-drv-api-funcs.html#IO-ETH-DRV-API-DELIVER"
288 >the Section called <I
293 >You create an instance of <SPAN
295 >struct eth_drv_sc</SPAN
303 sets up the structure, including the prototypes for the functions, etc.
304 By doing things this way, if the internal design of the ethernet drivers
305 changes (e.g. we need to add a new low-level implementation function),
306 existing drivers will no longer compile until updated. This is much
307 better than to have all of the definitions in the low-level drivers
308 themselves and have them be (quietly) broken if the interfaces change.</P
310 >The “magic”
311 which gets the drivers started (and indeed, linked) is
312 similar to what is used for the I/O subsystem.
313 This is done using the
316 >NETDEVTAB_ENTRY()</TT
318 macro, which defines an initialization function
319 and the basic data structures for the low-level driver.</P
328 CLASS="PROGRAMLISTING"
329 > typedef struct cyg_netdevtab_entry {
331 bool (*init)(struct cyg_netdevtab_entry *tab);
332 void *device_instance;
333 unsigned long status;
334 } cyg_netdevtab_entry_t;</PRE
343 entry here would point to the <SPAN
345 >struct eth_drv_sc</SPAN
347 entry previously defined. This allows the network driver
348 setup to work with any class of driver, not just ethernet drivers. In
349 the future, there will surely be serial <SPAN
353 drivers, etc. These will
356 >NETDEVTAB_ENTRY()</TT
358 setup to create the basic driver, but they will
359 most likely be built on top of other high-level device driver layers.</P
361 >To instantiate itself, and connect it to the system,
362 a hardware driver will have a template
363 (boilerplate) which looks something like this:
371 CLASS="PROGRAMLISTING"
372 >#include <cyg/infra/cyg_type.h>
373 #include <cyg/hal/hal_arch.h>
374 #include <cyg/infra/diag.h>
375 #include <cyg/hal/drv_api.h>
376 #include <cyg/io/eth/netdev.h>
377 #include <cyg/io/eth/eth_drv.h>
385 0, // No driver specific data needed
386 "eth0", // Name for this interface
472 >This, along with the referenced functions, completely define the driver.</P
480 >If one needed the same low-level driver to handle
481 multiple similar hardware interfaces, you would need multiple invocations
488 >NETDEVTAB_ENTRY()</TT
490 macros. You would add a pointer
491 to some instance specific data, e.g. containing base addresses, interrupt
492 numbers, etc, where the
500 CLASS="PROGRAMLISTING"
501 > 0, // No driver specific data</PRE
516 SUMMARY="Footer navigation table"
527 HREF="io-eth-drv-generic.html"
545 HREF="io-eth-drv-api-funcs.html"
555 >Ethernet Device Drivers</TD
561 HREF="io-eth-drv-generic.html"
569 >Review of the functions</TD