]> begriffs open source - cmsis-freertos/blob - Demo/lwIP_AVR32_UC3/NETWORK/lwip-port/AT32UC3A/ethernetif.c
Update README.md - branch main is now the base branch
[cmsis-freertos] / Demo / lwIP_AVR32_UC3 / NETWORK / lwip-port / AT32UC3A / ethernetif.c
1 /*
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, "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 SemaphoreHandle_t 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 SemaphoreHandle_t 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