root/net/tcp/dev.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. min
  2. dev_add_pack
  3. dev_remove_pack
  4. get_dev
  5. dev_queue_xmit
  6. dev_rint
  7. inet_bh
  8. dev_tint

   1 /* dev.c */
   2 /*
   3     Copyright (C) 1992  Ross Biro
   4 
   5     This program is free software; you can redistribute it and/or modify
   6     it under the terms of the GNU General Public License as published by
   7     the Free Software Foundation; either version 2, or (at your option)
   8     any later version.
   9 
  10     This program is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13     GNU General Public License for more details.
  14 
  15     You should have received a copy of the GNU General Public License
  16     along with this program; if not, write to the Free Software
  17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  18 
  19     The Author may be reached as bir7@leland.stanford.edu or
  20     C/O Department of Mathematics; Stanford University; Stanford, CA 94305
  21 */
  22 /* $Id: dev.c,v 0.8.4.10 1992/12/12 19:25:04 bir7 Exp $ */
  23 /* $Log: dev.c,v $
  24  * Revision 0.8.4.10  1992/12/12  19:25:04  bir7
  25  * Cleaned up Log messages.
  26  *
  27  * Revision 0.8.4.9  1992/12/12  01:50:49  bir7
  28  * *** empty log message ***
  29  *
  30  * Revision 0.8.4.8  1992/12/08  20:49:15  bir7
  31  * Edited ctrl-h's out of log messages.
  32  *
  33  * Revision 0.8.4.7  1992/12/06  23:29:59  bir7
  34  * Converted to using lower half interrupt routine.
  35  *
  36  * Revision 0.8.4.6  1992/12/05  21:35:53  bir7
  37  * Updated dev->init type.
  38  *
  39  * Revision 0.8.4.5  1992/12/03  19:52:20  bir7
  40  * Added paranoid queue checking.
  41  *
  42  * Revision 0.8.4.4  1992/11/18  15:38:03  bir7
  43  * Fixed bug in copying packets and changed some printk's
  44  *
  45  * Revision 0.8.4.3  1992/11/15  14:55:30  bir7
  46  * More sanity checks.
  47  *
  48  * Revision 0.8.4.2  1992/11/10  10:38:48  bir7
  49  * Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
  50  *
  51  * Revision 0.8.4.1  1992/11/10  00:17:18  bir7
  52  * version change only.
  53  *
  54  * Revision 0.8.3.5  1992/11/10  00:14:47  bir7
  55  * Changed malloc to kmalloc and added Id and Log
  56  *
  57  */
  58 
  59 #include <asm/segment.h>
  60 #include <asm/system.h>
  61 #include <linux/config.h>
  62 #include <linux/types.h>
  63 #include <linux/kernel.h>
  64 #include <linux/sched.h>
  65 #include <linux/string.h>
  66 #include <linux/mm.h>
  67 #include <linux/socket.h>
  68 #include <netinet/in.h>
  69 #include "dev.h"
  70 #include "eth.h"
  71 #include "timer.h"
  72 #include "ip.h"
  73 #include "tcp.h"
  74 #include "sock.h"
  75 #include <linux/errno.h>
  76 #include <linux/interrupt.h>
  77 #include "arp.h"
  78 
  79 #undef DEV_DEBUG
  80 #ifdef DEV_DEBUG
  81 #define PRINTK(x) printk x
  82 #else
  83 #define PRINTK(x) /**/
  84 #endif
  85 
  86 
  87 static  unsigned long
  88 min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90    if (a < b) return (a);
  91    return (b);
  92 }
  93 
  94 void
  95 dev_add_pack (struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97    struct packet_type *p1;
  98    pt->next = ptype_base;
  99 
 100    /* see if we need to copy it. */
 101    for (p1 = ptype_base; p1 != NULL; p1 = p1->next)
 102      {
 103         if (p1->type == pt->type)
 104           {
 105              pt->copy = 1;
 106              break;
 107           }
 108      }
 109 
 110    ptype_base = pt;
 111    
 112 }
 113 
 114 void
 115 dev_remove_pack (struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117    struct packet_type *lpt, *pt1;
 118    if (pt == ptype_base)
 119      {
 120         ptype_base = pt->next;
 121         return;
 122      }
 123 
 124    lpt = NULL;
 125 
 126    for (pt1 = ptype_base; pt1->next != NULL; pt1=pt1->next)
 127      {
 128         if (pt1->next == pt )
 129           {
 130              cli();
 131              if (!pt->copy && lpt) 
 132                lpt->copy = 0;
 133              pt1->next = pt->next;
 134              sti();
 135              return;
 136           }
 137 
 138         if (pt1->next -> type == pt ->type)
 139           {
 140              lpt = pt1->next;
 141           }
 142      }
 143 }
 144 
 145 struct device *
 146 get_dev (char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148    struct device *dev;
 149    for (dev = dev_base; dev != NULL; dev=dev->next)
 150      {
 151         if (strcmp (dev->name, name) == 0) return (dev);
 152      }
 153    return (NULL);
 154 }
 155 
 156 void
 157 dev_queue_xmit (struct sk_buff *skb, struct device *dev, int pri)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159   struct sk_buff *skb2;
 160   PRINTK (("dev_queue_xmit (skb=%X, dev=%X, pri = %d)\n", skb, dev, pri));
 161 
 162   if (dev == NULL)
 163     {
 164       printk ("dev.c: dev_queue_xmit: dev = NULL\n");
 165       return;
 166     }
 167   
 168   skb->dev = dev;
 169   if (skb->next != NULL)
 170     {
 171       /* make sure we haven't missed an interrupt. */
 172        dev->hard_start_xmit (NULL, dev);
 173        return;
 174     }
 175 
 176   if (pri < 0 || pri >= DEV_NUMBUFFS)
 177     {
 178        printk ("bad priority in dev_queue_xmit.\n");
 179        pri = 1;
 180     }
 181 
 182   if (dev->hard_start_xmit(skb, dev) == 0)
 183     {
 184        return;
 185     }
 186 
 187   /* put skb into a bidirectional circular linked list. */
 188   PRINTK (("dev_queue_xmit dev->buffs[%d]=%X\n",pri, dev->buffs[pri]));
 189   /* interrupts should already be cleared by hard_start_xmit. */
 190   cli();
 191   if (dev->buffs[pri] == NULL)
 192     {
 193       dev->buffs[pri]=skb;
 194       skb->next = skb;
 195       skb->prev = skb;
 196     }
 197   else
 198     {
 199       skb2=dev->buffs[pri];
 200       skb->next = skb2;
 201       skb->prev = skb2->prev;
 202       skb->next->prev = skb;
 203       skb->prev->next = skb;
 204     }
 205   skb->magic = DEV_QUEUE_MAGIC;
 206   sti();
 207 
 208 }
 209 
 210 
 211 /* this routine now just gets the data out of the card and returns.
 212    it's return values now mean.
 213 
 214    1 <- exit even if you have more packets.
 215    0 <- call me again no matter what.
 216   -1 <- last packet not processed, try again.
 217 
 218   It's changed now 
 219   1 <- exit I can't do any more
 220   0 <- feed me more. 
 221 
 222   */
 223 
 224 static volatile struct sk_buff * volatile backlog = NULL;
 225 
 226 int
 227 dev_rint(unsigned char *buff, long len, int flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 228          struct device * dev)
 229 {
 230    volatile struct sk_buff *skb=NULL;
 231    unsigned char *to;
 232    int amount;
 233 
 234    if (dev == NULL || buff == NULL || len <= 0) return (1);
 235 
 236    if (flags & IN_SKBUFF)
 237      {
 238        skb = (struct sk_buff *)buff;
 239      }
 240    else
 241      {
 242        skb = kmalloc (sizeof (*skb) + len, GFP_ATOMIC);
 243        if (skb == NULL)
 244          {
 245            printk ("dev_rint:dropping packet due to lack of memory.\n");
 246            return (1);
 247          }
 248        skb->lock = 0;
 249        skb->mem_len = sizeof (*skb) + len;
 250        skb->mem_addr = (struct sk_buff *)skb;
 251        /* first we copy the packet into a buffer, and save it for later. */
 252 
 253        to = (unsigned char *)(skb+1);
 254        while (len > 0)
 255          {
 256            amount = min (len, (unsigned long) dev->rmem_end -
 257                          (unsigned long) buff);
 258            memcpy (to, buff, amount);
 259            len -= amount;
 260            buff += amount;
 261            to += amount;
 262            if ((unsigned long)buff == dev->rmem_end)
 263              buff = (unsigned char *)dev->rmem_start;
 264          }
 265      }
 266 
 267    skb->len = len;
 268    skb->dev = dev;
 269    skb->sk = NULL;
 270 
 271    /* now add it to the backlog. */
 272    cli();
 273    if (backlog == NULL)
 274      {
 275        skb->prev = (struct sk_buff *)skb;
 276        skb->next = (struct sk_buff *)skb;
 277        backlog = skb;
 278      }
 279    else
 280      {
 281        skb->prev = backlog->prev;
 282        skb->next = (struct sk_buff *)backlog;
 283        skb->next->prev = (struct sk_buff *)skb;
 284        skb->prev->next = (struct sk_buff *)skb;
 285      }
 286    sti();
 287    
 288    if (backlog != NULL)
 289      mark_bh(INET_BH);
 290 
 291   return (0);
 292 }
 293 
 294 void
 295 inet_bh(void *tmp)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297   volatile struct sk_buff *skb;
 298   struct packet_type *ptype;
 299   unsigned short type;
 300   unsigned char flag =0;
 301   static volatile int in_bh=0;
 302 
 303   cli();
 304   if (in_bh != 0)
 305     {
 306       sti();
 307       return;
 308     }
 309   in_bh=1;
 310   
 311   /* anything left to process? */
 312   
 313   while (backlog != NULL)
 314      {
 315        cli();
 316        skb= backlog;
 317        if (skb->next == skb)
 318          {
 319            backlog = NULL;
 320          }
 321        else
 322          {
 323            backlog = skb->next;
 324            skb->next->prev = skb->prev;
 325            skb->prev->next = skb->next;
 326          }
 327        sti();
 328 
 329        /* bump the pointer to the next structure. */
 330        skb->h.raw = (unsigned char *)(skb+1) + skb->dev->hard_header_len;
 331        skb->len -= skb->dev->hard_header_len;
 332 
 333        /* convert the type to an ethernet type. */
 334        type = skb->dev->type_trans ((struct sk_buff *)skb, skb->dev);
 335 
 336        /* if there get to be a lot of types we should changes this to
 337           a bunch of linked lists like we do for ip protocols. */
 338        for (ptype = ptype_base; ptype != NULL; ptype=ptype->next)
 339          {
 340            if (ptype->type == type)
 341              {
 342                struct sk_buff *skb2;
 343                /* copy the packet if we need to. */
 344                if (ptype->copy)
 345                  {
 346                    skb2 = kmalloc (skb->mem_len, GFP_ATOMIC);
 347                    if (skb2 == NULL) continue;
 348                    memcpy (skb2, skb, skb->mem_len);
 349                    skb2->mem_addr = skb2;
 350                    skb2->lock = 0;
 351                    skb2->h.raw = (void *)((unsigned long)skb2
 352                                           + (unsigned long)skb->h.raw
 353                                           - (unsigned long)skb);
 354 
 355                  }
 356                else
 357                  {
 358                    skb2 = (struct sk_buff *)skb;
 359                    flag = 1;
 360                  }
 361                
 362                ptype->func (skb2, skb->dev, ptype);
 363              }
 364          }
 365 
 366        if (!flag)
 367          {
 368            PRINTK (("discarding packet type = %X\n", type));
 369            kfree_skb ((struct sk_buff *)skb, FREE_READ);
 370          }
 371      }
 372   in_bh = 0;
 373   sti();
 374 }
 375 
 376 /* This routine is called when an device interface is ready to
 377    transmit a packet.  Buffer points to where the packet should
 378    be put, and the routine returns the length of the packet.  A
 379    length of zero is interrpreted to mean the transmit buffers
 380    are empty, and the transmitter should be shut down. */
 381 
 382 unsigned long
 383 dev_tint(unsigned char *buff,  struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 384 {
 385   int i;
 386   int tmp;
 387   struct sk_buff *skb;
 388   for (i=0; i < DEV_NUMBUFFS; i++)
 389     {
 390       while (dev->buffs[i]!=NULL)
 391         {
 392           cli();
 393           skb=dev->buffs[i];
 394           if (skb->magic != DEV_QUEUE_MAGIC)
 395             {
 396               printk ("dev.c skb with bad magic-%X: squashing queue\n",
 397                       skb->magic);
 398               cli();
 399               dev->buffs[i] = NULL;
 400               sti();
 401               continue;
 402             }
 403 
 404           skb->magic = 0;
 405 
 406           if (skb->next == skb)
 407             {
 408               dev->buffs[i] = NULL;
 409             }
 410           else
 411             {
 412               /* extra consistancy check. */
 413               if (skb->next == NULL
 414 #ifdef CONFIG_MAX_16M
 415                   || (unsigned long)(skb->next) > 16*1024*1024
 416 #endif
 417                   )
 418 
 419                 {
 420                   printk ("dev.c: *** bug bad skb->next, squashing queue \n");
 421                   cli();
 422                   dev->buffs[i] = NULL;
 423                 }
 424               else
 425                 {
 426                   dev->buffs[i]= skb->next;
 427                   skb->prev->next = skb->next;
 428                   skb->next->prev = skb->prev;
 429                 }
 430             }
 431           skb->next = NULL;
 432           skb->prev = NULL;
 433 
 434           if (!skb->arp)
 435             {
 436                if (dev->rebuild_header (skb+1, dev))
 437                  {
 438                    skb->dev = dev;
 439                    sti();
 440                    arp_queue (skb);
 441                    continue;
 442                  }
 443             }
 444              
 445           tmp = skb->len;
 446           if (tmp <= dev->mtu)
 447             {
 448                if (dev->send_packet != NULL)
 449                  {
 450                     dev->send_packet(skb, dev);
 451                  }
 452                if (buff != NULL)
 453                  memcpy (buff, skb + 1, tmp);
 454 
 455                PRINTK ((">>\n"));
 456                print_eth ((struct enet_header *)(skb+1));
 457             }
 458           else
 459             {
 460                printk ("dev.c:**** bug len bigger than mtu, "
 461                        "squashing queue. \n");
 462                cli();
 463                dev->buffs[i] = NULL;
 464                continue;
 465 
 466             }
 467           sti();
 468           if (skb->free)
 469             {
 470                   kfree_skb(skb, FREE_WRITE);
 471             }
 472 
 473           if (tmp != 0)
 474             return (tmp);
 475         }
 476     }
 477   PRINTK (("dev_tint returning 0 \n"));
 478   return (0);
 479 }

/* [previous][next][first][last][top][bottom][index][help] */