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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [eth/] [current/] [src/] [lwip/] [eth_drv.c] - Blame information for rev 825

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

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/lwip/eth_drv.c
4
//
5
//      Hardware independent networking support for lwIP
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2008, 2009 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):    Simon Kallweit
43
// Contributors:
44
// Date:         2008-12-09
45
// Purpose:      Hardware independent networking support for lwIP.
46
// Description:  Based on the standalone driver for RedBoot.
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
#include <pkgconf/system.h>
53
#include <pkgconf/io_eth_drivers.h>
54
 
55
#include <cyg/infra/cyg_type.h>
56
#include <cyg/hal/hal_arch.h>
57
#include <cyg/infra/diag.h>
58
#include <cyg/hal/drv_api.h>
59
#include <cyg/hal/hal_if.h>
60
#include <cyg/io/eth/eth_drv.h>
61
#include <cyg/io/eth/netdev.h>
62
#include <string.h>
63
 
64
#include <cyg/hal/hal_tables.h>
65
#include <cyg/kernel/kapi.h>
66
 
67
#include <lwip/opt.h>
68
#include <lwip/ip.h>
69
#include <lwip/mem.h>
70
#include <lwip/pbuf.h>
71
#include <lwip/sys.h>
72
#include <lwip/dhcp.h>
73
#include <netif/etharp.h>
74
 
75
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
76
 
77
#include <cyg/hal/hal_if.h>
78
 
79
// Use with care!  Local variable defined!
80
#define START_CONSOLE()                                                                 \
81
{   /* NEW BLOCK */                                                                     \
82
    int _cur_console =                                                                  \
83
        CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);      \
84
    {                                                                                   \
85
        int i;                                                                          \
86
        if ( CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,                 \
87
                                          "info_console_force", &i,                     \
88
                                          CYGNUM_FLASH_CFG_TYPE_CONFIG_BOOL ) ) {       \
89
            if ( i ) {                                                                  \
90
                if ( CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,         \
91
                                                  "info_console_number", &i,            \
92
                                                  CYGNUM_FLASH_CFG_TYPE_CONFIG_INT ) ){ \
93
                    /* Then i is the console to force it to: */                         \
94
                    CYGACC_CALL_IF_SET_CONSOLE_COMM( i );                               \
95
                }                                                                       \
96
            }                                                                           \
97
        }                                                                               \
98
    }
99
 
100
#define END_CONSOLE()                                   \
101
    CYGACC_CALL_IF_SET_CONSOLE_COMM(_cur_console);      \
102
}   /* END BLOCK */
103
 
104
#else
105
#define START_CONSOLE()
106
#define END_CONSOLE()
107
#endif
108
// ------------------------------------------------------------------------
109
 
110
//
111
// Control whether any special locking needs to take place if we intend to
112
// cooperate with a ROM monitor (e.g. RedBoot) using this hardware.
113
//
114
#if defined(CYGSEM_HAL_USE_ROM_MONITOR) && \
115
    defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) && \
116
   !defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
117
 
118
// Indicate that special locking precautions are warranted.
119
#define _LOCK_WITH_ROM_MONITOR
120
 
121
// This defines the [well known] channel that RedBoot will use when it is
122
// using the network hardware for the debug channel.
123
#define RedBoot_TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
124
 
125
// Define this if you ever need to call 'diag_printf()' from interrupt level
126
// code (ISR) and the debug channel might be using the network hardware. If
127
// this is not the case, then disabling interrupts here is over-kill.
128
//#define _LOCK_USING_INTERRUPTS
129
#endif
130
 
131
// Static device configurations
132
 
133
#include "eth_conf.inl"
134
 
135
// Interfaces exported to drivers
136
 
137
static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr);
138
static void eth_drv_recv(struct eth_drv_sc *sc, int total_len);
139
static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status);
140
 
141
struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done};
142
 
143
static void eth_drv_send(struct netif *netif, struct pbuf *p);
144
 
