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/mem.h" 00087 #include "lwip/pbuf.h" 00088 #include "lwip/sys.h" 00089 #include "netif/etharp.h" 00090 #include "netif/rt_3c905x_exports.h" 00091 #include "netif/ethernetif.h" 00092 #include <unistd.h> 00093 #include "bcopy.h" 00094 #include <signal.h> 00095 #include <rtl_sema.h> 00096 00097 #define IFNAME0 'e' 00098 #define IFNAME1 't' 00099 #define COM3_SIGNAL RTL_SIGUSR2 00100 00101 ethernetif_thread_t com3_thread; 00102 00103 struct rt_3c905cif { 00104 struct eth_addr *ethaddr; 00105 }; 00106 00107 static const struct eth_addr rt_3c905cif_ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; 00108 static int rt_3c905cif_fd; 00109 static struct netif *rt_3c905cif_netif; 00110 00111 /* Forward declarations. */ 00112 static void rt_3c905cif_input(struct pbuf *p, struct netif *netif); 00113 static err_t rt_3c905cif_output(struct netif *netif, struct pbuf *p, 00114 struct ip_addr *ipaddr); 00115 static void rt_3c905cif_ethernetif_thread(void *arg); 00116 00117 /*-----------------------------------------------------------------------------------*/ 00118 static void 00119 rt_3com905cif_low_level_init(struct netif *netif) 00120 { 00121 struct rt_3c905cif *rt_3c905cif; 00122 char dev_name[]={"/dev/eth0"}; 00123 00124 rt_3c905cif = netif->state; 00125 00126 /* Do whatever else is needed to initialize interface. */ 00127 if((rt_3c905cif_fd=open(dev_name,0)) == -1) 00128 rtl_printf("ERROR OPENING /dev/%s0\n",COM3_905C_NAME); 00129 00130 /* Obtain MAC address from network interface. */ 00131 ioctl(rt_3c905cif_fd, 2, (unsigned long) rt_3c905cif->ethaddr->addr); 00132 00133 /* We set an IP filter to the ethernet card */ 00134 ioctl(rt_3c905cif_fd, 1, (unsigned long) netif->ip_addr.addr); 00135 00136 // rtl_printf("ADRESS: %x:%x:%x:%x:%x:%x \n",rt_3c905cif->ethaddr->addr[0],rt_3c905cif->ethaddr->addr[1],rt_3c905cif->ethaddr->addr[2],rt_3c905cif->ethaddr->addr[3],rt_3c905cif->ethaddr->addr[4],rt_3c905cif->ethaddr->addr[5]); 00137 00138 sys_thread_new(rt_3c905cif_ethernetif_thread, netif, 0); 00139 00140 return ; 00141 } 00142 00143 /*-----------------------------------------------------------------------------------*/ 00144 static void rt_3c905cif_ethernetif_thread(void *arg){ 00145 struct sched_param p; 00146 00147 p . sched_priority = 100000; 00148 pthread_setschedparam (pthread_self(), SCHED_FIFO, &p); 00149 00150 do{ 00151 rt_3c905cif_input(NULL, rt_3c905cif_netif); 00152 }while(1); 00153 00154 } 00155 00156 /*-----------------------------------------------------------------------------------*/ 00157 /* 00158 * rt_3com905cif_low_level_output(): 00159 * 00160 * Should do the actual transmission of the packet. The packet is 00161 * contained in the pbuf that is passed to the function. This pbuf 00162 * might be chained. 00163 * 00164 */ 00165 /*-----------------------------------------------------------------------------------*/ 00166 00167 err_t 00168 rt_3com905cif_low_level_output(struct netif *rt_3c905cif, struct pbuf *p) 00169 { 00170 00171 struct pbuf *q; 00172 unsigned char buf[1536]; 00173 unsigned char *bufptr; 00174 00175 //initiate transfer; 00176 bufptr = buf; 00177 00178 for(q = p; q != NULL; q = q->next) { 00179 /* Send the data from the pbuf to the interface, one pbuf at a 00180 time. The size of the data in each pbuf is kept in the ->len 00181 variable. */ 00182 bcopy(q->payload, bufptr, q->len); 00183 bufptr += q->len; 00184 } 00185 00186 //signal that packet should be sent; 00187 { 00188 int tmp; 00189 int counter=0; 00190 00191 while((tmp = write(rt_3c905cif_fd,buf,p->tot_len)) == -1){ 00192 counter++; 00193 usleep(1); 00194 } 00195 } 00196 00197 return ERR_OK; 00198 } 00199 /*-----------------------------------------------------------------------------------*/ 00200 /* 00201 * rt_3com905cif_low_level_input(): 00202 * 00203 * Should allocate a pbuf and transfer the bytes of the incoming 00204 * packet from the interface into the pbuf. 00205 * 00206 */ 00207 /*-----------------------------------------------------------------------------------*/ 00208 static struct pbuf * 00209 rt_3com905cif_low_level_input(struct rt_3c905cif *rt_3c905cif) 00210 { 00211 struct pbuf *p, *q; 00212 struct memory receive_buffer; 00213 unsigned char *bufptr; 00214 u16_t len; 00215 00216 /* Obtain the size of the packet and put it into the "len" 00217 variable. */ 00218 len = read(rt_3c905cif_fd,(void *) &receive_buffer,1536); 00219 00220 /* We allocate a pbuf chain of pbufs from the pool. */ 00221 p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL); 00222 00223 if(p != NULL) { 00224 /* We iterate over the pbuf chain until we have read the entire 00225 packet into the pbuf. */ 00226 bufptr = receive_buffer.mem; 00227 for(q = p; q != NULL; q = q->next) { 00228 /* Read enough bytes to fill this pbuf in the chain. The 00229 avaliable data in the pbuf is given by the q->len 00230 variable. */ 00231 bcopy(bufptr, q->payload, q->len); 00232 bufptr += q->len; 00233 } 00234 } else { 00235 rtl_printf("ERROR:Not enough memory!!!\n"); 00236 sys_arch_close(); 00237 } 00238 00239 return p; 00240 } 00241 /*-----------------------------------------------------------------------------------*/ 00242 /* 00243 * rt_3c905cif_output(): 00244 * 00245 * This function is called by the TCP/IP stack when an IP packet 00246 * should be sent. It calls the function called rt_3com905cif_low_level_output() to 00247 * do the actuall transmission of the packet. 00248 * 00249 */ 00250 /*-----------------------------------------------------------------------------------*/ 00251 static err_t 00252 rt_3c905cif_output(struct netif *netif, struct pbuf *p, 00253 struct ip_addr *ipaddr) 00254 { 00255 00256 p = etharp_output(netif, ipaddr, p); 00257 if(p != NULL) { 00258 rt_3com905cif_low_level_output(netif, p); 00259 } 00260 return ERR_OK; 00261 } 00262 00263 /*-----------------------------------------------------------------------------------*/ 00264 /* 00265 * rt_3c905cif_input(): 00266 * 00267 * This function should be called when a packet is ready to be read 00268 * from the interface. It uses the function rt_3com905cif_low_level_input() that 00269 * should handle the actual reception of bytes from the network 00270 * interface. 00271 * 00272 */ 00273 /*-----------------------------------------------------------------------------------*/ 00274 static void 00275 00276 rt_3c905cif_input(struct pbuf *o, struct netif *netif)//(struct netif *netif) 00277 { 00278 00279 /* Ethernet protocol layer */ 00280 struct eth_hdr *ethhdr; 00281 struct rt_3c905cif *rt_3c905cif = netif->state; 00282 struct pbuf *q = NULL , *p = NULL; 00283 00284 p = rt_3com905cif_low_level_input(rt_3c905cif); 00285 00286 ethhdr = p->payload; 00287 00288 switch(htons(ethhdr->type)) { 00289 case ETHTYPE_IP: 00290 q = etharp_ip_input(netif, p); 00291 pbuf_header(p, -14); 00292 netif->input(p, netif); 00293 break; 00294 case ETHTYPE_ARP: 00295 q = etharp_arp_input(netif, rt_3c905cif->ethaddr, p); 00296 break; 00297 default: 00298 pbuf_free(p); 00299 break; 00300 } 00301 if(q != NULL) { 00302 rt_3com905cif_low_level_output(netif, q); 00303 pbuf_free(q); 00304 } 00305 } 00306 00307 /*-----------------------------------------------------------------------------------*/ 00308 void rt_3com905cif_etharp_timer(int signo) 00309 { 00310 etharp_tmr(); 00311 sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)rt_3com905cif_etharp_timer, NULL); 00312 } 00313 00314 /*-----------------------------------------------------------------------------------*/ 00315 /* 00316 * rt_3c905cif_init(): 00317 * 00318 * Should be called at the beginning of the program to set up the 00319 * network interface. It calls the function rt_3com905cif_low_level_init() to do the 00320 * actual setup of the hardware. 00321 * 00322 */ 00323 /*-----------------------------------------------------------------------------------*/ 00324 err_t 00325 rt_3c905cif_init(struct netif *netif) 00326 { 00327 struct rt_3c905cif *rt_3c905cif; 00328 00329 rt_3c905cif = mem_malloc(sizeof(struct rt_3c905cif)); 00330 netif->state = rt_3c905cif; 00331 netif->name[0] = IFNAME0; 00332 netif->name[1] = IFNAME1; 00333 netif->output = rt_3c905cif_output; 00334 netif->linkoutput = rt_3com905cif_low_level_output; 00335 00336 rt_3c905cif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); 00337 netif->hwaddr_len = 6; 00338 00339 rt_3c905cif_netif = netif; 00340 00341 rt_3com905cif_low_level_init(netif); 00342 etharp_init(); 00343 00344 sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)rt_3com905cif_etharp_timer, NULL); 00345 00346 return ERR_OK; 00347 } 00348 00349 00350 /*-----------------------------------------------------------------------------------*/ 00351 void rt_3c905cif_close(void){ 00352 /* Unregistering the thread */ 00353 ioctl(rt_3c905cif_fd, 4, (unsigned long) &com3_thread); 00354 /* Closing the 3Com905C-X card */ 00355 close(rt_3c905cif_fd); 00356 } 00357