- Main Page
- Data Structures
- Files

# ethernetif.c

Go to the documentation of this file.

    00001
    00007 /*
    00008  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
    00009  * All rights reserved.
    00010  *
    00011  * Redistribution and use in source and binary forms, with or without modification,
    00012  * are permitted provided that the following conditions are met:
    00013  *
    00014  * 1. Redistributions of source code must retain the above copyright notice,
    00015  *    this list of conditions and the following disclaimer.
    00016  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00017  *    this list of conditions and the following disclaimer in the documentation
    00018  *    and/or other materials provided with the distribution.
    00019  * 3. The name of the author may not be used to endorse or promote products
    00020  *    derived from this software without specific prior written permission.
    00021  *
    00022  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00023  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00024  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    00025  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    00026  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    00027  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    00028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    00029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    00030  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
    00031  * OF SUCH DAMAGE.
    00032  *
    00033  * This file is part of the lwIP TCP/IP stack.
    00034  *
    00035  * Author: Adam Dunkels <adam@sics.se>
    00036  *
    00037  */
    00038
    00039 /*
    00040  * This file is a skeleton for developing Ethernet network interface
    00041  * drivers for lwIP. Add code to the low_level functions and do a
    00042  * search-and-replace for the word "ethernetif" to replace it with
    00043  * something that better describes your network interface.
    00044  */
    00045
    00046 #include "lwip/opt.h"
    00047
    00048 #include "lwip/def.h"
    00049 #include "lwip/mem.h"
    00050 #include "lwip/pbuf.h"
    00051 #include "lwip/sys.h"
    00052 #include <lwip/stats.h>
    00053 #include <lwip/snmp.h>
    00054 #include "netif/etharp.h"
    00055 #include "netif/ppp_oe.h"
    00056
    00057 #include "conf_eth.h"
    00058 #include "macb.h"
    00059
    00060
    00061 /* Define those to better describe your network interface. */
    00062 #define IFNAME0 'e'
    00063 #define IFNAME1 'n'
    00064
    00065 #define netifGUARD_BLOCK_NBTICKS       ( 250 )
    00066
    00073 struct ethernetif {
    00074   struct eth_addr *ethaddr;
    00075   /* Add whatever per-interface state that is needed here. */
    00076 };
    00077
    00078 /* Forward declarations. */
    00079 static void  ethernetif_input(void * );
    00080
    00088 static void
    00089 low_level_init(struct netif *netif)
    00090 {
    00091   unsigned portBASE_TYPE uxPriority;
    00092
    00093
    00094   /* set MAC hardware address length */
    00095   netif->hwaddr_len = ETHARP_HWADDR_LEN;
    00096
    00097   /* set MAC hardware address */
    00098   netif->hwaddr[0] = ETHERNET_CONF_ETHADDR0;
    00099   netif->hwaddr[1] = ETHERNET_CONF_ETHADDR1;
    00100   netif->hwaddr[2] = ETHERNET_CONF_ETHADDR2;
    00101   netif->hwaddr[3] = ETHERNET_CONF_ETHADDR3;
    00102   netif->hwaddr[4] = ETHERNET_CONF_ETHADDR4;
    00103   netif->hwaddr[5] = ETHERNET_CONF_ETHADDR5;
    00104
    00105   /* maximum transfer unit */
    00106   netif->mtu = 1500;
    00107
    00108   /* device capabilities */
    00109   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
    00110   netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
    00111
    00112   /* Do whatever else is needed to initialize interface. */
    00113   /* Initialise the MACB. */
    00114   // NOTE: This routine contains code that polls status bits. If the Ethernet
    00115   // cable is not plugged in then this can take a considerable time.  To prevent
    00116   // this from starving lower priority tasks of processing time we lower our
    00117   // priority prior to the call, then raise it back again once the initialization
    00118   // is complete.
    00119   // Read the priority of the current task.
    00120   uxPriority = uxTaskPriorityGet( NULL );
    00121   // Set the priority of the current task to the lowest possible.
    00122   vTaskPrioritySet( NULL, tskIDLE_PRIORITY );
    00123   // Init the MACB interface.
    00124   while( xMACBInit(&AVR32_MACB) == FALSE )
    00125   {
    00126     __asm__ __volatile__ ( "nop" );
    00127   }
    00128   // Restore the priority of the current task.
    00129   vTaskPrioritySet( NULL, uxPriority );
    00130
    00131   /* Create the task that handles the MACB input packets. */
    00132   sys_thread_new( "ETHINT", ethernetif_input, netif, netifINTERFACE_TASK_STACK_SIZE,
    00133                   netifINTERFACE_TASK_PRIORITY );
    00134 }
    00135
    00152 static err_t
    00153 low_level_output(struct netif *netif, struct pbuf *p)
    00154 {
    00155   struct pbuf             *q;
    00156   static xSemaphoreHandle xTxSemaphore = NULL;
    00157   err_t                   xReturn = ERR_OK;
    00158
    00159
    00160   ( void )netif; // Unused param, avoid a compiler warning.
    00161
    00162   if( xTxSemaphore == NULL )
    00163   {
    00164     vSemaphoreCreateBinary( xTxSemaphore );
    00165   }
    00166
    00167 #if ETH_PAD_SIZE
    00168   pbuf_header( p, -ETH_PAD_SIZE );    /* drop the padding word */
    00169 #endif
    00170
    00171   /* Access to the MACB is guarded using a semaphore. */
    00172   if( xSemaphoreTake( xTxSemaphore, netifGUARD_BLOCK_NBTICKS ) )
    00173   {
    00174     for( q = p; q != NULL; q = q->next )
    00175     {
    00176       /* Send the data from the pbuf to the interface, one pbuf at a
    00177       time. The size of the data in each pbuf is kept in the ->len
    00178       variable.  if q->next == NULL then this is the last pbuf in the
    00179       chain. */
    00180       if( !lMACBSend(&AVR32_MACB, q->payload, q->len, ( q->next == NULL ) ) )
    00181       {
    00182         xReturn = ~ERR_OK;
    00183       }
    00184     }
    00185     xSemaphoreGive( xTxSemaphore );
    00186   }
    00187
    00188 #if ETH_PAD_SIZE
    00189   pbuf_header( p, ETH_PAD_SIZE );     /* reclaim the padding word */
    00190 #endif
    00191
    00192   LINK_STATS_INC(link.xmit);  // Traces
    00193
    00194   return ERR_OK;
    00195 }
    00196
    00205 static struct pbuf *low_level_input(struct netif *netif)
    00206 {
    00207   struct pbuf             *p = NULL;
    00208   struct pbuf             *q;
    00209   u16_t                   len;
    00210   static xSemaphoreHandle xRxSemaphore = NULL;
    00211
    00212
    00213   /* Parameter not used. */
    00214   ( void ) netif;
    00215
    00216   if( xRxSemaphore == NULL )
    00217   {
    00218     vSemaphoreCreateBinary( xRxSemaphore );
    00219   }
    00220
    00221   /* Access to the MACB is guarded using a semaphore. */
    00222   if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_NBTICKS ) )
    00223   {
    00224     /* Obtain the size of the packet. */
    00225     len = ulMACBInputLength();
    00226
    00227     if( len )
    00228     {
    00229 #if ETH_PAD_SIZE
    00230       len += ETH_PAD_SIZE;    /* allow room for Ethernet padding */
    00231 #endif
    00232
    00233       /* We allocate a pbuf chain of pbufs from the pool. */
    00234       p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL );
    00235
    00236       if( p != NULL )
    00237       {
    00238 #if ETH_PAD_SIZE
    00239         pbuf_header( p, -ETH_PAD_SIZE );    /* drop the padding word */
    00240 #endif
    00241
    00242         /* Let the driver know we are going to read a new packet. */
    00243         vMACBRead( NULL, 0, len );
    00244
    00245         /* We iterate over the pbuf chain until we have read the entire
    00246         packet into the pbuf. */
    00247         for( q = p; q != NULL; q = q->next )
    00248         {
    00249           /* Read enough bytes to fill this pbuf in the chain. The
    00250           available data in the pbuf is given by the q->len variable. */
    00251           vMACBRead( q->payload, q->len, len );
    00252         }
    00253
    00254 #if ETH_PAD_SIZE
    00255         pbuf_header( p, ETH_PAD_SIZE );     /* reclaim the padding word */
    00256 #endif
    00257         LINK_STATS_INC(link.recv);
    00258       }
    00259       else
    00260       {
    00261         LINK_STATS_INC(link.memerr);
    00262         LINK_STATS_INC(link.drop);
    00263       }
    00264     }
    00265     xSemaphoreGive( xRxSemaphore );
    00266   }
    00267
    00268   return p;
    00269 }
    00270
    00280 static void ethernetif_input(void * pvParameters)
    00281 {
    00282   struct netif      *netif = (struct netif *)pvParameters;
    00283   struct pbuf       *p;
    00284
    00285
    00286   for( ;; )
    00287   {
    00288     do
    00289     {
    00290       /* move received packet into a new pbuf */
    00291       p = low_level_input( netif );
    00292       if( p == NULL )
    00293       {
    00294         /* No packet could be read.  Wait a for an interrupt to tell us
    00295         there is more data available. */
    00296         vMACBWaitForInput(100);
    00297       }
    00298     }while( p == NULL );
    00299
    00300     if( ERR_OK != ethernet_input( p, netif ) )
    00301     {
    00302       pbuf_free(p);
    00303       p = NULL;
    00304     }
    00305   }
    00306 }
    00307
    00308
    00309 /********
    00310  * Calling etharp_tmr() every ARP_TMR_INTERVAL.
    00311  *
    00312  */
    00313 /*static void
    00314 arp_timer(void *arg)
    00315 {
    00316   etharp_tmr();
    00317   sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
    00318 }*/
    00319
    00320
    00333 err_t
    00334 ethernetif_init(struct netif *netif)
    00335 {
    00336   /* struct ethernetif *ethernetif; */
    00337
    00338   LWIP_ASSERT("netif != NULL", (netif != NULL));
    00339
    00340   /*ethernetif = (struct ethernetif *)mem_malloc(sizeof(struct ethernetif));
    00341   if (ethernetif == NULL)
    00342   {
    00343     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    00344     return ERR_MEM;
    00345   }*/
    00346
    00347 #if LWIP_NETIF_HOSTNAME
    00348   /* Initialize interface hostname */
    00349   netif->hostname = "lwip";
    00350 #endif /* LWIP_NETIF_HOSTNAME */
    00351
    00352   /*
    00353    * Initialize the snmp variables and counters inside the struct netif.
    00354    * The last argument should be replaced with your link speed, in units
    00355    * of bits per second.
    00356    */
    00357 #if LWIP_SNMP
    00358   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
    00359 #endif /* LWIP_SNMP */
    00360
    00361   netif->state = NULL; /* ethernetif;
    00362   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); */
    00363   netif->name[0] = IFNAME0;
    00364   netif->name[1] = IFNAME1;
    00365   /* We directly use etharp_output() here to save a function call.
    00366    * You can instead declare your own function an call etharp_output()
    00367    * from it if you have to do some checks before sending (e.g. if link
    00368    * is available...) */
    00369   netif->output = etharp_output;
    00370   netif->linkoutput = low_level_output;
    00371
    00372   /* initialize the hardware */
    00373   low_level_init(netif);
    00374
    00375 /* DONE BY THE LWIP TASK.
    00376   // Initializes the ARP table and queue.
    00377   etharp_init();
    00378
    00379   // You must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval
    00380   // after this initialization.
    00381   sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
    00382 */
    00383   return ERR_OK;
    00384 }