145
#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
146
int cyg_io_eth_net_debug = CYGDBG_IO_ETH_DRIVERS_DEBUG_VERBOSITY;
147
// Usually just the header is enough, the body slows things too much.
148
#define DIAG_DUMP_BUF_HDR( a, b ) if (0 < cyg_io_eth_net_debug) diag_dump_buf( (a), (b) )
149
#define DIAG_DUMP_BUF_BDY( a, b ) if (1 < cyg_io_eth_net_debug) diag_dump_buf( (a), (b) )
150
#else
151
#define DIAG_DUMP_BUF_HDR( a, b )
152
#define DIAG_DUMP_BUF_BDY( a, b )
153
#endif
154
 
155
#define MAX_ETH_MSG 1540
156
 
157
// Interface to lwIP glue code
158
 
159
extern void lwip_eth_drv_new(struct netif *netif);
160
extern void lwip_eth_drv_dsr(void);
161
extern err_t lwip_eth_drv_input(struct pbuf *p, struct netif *netif);
162
 
163
 
164
 
165
//
166
// Called by lwIP to do the actual transmission of a packet. The packet passed
167
// to this function may be chained. This function passes the data to the
168
// hardware driver
169
//
170
static err_t eth_netif_linkoutput(struct netif *netif, struct pbuf *p)
171
{
172
    eth_drv_send(netif, p);
173
 
174
    return ERR_OK;
175
}
176
 
177
//
178
// Called by lwIP when an IP packet should be sent.
179
//
180
static err_t eth_netif_output(struct netif *netif, struct pbuf *p,
181
                          struct ip_addr *ipaddr)
182
{
183
    // Resolve hardware address, then send (or queue) packet
184
    return etharp_output(netif, p, ipaddr);
185
}
186
 
187
//
188
// Called by lwIP to init the netif.
189
//
190
static err_t eth_netif_init(struct netif *netif)
191
{
192
    netif->name[0] = 'e';
193
    netif->name[1] = 't';
194
    netif->hwaddr_len = 6;
195
    netif->output = eth_netif_output;
196
    netif->linkoutput = eth_netif_linkoutput;
197
    netif->mtu = 1500;
198
 
199
    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
200
 
201
    return ERR_OK;
202
}
203
 
204
//
205
// This function is called during system initialization to register a
206
// network interface with the system.
207
//
208
static void
209
eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr)
210
{
211
    struct netif *netif = &sc->sc_arpcom.ac_if;
212
    struct eth_conf *conf;
213
    struct ip_addr addr, netmask, gateway;
214
 
215
#ifdef CYGFUN_LWIP_MODE_SEQUENTIAL
216
    cyg_semaphore_init(&sc->sc_arpcom.send_sem, 1);
217
#endif
218
 
219
    // enaddr == 0 -> hardware init was incomplete (no ESA)
220
    if (enaddr == 0)
221
        return;
222
 
223
    netif->state = sc;
224
 
225
    // Configure the IP address
226
    conf = next_eth_conf();
227
    if (conf && !conf->dhcp) {
228
        IP4_ADDR(&addr,    conf->addr[0], conf->addr[1],
229
                           conf->addr[2], conf->addr[3]);
230
        IP4_ADDR(&netmask, conf->netmask[0], conf->netmask[1],
231
                           conf->netmask[2], conf->netmask[3]);
232
        IP4_ADDR(&gateway, conf->gateway[0], conf->gateway[1],
233
                           conf->gateway[2], conf->gateway[3]);
234
    } else {
235
        IP4_ADDR(&addr,    0, 0, 0, 0);
236
        IP4_ADDR(&netmask, 0, 0, 0, 0);
237
        IP4_ADDR(&gateway, 0, 0, 0, 0);
238
    }
239
 
240
    netif_add(netif, &addr, &netmask, &gateway, netif->state,
241
              eth_netif_init, lwip_eth_drv_input);
242
 
243
    lwip_eth_drv_new(netif);
244
 
245
    if (conf && conf->def)
246
        netif_set_default(netif);
247
 
248
    // Set up hardware address
249
    memcpy(netif->hwaddr, enaddr, ETHER_ADDR_LEN);
250
    (sc->funs->start)(sc, (unsigned char *) &netif->hwaddr, 0);
251
 
252
    if (conf && !conf->dhcp)
253
        netif_set_up(netif);
254
 
255
#if LWIP_DHCP
256
    // Start DHCP if configured
257
    if (conf && conf->dhcp) {
258
        dhcp_start(netif);
259
    }
260
#endif
261
}
262
 
