00001 /* 00002 * Copyright (c) 2001, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 */ 00030 00031 /*********************************************************************************/ 00032 /* This file is based in one file part of the lwIP TCP/IP stack. The file is: */ 00033 /* ethernetif.c */ 00034 /* which author is: Adam Dunkels <adam@sics.se> */ 00035 /* */ 00036 /* This file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> */ 00037 /* Departamento de Informática de Sistemas y Computadores */ 00038 /* Universidad Politécnica de Valencia */ 00039 /* Valencia (Spain) */ 00040 /* */ 00041 /* The RTL-lwIP project has been supported by the Spanish Government Research */ 00042 /* Office (CICYT) under grant TIC2002-04123-C03-03 */ 00043 /* */ 00044 /* Copyright (c) March, 2003 SISTEMAS DE TIEMPO REAL EMPOTRADOS, FIABLES Y */ 00045 /* DISTRIBUIDOS BASADOS EN COMPONENTES */ 00046 /* */ 00047 /* This program is free software; you can redistribute it and/or modify */ 00048 /* it under the terms of the GNU General Public License as published by */ 00049 /* the Free Software Foundation; either version 2 of the License, or */ 00050 /* (at your option) any later version. */ 00051 /* */ 00052 /* This program is distributed in the hope that it will be useful, */ 00053 /* but WITHOUT ANY WARRANTY; without even the implied warrabnty of */ 00054 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 00055 /* GNU General Public License for more details. */ 00056 /* */ 00057 /* You should have received a copy of the GNU General Public License */ 00058 /* along with this program; if not, write to the Free Software */ 00059 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00060 /* */ 00061 /* Linking RTL-lwIP statically or dynamically with other modules is making a */ 00062 /* combined work based on RTL-lwIP. Thus, the terms and conditions of the GNU */ 00063 /* General Public License cover the whole combination. */ 00064 /* */ 00065 /* As a special exception, the copyright holders of RTL-lwIP give you */ 00066 /* permission to link RTL-lwIP with independent modules that communicate with */ 00067 /* RTL-lwIP solely through the interfaces, regardless of the license terms of */ 00068 /* these independent modules, and to copy and distribute the resulting combined */ 00069 /* work under terms of your choice, provided that every copy of the combined */ 00070 /* work is accompanied by a complete copy of the source code of RTL-lwIP (the */ 00071 /* version of RTL-lwIP used to produce the combined work), being distributed */ 00072 /* under the terms of the GNU General Public License plus this exception. An */ 00073 /* independent module is a module which is not derived from or based on */ 00074 /* RTL-lwIP. */ 00075 /* */ 00076 /* Note that people who make modified versions of RTL-lwIP are not obligated to */ 00077 /* grant this special exception for their modified versions; it is their choice */ 00078 /* whether to do so. The GNU General Public License gives permission to */ 00079 /* release a modified version without this exception; this exception also makes */ 00080 /* it possible to release a modified version which carries forward this */ 00081 /* exception. */ 00082 /*********************************************************************************/ 00083 00084 #include "lwip/opt.h" 00085 #include "lwip/def.h" 00086 #include "lwip/ip.h" 00087 #include "lwip/mem.h" 00088 #include "lwip/pbuf.h" 00089 #include "lwip/sys.h" 00090 #include "bcopy.h" 00091 #include "netif/arp.h" 00092 #include <time.h> 00093 #include <rtl_sched.h> 00094 #include <rtl_fifo.h> 00095 00096 #ifdef __RTFIFOOPTS__ 00097 00098 #define DEVWRITE "/dev/rtf0" 00099 #define DEVREAD "/dev/rtf1" 00100 00101 #define IFNAME0 'r' 00102 #define IFNAME1 't' 00103 00104 #define SETBYTEONE(a,b) (a=(b & 0x000F)) 00105 #define SETBYTETWO(a,b) (a=(b & 0x00F0)) 00106 #define SETBYTETHREE(a,b) (a=(b & 0x0F00)) 00107 #define SETBYTEFOUR(a,b) (a=(b & 0xF000)) 00108 00109 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; 00110 00111 struct rtfifoif { 00112 struct eth_addr *ethaddr; 00113 int writefd; 00114 int readfd; 00115 }; 00116 00117 /* Forward declarations. */ 00118 static void rtfifoif_input(struct netif *netif); 00119 static err_t rtfifoif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr); 00120 static void rtfifoif_thread(void *arg); 00121 00122 /*-----------------------------------------------------------------------------------*/ 00123 static void 00124 low_level_init(struct netif *netif) 00125 { 00126 struct rtfifoif *rtfifoif; 00127 rtfifoif = netif->state; 00128 00129 /* Obtain MAC address from network interface. */ 00130 string2mac(rtfifoif->ethaddr,RTFIFO_MAC); 00131 00132 /* We use RTfifo 0 for writing */ 00133 rtfifoif->writefd = 0; 00134 /* We use RTfifo 1 for reading */ 00135 rtfifoif->readfd = 1; 00136 00137 sys_thread_new(rtfifoif_thread, netif, RTFIFO_THREAD_PERIOD); 00138 00139 } 00140 00141 /*-----------------------------------------------------------------------------------*/ 00142 static void 00143 rtfifoif_thread(void *arg){ 00144 struct netif *netif; 00145 struct rtfifoif *rtfifoif; 00146 00147 netif = arg; 00148 rtfifoif = netif->state; 00149 00150 while(1) { 00151 pthread_wait_np(); 00152 /* Wait for a packet to arrive. */ 00153 while(rtf_isempty(rtfifoif->readfd)){ 00154 usleep(RTFIFO_DELAY); 00155 } 00156 00157 /* Handle incoming packet. */ 00158 rtfifoif_input(netif); 00159 } 00160 } 00161 00162 /*-----------------------------------------------------------------------------------*/ 00163 /* 00164 * low_level_output(): 00165 * 00166 * Should do the actual transmission of the packet. The packet is 00167 * contained in the pbuf that is passed to the function. This pbuf 00168 * might be chained. 00169 * 00170 */ 00171 /*-----------------------------------------------------------------------------------*/ 00172 static err_t 00173 low_level_output(struct rtfifoif *rtfifoif, struct pbuf *p) 00174 { 00175 struct pbuf *q; 00176 char buf[1500]; 00177 char *bufptr; 00178 unsigned char size_of_packet[4]; 00179 00180 /* initiate transfer(); */ 00181 00182 bufptr = &buf[0]; 00183 00184 for(q = p; q != NULL; q = q->next) { 00185 /* Send the data from the pbuf to the interface, one pbuf at a 00186 time. The size of the data in each pbuf is kept in the ->len 00187 variable. */ 00188 /* send data from(q->payload, q->len); */ 00189 bcopy(q->payload, bufptr, q->len); 00190 bufptr += q->len; 00191 } 00192 00193 SETBYTEONE(size_of_packet[0],p->tot_len); 00194 SETBYTETWO(size_of_packet[1],p->tot_len); 00195 SETBYTETHREE(size_of_packet[2],p->tot_len); 00196 SETBYTEFOUR(size_of_packet[3],p->tot_len); 00197 00198 if(rtf_put(rtfifoif->writefd, &size_of_packet, 4) == -1) { 00199 rtl_printf("low_level_output: rtf_put error"); 00200 }else{ 00201 if(rtf_put(rtfifoif->writefd, buf, p->tot_len) == -1) { 00202 rtl_printf("low_level_output: rtf_put error"); 00203 } 00204 } 00205 00206 return ERR_OK; 00207 } 00208 /*-----------------------------------------------------------------------------------*/ 00209 /* 00210 * low_level_input(): 00211 * 00212 * Should allocate a pbuf and transfer the bytes of the incoming 00213 * packet from the interface into the pbuf. 00214 * 00215 */ 00216 /*-----------------------------------------------------------------------------------*/ 00217 static struct pbuf * 00218 low_level_input(struct rtfifoif *rtfifoif) 00219 { 00220 struct pbuf *p, *q; 00221 u16_t len; 00222 char buf[1500]; 00223 char *bufptr; 00224 unsigned char size_of_packet[4]; 00225 int packet_size; 00226 00227 /* Obtain the size of the packet and put it into the "len" 00228 variable. */ 00229 00230 rtf_get(rtfifoif->readfd, &size_of_packet, 4); 00231 00232 packet_size = size_of_packet[0] + size_of_packet[1] + size_of_packet[2] + size_of_packet[3]; 00233 00234 /* Wait for a packet to arrive. */ 00235 while(rtf_isempty(rtfifoif->readfd)){ 00236 usleep(10); 00237 } 00238 00239 len = rtf_get(rtfifoif->readfd, buf,(int) packet_size); 00240 00241 00242 /* We allocate a pbuf chain of pbufs from the pool. */ 00243 p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL); 00244 00245 if(p != NULL) { 00246 /* We iterate over the pbuf chain until we have read the entire 00247 packet into the pbuf. */ 00248 bufptr = &buf[0]; 00249 for(q = p; q != NULL; q = q->next) { 00250 /* Read enough bytes to fill this pbuf in the chain. The 00251 avaliable data in the pbuf is given by the q->len 00252 variable. */ 00253 /* read data into(q->payload, q->len); */ 00254 bcopy(bufptr, q->payload, q->len); 00255 bufptr += q->len; 00256 } 00257 /* acknowledge that packet has been read(); */ 00258 } else { 00259 rtl_printf("rtfifoif: Can't allocate memory for pbuf\n"); 00260 } 00261 00262 return p; 00263 } 00264 00265 /*-----------------------------------------------------------------------------------*/ 00266 /* 00267 * fifoif_output(): 00268 * 00269 * This function is called by the TCP/IP stack when an IP packet 00270 * should be sent. It calls the function called low_level_output() to 00271 * do the actuall transmission of the packet. 00272 * 00273 */ 00274 /*-----------------------------------------------------------------------------------*/ 00275 static err_t 00276 rtfifoif_output(struct netif *netif, struct pbuf *p, 00277 struct ip_addr *ipaddr) 00278 { 00279 struct rtfifoif *rtfifoif; 00280 struct pbuf *q; 00281 struct eth_hdr *ethhdr; 00282 struct eth_addr *dest, mcastaddr; 00283 struct ip_addr *queryaddr; 00284 err_t err; 00285 u8_t i; 00286 00287 rtfifoif = netif->state; 00288 00289 /* Make room for Ethernet header. */ 00290 if(pbuf_header(p, sizeof(struct eth_hdr)) != 0) { 00291 /* The pbuf_header() call shouldn't fail, but we allocate an extra 00292 pbuf just in case. */ 00293 q = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr), PBUF_RAM); 00294 if(q == NULL) { 00295 return ERR_MEM; 00296 } 00297 pbuf_chain(q, p); 00298 p = q; 00299 } 00300 00301 /* Construct Ethernet header. Start with looking up deciding which 00302 MAC address to use as a destination address. Broadcasts and 00303 multicasts are special, all other addresses are looked up in the 00304 ARP table. */ 00305 queryaddr = ipaddr; 00306 if(ip_addr_isany(ipaddr) || 00307 ip_addr_isbroadcast(ipaddr, &(netif->netmask))) { 00308 dest = (struct eth_addr *)ðbroadcast; 00309 } else if(ip_addr_ismulticast(ipaddr)) { 00310 /* Hash IP multicast address to MAC address. */ 00311 mcastaddr.addr[0] = 0x01; 00312 mcastaddr.addr[1] = 0x0; 00313 mcastaddr.addr[2] = 0x5e; 00314 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; 00315 mcastaddr.addr[4] = ip4_addr3(ipaddr); 00316 mcastaddr.addr[5] = ip4_addr4(ipaddr); 00317 dest = &mcastaddr; 00318 } else { 00319 if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { 00320 /* Use destination IP address if the destination is on the same 00321 subnet as we are. */ 00322 queryaddr = ipaddr; 00323 } else { 00324 /* Otherwise we use the default router as the address to send 00325 the Ethernet frame to. */ 00326 queryaddr = &(netif->gw); 00327 } 00328 dest = arp_lookup(queryaddr); 00329 } 00330 00331 /* If the arp_lookup() didn't find an address, we send out an ARP 00332 query for the IP address. */ 00333 if(dest == NULL) { 00334 q = arp_query(netif, rtfifoif->ethaddr, queryaddr); 00335 if(q != NULL) { 00336 err = low_level_output(rtfifoif, q); 00337 pbuf_free(q); 00338 return err; 00339 } 00340 return ERR_MEM; 00341 } 00342 ethhdr = p->payload; 00343 00344 for(i = 0; i < 6; i++) { 00345 ethhdr->dest.addr[i] = dest->addr[i]; 00346 ethhdr->src.addr[i] = rtfifoif->ethaddr->addr[i]; 00347 } 00348 00349 ethhdr->type = htons(ETHTYPE_IP); 00350 00351 return low_level_output(rtfifoif, p); 00352 00353 } 00354 /*-----------------------------------------------------------------------------------*/ 00355 /* 00356 * rtfifoif_input(): 00357 * 00358 * This function should be called when a packet is ready to be read 00359 * from the interface. It uses the function low_level_input() that 00360 * should handle the actual reception of bytes from the network 00361 * interface. 00362 * 00363 */ 00364 /*-----------------------------------------------------------------------------------*/ 00365 static void 00366 rtfifoif_input(struct netif *netif) 00367 { 00368 struct rtfifoif *rtfifoif; 00369 struct eth_hdr *ethhdr; 00370 struct pbuf *p; 00371 00372 00373 rtfifoif = netif->state; 00374 00375 p = low_level_input(rtfifoif); 00376 00377 if(p == NULL) { 00378 return; 00379 } 00380 ethhdr = p->payload; 00381 00382 switch(htons(ethhdr->type)) { 00383 case ETHTYPE_IP: 00384 arp_ip_input(netif, p); 00385 pbuf_header(p, -14); 00386 if(ip_lookup(p->payload, netif)) { 00387 netif->input(p, netif); 00388 } 00389 break; 00390 case ETHTYPE_ARP: 00391 00392 p = arp_arp_input(netif, rtfifoif->ethaddr, p); 00393 if(p != NULL) { 00394 low_level_output(rtfifoif, p); 00395 pbuf_free(p); 00396 } 00397 break; 00398 default: 00399 pbuf_free(p); 00400 break; 00401 } 00402 } 00403 /*-----------------------------------------------------------------------------------*/ 00404 static void 00405 arp_timer(void *arg) 00406 { 00407 arp_tmr(); 00408 sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL); 00409 } 00410 /*-----------------------------------------------------------------------------------*/ 00411 /* 00412 * rtfifoif_init(): 00413 * 00414 * Should be called at the beginning of the program to set up the 00415 * network interface. It calls the function low_level_init() to do the 00416 * actual setup of the hardware. 00417 * 00418 */ 00419 /*-----------------------------------------------------------------------------------*/ 00420 void 00421 rtfifoif_init(struct netif *netif) 00422 { 00423 struct rtfifoif *rtfifoif; 00424 00425 rtfifoif = mem_malloc(sizeof(struct rtfifoif)); 00426 netif->state = rtfifoif; 00427 netif->name[0] = IFNAME0; 00428 netif->name[1] = IFNAME1; 00429 netif->output = rtfifoif_output; 00430 netif->linkoutput = low_level_output; 00431 00432 rtfifoif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); 00433 00434 low_level_init(netif); 00435 arp_init(); 00436 00437 _timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL); 00438 } 00439 /*-----------------------------------------------------------------------------------*/ 00440 #endif //__RTFIFOOPTS__