lwip-1.4.1 (partial)
Embed:
(wiki syntax)
Show/hide line numbers
ethernetif.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * Ethernet Interface Skeleton 00004 * 00005 */ 00006 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 #if 0 /* don't build, this is only a skeleton, see previous comment */ 00049 00050 #include "lwip/def.h" 00051 #include "lwip/mem.h" 00052 #include "lwip/pbuf.h" 00053 #include <lwip/stats.h> 00054 #include <lwip/snmp.h> 00055 #include "netif/etharp.h" 00056 #include "netif/ppp_oe.h" 00057 00058 /* Define those to better describe your network interface. */ 00059 #define IFNAME0 'e' 00060 #define IFNAME1 'n' 00061 00062 /** 00063 * Helper struct to hold private data used to operate your ethernet interface. 00064 * Keeping the ethernet address of the MAC in this struct is not necessary 00065 * as it is already kept in the struct netif. 00066 * But this is only an example, anyway... 00067 */ 00068 struct ethernetif { 00069 struct eth_addr *ethaddr; 00070 /* Add whatever per-interface state that is needed here. */ 00071 }; 00072 00073 /* Forward declarations. */ 00074 static void ethernetif_input(struct netif *netif); 00075 00076 /** 00077 * In this function, the hardware should be initialized. 00078 * Called from ethernetif_init(). 00079 * 00080 * @param netif the already initialized lwip network interface structure 00081 * for this ethernetif 00082 */ 00083 static void 00084 low_level_init(struct netif *netif) 00085 { 00086 struct ethernetif *ethernetif = netif->state; 00087 00088 /* set MAC hardware address length */ 00089 netif->hwaddr_len = ETHARP_HWADDR_LEN; 00090 00091 /* set MAC hardware address */ 00092 netif->hwaddr[0] = ; 00093 ... 00094 netif->hwaddr[5] = ; 00095 00096 /* maximum transfer unit */ 00097 netif->mtu = 1500; 00098 00099 /* device capabilities */ 00100 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ 00101 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; 00102 00103 /* Do whatever else is needed to initialize interface. */ 00104 } 00105 00106 /** 00107 * This function should do the actual transmission of the packet. The packet is 00108 * contained in the pbuf that is passed to the function. This pbuf 00109 * might be chained. 00110 * 00111 * @param netif the lwip network interface structure for this ethernetif 00112 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) 00113 * @return ERR_OK if the packet could be sent 00114 * an err_t value if the packet couldn't be sent 00115 * 00116 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to 00117 * strange results. You might consider waiting for space in the DMA queue 00118 * to become availale since the stack doesn't retry to send a packet 00119 * dropped because of memory failure (except for the TCP timers). 00120 */ 00121 00122 static err_t 00123 low_level_output(struct netif *netif, struct pbuf *p) 00124 { 00125 struct ethernetif *ethernetif = netif->state; 00126 struct pbuf *q; 00127 00128 initiate transfer(); 00129 00130 #if ETH_PAD_SIZE 00131 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 00132 #endif 00133 00134 for(q = p; q != NULL; q = q->next) { 00135 /* Send the data from the pbuf to the interface, one pbuf at a 00136 time. The size of the data in each pbuf is kept in the ->len 00137 variable. */ 00138 send data from(q->payload, q->len); 00139 } 00140 00141 signal that packet should be sent(); 00142 00143 #if ETH_PAD_SIZE 00144 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 00145 #endif 00146 00147 LINK_STATS_INC(link.xmit); 00148 00149 return ERR_OK; 00150 } 00151 00152 /** 00153 * Should allocate a pbuf and transfer the bytes of the incoming 00154 * packet from the interface into the pbuf. 00155 * 00156 * @param netif the lwip network interface structure for this ethernetif 00157 * @return a pbuf filled with the received packet (including MAC header) 00158 * NULL on memory error 00159 */ 00160 static struct pbuf * 00161 low_level_input(struct netif *netif) 00162 { 00163 struct ethernetif *ethernetif = netif->state; 00164 struct pbuf *p, *q; 00165 u16_t len; 00166 00167 /* Obtain the size of the packet and put it into the "len" 00168 variable. */ 00169 len = ; 00170 00171 #if ETH_PAD_SIZE 00172 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ 00173 #endif 00174 00175 /* We allocate a pbuf chain of pbufs from the pool. */ 00176 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 00177 00178 if (p != NULL) { 00179 00180 #if ETH_PAD_SIZE 00181 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 00182 #endif 00183 00184 /* We iterate over the pbuf chain until we have read the entire 00185 * packet into the pbuf. */ 00186 for(q = p; q != NULL; q = q->next) { 00187 /* Read enough bytes to fill this pbuf in the chain. The 00188 * available data in the pbuf is given by the q->len 00189 * variable. 00190 * This does not necessarily have to be a memcpy, you can also preallocate 00191 * pbufs for a DMA-enabled MAC and after receiving truncate it to the 00192 * actually received size. In this case, ensure the tot_len member of the 00193 * pbuf is the sum of the chained pbuf len members. 00194 */ 00195 read data into(q->payload, q->len); 00196 } 00197 acknowledge that packet has been read(); 00198 00199 #if ETH_PAD_SIZE 00200 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 00201 #endif 00202 00203 LINK_STATS_INC(link.recv); 00204 } else { 00205 drop packet(); 00206 LINK_STATS_INC(link.memerr); 00207 LINK_STATS_INC(link.drop); 00208 } 00209 00210 return p; 00211 } 00212 00213 /** 00214 * This function should be called when a packet is ready to be read 00215 * from the interface. It uses the function low_level_input() that 00216 * should handle the actual reception of bytes from the network 00217 * interface. Then the type of the received packet is determined and 00218 * the appropriate input function is called. 00219 * 00220 * @param netif the lwip network interface structure for this ethernetif 00221 */ 00222 static void 00223 ethernetif_input(struct netif *netif) 00224 { 00225 struct ethernetif *ethernetif; 00226 struct eth_hdr *ethhdr; 00227 struct pbuf *p; 00228 00229 ethernetif = netif->state; 00230 00231 /* move received packet into a new pbuf */ 00232 p = low_level_input(netif); 00233 /* no packet could be read, silently ignore this */ 00234 if (p == NULL) return; 00235 /* points to packet payload, which starts with an Ethernet header */ 00236 ethhdr = p->payload; 00237 00238 switch (htons(ethhdr->type)) { 00239 /* IP or ARP packet? */ 00240 case ETHTYPE_IP: 00241 case ETHTYPE_ARP: 00242 #if PPPOE_SUPPORT 00243 /* PPPoE packet? */ 00244 case ETHTYPE_PPPOEDISC: 00245 case ETHTYPE_PPPOE: 00246 #endif /* PPPOE_SUPPORT */ 00247 /* full packet send to tcpip_thread to process */ 00248 if (netif->input(p, netif)!=ERR_OK) 00249 { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); 00250 pbuf_free(p); 00251 p = NULL; 00252 } 00253 break; 00254 00255 default: 00256 pbuf_free(p); 00257 p = NULL; 00258 break; 00259 } 00260 } 00261 00262 /** 00263 * Should be called at the beginning of the program to set up the 00264 * network interface. It calls the function low_level_init() to do the 00265 * actual setup of the hardware. 00266 * 00267 * This function should be passed as a parameter to netif_add(). 00268 * 00269 * @param netif the lwip network interface structure for this ethernetif 00270 * @return ERR_OK if the loopif is initialized 00271 * ERR_MEM if private data couldn't be allocated 00272 * any other err_t on error 00273 */ 00274 err_t 00275 ethernetif_init(struct netif *netif) 00276 { 00277 struct ethernetif *ethernetif; 00278 00279 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00280 00281 ethernetif = mem_malloc(sizeof(struct ethernetif)); 00282 if (ethernetif == NULL) { 00283 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); 00284 return ERR_MEM; 00285 } 00286 00287 #if LWIP_NETIF_HOSTNAME 00288 /* Initialize interface hostname */ 00289 netif->hostname = "lwip"; 00290 #endif /* LWIP_NETIF_HOSTNAME */ 00291 00292 /* 00293 * Initialize the snmp variables and counters inside the struct netif. 00294 * The last argument should be replaced with your link speed, in units 00295 * of bits per second. 00296 */ 00297 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); 00298 00299 netif->state = ethernetif; 00300 netif->name[0] = IFNAME0; 00301 netif->name[1] = IFNAME1; 00302 /* We directly use etharp_output() here to save a function call. 00303 * You can instead declare your own function an call etharp_output() 00304 * from it if you have to do some checks before sending (e.g. if link 00305 * is available...) */ 00306 netif->output = etharp_output; 00307 netif->linkoutput = low_level_output; 00308 00309 ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); 00310 00311 /* initialize the hardware */ 00312 low_level_init(netif); 00313 00314 return ERR_OK; 00315 } 00316 00317 #endif /* 0 */
Generated on Wed Jul 13 2022 09:48:37 by 1.7.2