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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_Demo_Rowley_ARM7/] [lwip-1.1.0/] [src/] [netif/] [ethernetif.c] - Blame information for rev 583

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/*
2
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without modification,
6
 * are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. The name of the author may not be used to endorse or promote products
14
 *    derived from this software without specific prior written permission.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
 * OF SUCH DAMAGE.
26
 *
27
 * This file is part of the lwIP TCP/IP stack.
28
 *
29
 * Author: Adam Dunkels <adam@sics.se>
30
 *
31
 */
32
 
33
/* lwIP includes. */
34
#include <string.h>
35
#include "lwip/opt.h"
36
#include "lwip/def.h"
37
#include "lwip/mem.h"
38
#include "lwip/pbuf.h"
39
#include "lwip/sys.h"
40
#include <lwip/stats.h>
41
#include "netif/etharp.h"
42
 
43
/* FreeRTOS includes. */
44
#include "FreeRTOS.h"
45
#include "SAM7_EMAC.h"
46
#include "Emac.h"
47
 
48
#define netifMTU                                                        ( 1500 )
49
#define netifINTERFACE_TASK_STACK_SIZE          ( 350 )
50
#define netifINTERFACE_TASK_PRIORITY            ( configMAX_PRIORITIES - 1 )
51
#define netifGUARD_BLOCK_TIME                           ( 250 )
52
#define IFNAME0 'e'
53
#define IFNAME1 'm'
54
 
55
/* lwIP definitions. */
56
struct ethernetif
57
{
58
        struct eth_addr *ethaddr;
59
};
60
static const struct eth_addr    ethbroadcast = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
61
static struct netif *xNetIf = NULL;
62
 
63
/* Forward declarations. */
64
static void ethernetif_input( void * );
65
static err_t ethernetif_output( struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr );
66
err_t ethernetif_init( struct netif *netif );
67
 
68
 
69
/*-----------------------------------------------------------*/
70
 
71
static void low_level_init( struct netif *netif )
72
{
73
unsigned portBASE_TYPE uxPriority;
74
 
75
        /* set MAC hardware address length */
76
        netif->hwaddr_len = 6;
77
 
78
        /* set MAC hardware address */
79
        netif->hwaddr[0] = emacETHADDR0;
80
        netif->hwaddr[1] = emacETHADDR1;
81
        netif->hwaddr[2] = emacETHADDR2;
82
        netif->hwaddr[3] = emacETHADDR3;
83
        netif->hwaddr[4] = emacETHADDR4;
84
        netif->hwaddr[5] = emacETHADDR5;
85
 
86
        /* maximum transfer unit */
87
        netif->mtu = netifMTU;
88
 
89
        /* broadcast capability */
90
        netif->flags = NETIF_FLAG_BROADCAST;
91
 
92
        xNetIf = netif;
93
 
94
        /* Initialise the EMAC.  This routine contains code that polls status bits.
95
        If the Ethernet cable is not plugged in then this can take a considerable
96
        time.  To prevent this starving lower priority tasks of processing time we
97
        lower our priority prior to the call, then raise it back again once the
98
        initialisation is complete. */
99
        uxPriority = uxTaskPriorityGet( NULL );
100
        vTaskPrioritySet( NULL, tskIDLE_PRIORITY );
101
        while( xEMACInit() == NULL )
102
        {
103
                __asm( "NOP" );
104
        }
105
        vTaskPrioritySet( NULL, uxPriority );
106
 
107
        /* Create the task that handles the EMAC. */
108
        xTaskCreate( ethernetif_input, ( signed char * ) "ETH_INT", netifINTERFACE_TASK_STACK_SIZE, NULL, netifINTERFACE_TASK_PRIORITY, NULL );
109
}
110
/*-----------------------------------------------------------*/
111
 
112
/*
113
 * low_level_output(): Should do the actual transmission of the packet. The
114
 * packet is contained in the pbuf that is passed to the function. This pbuf
115
 * might be chained.
116
 */
