1 /** 2 * @file 3 * Ethernet Interface for quadradio 4 */ 5 6 /* 7 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 8 * Copyright (c) 2010 Ettus Research LLC 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, 12 * are permitted provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 * This file is part of the lwIP TCP/IP stack. 34 * 35 * Author: Adam Dunkels <adam@sics.se> 36 * 37 */ 38 39 #include "lwip/opt.h" 40 41 #include "lwip/def.h" 42 #include "lwip/mem.h" 43 #include "lwip/pbuf.h" 44 #include "lwip/sys.h" 45 #include <lwip/stats.h> 46 #include <lwip/snmp.h> 47 #include "netif/etharp.h" 48 #include "netif/ppp_oe.h" 49 #include "eth_driver.h" 50 51 #if 0 // don't build 52 53 /* Define those to better describe your network interface. */ 54 #define IFNAME0 'e' 55 #define IFNAME1 'n' 56 57 /** 58 * Helper struct to hold private data used to operate your ethernet interface. 59 */ 60 struct quadradioif { 61 int ethno; 62 }; 63 64 /* Forward declarations. */ 65 static void quadradioif_input(struct netif *netif); 66 67 /** 68 * In this function, the hardware should be initialized. 69 * Called from quadradioif_init(). 70 * 71 * @param netif the already initialized lwip network interface structure 72 * for this quadradioif 73 */ 74 static void 75 low_level_init(struct netif *netif) 76 { 77 struct quadradioif *quadradioif = netif->state; 78 79 /* set MAC hardware address length */ 80 netif->hwaddr_len = ETHARP_HWADDR_LEN; 81 82 /* set MAC hardware address */ 83 netif->hwaddr[0] = ; 84 ... 85 netif->hwaddr[5] = ; 86 87 /* maximum transfer unit */ 88 netif->mtu = 1500; 89 90 /* device capabilities */ 91 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ 92 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; 93 94 /* Do whatever else is needed to initialize interface. */ 95 } 96 97 /** 98 * This function should do the actual transmission of the packet. The packet is 99 * contained in the pbuf that is passed to the function. This pbuf 100 * might be chained. 101 * 102 * @param netif the lwip network interface structure for this quadradioif 103 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) 104 * @return ERR_OK if the packet could be sent 105 * an err_t value if the packet couldn't be sent 106 * 107 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to 108 * strange results. You might consider waiting for space in the DMA queue 109 * to become availale since the stack doesn't retry to send a packet 110 * dropped because of memory failure (except for the TCP timers). 111 */ 112 113 static err_t 114 low_level_output(struct netif *netif, struct pbuf *p) 115 { 116 struct quadradioif *quadradioif = netif->state; 117 struct pbuf *q; 118 119 initiate transfer(); 120 121 #if ETH_PAD_SIZE 122 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 123 #endif 124 125 for(q = p; q != NULL; q = q->next) { 126 /* Send the data from the pbuf to the interface, one pbuf at a 127 time. The size of the data in each pbuf is kept in the ->len 128 variable. */ 129 send data from(q->payload, q->len); 130 } 131 132 signal that packet should be sent(); 133 134 #if ETH_PAD_SIZE 135 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 136 #endif 137 138 LINK_STATS_INC(link.xmit); 139 140 return ERR_OK; 141 } 142 143 /** 144 * Should allocate a pbuf and transfer the bytes of the incoming 145 * packet from the interface into the pbuf. 146 * 147 * @param netif the lwip network interface structure for this quadradioif 148 * @return a pbuf filled with the received packet (including MAC header) 149 * NULL on memory error 150 */ 151 static struct pbuf * 152 low_level_input(struct netif *netif) 153 { 154 struct quadradioif *quadradioif = netif->state; 155 struct pbuf *p, *q; 156 u16_t len; 157 158 /* Obtain the size of the packet and put it into the "len" 159 variable. */ 160 len = ; 161 162 #if ETH_PAD_SIZE 163 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ 164 #endif 165 166 /* We allocate a pbuf chain of pbufs from the pool. */ 167 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 168 169 if (p != NULL) { 170 171 #if ETH_PAD_SIZE 172 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 173 #endif 174 175 /* We iterate over the pbuf chain until we have read the entire 176 * packet into the pbuf. */ 177 for(q = p; q != NULL; q = q->next) { 178 /* Read enough bytes to fill this pbuf in the chain. The 179 * available data in the pbuf is given by the q->len 180 * variable. */ 181 read data into(q->payload, q->len); 182 } 183 acknowledge that packet has been read(); 184 185 #if ETH_PAD_SIZE 186 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 187 #endif 188 189 LINK_STATS_INC(link.recv); 190 } else { 191 drop packet(); 192 LINK_STATS_INC(link.memerr); 193 LINK_STATS_INC(link.drop); 194 } 195 196 return p; 197 } 198 199 /** 200 * This function should be called when a packet is ready to be read 201 * from the interface. It uses the function low_level_input() that 202 * should handle the actual reception of bytes from the network 203 * interface. Then the type of the received packet is determined and 204 * the appropriate input function is called. 205 * 206 * @param netif the lwip network interface structure for this quadradioif 207 */ 208 static void 209 quadradioif_input(struct netif *netif) 210 { 211 struct quadradioif *quadradioif; 212 struct eth_hdr *ethhdr; 213 struct pbuf *p; 214 215 quadradioif = netif->state; 216 217 /* move received packet into a new pbuf */ 218 p = low_level_input(netif); 219 /* no packet could be read, silently ignore this */ 220 if (p == NULL) return; 221 /* points to packet payload, which starts with an Ethernet header */ 222 ethhdr = p->payload; 223 224 switch (htons(ethhdr->type)) { 225 /* IP or ARP packet? */ 226 case ETHTYPE_IP: 227 case ETHTYPE_ARP: 228 #if PPPOE_SUPPORT 229 /* PPPoE packet? */ 230 case ETHTYPE_PPPOEDISC: 231 case ETHTYPE_PPPOE: 232 #endif /* PPPOE_SUPPORT */ 233 /* full packet send to tcpip_thread to process */ 234 if (netif->input(p, netif)!=ERR_OK) 235 { LWIP_DEBUGF(NETIF_DEBUG, ("quadradioif_input: IP input error\n")); 236 pbuf_free(p); 237 p = NULL; 238 } 239 break; 240 241 default: 242 pbuf_free(p); 243 p = NULL; 244 break; 245 } 246 } 247 248 /** 249 * Should be called at the beginning of the program to set up the 250 * network interface. It calls the function low_level_init() to do the 251 * actual setup of the hardware. 252 * 253 * This function should be passed as a parameter to netif_add(). 254 * 255 * @param netif the lwip network interface structure for this quadradioif 256 * @return ERR_OK if the loopif is initialized 257 * ERR_MEM if private data couldn't be allocated 258 * any other err_t on error 259 */ 260 err_t 261 quadradioif_init(struct netif *netif) 262 { 263 struct quadradioif *quadradioif; 264 265 LWIP_ASSERT("netif != NULL", (netif != NULL)); 266 267 quadradioif = mem_malloc(sizeof(struct quadradioif)); 268 if (quadradioif == NULL) { 269 LWIP_DEBUGF(NETIF_DEBUG, ("quadradioif_init: out of memory\n")); 270 return ERR_MEM; 271 } 272 273 #if LWIP_NETIF_HOSTNAME 274 /* Initialize interface hostname */ 275 netif->hostname = "lwip"; 276 #endif /* LWIP_NETIF_HOSTNAME */ 277 278 /* 279 * Initialize the snmp variables and counters inside the struct netif. 280 * The last argument should be replaced with your link speed, in units 281 * of bits per second. 282 */ 283 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); 284 285 netif->state = quadradioif; 286 netif->name[0] = IFNAME0; 287 netif->name[1] = IFNAME1; 288 /* We directly use etharp_output() here to save a function call. 289 * You can instead declare your own function an call etharp_output() 290 * from it if you have to do some checks before sending (e.g. if link 291 * is available...) */ 292 netif->output = etharp_output; 293 netif->linkoutput = low_level_output; 294 295 quadradioif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); 296 297 /* initialize the hardware */ 298 low_level_init(netif); 299 300 return ERR_OK; 301 } 302 303 #endif /* 0 */ 304