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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [usb/] [eth/] [slave/] [v2_0/] [src/] [usbsethdrv.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      usbethdrv.c
4
//
5
//      Network device driver for USB-ethernet devices.
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    bartv
44
// Contributors: bartv
45
// Date:         2000-10-04
46
//
47
//####DESCRIPTIONEND####
48
//==========================================================================
49
 
50
#include <cyg/infra/cyg_type.h>
51
#include <cyg/hal/hal_arch.h>
52
#include <cyg/infra/diag.h>
53
#include <cyg/hal/drv_api.h>
54
 
55
#define __ECOS 1
56
#include <cyg/io/eth/netdev.h>
57
#include <cyg/io/eth/eth_drv.h>
58
#include <cyg/io/eth/eth_drv_stats.h>
59
 
60
#include <pkgconf/io_usb_slave_eth.h>
61
#include <cyg/io/usb/usbs_eth.h>
62
 
63
// ----------------------------------------------------------------------------
64
// The network driver data structure.
65
ETH_DRV_SC(usbs_eth_sc0,
66
           (void*) &usbs_eth0,
67
           CYGDAT_USBS_ETHDRV_NAME,
68
           usbs_ethdrv_start,
69
           usbs_ethdrv_stop,
70
           usbs_ethdrv_ioctl,
71
           usbs_ethdrv_can_send,
72
           usbs_ethdrv_send,
73
           usbs_ethdrv_recv,
74
           usbs_ethdrv_deliver,
75
           usbs_ethdrv_poll,
76
           usbs_ethdrv_intvector);
77
 
78
NETDEVTAB_ENTRY(usbs_eth_netdev0,
79
                "usbs_eth0",
80
                usbs_ethdrv_init,
81
                &usbs_eth_sc0);
82
 
83
// ----------------------------------------------------------------------------
84
// Statics gathering. The following macro can be used to increment a
85
// statistic without having to use a #ifdef for the statistics
86
// configuration option everywhere.
87
#ifdef CYGFUN_USBS_ETHDRV_STATISTICS
88
# define INCR_STAT(a)   \
89
     CYG_MACRO_START    \
90
     (a) += 1;          \
91
     CYG_MACRO_END
92
#else
93
# define INCR_STAT(a)      CYG_EMPTY_STATEMENT
94
#endif
95
 
96
// Various constants related to SNMP statistics. It is not clear
97
// what these are all for.
98
#ifdef CYGFUN_USBS_ETHDRV_STATISTICS
99
# define CYGDAT_USBS_ETHDRV_DESCRIPTION "eCos USB ethernet device"
100
#endif
101
// ----------------------------------------------------------------------------
102
// Utility functions.
103
//
104
// The TCP/IP stack works in terms of scatter/gather buffers. USB tends to
105
// involve DMA operations so it is more convenient to work in terms of
106
// 1514 byte flat buffers. Actually, the first two bytes of the buffer
107
// are used to hold the ethernet frame size to work around restrictions
108
// with certain hardware implementations of USB that may be unable to
109
// transfer certain packet sizes.
110
 
111
static bool
112
scatter(unsigned char* buf, struct eth_drv_sg* sg, int sg_len)
113
{
114
    unsigned int size;
115
 
116
    size = buf[0] | (buf[1] << 8);
117
    buf++; buf++;
118
 
119
    CYG_ASSERT((size >= CYGNUM_USBS_ETH_MIN_FRAME_SIZE) && (size <= CYGNUM_USBS_ETH_MAX_FRAME_SIZE),\
120
               "ethernet frame size limits must be observed");
121
 
122
    while ((size > 0) && (sg_len > 0)) {
123
        if (size > sg->len) {
124
            memcpy((void*) sg->buf, buf, sg->len);
125
            buf  += sg->len;
126
            size -= sg->len;
127
            sg++;
128
            sg_len--;
129
        } else {
130
            memcpy((void*) sg->buf, buf, size);
131
            size = 0;
132
        }
133
    }
134
 
135
    return 0 == size;
136
}
137
 
138
static bool
139
gather(unsigned char* buf, unsigned int size, struct eth_drv_sg* sg, int sg_len)
140
{
141
    unsigned int    left = size;
142
    unsigned char*  base = buf;
143
 
144
    buf++; buf++;
145
    while ((left > 0) && (sg_len > 0)) {
146
        if (left > sg->len) {
147
            memcpy(buf, (void*) sg->buf, sg->len);
148
            buf  += sg->len;
149
            left -= sg->len;
150
            sg++;
151
            sg_len--;
152
        } else {
153
            memcpy(buf, (void*) sg->buf, left);
154
            left = 0;
155
        }
156
    }
157
    size    = size - left;
158
    base[0] = size & 0x00FF;
159
    base[1] = (size >> 8) & 0x00FF;
160
 
161
    return 0 == left;
162
}
163
 
164
 
165
// ----------------------------------------------------------------------------
166
// usbs_ethdrv_init()
167
//
168
// This function is called during system initialization to decide
169
// whether or not this particular network device is usable. For
170
// USB-ethernet this is problematical, the device is only really
171
// usable once both sides have come up. The typical sequence
172
// of events is something like:
173
//
174
// 1) the eCos peripheral is powered up. Static constructors are
175
//    run resulting in basic initialization.
176
//
177
// 2) the eCos TCP/IP stack initialization happens. Roughly in
178
//    parallel the eCos USB slave side is initialized as well,
179
//    i.e. enumeration data is supplied to control endpoints,
180
//    endpoints are associated with application classes, and so
181
//    on. The relative order of TCP/IP and USB initialization is
182
//    not particularly important.
183
//
184
//    It is the TCP/IP stack's initialization code that will
185
//    invoke usbs_eth_init().
186
//
187
// 3) host-side USB detects that the eCos peripheral has been
188
//    connected or powered up. It goes through the enumeration
189
//    process and will end up loading a host-side network driver.
190
//    This connects to the eCos-side USB ethernet code to
191
//    e.g. obtain the MAC address. 
192
//
193
// 4) when the host-side is ready, the eCos side can be brought up.
194
//    The required call is (sc->funs->eth_drv->init)(sc, enaddr)
195
//
196
// In practice it is easier for now to invoke the init() function
197
// immediately. There are not going to be any incoming packets
198
// until the host is ready, and can_send() can just return false
199
// for the time being.
200
//
201
// Invoked in: thread context only
202
// ----------------------------------------------------------------------------
203
 
204
static bool
205
usbs_ethdrv_init(struct cyg_netdevtab_entry* ndp)
206
{
207
    struct eth_drv_sc*  sc  = (struct eth_drv_sc*)(ndp->device_instance);
208
    usbs_eth*           eth = (usbs_eth*)(sc->driver_private);
209
 
210
    (*sc->funs->eth_drv->init)(sc, eth->ecos_MAC);
211
    return true;
212
}
213
 
214
// ----------------------------------------------------------------------------
215
// The receive process that is used to transfer a received ethernet
216
// packet into the stack. The calling sequence is somewhat convoluted.
217
// It started off as:
218
//
219
//   1) Ethernet hw ISR invoked by hardware, schedules its own
220
//      hw_dsr(), and blocks further interrupts in the ethernet chip
221
//   2) hw_dsr() calls generic eth_drv_dsr() from io/eth common package
222
//   3) eth_drv_dsr() interacts with the TCP/IP stack and allocates mbufs
223
//      (typically, the TCP/IP stack might not be in use)
224
//   4) eth_drv_dsr() calls usbs_eth_recv() to transfer the data to mbufs
225
//   5) eth_drv_dsr() returns to hw_dsr() which reenables interrupts
226
//   6) hw_dsr() completes and everything can proceed.
227
//
228
// The problem with this is that the whole ethernet packet gets copied
229
// inside a DSR, affecting dispatch latency (but not interrupt latency).
230
// This is bad. Hence there is an alternative route involving a separate
231
// thread in the TCP/IP stack.
232
//
233
//   1) Ethernet hw ISR runs as before, scheduling hw_dsr()
234
//   2) hw_dsr() calls up into eth_drv_dsr()
235
//   3) eth_drv_dsr() wakes up a thread inside the TCP/IP stack
236
//   4) eth_drv_dsr() returns to hw_dsr(), which performs no further
237
//      processing. Ethernet chip interrupts remain disabled.
238
//   5) The TCP/IP thread ends up calling hw_deliver(). This should take
239
//      care of any pending activity. For every buffered packet there should
240
//      be a call to a generic recv() function which then goes back into
241
//      the driver-specific recv() function.
242
//
243
// The advantage is that ethernet packet copying now happens at thread
244
// level rather than DSR level so thread priorities can be used to
245
// schedule things.
246
//
247
// USB-ethernet does not interact directly with any hardware, instead
248
// it just passes information to lower levels of USB code. The reception
249
// process is started by usbs_ethdrv_start() when the TCP/IP stack brings
250
// up the interface. 
251
//
252
// When the USB transfer has completed a callback will be invoked, at
253
// DSR level. Assuming the transfer went ok, the callback will invoke
254
// eth_drv_dsr() to inform the higher level code. 
255
//
256
// The deliver function can check the state of the buffer
257
// and go through the sc->funs->eth_drv->recv()/recv() sequence
258
// to transfer the data into the stack. 
259
//
260
// usbs_ethdrv_recv() does a scatter from the internal buffer into the
261
// mbuf, thus freeing up the buffer. This allows it to start another
262
// receive,
263
//
264
// Synchronisation involves the scheduler lock because the recv
265
// callback is invoked inside a DSR.
266
 
267
static void usbs_ethdrv_halted_callback(void*, int);
268
 
269
static void
270
usbs_ethdrv_recv_callback(usbs_eth* eth, void* callback_data, int size)
271
{
272
    cyg_bool resubmit = true;
273
 
274
    struct eth_drv_sc* sc = (struct eth_drv_sc*) callback_data;
275
    CYG_ASSERT( eth == (usbs_eth*)(sc->driver_private), "USB and TCP/IP worlds need to be consistent");
276
 
277
    INCR_STAT(eth->interrupts);
278
    if (!eth->ecos_up) {
279
        // This message should just be discarded since the eCos TCP/IP
280
        // stack is not expecting anything from this interface.
281
        // Reception will resume when the interface comes back up.
282
        eth->rx_active  = false;
283
        resubmit        = false;
284
    } else if (size < 0) {
285
        // An error has occurred. The likely possibilities are:
286
        // -EPIPE:      connection to the host has been broken
287
        // -EAGAIN:     the endpoint is haltedn
288
        // -EMSGSIZE:   bogus message from host
289
        // -EIO:        other
290
 
291
        if (-EAGAIN == size) {
292
            // EAGAIN should be handled by waiting for the endpoint to be reset.
293
            resubmit = false;
294
            usbs_start_rx_endpoint_wait(eth->rx_endpoint, &usbs_ethdrv_halted_callback, (void*) sc);
295
        } else if (-EMSGSIZE == size) {
296
            // Do nothing for now
297
        } else {
298
            // EPIPE should be resubmitted, the usbseth.c will use the
299
            // pending rx support. EIO could mean anything.
300
        }
301
    } else if (0 == size) {
302
        // The endpoint is no longer halted. Just do the resubmit at
303
        // the end.
304
    } else {
305
        // A packet has been received. Now do a size sanity check
306
        // based on the first two bytes.
307
        int real_size = eth->rx_bufptr[0] + (eth->rx_bufptr[1] << 8);
308
        if (real_size < CYGNUM_USBS_ETH_MIN_FRAME_SIZE) {
309
            INCR_STAT(eth->rx_short_frames);
310
        } else if (real_size > CYGNUM_USBS_ETH_MAX_FRAME_SIZE) {
311
            INCR_STAT(eth->rx_too_long_frames);
312
        } else {
313
            // The packet appears to be valid. Inform higher level
314
            // code and mark the buffer as in use.
315
            resubmit            = false;
316
            eth->rx_buffer_full = true;
317
            eth->rx_active      = false;
318
            eth_drv_dsr(0, 0, (cyg_addrword_t) sc);
319
        }
320
    }
321
 
322
    if (resubmit) {
323
        eth->rx_active = true;
324
        usbs_eth_start_rx(eth, eth->rx_bufptr, &usbs_ethdrv_recv_callback, callback_data);
325
    }
326
}
327
 
328
// Another callback, used to wait while an endpoint is halted.
329
static void
330
usbs_ethdrv_halted_callback(void* callback_data, int size)
331
{
332
    struct eth_drv_sc* sc = (struct eth_drv_sc*) callback_data;
333
    usbs_ethdrv_recv_callback((usbs_eth*) sc->driver_private, callback_data, 0);
334
}
335
 
336
// Start a receive operation. It is not possible to abort an existing
337
// rx operation, so a valid sequence of events is: start, rx ongoing,
338
// stop, restart. The rx_active field is used to keep track of whether
339
// or not there is still a receive in progress. The receive callback
340
// will just discard incoming data if the eCos stack is not currently
341
// running.
342
static void
343
usbs_ethdrv_start_recv(struct eth_drv_sc* sc, usbs_eth* eth)
344
{
345
    cyg_drv_dsr_lock();
346
    if (!eth->rx_active) {
347
        eth->rx_active = true;
348
        usbs_eth_start_rx(eth, eth->rx_bufptr, &usbs_ethdrv_recv_callback, (void*) sc);
349
    }
350
    cyg_drv_dsr_unlock();
351
}
352
 
353
// This is invoked from the delivery thread when a valid buffer
354
// has been received. The buffer should be scattered into the
355
// supplied list, then another receive should be started.
356
 
357
static void
358
usbs_ethdrv_recv(struct eth_drv_sc* sc,
359
                 struct eth_drv_sg* sg_list, int sg_len)
360
{
361
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
362
 
363
    CYG_ASSERT( eth->rx_buffer_full, "This function should only be called when there is a buffer available");
364
    (void) scatter(eth->rx_bufptr, sg_list, sg_len);
365
    eth->rx_buffer_full = false;
366
    eth->rx_active      = true;
367
    usbs_eth_start_rx(eth, eth->rx_bufptr, &usbs_ethdrv_recv_callback, (void*) sc);
368
}
369
 
370
// ----------------------------------------------------------------------------
371
// Now for the transmit process.
372
//
373
// When an application thread writes down a socket the data gets moved
374
// into mbufs, and then passed to the appropriate device driver - which
375
// may or may not be able to process it immediately. There is also a
376
// timeout thread within the TCP/IP to handle retransmits etc.
377
//
378
// The stack will start by calling usbs_ethdrv_can_send() to determine
379
// whether or not the driver can accept the packet. For the purposes
380
// of the USB-ethernet driver this is true provided both host
381
// and target are up and there is a spare buffer available.
382
//
383
// If the usbs_eth_can_send() returns true then there will be a call
384
// to usbs_ethdrv_send(). This gathers the data into a single
385
// buffer. If there is no transmit in progress yet then one is started.
386
//
387
// At some point the packet will have been transmitted and a callback
388
// gets invoked. This needs to call eth_drv_dsr(), waking up the
389
// delivery thread. The deliver() function can then check which
390
// transmissions have completed and inform the higher level code
391
// via sc->funs->eth_drv->tx_done(). The buffer can be re-used at
392
// that point.
393
 
394
static void
395
usbs_ethdrv_send_callback(usbs_eth* eth, void* callback_data, int size)
396
{
397
    struct eth_drv_sc* sc = (struct eth_drv_sc*) callback_data;
398
    CYG_ASSERT( eth == (usbs_eth*)(sc->driver_private), "USB and TCP/IP worlds need to be consistent");
399
 
400
    INCR_STAT(eth->interrupts);
401
 
402
    // There are a variety of possible error codes. -EAGAIN indicates
403
    // that the endpoint is stalled. -EPIPE indicates that the
404
    // connection to the host has been lost. These are not really
405
    // particularly interesting. Whatever happens the buffer
406
    // must be cleared and higher-level code informed so that
407
    // the mbufs can be released.
408
    if (size > 0) {
409
        INCR_STAT(eth->tx_count);
410
    }
411
    eth->tx_done = true;
412
    eth_drv_dsr(0, 0, (cyg_addrword_t) sc);
413
}
414
 
415
// Is it possible to send an ethernet frame? This requires
416
// an empty buffer, i.e. there should be no existing
417
// transmit in progress. It also requires that the host
418
// is connected and that the endpoint is not currently halted.
419
static int
420
usbs_ethdrv_can_send(struct eth_drv_sc* sc)
421
{
422
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
423
    return eth->host_up && !eth->tx_buffer_full && !eth->tx_endpoint->halted;
424
}
425
 
426
// Actually start a packet transmission. This means collecting
427
// all the data into a single buffer and then invoking the
428
// lower-level code. The latter may discard the packet immediately
429
// if the MAC is not appropriate: it would be more efficient to
430
// catch that here, especially for large packets, but the check
431
// has to happen inside the lower-level code anyway in case
432
// that is being invoked directly rather than via the driver.
433
//
434
// There is a possible recursion problem,
435
// send->start_tx->tx_done->can_send->send, which is guarded
436
// against using the tx_in_send flag.
437
 
438
static void
439
usbs_ethdrv_send(struct eth_drv_sc* sc,
440
              struct eth_drv_sg* sgl_list, int sg_len, int total_len,
441
              unsigned long key)
442
{
443
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
444
 
445
    CYG_ASSERT( 0 == eth->tx_in_send, "send() should not be invoked recursively");
446
    CYG_ASSERT( total_len <= CYGNUM_USBS_ETH_MAX_FRAME_SIZE, "ethernet maximum frame size should be observed");
447
    CYG_ASSERT( CYGNUM_USBS_ETH_MIN_FRAME_SIZE <= total_len, "ethernet minimum frame size should be observed");
448
 
449
    eth->tx_in_send = true;
450
    CYG_ASSERT( !eth->tx_buffer_full, "the transmit buffer should be empty");
451
    gather(eth->tx_buffer, CYGNUM_USBS_ETH_MAX_FRAME_SIZE, sgl_list, sg_len);
452
    eth->tx_buffer_full = true;
453
    eth->tx_done        = false;
454
    eth->tx_key         = key;
455
    usbs_eth_start_tx(eth, eth->tx_buffer, &usbs_ethdrv_send_callback, (void*) sc);
456
    eth->tx_in_send = false;
457
}
458
 
459
// ----------------------------------------------------------------------------
460
// Deliver needs to take into account both receive and transmit buffers.
461
 
462
static void
463
usbs_ethdrv_deliver(struct eth_drv_sc* sc)
464
{
465
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
466
 
467
    if (eth->rx_buffer_full) {
468
        int size = eth->rx_bufptr[0] + (eth->rx_bufptr[1] << 8);
469
        (*sc->funs->eth_drv->recv)(sc, size);
470
    }
471
    if (eth->tx_done) {
472
        unsigned long key   = eth->tx_key;
473
        eth->tx_buffer_full = false;
474
        eth->tx_done        = false;
475
        (*sc->funs->eth_drv->tx_done)(sc, key, 1);
476
    }
477
}
478
 
479
// ----------------------------------------------------------------------------
480
// usbs_ethdrv_start()
481
//
482
// This gets called by the TCP/IP stack later on during
483
// initialization, when the stack is ready to send and receive
484
// packets. It may get called multiple times while the stack
485
// is running, with different flags values.
486
//
487
// As far as transmits are concerned, nothing needs to be done. If no
488
// transmit is in progress then everything is fine anyway. If a
489
// transmit is already in progress then it must be allowed to complete
490
// via the usual route. Receives should however be restarted, the
491
// start function has appropriate safeguards.
492
//
493
// Invoked in: thread context only
494
// ----------------------------------------------------------------------------
495
 
496
static void
497
usbs_ethdrv_start(struct eth_drv_sc* sc, unsigned char* enaddr, int flags)
498
{
499
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
500
    if (!eth->ecos_up) {
501
        eth->ecos_up = true;
502
        usbs_ethdrv_start_recv(sc, eth);
503
    }
504
}
505
 
506
// ----------------------------------------------------------------------------
507
// usbs_ethdrv_stop()
508
//
509
// Similarly this gets called by the TCP/IP stack to bring the network
510
// interface down. Nothing should happen for any packets currently
511
// being transmitted or received, that would cause confusion everywhere.
512
// The receive callback checks the ecos_up flag and does the right
513
// thing. The TCP/IP stack should not call can_send() after taking
514
// the interface down so no new transmits will be initiated.
515
//
516
// Invoked in: thread context only
517
// ----------------------------------------------------------------------------
518
 
519
static void
520
usbs_ethdrv_stop(struct eth_drv_sc* sc)
521
{
522
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
523
    eth->ecos_up = false;
524
}
525
 
526
// ----------------------------------------------------------------------------
527
// usbs_eth_ioctl()
528
//
529
// The operations to worry about here are:
530
//
531
//    SET_MAC_ADDRESS,via the SIOCSIFHWADDR ioctl
532
//
533
//    GET_IF_STATS and GET_IF_STATS_UD, to report gathered statistics.
534
//
535
// Invoked in: thread context only
536
// ----------------------------------------------------------------------------
537
 
538
static int
539
usbs_ethdrv_ioctl(struct eth_drv_sc* sc, unsigned long key, void* data, int data_length)
540
{
541
    usbs_eth* eth = (usbs_eth*)(sc->driver_private);
542
    int       result = EINVAL;
543
 
544
    switch(key) {
545
      case ETH_DRV_SET_MAC_ADDRESS:
546
        {
547
            if (6 == data_length) {
548
                memcpy(eth->ecos_MAC, data, 6);
549
                result = 0;
550
            }
551
        }
552
        break;
553
#if defined(CYGFUN_USBS_ETHDRV_STATISTICS) && defined(ETH_DRV_GET_IF_STATS_UD)
554
      case ETH_DRV_GET_IF_STATS_UD:
555
      case ETH_DRV_GET_IF_STATS:
556
        {
557
            static unsigned char my_chipset[] = { 0, 0 };
558
            struct ether_drv_stats *p = (struct ether_drv_stats*) data;
559
            int    i;
560
            strcpy(p->description, CYGDAT_USBS_ETHDRV_DESCRIPTION);
561
            for ( i = 0; i < SNMP_CHIPSET_LEN; i++ ) {
562
                if ( 0 == (p->snmp_chipset[i] = my_chipset[i]) ) {
563
                    break;
564
                }
565
            }
566
            p->duplex               = 3;        // 3 == duplex
567
            p->operational          = (eth->host_up && eth->ecos_up) ? 3 : 2;   // 3 == up, 2 == down
568
            p->speed                = 10 * 1000000;
569
            p->supports_dot3        = 1;
570
            p->rx_too_long_frames   = eth->rx_too_long_frames;
571
            p->rx_short_frames      = eth->rx_short_frames;
572
            p->interrupts           = eth->interrupts;
573
            p->rx_count             = eth->rx_count;
574
            p->tx_count             = eth->tx_count;
575
            p->tx_queue_len         = 1;
576
        }
577
        break;
578
#endif
579
 
580
      default:
581
        break;
582
    }
583
 
584
    return result;
585
}
586
 
587
 
588
// ----------------------------------------------------------------------------
589
// usbs_ethdrv_poll()
590
//
591
// On real ethernet hardware this is used by RedBoot once the
592
// application has started running, so that the network device can be
593
// used for debugging purposes as well as for the application's own
594
// needs. The lower-level USB device may supply a poll function as well.
595
// ----------------------------------------------------------------------------
596
static void
597
usbs_ethdrv_poll(struct eth_drv_sc* sc)
598
{
599
    usbs_eth*   eth = (usbs_eth*)(sc->driver_private);
600
    (*eth->control_endpoint->poll_fn)(eth->control_endpoint);
601
}
602
 
603
// ----------------------------------------------------------------------------
604
// usbs_ethdrv_intvector()
605
//
606
// See usbs_eth_poll().
607
// ----------------------------------------------------------------------------
608
 
609
static int
610
usbs_ethdrv_intvector(struct eth_drv_sc* sc)
611
{
612
    usbs_eth*   eth = (usbs_eth*)(sc->driver_private);
613
    return eth->control_endpoint->interrupt_vector;
614
}
615
 
616
 

powered by: WebSVN 2.1.0

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