263
//
264
// This function is called from the hardware driver when an output operation
265
// has completed - i.e. the packet has been sent.
266
//
267
static void
268
eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status)
269
{
270
#ifdef CYGFUN_LWIP_MODE_SIMPLE
271
    // Stop polling
272
    cyg_bool *done = (cyg_bool *) key;
273
    *done = true;
274
#endif
275
#ifdef CYGFUN_LWIP_MODE_SEQUENTIAL
276
    // Wake-up the lwip-thread
277
    cyg_semaphore_post(&sc->sc_arpcom.send_sem);
278
#endif    
279
}
280
 
281
//
282
// Send a packet of data to the hardware.
283
//
284
static void
285
eth_drv_send(struct netif *netif, struct pbuf *p)
286
{
287
    struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
288
    struct eth_drv_sc *sc = netif->state;
289
    int sg_len = 0;
290
    struct pbuf *q;
291
#ifdef _LOCK_WITH_ROM_MONITOR
292
#ifdef _LOCK_USING_INTERRUPTS
293
    cyg_uint32 ints;
294
#endif
295
    bool need_lock = false;
296
    int debug_chan;
297
#endif
298
#ifdef CYGFUN_LWIP_MODE_SIMPLE
299
    cyg_bool done = false;
300
    int wait_cycles = 100;
301
#endif
302
 
303
#ifdef CYGFUN_LWIP_MODE_SIMPLE
304
    // Wait until we can send
305
    while (!(sc->funs->can_send)(sc)) {
306
        // Give driver a chance to service hardware
307
        (sc->funs->poll)(sc);
308
        if (--wait_cycles <= 0) {
309
            START_CONSOLE();
310
            diag_printf("cannot send packet\n");
311
            END_CONSOLE();
312
            return;
313
        }
314
    }
315
#endif // CYGFUN_LWIP_MODE_SIMPLE
316
 
317
#ifdef CYGFUN_LWIP_MODE_SEQUENTIAL
318
    // Wait until we can send
319
    if ((sc->funs->can_send)(sc) < 1)
320
        cyg_semaphore_wait(&sc->sc_arpcom.send_sem);
321
    if ((sc->funs->can_send)(sc) < 1)
322
        CYG_FAIL("cannot send packet");
323
#endif // CYGFUN_LWIP_MODE_SEQUENTIAL
324
 
325
    // Create scatter list
326
    for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) {
327
        sg_list[sg_len].buf = (CYG_ADDRESS) q->payload;
328
        sg_list[sg_len++].len = q->len;
329
    }
330
 
331
#ifdef _LOCK_WITH_ROM_MONITOR
332
    // Firm lock on this portion of the driver.  Since we are about to
333
    // start messing with the actual hardware, it is imperative that the
334
    // current thread not loose control of the CPU at this time.  Otherwise,
335
    // the hardware could be left in an unusable state.  This caution is
336
    // only warranted if there is a possibility of some other thread trying
337
    // to use the hardware simultaneously.  The network stack would prevent
338
    // this implicitly since all accesses are controlled by the "splX()"
339
    // locks, but if there is a ROM monitor, such as RedBoot, also using
340
    // the hardware, all bets are off.
341
 
342
    // Note: these operations can be avoided if it were well known that
343
    // RedBoot was not using the network hardware for diagnostic I/O.  This
344
    // can be inferred by checking which I/O channel RedBoot is currently
