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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_AVR32_UC3/] [NETWORK/] [lwip-port/] [AT32UC3A/] [ethernetif.c] - Blame information for rev 867

Go to most recent revision | 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
/*
34
 * This file is a skeleton for developing Ethernet network interface
35
 * drivers for lwIP. Add code to the low_level functions and do a
36
 * search-and-replace for the word "ethernetif" to replace it with
37
 * something that better describes your network interface.
38
 */
39
 
40
#include "lwip/opt.h"
41
#include "lwip/def.h"
42
#include "lwip/mem.h"
43
#include "lwip/pbuf.h"
44
#include "lwip/sys.h"
45
#include <lwip/stats.h>
46
 
47
#include "conf_eth.h"
48
 
49
#include "netif/etharp.h"
50
 
51
/* FreeRTOS includes. */
52
#include "FreeRTOS.h"
53
#include "macb.h"
54
 
55
#define netifMTU              ( 1500 )
56
#define netifGUARD_BLOCK_TIME       ( 250 )
57
#define IFNAME0 'e'
58
#define IFNAME1 'm'
59
 
60
 
61
struct ethernetif {
62
  struct eth_addr *ethaddr;
63
  /* Add whatever per-interface state that is needed here. */
64
};
65
 
66
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
67
 
68
/* Forward declarations. */
69
void  ethernetif_input(void * );
70
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
71
             struct ip_addr *ipaddr);
72
static struct netif *xNetIf = NULL;
73
 
74
 
75
static void
76
low_level_init(struct netif *netif)
77
{
78
//  struct ethernetif *ethernetif = netif->state;
79
  unsigned portBASE_TYPE uxPriority;
80
 
81
  /* maximum transfer unit */
82
  netif->mtu = netifMTU;
83
 
84
  /* broadcast capability */
85
  netif->flags = NETIF_FLAG_BROADCAST;
86
 
87
  /* Do whatever else is needed to initialize interface. */
88
  xNetIf = netif;
89
 
90
  /* Initialise the MACB.  This routine contains code that polls status bits.
91
  If the Ethernet cable is not plugged in then this can take a considerable
92
  time.  To prevent this starving lower priority tasks of processing time we
93
  lower our priority prior to the call, then raise it back again once the
94
  initialisation is complete. */
95
  uxPriority = uxTaskPriorityGet( NULL );
96
  vTaskPrioritySet( NULL, tskIDLE_PRIORITY );
97
  while( xMACBInit(&AVR32_MACB) == FALSE )
98
  {
99
    __asm__ __volatile__ ( "nop" );
100
  }
101
  vTaskPrioritySet( NULL, uxPriority );
102
 
103
  /* Create the task that handles the MACB. */
104
  // xTaskCreate( ethernetif_input, ( signed portCHAR * ) "ETH_INT", netifINTERFACE_TASK_STACK_SIZE, NULL, netifINTERFACE_TASK_PRIORITY, NULL );
105
  sys_thread_new( ethernetif_input, NULL, netifINTERFACE_TASK_PRIORITY );
106
}
107
 
108
/*
109
 * low_level_output():
110
 *
111
 * Should do the actual transmission of the packet. The packet is
112
 * contained in the pbuf that is passed to the function. This pbuf
113
 * might be chained.
114
 *
115
 */
116
 
