ethernetif.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  * This file is part of the lwIP TCP/IP stack.
00030  * 
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: ethernetif_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
00034  */
00035 
00036 /*
00037  * This file is a skeleton for developing Ethernet network interface
00038  * drivers for lwIP. Add code to the low_level functions and do a
00039  * search-and-replace for the word "ethernetif" to replace it with
00040  * something that better describes your network interface.
00041  */
00042 
00043 #include <ubixos/types.h>
00044 #include <ubixos/sched.h>
00045 #include <lib/kmalloc.h>
00046 #include <lib/kprintf.h>
00047 #include <sys/device.old.h>
00048 #include <isa/ne2k.h>
00049 
00050 
00051 #include "net/debug.h"
00052 
00053 #include "net/opt.h"
00054 #include "net/def.h"
00055 #include "net/mem.h"
00056 #include "net/pbuf.h"
00057 #include "net/sys.h"
00058 
00059 #include "netif/arp.h"
00060 
00061 /* Define those to better describe your network interface. */
00062 #define IFNAME0 'e'
00063 #define IFNAME1 'd'
00064 
00065 struct nicBuffer *tmpBuf = 0x0;
00066 
00067 struct ethernetif {
00068   struct eth_addr *ethaddr;
00069   /* Add whatever per-interface state that is needed here. */
00070 };
00071 
00072 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
00073 
00074 /* Forward declarations. */
00075 static void  ethernetif_input(struct netif *netif);
00076 static err_t ethernetif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
00077 static void ethernetif_thread();
00078 struct device *dev = 0x0;
00079 
00080 /*-----------------------------------------------------------------------------------*/
00081 static void low_level_init(struct netif *netif) {
00082   struct ethernetif *ethernetif;
00083 
00084   ethernetif = netif->state;
00085   dev = (struct device *)kmalloc(sizeof(struct device));
00086   dev->ioAddr = 0x280;
00087   dev->irq    = 0x10;
00088   
00089   /* Obtain MAC address from network interface. */
00090   ethernetif->ethaddr->addr[0] = 0x00;
00091   ethernetif->ethaddr->addr[1] = 0x00;
00092   ethernetif->ethaddr->addr[2] = 0xC0;
00093   ethernetif->ethaddr->addr[3] = 0x97;
00094   ethernetif->ethaddr->addr[4] = 0xC6;
00095   ethernetif->ethaddr->addr[5] = 0x93;
00096 
00097   /* Do whatever else is needed to initialize interface. */  
00098   kprintf("NETIF: [0x%X:0x%X]\n",netif,ethernetif_thread);
00099   sys_thread_new(ethernetif_thread, netif);
00100  
00101   }
00102 /*-----------------------------------------------------------------------------------*/
00103 /*
00104  * low_level_output():
00105  *
00106  * Should do the actual transmission of the packet. The packet is
00107  * contained in the pbuf that is passed to the function. This pbuf
00108  * might be chained.
00109  *
00110  */
00111 /*-----------------------------------------------------------------------------------*/
00112 
00113 static err_t low_level_output(struct ethernetif *ethernetif, struct pbuf *p) {
00114   struct pbuf *q;
00115   char buf[1500];
00116   char *bufptr = 0x0;
00117 
00118   dev->ioAddr = 0x280;
00119   dev->irq    = 10;
00120 
00121   bufptr = &buf[0];
00122 
00123   for(q = p; q != NULL; q = q->next) {
00124     bcopy(q->payload, bufptr, q->len);
00125     bufptr += q->len;
00126     }
00127   PCtoNIC(dev,buf,p->tot_len);
00128   //kprintf("Sending Data[%i]\n",p->tot_len); 
00129   return ERR_OK;
00130   }
00131 
00132 
00133 /*-----------------------------------------------------------------------------------*/
00134 /*
00135  * low_level_input():
00136  *
00137  * Should allocate a pbuf and transfer the bytes of the incoming
00138  * packet from the interface into the pbuf.
00139  *
00140  */
00141 /*-----------------------------------------------------------------------------------*/
00142 static struct pbuf *low_level_input(struct ethernetif *ethernetif) {
00143   struct pbuf *p, *q;
00144   uInt16 len;
00145   char *bufptr;
00146   char *buf;
00147 
00148   len = tmpBuf->length;
00149   bufptr = tmpBuf->buffer;
00150 
00151 
00152   /* We allocate a pbuf chain of pbufs from the pool. */
00153   p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
00154 
00155   if(p != NULL) {
00156     /* We iterate over the pbuf chain until we have read the entire
00157        packet into the pbuf. */
00158     //bufptr = &buf[0];
00159     for(q = p; q != NULL; q = q->next) {
00160       /* Read enough bytes to fill this pbuf in the chain. The
00161          avaliable data in the pbuf is given by the q->len
00162          variable. */
00163       /* read data into(q->payload, q->len); */
00164       bcopy(bufptr, q->payload, q->len);
00165       buf = q->payload;
00166       bufptr += q->len;
00167     }
00168     /* acknowledge that packet has been read(); */
00169   } else {
00170     /* drop packet(); */
00171   }
00172   return p;
00173 }
00174 
00175 
00176 /*-----------------------------------------------------------------------------------*/
00177 /*
00178  * ethernetif_output():
00179  *
00180  * This function is called by the TCP/IP stack when an IP packet
00181  * should be sent. It calls the function called low_level_output() to
00182  * do the actuall transmission of the packet.
00183  *
00184  */
00185 /*-----------------------------------------------------------------------------------*/
00186 static err_t ethernetif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) {
00187   struct ethernetif *ethernetif;
00188   struct pbuf *q;
00189   struct eth_hdr *ethhdr;
00190   struct eth_addr *dest, mcastaddr;
00191   struct ip_addr *queryaddr;
00192   err_t err;
00193   uInt8 i;
00194   
00195   ethernetif = netif->state;
00196 
00197 
00198   /* Make room for Ethernet header. */
00199   if(pbuf_header(p, sizeof(struct eth_hdr)) != 0) {
00200     /* The pbuf_header() call shouldn't fail, but we allocate an extra
00201        pbuf just in case. */
00202     q = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr), PBUF_RAM);
00203     if(q == NULL) {
00204       return ERR_MEM;
00205     }
00206     pbuf_chain(q, p);
00207     p = q;
00208   }
00209 
00210   /* Construct Ethernet header. Start with looking up deciding which
00211      MAC address to use as a destination address. Broadcasts and
00212      multicasts are special, all other addresses are looked up in the
00213      ARP table. */
00214   queryaddr = ipaddr;
00215   if(ip_addr_isany(ipaddr) ||
00216      ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
00217     dest = (struct eth_addr *)&ethbroadcast;
00218   } else if(ip_addr_ismulticast(ipaddr)) {
00219     /* Hash IP multicast address to MAC address. */
00220     mcastaddr.addr[0] = 0x01;
00221     mcastaddr.addr[1] = 0x0;
00222     mcastaddr.addr[2] = 0x5e;
00223     mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
00224     mcastaddr.addr[4] = ip4_addr3(ipaddr);
00225     mcastaddr.addr[5] = ip4_addr4(ipaddr);
00226     dest = &mcastaddr;
00227   } else {
00228     if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
00229       /* Use destination IP address if the destination is on the same
00230          subnet as we are. */
00231       queryaddr = ipaddr;
00232     } else {
00233       /* Otherwise we use the default router as the address to send
00234          the Ethernet frame to. */
00235       queryaddr = &(netif->gw);
00236     }
00237     dest = arp_lookup(queryaddr);
00238   }
00239 
00240 
00241   /* If the arp_lookup() didn't find an address, we send out an ARP
00242      query for the IP address. */
00243   if(dest == NULL) {
00244     q = arp_query(netif, ethernetif->ethaddr, queryaddr);
00245     if(q != NULL) {
00246       err = low_level_output(ethernetif, q);
00247       pbuf_free(q);
00248       return err;
00249     }
00250     return ERR_MEM;
00251   }
00252   ethhdr = p->payload;
00253 
00254   for(i = 0; i < 6; i++) {
00255     ethhdr->dest.addr[i] = dest->addr[i];
00256     ethhdr->src.addr[i] = ethernetif->ethaddr->addr[i];
00257   }
00258   
00259   ethhdr->type = htons(ETHTYPE_IP);
00260   
00261   return low_level_output(ethernetif, p);
00262 
00263 }
00264 /*-----------------------------------------------------------------------------------*/
00265 /*
00266  * ethernetif_input():
00267  *
00268  * This function should be called when a packet is ready to be read
00269  * from the interface. It uses the function low_level_input() that
00270  * should handle the actual reception of bytes from the network
00271  * interface.
00272  *
00273  */
00274 /*-----------------------------------------------------------------------------------*/
00275 static void ethernetif_input(struct netif *netif) {
00276   struct ethernetif *ethernetif = 0x0;
00277   struct eth_hdr *ethhdr = 0x0;
00278   struct pbuf *p = 0x0;
00279 
00280   ethernetif = netif->state;
00281  
00282   p = low_level_input(ethernetif);
00283 
00284   if(p != NULL) {
00285 
00286     ethhdr = p->payload;
00287     
00288     switch(htons(ethhdr->type)) {
00289     case ETHTYPE_IP:
00290       arp_ip_input(netif, p);
00291       pbuf_header(p, -14);
00292       netif->input(p, netif);
00293       break;
00294     case ETHTYPE_ARP:
00295       p = arp_arp_input(netif, ethernetif->ethaddr, p);
00296       if(p != NULL) {
00297         low_level_output(ethernetif, p);
00298         pbuf_free(p);
00299       }
00300       break;
00301     default:
00302       pbuf_free(p);
00303       break;
00304     }
00305   }
00306 }
00307 /*-----------------------------------------------------------------------------------*/
00308 static void
00309 arp_timer(void *arg)
00310 {
00311   arp_tmr();
00312   sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
00313 }
00314 
00315 /*-----------------------------------------------------------------------------------*/
00316 /*
00317  * ethernetif_init():
00318  *
00319  * Should be called at the beginning of the program to set up the
00320  * network interface. It calls the function low_level_init() to do the
00321  * actual setup of the hardware.
00322  *
00323  */
00324 /*-----------------------------------------------------------------------------------*/
00325 void ethernetif_init(struct netif *netif) {
00326   struct ethernetif *ethernetif;
00327     
00328   ethernetif = mem_malloc(sizeof(struct ethernetif));
00329   netif->state = ethernetif;
00330   netif->name[0] = IFNAME0;
00331   netif->name[1] = IFNAME1;
00332   netif->output = ethernetif_output;
00333   netif->linkoutput = (void *)low_level_output;
00334   
00335   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
00336   
00337   low_level_init(netif);
00338   arp_init();
00339 
00340   sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
00341   }
00342 
00343 /*-----------------------------------------------------------------------------------*/
00344 
00345 void ethernetif_thread(void *arg) {
00346   struct netif *netif = 0x0;
00347  
00348   netif = arg;
00349   
00350   while (1) {
00351     tmpBuf = ne2kGetBuffer();
00352     if (tmpBuf && tmpBuf->length > 0x0) {
00353       ethernetif_input(netif);  
00354       }
00355     }
00356   ne2kFreeBuffer(tmpBuf);
00357   }

Generated on Tue Dec 12 08:52:07 2006 for UbixOS V2 by  doxygen 1.4.7