345
    // hooked to.
346
    debug_chan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
347
    if (debug_chan == RedBoot_TCP_CHANNEL) {
348
        need_lock = true;
349
#ifdef _LOCK_USING_INTERRUPTS
350
        HAL_DISABLE_INTERRUPTS(ints);
351
#endif
352
        cyg_drv_dsr_lock();
353
    }
354
#endif // _LOCK_WITH_ROM_MONITOR
355
 
356
#ifdef CYGFUN_LWIP_MODE_SIMPLE
357
    // Tell hardware to send this packet
358
    if (sg_len)
359
        (sc->funs->send)(sc, sg_list, sg_len, p->tot_len, (CYG_ADDRWORD) &done);
360
    // Wait until packet has been sent
361
    wait_cycles = 100;
362
    while (!done) {
363
        (sc->funs->poll)(sc);
364
        if (--wait_cycles <= 0) {
365
            START_CONSOLE();
366
            diag_printf("packet failed to send\n");
367
            END_CONSOLE();
368
            break;
369
        }
370
    }
371
#endif // CYGFUN_LWIP_MODE_SIMPLE
372
 
373
#ifdef CYGFUN_LWIP_MODE_SEQUENTIAL
374
    // Tell hardware to send this packet
375
    if (sg_len)
376
        (sc->funs->send)(sc, sg_list, sg_len, p->tot_len, 0);
377
#endif // CYGFUN_LWIP_MODE_SEQUENTIAL
378
 
379
#ifdef _LOCK_WITH_ROM_MONITOR
380
    // Unlock the driver & hardware.  It can once again be safely shared.
381
    if (need_lock) {
382
        cyg_drv_dsr_unlock();
383
#ifdef _LOCK_USING_INTERRUPTS
384
        HAL_RESTORE_INTERRUPTS(ints);
385
#endif
386
    }
387
#endif // _LOCK_WITH_ROM_MONITOR
388
#undef _LOCK_WITH_ROM_MONITOR
389
}
390
 
391
//
392
// This function is called from a hardware driver to indicate that an input
393
// packet has arrived.  The routine will set up appropriate network resources
394
// to hold the data and call back into the driver to retrieve the data.
395
//
396
static void
397
eth_drv_recv(struct eth_drv_sc *sc, int total_len)
398
{
399
    struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
400
    struct netif *netif = &sc->sc_arpcom.ac_if;
401
    struct pbuf *p, *q;
402
    int sg_len = 0;
403
 
404
    CYG_ASSERT(total_len != 0, "total_len is zero!");
405
    CYG_ASSERT(total_len >= 0, "total_len is negative!");
406
 
407
    CYGARC_HAL_SAVE_GP();
408
 
409
    if ((total_len > MAX_ETH_MSG) || (total_len < 0))
410
        total_len = MAX_ETH_MSG;
411
 
412
    // Allocate buffer to store received packet
413
    p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL);
414
    if (p == NULL) {
415
        START_CONSOLE();
416
        diag_printf("cannot allocate pbuf to receive packet\n");
417
        END_CONSOLE();
418
        return;
419
    }
420
 
421
    // Create scatter list
422
    for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) {
423
        sg_list[sg_len].buf = (CYG_ADDRESS) q->payload;
424
        sg_list[sg_len++].len = q->len;
425
    }
426
 
427
    // Get buffers from hardware
428
    (sc->funs->recv)(sc, sg_list, sg_len);
429
 
430
    // Pass received packet to the interface
431
    netif->input(p, netif);
432
 
433
    CYGARC_HAL_RESTORE_GP();
434
}
435
 
436
//
437
// DSR called from the low level driver.
438
//
439
void
440
eth_drv_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
441
{
442
    struct eth_drv_sc *sc = (struct eth_drv_sc *) data;
443
 
444
    sc->state |= ETH_DRV_NEEDS_DELIVERY;
445
    lwip_eth_drv_dsr();
446
}

powered by: WebSVN 2.1.0

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