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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [ARM9_STR91X_IAR/] [lwip/] [netif/] [ethernetif.c] - Blame information for rev 773

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

Line No. Rev Author Line
1 577 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 "netif/etharp.h"
48
#include "91x_enet.h"
49
 
50
// Standard library include
51
#include <string.h>
52
 
53
#define netifMTU                                ( 1500 )
54
#define netifINTERFACE_TASK_STACK_SIZE          ( 350 )
55
#define netifINTERFACE_TASK_PRIORITY            ( configMAX_PRIORITIES - 1 )
56
#define netifGUARD_BLOCK_TIME                   ( 250 )
57
#define IFNAME0 'e'
58
#define IFNAME1 'm'
59
 
60
/* The time to block waiting for input. */
61
#define emacBLOCK_TIME_WAITING_FOR_INPUT        ( ( portTickType ) 100 )
62
 
63
/* Interrupt status bit definition. */
64
#define DMI_RX_CURRENT_DONE 0x8000
65
 
66
extern u8 TxBuff[1520];
67
 
68
static u8_t s_rxBuff[1520];
69
 
70
/* The semaphore used by the ISR to wake the lwIP task. */
71
static xSemaphoreHandle s_xSemaphore = NULL;
72
 
73
struct ethernetif {
74
  struct eth_addr *ethaddr;
75
  /* Add whatever per-interface state that is needed here. */
76
};
77
 
78
static struct netif *s_pxNetIf = NULL;
79
 
80
/* Forward declarations. */
81
static err_t ethernetif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
82
static void ethernetif_input( void * pvParameters );
83
static void vEMACWaitForInput( void );
84
 
85
 
86
 
87
static void low_level_init(struct netif *netif)
88
{
89
  /* set MAC hardware address length */
90
  netif->hwaddr_len = 6;
91
 
92
  /* set MAC hardware address */
93
  netif->hwaddr[0] = MAC_ADDR0;
94
  netif->hwaddr[1] = MAC_ADDR1;
95
  netif->hwaddr[2] = MAC_ADDR2;
96
  netif->hwaddr[3] = MAC_ADDR3;
97
  netif->hwaddr[4] = MAC_ADDR4;
98
  netif->hwaddr[5] = MAC_ADDR5;
99
 
100
  /* maximum transfer unit */
101
  netif->mtu = netifMTU;
102
 
103
  /* broadcast capability */
104
  netif->flags = NETIF_FLAG_BROADCAST;
105
 
106
  s_pxNetIf = netif;
107
 
108
  if( s_xSemaphore == NULL )
109
  {
110
      vSemaphoreCreateBinary( s_xSemaphore );
111
      xSemaphoreTake( s_xSemaphore,  0);
112
  }
113
 
114
  /* Do whatever else is needed to initialize interface. */
115
  /* Initialise the MAC. */
116
  ENET_InitClocksGPIO();
117
  ENET_Init();
118
  ENET_Start();
119
 
120
  portENTER_CRITICAL();
121
  {
122
      /*set MAC physical*/
123
      ENET_MAC->MAH = (MAC_ADDR5<<8) + MAC_ADDR4;
124
      ENET_MAC->MAL = (MAC_ADDR3<<24) + (MAC_ADDR2<<16) + (MAC_ADDR1<<8) + MAC_ADDR0;
125
 
126
      VIC_Config( ENET_ITLine, VIC_IRQ, 1 );
127
      VIC_ITCmd( ENET_ITLine, ENABLE );
128
      ENET_DMA->ISR = DMI_RX_CURRENT_DONE;
129
      ENET_DMA->IER = DMI_RX_CURRENT_DONE;
130
  }
131
  portEXIT_CRITICAL();
132
 
133
  /* Create the task that handles the EMAC. */
134
  xTaskCreate( ethernetif_input, ( signed char * ) "ETH_INT", netifINTERFACE_TASK_STACK_SIZE, NULL, netifINTERFACE_TASK_PRIORITY, NULL );
135
}
136
 
137
 
138
/*
139
 * low_level_output():
140
 *
141
 * Should do the actual transmission of the packet. The packet is
142
 * contained in the pbuf that is passed to the function. This pbuf
143
 * might be chained.
144
 *
145
 */
146
 
