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