117
static err_t low_level_output( struct netif *netif, struct pbuf *p )
118
{
119
struct pbuf *q;
120
static xSemaphoreHandle xTxSemaphore = NULL;
121
err_t xReturn = ERR_OK;
122
 
123
        /* Parameter not used. */
124
        ( void ) netif;
125
 
126
        if( xTxSemaphore == NULL )
127
        {
128
                vSemaphoreCreateBinary( xTxSemaphore );
129
        }
130
 
131
        #if ETH_PAD_SIZE
132
                pbuf_header( p, -ETH_PAD_SIZE );    /* drop the padding word */
133
        #endif
134
 
135
        /* Access to the EMAC is guarded using a semaphore. */
136
        if( xSemaphoreTake( xTxSemaphore, netifGUARD_BLOCK_TIME ) )
137
        {
138
                for( q = p; q != NULL; q = q->next )
139
                {
140
                        /* Send the data from the pbuf to the interface, one pbuf at a
141
                        time. The size of the data in each pbuf is kept in the ->len
142
                        variable.  if q->next == NULL then this is the last pbuf in the
143
                        chain. */
144
                        if( !lEMACSend( q->payload, q->len, ( q->next == NULL ) ) )
145
                        {
146
                                xReturn = ~ERR_OK;
147
                        }
148
                }
149
 
150
        xSemaphoreGive( xTxSemaphore );
151
        }
152
 
153
 
154
        #if ETH_PAD_SIZE
155
                pbuf_header( p, ETH_PAD_SIZE );     /* reclaim the padding word */
156
        #endif
157
 
158
        #if LINK_STATS
159
                lwip_stats.link.xmit++;
160
        #endif /* LINK_STATS */
161
 
162
    return xReturn;
163
}
164
/*-----------------------------------------------------------*/
165
 
166
/*
167
 * low_level_input(): Should allocate a pbuf and transfer the bytes of the
168
 * incoming packet from the interface into the pbuf.
169
 */
170
static struct pbuf *low_level_input( struct netif *netif )
171
{
172
struct pbuf         *p = NULL, *q;
173
u16_t               len = 0;
174
static xSemaphoreHandle xRxSemaphore = NULL;
175
 
176
        /* Parameter not used. */
177
        ( void ) netif;
178
 
179
        if( xRxSemaphore == NULL )
180
        {
181
                vSemaphoreCreateBinary( xRxSemaphore );
182
        }
183
 
184
        /* Access to the emac is guarded using a semaphore. */
185
        if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_TIME ) )
186
        {
187
                /* Obtain the size of the packet. */
188
                len = ulEMACInputLength();
189
 
190
                if( len )
191
                {
192
                        #if ETH_PAD_SIZE
193
                                len += ETH_PAD_SIZE;    /* allow room for Ethernet padding */
194
                        #endif
195
 
196
                        /* We allocate a pbuf chain of pbufs from the pool. */
197
                        p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL );
198
 
199
                        if( p != NULL )
200
                        {
201
                                #if ETH_PAD_SIZE
202
                                        pbuf_header( p, -ETH_PAD_SIZE );    /* drop the padding word */
203
                                #endif
204
 
205
                                /* Let the driver know we are going to read a new packet. */
206
                                vEMACRead( NULL, 0, len );
207
 
208
                                /* We iterate over the pbuf chain until we have read the entire
209
                                packet into the pbuf. */
210
                                for( q = p; q != NULL; q = q->next )
211
                                {
212
                                        /* Read enough bytes to fill this pbuf in the chain. The
213
                                        available data in the pbuf is given by the q->len variable. */
214
                                        vEMACRead( q->payload, q->len, len );
215
                                }
216
 
217
                                #if ETH_PAD_SIZE
218
                                        pbuf_header( p, ETH_PAD_SIZE );     /* reclaim the padding word */
219
                                #endif
220
                                #if LINK_STATS
221
                                        lwip_stats.link.recv++;
222
                                #endif /* LINK_STATS */
223
                        }
224
                        else
225
                        {
226
                                #if LINK_STATS
227
                                        lwip_stats.link.memerr++;
228
                                        lwip_stats.link.drop++;
229
                                #endif /* LINK_STATS */
230
                        }
231
                }