147
static err_t low_level_output(struct netif *netif, struct pbuf *p)
148
{
149
  static xSemaphoreHandle xTxSemaphore = NULL;
150
  struct pbuf *q;
151
  u32_t l = 0;
152
 
153
  if( xTxSemaphore == NULL )
154
  {
155
      vSemaphoreCreateBinary( xTxSemaphore );
156
  }
157
 
158
 
159
#if ETH_PAD_SIZE
160
  pbuf_header(p, -ETH_PAD_SIZE);                        /* drop the padding word */
161
#endif
162
 
163
 
164
  /* Access to the EMAC is guarded using a semaphore. */
165
  if( xSemaphoreTake( xTxSemaphore, netifGUARD_BLOCK_TIME ) )
166
  {
167
      for(q = p; q != NULL; q = q->next) {
168
        /* Send the data from the pbuf to the interface, one pbuf at a
169
           time. The size of the data in each pbuf is kept in the ->len
170
           variable. */
171
        memcpy(&TxBuff[l], (u8_t*)q->payload, q->len);
172
        l += q->len;
173
      }
174
 
175
      ENET_TxPkt(0, l);
176
 
177
      #if ETH_PAD_SIZE
178
        pbuf_header(p, ETH_PAD_SIZE);                   /* reclaim the padding word */
179
      #endif
180
 
181
      #if LINK_STATS
182
        lwip_stats.link.xmit++;
183
      #endif /* LINK_STATS */
184
 
185
      xSemaphoreGive( xTxSemaphore );
186
  }
187
 
188
  return ERR_OK;
189
}
190
 
191
/*
192
 * low_level_input():
193
 *
194
 * Should allocate a pbuf and transfer the bytes of the incoming
195
 * packet from the interface into the pbuf.
196
 *
197
 */
198
 
199
static struct pbuf *
200
low_level_input(struct netif *netif)
201
{
202
  static xSemaphoreHandle xRxSemaphore = NULL;
203
  struct pbuf *p, *q;
204
  u16_t len, l;
205
 
206
  l = 0;
207
  p = NULL;
208
 
209
  if( xRxSemaphore == NULL )
210
  {
211
    vSemaphoreCreateBinary( xRxSemaphore );
212
  }
213
 
214
  /* Access to the emac is guarded using a semaphore. */
215
  if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_TIME ) )
216
  {
217
        /* Obtain the size of the packet and put it into the "len"
218
           variable. */
219
        len = ENET_HandleRxPkt(s_rxBuff);
220
 
221
        if(len)
222
        {
223
              #if ETH_PAD_SIZE
224
                len += ETH_PAD_SIZE;                                            /* allow room for Ethernet padding */
225
              #endif
226
 
227
                /* We allocate a pbuf chain of pbufs from the pool. */
228
                p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
229
 
230
                if (p != NULL) {
231
 
232
              #if ETH_PAD_SIZE
233
                  pbuf_header(p, -ETH_PAD_SIZE);                        /* drop the padding word */
234
              #endif
235
 
236
                  /* We iterate over the pbuf chain until we have read the entire
237
                   * packet into the pbuf. */
238
                  for(q = p; q != NULL; q = q->next) {
239
                    /* Read enough bytes to fill this pbuf in the chain. The
240
                     * available data in the pbuf is given by the q->len
241
                     * variable. */
242
                    memcpy((u8_t*)q->payload, &s_rxBuff[l], q->len);
243
                    l = l + q->len;
244
                  }
245
 
246
 
247
              #if ETH_PAD_SIZE
248
                  pbuf_header(p, ETH_PAD_SIZE);                 /* reclaim the padding word */
249
              #endif
250
 
251
              #if LINK_STATS
252
                  lwip_stats.link.recv++;
253
              #endif /* LINK_STATS */
254
                } else {
255
              #if LINK_STATS
256
                  lwip_stats.link.memerr++;
257
                  lwip_stats.link.drop++;
258
              #endif /* LINK_STATS */
259
                } /* End else */
260
        } /* End if */
261
 
262
       xSemaphoreGive( xRxSemaphore );
263
  }
264
 
265
  return p;
266
}
267
 
268
/*
269
 * ethernetif_output():
270
 *
271
 * This function is called by the TCP/IP stack when an IP packet
272
 * should be sent. It calls the function called low_level_output() to
273
 * do the actual transmission of the packet.
274
 *
275
 */
276
 
277
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,  struct ip_addr *ipaddr)
278
{
279
 
280
 /* resolve hardware address, then send (or queue) packet */
281
  return etharp_output(netif, ipaddr, p);
282
 
283
}
284
 
