]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/ref/io-eth-drv-generic1.html
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / doc / html / ref / io-eth-drv-generic1.html
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.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >Generic Ethernet Device Driver</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
14 <META
15 NAME="GENERATOR"
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17 "><LINK
18 REL="HOME"
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
21 REL="UP"
22 TITLE="Ethernet Device Drivers"
23 HREF="io-eth-drv-generic.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Ethernet Device Drivers"
26 HREF="io-eth-drv-generic.html"><LINK
27 REL="NEXT"
28 TITLE="Review of the functions"
29 HREF="io-eth-drv-api-funcs.html"></HEAD
30 ><BODY
31 CLASS="CHAPTER"
32 BGCOLOR="#FFFFFF"
33 TEXT="#000000"
34 LINK="#0000FF"
35 VLINK="#840084"
36 ALINK="#0000FF"
37 ><DIV
38 CLASS="NAVHEADER"
39 ><TABLE
40 SUMMARY="Header navigation table"
41 WIDTH="100%"
42 BORDER="0"
43 CELLPADDING="0"
44 CELLSPACING="0"
45 ><TR
46 ><TH
47 COLSPAN="3"
48 ALIGN="center"
49 >eCos Reference Manual</TH
50 ></TR
51 ><TR
52 ><TD
53 WIDTH="10%"
54 ALIGN="left"
55 VALIGN="bottom"
56 ><A
57 HREF="io-eth-drv-generic.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 ></TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="io-eth-drv-api-funcs.html"
72 ACCESSKEY="N"
73 >Next</A
74 ></TD
75 ></TR
76 ></TABLE
77 ><HR
78 ALIGN="LEFT"
79 WIDTH="100%"></DIV
80 ><DIV
81 CLASS="CHAPTER"
82 ><H1
83 ><A
84 NAME="IO-ETH-DRV-GENERIC1">Chapter 46. Generic Ethernet Device Driver</H1
85 ><DIV
86 CLASS="TOC"
87 ><DL
88 ><DT
89 ><B
90 >Table of Contents</B
91 ></DT
92 ><DT
93 ><A
94 HREF="io-eth-drv-generic1.html#IO-ETH-DRV-API"
95 >Generic Ethernet API</A
96 ></DT
97 ><DT
98 ><A
99 HREF="io-eth-drv-api-funcs.html"
100 >Review of the functions</A
101 ></DT
102 ><DT
103 ><A
104 HREF="io-eth-drv-upper-api.html"
105 >Upper Layer Functions</A
106 ></DT
107 ><DT
108 ><A
109 HREF="io-eth-call-graph.html"
110 >Calling graph for Transmission and Reception</A
111 ></DT
112 ></DL
113 ></DIV
114 ><DIV
115 CLASS="SECT1"
116 ><H1
117 CLASS="SECT1"
118 ><A
119 NAME="IO-ETH-DRV-API">Generic Ethernet API</H1
120 ><P
121 >This file provides a simple description of how to write a low-level,
122 hardware dependent ethernet driver.</P
123 ><P
124 >There is a high-level driver (which is only code &#8212; 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
130 <SPAN
131 CLASS="PRODUCTNAME"
132 >eCos</SPAN
133 >
134 supported
135 <SPAN
136 CLASS="ACRONYM"
137 >TCP/IP</SPAN
138 >
139 stack,
140 <SPAN
141 CLASS="PRODUCTNAME"
142 >RedBoot</SPAN
143 >,
144 or any other, with no changes.</P
145 ><P
146 >A driver instance is contained within a
147 <SPAN
148 CLASS="TYPE"
149 >struct eth_drv_sc</SPAN
150 >:
151 <TABLE
152 BORDER="5"
153 BGCOLOR="#E0E0F0"
154 WIDTH="70%"
155 ><TR
156 ><TD
157 ><PRE
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,
163                   int flags);
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,
168                     unsigned long key,
169                     void *data,
170                     int   data_length);
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,
176                  int sg_len,
177                  int total_len,
178                  unsigned long key);
179     // Receive [unload] a packet of data
180     void (*recv)(struct eth_drv_sc *sc,
181                  struct eth_drv_sg *sg_list,
182                  int sg_len);
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;
192 };
193
194 struct eth_drv_sc {
195     struct eth_hwr_funs *funs;
196     void                *driver_private;
197     const char          *dev_name;
198     int                  state;
199     struct arpcom        sc_arpcom; /* ethernet common */
200 };</PRE
201 ></TD
202 ></TR
203 ></TABLE
204 ></P
205 ><DIV
206 CLASS="NOTE"
207 ><BLOCKQUOTE
208 CLASS="NOTE"
209 ><P
210 ><B
211 >Note: </B
212 >If you have two instances of the same hardware, you only need one
213 <SPAN
214 CLASS="TYPE"
215 >struct eth_hwr_funs</SPAN
216 > shared between them.</P
217 ></BLOCKQUOTE
218 ></DIV
219 ><P
220 >There is another structure which is used to communicate with the rest of
221 the stack:
222 <TABLE
223 BORDER="5"
224 BGCOLOR="#E0E0F0"
225 WIDTH="70%"
226 ><TR
227 ><TD
228 ><PRE
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, 
236                  int total_len);
237     // Logical driver - outgoing packet notifier
238     void (*tx_done)(struct eth_drv_sc *sc, 
239                     CYG_ADDRESS key, 
240                     int status);
241 };</PRE
242 ></TD
243 ></TR
244 ></TABLE
245 >
246 Your driver does <SPAN
247 CLASS="emphasis"
248 ><I
249 CLASS="EMPHASIS"
250 >not</I
251 ></SPAN
252 > create an instance of this
253 structure.  It is provided for driver code to use in the
254 <SPAN
255 CLASS="TYPE"
256 >eth_drv</SPAN
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
262 ></A
263 ></P
264 ><P
265 >One more function completes the API with which your driver communicates
266 with the rest of the stack:
267 <TABLE
268 BORDER="5"
269 BGCOLOR="#E0E0F0"
270 WIDTH="70%"
271 ><TR
272 ><TD
273 ><PRE
274 CLASS="PROGRAMLISTING"
275 >extern void eth_drv_dsr(cyg_vector_t vector,
276                         cyg_ucount32 count,
277                         cyg_addrword_t data);</PRE
278 ></TD
279 ></TR
280 ></TABLE
281 ></P
282 ><P
283 >This function is designed so that it can be registered as the DSR for your
284 interrupt handler.  It will awaken the
285 &#8220;Network Delivery Thread&#8221;
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
289 >Deliver function</I
290 ></A
291 >.</P
292 ><P
293 >You create an instance of <SPAN
294 CLASS="TYPE"
295 >struct eth_drv_sc</SPAN
296 >
297 using the
298 <TT
299 CLASS="FUNCTION"
300 >ETH_DRV_SC()</TT
301 >
302 macro which
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
309 ><P
310 >The &#8220;magic&#8221;
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
314 <TT
315 CLASS="FUNCTION"
316 >NETDEVTAB_ENTRY()</TT
317 >
318 macro, which defines an initialization function
319 and the basic data structures for the low-level driver.</P
320 ><P
321 ><TABLE
322 BORDER="5"
323 BGCOLOR="#E0E0F0"
324 WIDTH="70%"
325 ><TR
326 ><TD
327 ><PRE
328 CLASS="PROGRAMLISTING"
329 >  typedef struct cyg_netdevtab_entry {
330       const char        *name;
331       bool             (*init)(struct cyg_netdevtab_entry *tab);
332       void              *device_instance;
333       unsigned long     status;
334   } cyg_netdevtab_entry_t;</PRE
335 ></TD
336 ></TR
337 ></TABLE
338 >
339 The <TT
340 CLASS="VARNAME"
341 >device_instance</TT
342 >
343 entry here would point to the <SPAN
344 CLASS="TYPE"
345 >struct eth_drv_sc</SPAN
346 >
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
350 CLASS="ACRONYM"
351 >PPP</SPAN
352 >
353 drivers, etc.  These will
354 use the <TT
355 CLASS="FUNCTION"
356 >NETDEVTAB_ENTRY()</TT
357 >
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
360 ><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:
364 <TABLE
365 BORDER="5"
366 BGCOLOR="#E0E0F0"
367 WIDTH="70%"
368 ><TR
369 ><TD
370 ><PRE
371 CLASS="PROGRAMLISTING"
372 >#include &lt;cyg/infra/cyg_type.h&gt;
373 #include &lt;cyg/hal/hal_arch.h&gt;
374 #include &lt;cyg/infra/diag.h&gt;
375 #include &lt;cyg/hal/drv_api.h&gt;
376 #include &lt;cyg/io/eth/netdev.h&gt;
377 #include &lt;cyg/io/eth/eth_drv.h&gt;
378
379 ETH_DRV_SC(<TT
380 CLASS="REPLACEABLE"
381 ><I
382 >DRV</I
383 ></TT
384 >_sc,
385            0,             // No driver specific data needed
386            "eth0",        // Name for this interface
387            <TT
388 CLASS="REPLACEABLE"
389 ><I
390 >HRDWR</I
391 ></TT
392 >_start,
393            <TT
394 CLASS="REPLACEABLE"
395 ><I
396 >HRDWR</I
397 ></TT
398 >_stop,
399            <TT
400 CLASS="REPLACEABLE"
401 ><I
402 >HRDWR</I
403 ></TT
404 >_control,
405            <TT
406 CLASS="REPLACEABLE"
407 ><I
408 >HRDWR</I
409 ></TT
410 >_can_send
411            <TT
412 CLASS="REPLACEABLE"
413 ><I
414 >HRDWR</I
415 ></TT
416 >_send,
417            <TT
418 CLASS="REPLACEABLE"
419 ><I
420 >HRDWR</I
421 ></TT
422 >_recv,
423            <TT
424 CLASS="REPLACEABLE"
425 ><I
426 >HRDWR</I
427 ></TT
428 >_deliver,
429            <TT
430 CLASS="REPLACEABLE"
431 ><I
432 >HRDWR</I
433 ></TT
434 >_poll,
435            <TT
436 CLASS="REPLACEABLE"
437 ><I
438 >HRDWR</I
439 ></TT
440 >_int_vector
441 );
442
443 NETDEVTAB_ENTRY(<TT
444 CLASS="REPLACEABLE"
445 ><I
446 >DRV</I
447 ></TT
448 >_netdev, 
449                 "<TT
450 CLASS="REPLACEABLE"
451 ><I
452 >DRV</I
453 ></TT
454 >", 
455                 <TT
456 CLASS="REPLACEABLE"
457 ><I
458 >DRV_HRDWR</I
459 ></TT
460 >_init, 
461                 &amp;<TT
462 CLASS="REPLACEABLE"
463 ><I
464 >DRV</I
465 ></TT
466 >_sc);</PRE
467 ></TD
468 ></TR
469 ></TABLE
470 ></P
471 ><P
472 >This, along with the referenced functions, completely define the driver.</P
473 ><DIV
474 CLASS="NOTE"
475 ><BLOCKQUOTE
476 CLASS="NOTE"
477 ><P
478 ><B
479 >Note: </B
480 >If one needed the same low-level driver to handle
481 multiple similar hardware interfaces, you would need multiple invocations
482 of the
483 <TT
484 CLASS="FUNCTION"
485 >ETH_DRV_SC()</TT
486 >/<TT
487 CLASS="FUNCTION"
488 >NETDEVTAB_ENTRY()</TT
489 >
490 macros.  You would add a pointer
491 to some instance specific data, e.g. containing base addresses, interrupt
492 numbers, etc, where the
493 <TABLE
494 BORDER="5"
495 BGCOLOR="#E0E0F0"
496 WIDTH="70%"
497 ><TR
498 ><TD
499 ><PRE
500 CLASS="PROGRAMLISTING"
501 >       0, // No driver specific data</PRE
502 ></TD
503 ></TR
504 ></TABLE
505 >
506 is currently.</P
507 ></BLOCKQUOTE
508 ></DIV
509 ></DIV
510 ></DIV
511 ><DIV
512 CLASS="NAVFOOTER"
513 ><HR
514 ALIGN="LEFT"
515 WIDTH="100%"><TABLE
516 SUMMARY="Footer navigation table"
517 WIDTH="100%"
518 BORDER="0"
519 CELLPADDING="0"
520 CELLSPACING="0"
521 ><TR
522 ><TD
523 WIDTH="33%"
524 ALIGN="left"
525 VALIGN="top"
526 ><A
527 HREF="io-eth-drv-generic.html"
528 ACCESSKEY="P"
529 >Prev</A
530 ></TD
531 ><TD
532 WIDTH="34%"
533 ALIGN="center"
534 VALIGN="top"
535 ><A
536 HREF="ecos-ref.html"
537 ACCESSKEY="H"
538 >Home</A
539 ></TD
540 ><TD
541 WIDTH="33%"
542 ALIGN="right"
543 VALIGN="top"
544 ><A
545 HREF="io-eth-drv-api-funcs.html"
546 ACCESSKEY="N"
547 >Next</A
548 ></TD
549 ></TR
550 ><TR
551 ><TD
552 WIDTH="33%"
553 ALIGN="left"
554 VALIGN="top"
555 >Ethernet Device Drivers</TD
556 ><TD
557 WIDTH="34%"
558 ALIGN="center"
559 VALIGN="top"
560 ><A
561 HREF="io-eth-drv-generic.html"
562 ACCESSKEY="U"
563 >Up</A
564 ></TD
565 ><TD
566 WIDTH="33%"
567 ALIGN="right"
568 VALIGN="top"
569 >Review of the functions</TD
570 ></TR
571 ></TABLE
572 ></DIV
573 ></BODY
574 ></HTML
575 >