232
 
233
                xSemaphoreGive( xRxSemaphore );
234
        }
235
 
236
        return p;
237
}
238
/*-----------------------------------------------------------*/
239
 
240
/*
241
 * ethernetif_output(): This function is called by the TCP/IP stack when an
242
 * IP packet should be sent. It calls the function called low_level_output()
243
 * to do the actual transmission of the packet.
244
 */
245
static err_t ethernetif_output( struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr )
246
{
247
    /* resolve hardware address, then send (or queue) packet */
248
    return etharp_output( netif, ipaddr, p );
249
}
250
/*-----------------------------------------------------------*/
251
 
252
/*
253
 * ethernetif_input(): This function should be called when a packet is ready to
254
 * be read from the interface. It uses the function low_level_input() that
255
 * should handle the actual reception of bytes from the network interface.
256
 */
257
static void ethernetif_input( void * pvParameters )
258
{
259
struct ethernetif   *ethernetif;
260
struct eth_hdr      *ethhdr;
261
struct pbuf         *p;
262
 
263
        ( void ) pvParameters;
264
 
265
        for( ;; )
266
        {
267
                do
268
                {
269
                        ethernetif = xNetIf->state;
270
 
271
                        /* move received packet into a new pbuf */
272
                        p = low_level_input( xNetIf );
273
 
274
                        if( p == NULL )
275
                        {
276
                                /* No packet could be read.  Wait a for an interrupt to tell us
277
                                there is more data available. */
278
                                vEMACWaitForInput();
279
                        }
280
 
281
                } while( p == NULL );
282
 
283
                /* points to packet payload, which starts with an Ethernet header */
284
                ethhdr = p->payload;
285
 
286
                #if LINK_STATS
287
                        lwip_stats.link.recv++;
288
                #endif /* LINK_STATS */
289
 
290
                ethhdr = p->payload;
291
 
292
                switch( htons( ethhdr->type ) )
293
                {
294
                        /* IP packet? */
295
                        case ETHTYPE_IP:
296
                                /* update ARP table */
297
                                etharp_ip_input( xNetIf, p );
298
 
299
                                /* skip Ethernet header */
300
                                pbuf_header( p, (s16_t)-sizeof(struct eth_hdr) );
301
 
302
                                /* pass to network layer */
303
                                xNetIf->input( p, xNetIf );
304
                                break;
305
 
306
                        case ETHTYPE_ARP:
307
                                /* pass p to ARP module */
308
                                etharp_arp_input( xNetIf, ethernetif->ethaddr, p );
309
                                break;
310
 
311
                        default:
312
                                pbuf_free( p );
313
                                p = NULL;
314
                                break;
315
                }
316
        }
317
}
318
/*-----------------------------------------------------------*/
319
 
320
static void arp_timer( void *arg )
321
{
322
        ( void ) arg;
323
 
324
    etharp_tmr();
325
    sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL );
326
}
327
/*-----------------------------------------------------------*/
328
 
329
err_t ethernetif_init( struct netif *netif )
330
{
331
struct ethernetif   *ethernetif;
332
 
333
        ethernetif = mem_malloc( sizeof(struct ethernetif) );
334
 
335
        if( ethernetif == NULL )
336
        {
337
                LWIP_DEBUGF( NETIF_DEBUG, ("ethernetif_init: out of memory\n") );
338
                return ERR_MEM;
339
        }
340
 
341
        netif->state = ethernetif;
342
        netif->name[0] = IFNAME0;
343
        netif->name[1] = IFNAME1;
344
        netif->output = ethernetif_output;
345
        netif->linkoutput = low_level_output;
346
 
347
        ethernetif->ethaddr = ( struct eth_addr * ) &( netif->hwaddr[0] );
348
 
349
        low_level_init( netif );
350
        etharp_init();
351
        sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL );
352
 
353
        return ERR_OK;
354
}

powered by: WebSVN 2.1.0

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