2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
\r
3 * All rights reserved.
\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
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
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
27 * This file is part of the lwIP TCP/IP stack.
\r
29 * Author: Adam Dunkels <adam@sics.se>
\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
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
47 #include "conf_eth.h"
\r
49 #include "netif/etharp.h"
\r
51 /* FreeRTOS includes. */
\r
52 #include "FreeRTOS.h"
\r
55 #define netifMTU ( 1500 )
\r
56 #define netifGUARD_BLOCK_TIME ( 250 )
\r
62 struct eth_addr *ethaddr;
\r
63 /* Add whatever per-interface state that is needed here. */
\r
66 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
\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
76 low_level_init(struct netif *netif)
\r
78 // struct ethernetif *ethernetif = netif->state;
\r
79 unsigned portBASE_TYPE uxPriority;
\r
81 /* maximum transfer unit */
\r
82 netif->mtu = netifMTU;
\r
84 /* broadcast capability */
\r
85 netif->flags = NETIF_FLAG_BROADCAST;
\r
87 /* Do whatever else is needed to initialize interface. */
\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
99 __asm__ __volatile__ ( "nop" );
\r
101 vTaskPrioritySet( NULL, uxPriority );
\r
103 /* Create the task that handles the MACB. */
\r
104 // xTaskCreate( ethernetif_input, ( signed portCHAR * ) "ETH_INT", netifINTERFACE_TASK_STACK_SIZE, NULL, netifINTERFACE_TASK_PRIORITY, NULL );
\r
105 sys_thread_new( ethernetif_input, NULL, netifINTERFACE_TASK_PRIORITY );
\r
109 * low_level_output():
\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
118 low_level_output(struct netif *netif, struct pbuf *p)
\r
121 static xSemaphoreHandle xTxSemaphore = NULL;
\r
122 err_t xReturn = ERR_OK;
\r
124 /* Parameter not used. */
\r
127 if( xTxSemaphore == NULL )
\r
129 vSemaphoreCreateBinary( xTxSemaphore );
\r
133 pbuf_header( p, -ETH_PAD_SIZE ); /* drop the padding word */
\r
136 /* Access to the MACB is guarded using a semaphore. */
\r
137 if( xSemaphoreTake( xTxSemaphore, netifGUARD_BLOCK_TIME ) )
\r
139 for( q = p; q != NULL; q = q->next )
\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
145 if( !lMACBSend(&AVR32_MACB, q->payload, q->len, ( q->next == NULL ) ) )
\r
150 xSemaphoreGive( xTxSemaphore );
\r
155 pbuf_header( p, ETH_PAD_SIZE ); /* reclaim the padding word */
\r
159 lwip_stats.link.xmit++;
\r
160 #endif /* LINK_STATS */
\r
166 * low_level_input():
\r
168 * Should allocate a pbuf and transfer the bytes of the incoming
\r
169 * packet from the interface into the pbuf.
\r
173 static struct pbuf *
\r
174 low_level_input(struct netif *netif) {
\r
175 struct pbuf *p = NULL;
\r
178 static xSemaphoreHandle xRxSemaphore = NULL;
\r
180 /* Parameter not used. */
\r
183 if( xRxSemaphore == NULL )
\r
185 vSemaphoreCreateBinary( xRxSemaphore );
\r
188 /* Access to the emac is guarded using a semaphore. */
\r
189 if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_TIME ) )
\r
191 /* Obtain the size of the packet. */
\r
192 len = ulMACBInputLength();
\r
197 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
\r
200 /* We allocate a pbuf chain of pbufs from the pool. */
\r
201 p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL );
\r
206 pbuf_header( p, -ETH_PAD_SIZE ); /* drop the padding word */
\r
209 /* Let the driver know we are going to read a new packet. */
\r
210 vMACBRead( NULL, 0, len );
\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
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
222 pbuf_header( p, ETH_PAD_SIZE ); /* reclaim the padding word */
\r
225 lwip_stats.link.recv++;
\r
226 #endif /* LINK_STATS */
\r
231 lwip_stats.link.memerr++;
\r
232 lwip_stats.link.drop++;
\r
233 #endif /* LINK_STATS */
\r
236 xSemaphoreGive( xRxSemaphore );
\r
243 * ethernetif_output():
\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
252 ethernetif_output(struct netif *netif, struct pbuf *p,
\r
253 struct ip_addr *ipaddr)
\r
256 /* resolve hardware address, then send (or queue) packet */
\r
257 return etharp_output(netif, ipaddr, p);
\r
262 * ethernetif_input():
\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
271 void ethernetif_input( void * pvParameters )
\r
273 struct ethernetif *ethernetif;
\r
274 struct eth_hdr *ethhdr;
\r
277 ( void ) pvParameters;
\r
281 ethernetif = xNetIf->state;
\r
284 ethernetif = xNetIf->state;
\r
286 /* move received packet into a new pbuf */
\r
287 p = low_level_input( xNetIf );
\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
296 } while( p == NULL );
\r
298 /* points to packet payload, which starts with an Ethernet header */
\r
299 ethhdr = p->payload;
\r
302 lwip_stats.link.recv++;
\r
303 #endif /* LINK_STATS */
\r
305 ethhdr = p->payload;
\r
307 switch( htons( ethhdr->type ) )
\r
311 /* update ARP table */
\r
312 etharp_ip_input( xNetIf, p );
\r
314 /* skip Ethernet header */
\r
315 pbuf_header( p, (s16_t)-sizeof(struct eth_hdr) );
\r
317 /* pass to network layer */
\r
318 xNetIf->input( p, xNetIf );
\r
322 /* pass p to ARP module */
\r
323 etharp_arp_input( xNetIf, ethernetif->ethaddr, p );
\r
335 arp_timer(void *arg)
\r
338 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
\r
342 * ethernetif_init():
\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
349 extern struct netif MACB_if;
\r
351 ethernetif_init(struct netif *netif)
\r
353 struct ethernetif *ethernetif;
\r
356 ethernetif = (struct ethernetif *)mem_malloc(sizeof(struct ethernetif));
\r
358 if (ethernetif == NULL)
\r
360 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
\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
370 for(i = 0; i < 6; i++) netif->hwaddr[i] = MACB_if.hwaddr[i];
\r
372 low_level_init(netif);
\r
376 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
\r