285
/*
286
 * ethernetif_input():
287
 *
288
 * This function should be called when a packet is ready to be read
289
 * from the interface. It uses the function low_level_input() that
290
 * should handle the actual reception of bytes from the network
291
 * interface.
292
 *
293
 */
294
 
295
static void ethernetif_input( void * pvParameters )
296
{
297
  struct ethernetif *ethernetif;
298
  struct eth_hdr *ethhdr;
299
  struct pbuf *p;
300
 
301
        for( ;; )
302
        {
303
                do
304
                {
305
                        ethernetif = s_pxNetIf->state;
306
 
307
                        /* move received packet into a new pbuf */
308
                        p = low_level_input( s_pxNetIf );
309
 
310
                        if( p == NULL )
311
                        {
312
                                /* No packet could be read.  Wait a for an interrupt to tell us
313
                                there is more data available. */
314
                                vEMACWaitForInput();
315
                        }
316
 
317
                } while( p == NULL );
318
 
319
                /* points to packet payload, which starts with an Ethernet header */
320
                ethhdr = p->payload;
321
 
322
                #if LINK_STATS
323
                        lwip_stats.link.recv++;
324
                #endif /* LINK_STATS */
325
 
326
                ethhdr = p->payload;
327
 
328
                switch (htons(ethhdr->type))
329
                {
330
                        /* IP packet? */
331
                        case ETHTYPE_IP:
332
                                /* update ARP table */
333
                                etharp_ip_input(s_pxNetIf, p);
334
                                /* skip Ethernet header */
335
                                pbuf_header(p, (s16_t)-sizeof(struct eth_hdr));
336
                                /* pass to network layer */
337
                                s_pxNetIf->input(p, s_pxNetIf);
338
                                break;
339
 
340
                        case ETHTYPE_ARP:
341
                                  /* pass p to ARP module  */
342
                                  etharp_arp_input(s_pxNetIf, ethernetif->ethaddr, p);
343
                                  break;
344
 
345
                        default:
346
                                  pbuf_free(p);
347
                                  p = NULL;
348
                                  break;
349
                }
350
        }
351
}
352
 
353
static void
354
arp_timer(void *arg)
355
{
356
  etharp_tmr();
357
  sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
358
}
359
 
360
/*
361
 * ethernetif_init():
362
 *
363
 * Should be called at the beginning of the program to set up the
364
 * network interface. It calls the function low_level_init() to do the
365
 * actual setup of the hardware.
366
 *
367
 */
368
 
369
err_t
370
ethernetif_init(struct netif *netif)
371
{
372
  struct ethernetif *ethernetif;
373
 
374
  ethernetif = mem_malloc(sizeof(struct ethernetif));
375
 
376
  if (ethernetif == NULL)
377
  {
378
        LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
379
        return ERR_MEM;
380
  }
381
 
382
#if LWIP_SNMP
383
        /* ifType ethernetCsmacd(6) @see RFC1213 */
384
        netif->link_type = 6;
385
        /* your link speed here */
386
        netif->link_speed = ;
387
        netif->ts = 0;
388
        netif->ifinoctets = 0;
389
        netif->ifinucastpkts = 0;
390
        netif->ifinnucastpkts = 0;
391
        netif->ifindiscards = 0;
392
        netif->ifoutoctets = 0;
393
        netif->ifoutucastpkts = 0;
394
        netif->ifoutnucastpkts = 0;
395
        netif->ifoutdiscards = 0;
396
#endif
397
 
398
  netif->state = ethernetif;
399
  netif->name[0] = IFNAME0;
400
  netif->name[1] = IFNAME1;
401
  netif->output = ethernetif_output;
402
  netif->linkoutput = low_level_output;
403
 
404
  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
405
 
406
  low_level_init(netif);
407
 
408
  etharp_init();
409
 
410
  sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
411
 
412
  return ERR_OK;
413
}
414
/*-----------------------------------------------------------*/
415
 
416
void ENET_IRQHandler(void)
417
{
418
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
419
 
420
        /* Give the semaphore in case the lwIP task needs waking. */
421
        xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
422
 
423
        /* Clear the interrupt. */
424
        ENET_DMA->ISR = DMI_RX_CURRENT_DONE;
425
 
426
        /* Switch tasks if necessary. */
427
        portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
428
}
429
/*-----------------------------------------------------------*/
430
 
431
void vEMACWaitForInput( void )
432
{
433
        /* Just wait until we are signled from an ISR that data is available, or
434
        we simply time out. */
435
        xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT );
436
}

powered by: WebSVN 2.1.0

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