# 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   }