Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/lwip/netif/ethernetif.c need to be fixed.

0001 /**
0002  * @file
0003  * Ethernet Interface Skeleton
0004  *
0005  */
0006 
0007 /*
0008  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
0009  * All rights reserved. 
0010  * 
0011  * Redistribution and use in source and binary forms, with or without modification, 
0012  * are permitted provided that the following conditions are met:
0013  *
0014  * 1. Redistributions of source code must retain the above copyright notice,
0015  *    this list of conditions and the following disclaimer.
0016  * 2. Redistributions in binary form must reproduce the above copyright notice,
0017  *    this list of conditions and the following disclaimer in the documentation
0018  *    and/or other materials provided with the distribution.
0019  * 3. The name of the author may not be used to endorse or promote products
0020  *    derived from this software without specific prior written permission. 
0021  *
0022  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
0023  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
0024  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
0025  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
0026  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
0027  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
0030  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
0031  * OF SUCH DAMAGE.
0032  *
0033  * This file is part of the lwIP TCP/IP stack.
0034  * 
0035  * Author: Adam Dunkels <adam@sics.se>
0036  *
0037  */
0038 
0039 /*
0040  * This file is a skeleton for developing Ethernet network interface
0041  * drivers for lwIP. Add code to the low_level functions and do a
0042  * search-and-replace for the word "ethernetif" to replace it with
0043  * something that better describes your network interface.
0044  */
0045 
0046 #include "lwip/opt.h"
0047 
0048 #if 0 /* don't build, this is only a skeleton, see previous comment */
0049 
0050 #include "lwip/def.h"
0051 #include "lwip/mem.h"
0052 #include "lwip/pbuf.h"
0053 #include "lwip/sys.h"
0054 #include <lwip/stats.h>
0055 #include <lwip/snmp.h>
0056 #include "netif/etharp.h"
0057 #include "netif/ppp_oe.h"
0058 
0059 /* Define those to better describe your network interface. */
0060 #define IFNAME0 'e'
0061 #define IFNAME1 'n'
0062 
0063 /**
0064  * Helper struct to hold private data used to operate your ethernet interface.
0065  * Keeping the ethernet address of the MAC in this struct is not necessary
0066  * as it is already kept in the struct netif.
0067  * But this is only an example, anyway...
0068  */
0069 struct ethernetif {
0070   struct eth_addr *ethaddr;
0071   /* Add whatever per-interface state that is needed here. */
0072 };
0073 
0074 /* Forward declarations. */
0075 static void  ethernetif_input(struct netif *netif);
0076 
0077 /**
0078  * In this function, the hardware should be initialized.
0079  * Called from ethernetif_init().
0080  *
0081  * @param netif the already initialized lwip network interface structure
0082  *        for this ethernetif
0083  */
0084 static void
0085 low_level_init(struct netif *netif)
0086 {
0087   struct ethernetif *ethernetif = netif->state;
0088   
0089   /* set MAC hardware address length */
0090   netif->hwaddr_len = ETHARP_HWADDR_LEN;
0091 
0092   /* set MAC hardware address */
0093   netif->hwaddr[0] = ;
0094   ...
0095   netif->hwaddr[5] = ;
0096 
0097   /* maximum transfer unit */
0098   netif->mtu = 1500;
0099   
0100   /* device capabilities */
0101   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
0102   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
0103  
0104   /* Do whatever else is needed to initialize interface. */  
0105 }
0106 
0107 /**
0108  * This function should do the actual transmission of the packet. The packet is
0109  * contained in the pbuf that is passed to the function. This pbuf
0110  * might be chained.
0111  *
0112  * @param netif the lwip network interface structure for this ethernetif
0113  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
0114  * @return ERR_OK if the packet could be sent
0115  *         an err_t value if the packet couldn't be sent
0116  *
0117  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
0118  *       strange results. You might consider waiting for space in the DMA queue
0119  *       to become availale since the stack doesn't retry to send a packet
0120  *       dropped because of memory failure (except for the TCP timers).
0121  */
0122 
0123 static err_t
0124 low_level_output(struct netif *netif, struct pbuf *p)
0125 {
0126   struct ethernetif *ethernetif = netif->state;
0127   struct pbuf *q;
0128 
0129   initiate transfer();
0130   
0131 #if ETH_PAD_SIZE
0132   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
0133 #endif
0134 
0135   for(q = p; q != NULL; q = q->next) {
0136     /* Send the data from the pbuf to the interface, one pbuf at a
0137        time. The size of the data in each pbuf is kept in the ->len
0138        variable. */
0139     send data from(q->payload, q->len);
0140   }
0141 
0142   signal that packet should be sent();
0143 
0144 #if ETH_PAD_SIZE
0145   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
0146 #endif
0147   
0148   LINK_STATS_INC(link.xmit);
0149 
0150   return ERR_OK;
0151 }
0152 
0153 /**
0154  * Should allocate a pbuf and transfer the bytes of the incoming
0155  * packet from the interface into the pbuf.
0156  *
0157  * @param netif the lwip network interface structure for this ethernetif
0158  * @return a pbuf filled with the received packet (including MAC header)
0159  *         NULL on memory error
0160  */
0161 static struct pbuf *
0162 low_level_input(struct netif *netif)
0163 {
0164   struct ethernetif *ethernetif = netif->state;
0165   struct pbuf *p, *q;
0166   u16_t len;
0167 
0168   /* Obtain the size of the packet and put it into the "len"
0169      variable. */
0170   len = ;
0171 
0172 #if ETH_PAD_SIZE
0173   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
0174 #endif
0175 
0176   /* We allocate a pbuf chain of pbufs from the pool. */
0177   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
0178   
0179   if (p != NULL) {
0180 
0181 #if ETH_PAD_SIZE
0182     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
0183 #endif
0184 
0185     /* We iterate over the pbuf chain until we have read the entire
0186      * packet into the pbuf. */
0187     for(q = p; q != NULL; q = q->next) {
0188       /* Read enough bytes to fill this pbuf in the chain. The
0189        * available data in the pbuf is given by the q->len
0190        * variable.
0191        * This does not necessarily have to be a memcpy, you can also preallocate
0192        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
0193        * actually received size. In this case, ensure the tot_len member of the
0194        * pbuf is the sum of the chained pbuf len members.
0195        */
0196       read data into(q->payload, q->len);
0197     }
0198     acknowledge that packet has been read();
0199 
0200 #if ETH_PAD_SIZE
0201     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
0202 #endif
0203 
0204     LINK_STATS_INC(link.recv);
0205   } else {
0206     drop packet();
0207     LINK_STATS_INC(link.memerr);
0208     LINK_STATS_INC(link.drop);
0209   }
0210 
0211   return p;  
0212 }
0213 
0214 /**
0215  * This function should be called when a packet is ready to be read
0216  * from the interface. It uses the function low_level_input() that
0217  * should handle the actual reception of bytes from the network
0218  * interface. Then the type of the received packet is determined and
0219  * the appropriate input function is called.
0220  *
0221  * @param netif the lwip network interface structure for this ethernetif
0222  */
0223 static void
0224 ethernetif_input(struct netif *netif)
0225 {
0226   struct ethernetif *ethernetif;
0227   struct eth_hdr *ethhdr;
0228   struct pbuf *p;
0229 
0230   ethernetif = netif->state;
0231 
0232   /* move received packet into a new pbuf */
0233   p = low_level_input(netif);
0234   /* no packet could be read, silently ignore this */
0235   if (p == NULL) return;
0236   /* points to packet payload, which starts with an Ethernet header */
0237   ethhdr = p->payload;
0238 
0239   switch (htons(ethhdr->type)) {
0240   /* IP or ARP packet? */
0241   case ETHTYPE_IP:
0242   case ETHTYPE_ARP:
0243 #if PPPOE_SUPPORT
0244   /* PPPoE packet? */
0245   case ETHTYPE_PPPOEDISC:
0246   case ETHTYPE_PPPOE:
0247 #endif /* PPPOE_SUPPORT */
0248     /* full packet send to tcpip_thread to process */
0249     if (netif->input(p, netif)!=ERR_OK)
0250      { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
0251        pbuf_free(p);
0252        p = NULL;
0253      }
0254     break;
0255 
0256   default:
0257     pbuf_free(p);
0258     p = NULL;
0259     break;
0260   }
0261 }
0262 
0263 /**
0264  * Should be called at the beginning of the program to set up the
0265  * network interface. It calls the function low_level_init() to do the
0266  * actual setup of the hardware.
0267  *
0268  * This function should be passed as a parameter to netif_add().
0269  *
0270  * @param netif the lwip network interface structure for this ethernetif
0271  * @return ERR_OK if the loopif is initialized
0272  *         ERR_MEM if private data couldn't be allocated
0273  *         any other err_t on error
0274  */
0275 err_t
0276 ethernetif_init(struct netif *netif)
0277 {
0278   struct ethernetif *ethernetif;
0279 
0280   LWIP_ASSERT("netif != NULL", (netif != NULL));
0281     
0282   ethernetif = mem_malloc(sizeof(struct ethernetif));
0283   if (ethernetif == NULL) {
0284     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
0285     return ERR_MEM;
0286   }
0287 
0288 #if LWIP_NETIF_HOSTNAME
0289   /* Initialize interface hostname */
0290   netif->hostname = "lwip";
0291 #endif /* LWIP_NETIF_HOSTNAME */
0292 
0293   /*
0294    * Initialize the snmp variables and counters inside the struct netif.
0295    * The last argument should be replaced with your link speed, in units
0296    * of bits per second.
0297    */
0298   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
0299 
0300   netif->state = ethernetif;
0301   netif->name[0] = IFNAME0;
0302   netif->name[1] = IFNAME1;
0303   /* We directly use etharp_output() here to save a function call.
0304    * You can instead declare your own function an call etharp_output()
0305    * from it if you have to do some checks before sending (e.g. if link
0306    * is available...) */
0307   netif->output = etharp_output;
0308   netif->linkoutput = low_level_output;
0309   
0310   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
0311   
0312   /* initialize the hardware */
0313   low_level_init(netif);
0314 
0315   return ERR_OK;
0316 }
0317 
0318 #endif /* 0 */