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

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