117
static err_t
118
low_level_output(struct netif *netif, struct pbuf *p)
119
{
120
struct pbuf *q;
121
static xSemaphoreHandle xTxSemaphore = NULL;
122
err_t xReturn = ERR_OK;
123
 
124
  /* Parameter not used. */
125
  ( void ) netif;
126
 
127
  if( xTxSemaphore == NULL )
128
  {
129
    vSemaphoreCreateBinary( xTxSemaphore );
130
  }
131
 
132
  #if ETH_PAD_SIZE
133
    pbuf_header( p, -ETH_PAD_SIZE );    /* drop the padding word */
134
  #endif
135
 
136
  /* Access to the MACB is guarded using a semaphore. */
137
  if( xSemaphoreTake( xTxSemaphore, netifGUARD_BLOCK_TIME ) )
138
  {
139
    for( q = p; q != NULL; q = q->next )
140
    {
141
      /* Send the data from the pbuf to the interface, one pbuf at a
142
      time. The size of the data in each pbuf is kept in the ->len
143
      variable.  if q->next == NULL then this is the last pbuf in the
144
      chain. */
145
      if( !lMACBSend(&AVR32_MACB, q->payload, q->len, ( q->next == NULL ) ) )
146
      {
147
        xReturn = ~ERR_OK;
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
 * low_level_input():
167
 *
168
 * Should allocate a pbuf and transfer the bytes of the incoming
169
 * packet from the interface into the pbuf.
170
 *
171
 */
172
 
173
static struct pbuf *
174
low_level_input(struct netif *netif) {
175
struct pbuf         *p = NULL;
176
struct pbuf         *q;
177
u16_t               len = 0;
178
static xSemaphoreHandle xRxSemaphore = NULL;
179
 
180
  /* Parameter not used. */
181
  ( void ) netif;
182
 
183
  if( xRxSemaphore == NULL )
184
  {
185
    vSemaphoreCreateBinary( xRxSemaphore );
186
  }
187
 
188
  /* Access to the emac is guarded using a semaphore. */
189
  if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_TIME ) )
190
  {
191
    /* Obtain the size of the packet. */
192
    len = ulMACBInputLength();
193
 
194
    if( len )
195
    {
196
      #if ETH_PAD_SIZE
197
        len += ETH_PAD_SIZE;    /* allow room for Ethernet padding */
198
      #endif
199
 
200
      /* We allocate a pbuf chain of pbufs from the pool. */
201
      p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL );
202
 
203
      if( p != NULL )
204
      {
205
        #if ETH_PAD_SIZE
206
          pbuf_header( p, -ETH_PAD_SIZE );    /* drop the padding word */
207
        #endif
208
 
209
        /* Let the driver know we are going to read a new packet. */
210
        vMACBRead( NULL, 0, len );
211
 
212
        /* We iterate over the pbuf chain until we have read the entire
213
        packet into the pbuf. */
214
        for( q = p; q != NULL; q = q->next )
215
        {
216
          /* Read enough bytes to fill this pbuf in the chain. The
217
          available data in the pbuf is given by the q->len variable. */
218
          vMACBRead( q->payload, q->len, len );
219
        }
220
 
221
        #if ETH_PAD_SIZE
222
          pbuf_header( p, ETH_PAD_SIZE );     /* reclaim the padding word */
223
        #endif
224
        #if LINK_STATS
225
          lwip_stats.link.recv++;
226
        #endif /* LINK_STATS */
227
      }
228
      else
229
      {
230
        #if LINK_STATS
231
          lwip_stats.link.memerr++;
232
          lwip_stats.link.drop++;
233
        #endif /* LINK_STATS */
234
      }
235
    }
236
    xSemaphoreGive( xRxSemaphore );
237
  }
238
 
239
  return p;
240
}
241
 
242
/*
243
 * ethernetif_output():
244
 *
245
 * This function is called by the TCP/IP stack when an IP packet
246
 * should be sent. It calls the function called low_level_output() to
247
 * do the actual transmission of the packet.
248
 *
249
 */
250
 
251
static err_t
252
ethernetif_output(struct netif *netif, struct pbuf *p,
253
      struct ip_addr *ipaddr)
254
{
255
 
256
 /* resolve hardware address, then send (or queue) packet */
257
  return etharp_output(netif, ipaddr, p);
258
 
259
}
260
 
261
/*
262
 * ethernetif_input():
263
 *
264
 * This function should be called when a packet is ready to be read
265
 * from the interface. It uses the function low_level_input() that
266
 * should handle the actual reception of bytes from the network
267
 * interface.
268
 *
269
 */
270
 
271
void ethernetif_input( void * pvParameters )
272
{
273
struct ethernetif   *ethernetif;
274
struct eth_hdr      *ethhdr;
275
struct pbuf         *p;
276
 
277
  ( void ) pvParameters;
278
 
279
  for( ;; )  {
280
 
281
    ethernetif = xNetIf->state;
282
    do
283
    {
284
      ethernetif = xNetIf->state;
285
 
286
      /* move received packet into a new pbuf */
287
      p = low_level_input( xNetIf );
288
 
289
      if( p == NULL )
290
      {
291
        /* No packet could be read.  Wait a for an interrupt to tell us
292
        there is more data available. */
293
        vMACBWaitForInput(100);
294
      }
295
 
296
    } while( p == NULL );
297
 
298
    /* points to packet payload, which starts with an Ethernet header */
299
    ethhdr = p->payload;
300
 
301
    #if LINK_STATS
302
      lwip_stats.link.recv++;
303
    #endif /* LINK_STATS */
304
 
305
    ethhdr = p->payload;
306
 
307
    switch( htons( ethhdr->type ) )
308
    {
309
      /* IP packet? */
310
      case ETHTYPE_IP:
311
        /* update ARP table */
312
        etharp_ip_input( xNetIf, p );
313
 
314
        /* skip Ethernet header */
315
        pbuf_header( p, (s16_t)-sizeof(struct eth_hdr) );
316
 
317
        /* pass to network layer */
318
        xNetIf->input( p, xNetIf );
319
        break;
320
 
321
      case ETHTYPE_ARP:
322
        /* pass p to ARP module */
323
        etharp_arp_input( xNetIf, ethernetif->ethaddr, p );
324
        break;
325
 
326
      default:
327
        pbuf_free( p );
328
        p = NULL;
329
        break;
330
    }
331
  }
332
}
333
 
334
static void
335
arp_timer(void *arg)
336
{
337
  etharp_tmr();
338
  sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
339
}
340
 
341
/*
342
 * ethernetif_init():
343
 *
344
 * Should be called at the beginning of the program to set up the
345
 * network interface. It calls the function low_level_init() to do the
346
 * actual setup of the hardware.
347
 *
348
 */
349
extern struct netif MACB_if;
350
err_t
351
ethernetif_init(struct netif *netif)
352
{
353
  struct ethernetif *ethernetif;
354
  int i;
355
 
356
  ethernetif = (struct ethernetif *)mem_malloc(sizeof(struct ethernetif));
357
 
358
  if (ethernetif == NULL)
359
  {
360
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
361
    return ERR_MEM;
362
  }
363
 
364
  netif->state = ethernetif;
365
  netif->name[0] = IFNAME0;
366
  netif->name[1] = IFNAME1;
367
  netif->output = ethernetif_output;
368
  netif->linkoutput = low_level_output;
369
 
370
  for(i = 0; i < 6; i++) netif->hwaddr[i] = MACB_if.hwaddr[i];
371
 
372
  low_level_init(netif);
373
 
374
  etharp_init();
375
 
376
  sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
377
 
378
  return ERR_OK;
379
}
380
 

powered by: WebSVN 2.1.0

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