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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [usb/] [eth/] [slave/] [current/] [src/] [usbsethdrv.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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