Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

rtfifoif.c

Go to the documentation of this file.
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 *)&ethbroadcast;
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__

Generated on Wed Jan 14 12:58:56 2004 for RTL-lwIP-0.4 by doxygen 1.3.4