OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [doc/] [html/] [ref/] [io-eth-drv-generic1.html] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 28 unneback
<!-- 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
>

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.