root/net/inet/slip.c

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

DEFINITIONS

This source file includes following definitions.
  1. ip_dump
  2. sl_initialize
  3. sl_find
  4. sl_alloc
  5. sl_free
  6. sl_enqueue
  7. sl_dequeue
  8. sl_lock
  9. sl_unlock
  10. sl_bump
  11. sl_next
  12. sl_encaps
  13. sl_xmit
  14. sl_type_trans
  15. sl_header
  16. sl_add_arp
  17. sl_rebuild_header
  18. sl_open
  19. sl_close
  20. slip_recv
  21. slip_open
  22. slip_close
  23. slip_ioctl
  24. slip_init

   1 /*
   2  * slip.c       This module implements the SLIP protocol for kernel-based
   3  *              devices like TTY.  It interfaces between a raw TTY, and the
   4  *              kernel's INET protocol layers (via DDI).
   5  *
   6  * Version:     @(#)slip.c      0.7.6   05/25/93
   7  *
   8  * Authors:     Laurence Culhane, <loz@holmes.demon.co.uk>
   9  *              Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  10  */
  11 #include <asm/segment.h>
  12 #include <asm/system.h>
  13 #include <linux/types.h>
  14 #include <linux/kernel.h>
  15 #include <linux/sched.h>
  16 #include <linux/string.h>
  17 #include <linux/mm.h>
  18 #include <linux/socket.h>
  19 #include <linux/termios.h>
  20 #include <linux/sockios.h>
  21 #include <linux/interrupt.h>
  22 #include <linux/tty.h>
  23 #include <linux/errno.h>
  24 #include <linux/stat.h>
  25 #include <linux/tty.h>
  26 #include <linux/in.h>
  27 #include "inet.h"
  28 #include "dev.h"
  29 #include "eth.h"
  30 #include "timer.h"
  31 #include "ip.h"
  32 #include "route.h"
  33 #include "protocol.h"
  34 #include "tcp.h"
  35 #include "skbuff.h"
  36 #include "sock.h"
  37 #include "arp.h"
  38 #include "slip.h"
  39 
  40 
  41 #define SLIP_VERSION    "0.7.5"
  42 
  43 
  44 /* Define some IP layer stuff.  Not all systems have it. */
  45 #ifdef SL_DUMP
  46 #   define      IP_VERSION      4       /* version# of our IP software  */
  47 #   define      IPF_F_OFFSET    0x1fff  /* Offset field                 */
  48 #   define      IPF_DF          0x4000  /* Don't fragment flag          */
  49 #   define      IPF_MF          0x2000  /* More Fragments flag          */
  50 #   define      IP_OF_COPIED    0x80    /* Copied-on-fragmentation flag */
  51 #   define      IP_OF_CLASS     0x60    /* Option class                 */
  52 #   define      IP_OF_NUMBER    0x1f    /* Option number                */
  53 #endif
  54 
  55 
  56 static struct slip      sl_ctrl[SL_NRUNIT];
  57 static struct tty_ldisc sl_ldisc;
  58 static int              already = 0;
  59 
  60 
  61 /* Dump the contents of an IP datagram. */
  62 static void
  63 ip_dump(unsigned char *ptr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65 #ifdef SL_DUMP
  66   struct iphdr *ip;
  67   int dlen, doff;
  68 
  69   if (inet_debug != DBG_SLIP) return;
  70 
  71   ip = (struct iphdr *) ptr;
  72   dlen = ntohs(ip->tot_len);
  73   doff = ((ntohs(ip->frag_off) & IPF_F_OFFSET) << 3);
  74 
  75   printk("\r*****\n");
  76   printk("SLIP: %s->", in_ntoa(ip->saddr));
  77   printk("%s\n", in_ntoa(ip->daddr));
  78   printk(" len %u ihl %u ver %u ttl %u prot %u",
  79         dlen, ip->ihl, ip->version, ip->ttl, ip->protocol);
  80 
  81   if (ip->tos != 0) printk(" tos %u", ip->tos);
  82   if (doff != 0 || (ntohs(ip->frag_off) & IPF_MF))
  83         printk(" id %u offs %u", ntohs(ip->id), doff);
  84 
  85   if (ntohs(ip->frag_off) & IPF_DF) printk(" DF");
  86   if (ntohs(ip->frag_off) & IPF_MF) printk(" MF");
  87   printk("\n*****\n");
  88 #endif
  89 }
  90 
  91 
  92 /* Initialize a SLIP control block for use. */
  93 static void
  94 sl_initialize(struct slip *sl, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96   sl->inuse             = 0;
  97   sl->sending           = 0;
  98   sl->escape            = 0;
  99 
 100   sl->line              = dev->base_addr;
 101   sl->tty               = NULL;
 102   sl->dev               = dev;
 103 
 104   /* Clear all pointers. */
 105   sl->rbuff             = NULL;
 106   sl->xbuff             = NULL;
 107 
 108   sl->rhead             = NULL;
 109   sl->rend              = NULL;
 110   dev->rmem_end         = (unsigned long) NULL;
 111   dev->rmem_start       = (unsigned long) NULL;
 112   dev->mem_end          = (unsigned long) NULL;
 113   dev->mem_start        = (unsigned long) NULL;
 114 }
 115 
 116 
 117 /* Find a SLIP channel from its `tty' link. */
 118 static struct slip *
 119 sl_find(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121   struct slip *sl;
 122   int i;
 123 
 124   if (tty == NULL) return(NULL);
 125   for (i = 0; i < SL_NRUNIT; i++) {
 126         sl = &sl_ctrl[i];
 127         if (sl->tty == tty) return(sl);
 128   }
 129   return(NULL);
 130 }
 131 
 132 
 133 /* Find a free SLIP channel, and link in this `tty' line. */
 134 static inline struct slip *
 135 sl_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137   unsigned long flags;
 138   struct slip *sl;
 139   int i;
 140 
 141   for (i = 0; i < SL_NRUNIT; i++) {
 142         sl = &sl_ctrl[i];
 143         if (sl->inuse == 0) {
 144                 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 145                 sl->inuse = 1;
 146                 sl->tty = NULL;
 147                 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 148                 return(sl);
 149         }
 150   }
 151   return(NULL);
 152 }
 153 
 154 
 155 /* Free a SLIP channel. */
 156 static inline void
 157 sl_free(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159   unsigned long flags;
 160 
 161   if (sl->inuse) {
 162         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 163         sl->inuse = 0;
 164         sl->tty = NULL;
 165         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 166   }
 167 }
 168 
 169 
 170 /* Stuff one byte into a SLIP receiver buffer. */
 171 static inline void
 172 sl_enqueue(struct slip *sl, unsigned char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174   unsigned long flags;
 175 
 176   __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 177   if (sl->rhead < sl->rend) {
 178         *sl->rhead = c;
 179         sl->rhead++;
 180         sl->rcount++;
 181   } else sl->roverrun++;
 182   __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 183 }
 184 
 185 
 186 /* Release 'i' bytes from a SLIP receiver buffer. */
 187 static inline void
 188 sl_dequeue(struct slip *sl, int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190   unsigned long flags;
 191 
 192   __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 193   if (sl->rhead > sl->rbuff) {
 194         sl->rhead -= i;
 195         sl->rcount -= i;
 196   }
 197   __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 198 }
 199 
 200 
 201 /* Set the "sending" flag.  This must be atomic, hence the ASM. */
 202 static inline void
 203 sl_lock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205   unsigned long flags;
 206 
 207   __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 208   sl->sending = 1;
 209   sl->dev->tbusy = 1;
 210   __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 211 }
 212 
 213 
 214 /* Clear the "sending" flag.  This must be atomic, hence the ASM. */
 215 static inline void
 216 sl_unlock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 217 {
 218   unsigned long flags;
 219 
 220   __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 221   sl->sending = 0;
 222   sl->dev->tbusy = 0;
 223   __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 224 }
 225 
 226 
 227 /* Send one completely decapsulated IP datagram to the IP layer. */
 228 static void
 229 sl_bump(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231   int done;
 232 
 233   DPRINTF((DBG_SLIP, "<< \"%s\" recv:\r\n", sl->dev->name));
 234   ip_dump(sl->rbuff, sl->rcount);
 235 
 236   /* Bump the datagram to the upper layers... */
 237   do {
 238         DPRINTF((DBG_SLIP, "SLIP: packet is %d at 0x%X\n",
 239                                         sl->rcount, sl->rbuff));
 240         done = dev_rint(sl->rbuff, sl->rcount, 0, sl->dev);
 241         if (done == 0 || done == 1) break;
 242   } while(1);
 243   sl->rpacket++;
 244 }
 245 
 246 
 247 /* TTY finished sending a datagram, so clean up. */
 248 static void
 249 sl_next(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 250 {
 251   DPRINTF((DBG_SLIP, "SLIP: sl_next(0x%X) called!\n", sl));
 252   sl_unlock(sl);
 253 }
 254 
 255 
 256 /* Encapsulate one IP datagram and stuff into a TTY queue. */
 257 static void
 258 sl_encaps(struct slip *sl, unsigned char *p, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260   unsigned char *bp;
 261   unsigned char c;
 262   int count;
 263 
 264   DPRINTF((DBG_SLIP, "SLIP: sl_encaps(0x%X, %d) called\n", p, len));
 265   DPRINTF((DBG_SLIP, ">> \"%s\" sent:\r\n", sl->dev->name));
 266   ip_dump(p, len);
 267 
 268   /*
 269    * Send an initial END character to flush out any
 270    * data that may have accumulated in the receiver
 271    * due to line noise.
 272    */
 273   bp = (unsigned char *) sl->xbuff;
 274   *bp++ = END;
 275   count = 1;
 276 
 277   /*
 278    * For each byte in the packet, send the appropriate
 279    * character sequence, according to the SLIP protocol.
 280    */
 281   while(len-- > 0) {
 282         c = *p++;
 283         switch((c & 0377)) {
 284                 case END:
 285                         *bp++ = ESC;
 286                         *bp++ = ESC_END;
 287                         count += 2;
 288                         break;
 289                 case ESC:
 290                         *bp++ = ESC;
 291                         *bp++ = ESC_ESC;
 292                         count += 2;
 293                         break;
 294                 default:
 295                         *bp++ = c;
 296                         count++;
 297         }
 298   }
 299   *bp++ = END;
 300   count++;
 301   sl->spacket++;
 302   bp = (unsigned char *) sl->xbuff;
 303 
 304   /* Tell TTY to send it on its way. */
 305   DPRINTF((DBG_SLIP, "SLIP: kicking TTY for %d bytes at 0x%X\n", count, bp));
 306   if (tty_write_data(sl->tty, (char *) bp, count,
 307              (void (*)(void *))sl_next, (void *) sl) == 0) {
 308         DPRINTF((DBG_SLIP, "SLIP: TTY already done with %d bytes!\n", count));
 309         sl_next(sl);
 310   }
 311 }
 312 
 313 
 314 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 315 static int
 316 sl_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318   struct tty_struct *tty;
 319   struct slip *sl;
 320 
 321   /* Find the correct SLIP channel to use. */
 322   sl = &sl_ctrl[dev->base_addr];
 323   tty = sl->tty;
 324   DPRINTF((DBG_SLIP, "SLIP: sl_xmit(\"%s\") skb=0x%X busy=%d\n",
 325                                 dev->name, skb, sl->sending));
 326 
 327   /*
 328    * If we are busy already- too bad.  We ought to be able
 329    * to queue things at this point, to allow for a little
 330    * frame buffer.  Oh well...
 331    */
 332   if (sl->sending) {
 333         DPRINTF((DBG_SLIP, "SLIP: sl_xmit: BUSY\r\n"));
 334         sl->sbusy++;
 335         return(1);
 336   }
 337 
 338   /* We were not, so we are now... :-) */
 339   if (skb != NULL) {
 340         sl_lock(sl);
 341         sl_encaps(sl, (unsigned char *) (skb + 1), skb->len);
 342         if (skb->free) kfree_skb(skb, FREE_WRITE);
 343   }
 344   return(0);
 345 }
 346 
 347 
 348 /* Return the frame type ID.  This is always IP. */
 349 static unsigned short
 350 sl_type_trans (struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352   return(NET16(ETH_P_IP));
 353 }
 354 
 355 
 356 /* Fill in the MAC-level header. Not used by SLIP. */
 357 static int
 358 sl_header(unsigned char *buff, struct device *dev, unsigned short type,
     /* [previous][next][first][last][top][bottom][index][help] */
 359           unsigned long daddr, unsigned long saddr, unsigned len)
 360 {
 361   return(0);
 362 }
 363 
 364 
 365 /* Add an ARP-entry for this device's broadcast address. Not used. */
 366 static void
 367 sl_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369 }
 370 
 371 
 372 /* Rebuild the MAC-level header.  Not used by SLIP. */
 373 static int
 374 sl_rebuild_header(void *buff, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 375 {
 376   return(0);
 377 }
 378 
 379 
 380 /* Open the low-level part of the SLIP channel. Easy! */
 381 static int
 382 sl_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 383 {
 384   struct slip *sl;
 385   unsigned char *p;
 386   unsigned long l;
 387 
 388   sl = &sl_ctrl[dev->base_addr];
 389   if (sl->tty == NULL) {
 390         DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));
 391         return(-ENXIO);
 392   }
 393   sl->dev = dev;
 394 
 395   /*
 396    * Allocate the SLIP frame buffers:
 397    *
 398    * mem_end    Top of frame buffers
 399    * mem_start  Start of frame buffers
 400    * rmem_end   Top of RECV frame buffer
 401    * rmem_start Start of RECV frame buffer
 402    */
 403   l = (dev->mtu * 2);
 404   p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 405   if (p == NULL) {
 406         DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP XMIT buffer!\n"));
 407         return(-ENOMEM);
 408   }
 409   sl->dev->mem_start    = (unsigned long) p;
 410   sl->dev->mem_end      = (unsigned long) (sl->dev->mem_start + l);
 411 
 412   p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 413   if (p == NULL) {
 414         DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP RECV buffer!\n"));
 415         return(-ENOMEM);
 416   }
 417   sl->dev->rmem_start   = (unsigned long) p;
 418   sl->dev->rmem_end     = (unsigned long) (sl->dev->rmem_start + l);
 419 
 420   sl->xbuff             = (unsigned char *) sl->dev->mem_start;
 421   sl->rbuff             = (unsigned char *) sl->dev->rmem_start;
 422   sl->rend              = (unsigned char *) sl->dev->rmem_end;
 423   sl->rhead             = sl->rbuff;
 424 
 425   sl->escape            = 0;
 426   sl->sending           = 0;
 427   sl->rcount            = 0;
 428 
 429   DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line));
 430   return(0);
 431 }
 432 
 433 
 434 /* Close the low-level part of the SLIP channel. Easy! */
 435 static int
 436 sl_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 437 {
 438   struct slip *sl;
 439 
 440   sl = &sl_ctrl[dev->base_addr];
 441   if (sl->tty == NULL) {
 442         DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));
 443         return(-EBUSY);
 444   }
 445   sl_free(sl);
 446 
 447   /* Free all SLIP frame buffers. */
 448   kfree(sl->rbuff);
 449   kfree(sl->xbuff);
 450   sl_initialize(sl, dev);
 451 
 452   DPRINTF((DBG_SLIP, "SLIP: channel %d closed.\n", sl->line));
 453   return(0);
 454 }
 455 
 456 
 457 /*
 458  * Handle the 'receiver data ready' interrupt.
 459  * This function is called by the 'tty_io' module in the kernel when
 460  * a block of SLIP data has been received, which can now be decapsulated
 461  * and sent on to some IP layer for further processing.
 462  */
 463 static void
 464 slip_recv(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 465 {
 466   unsigned char buff[128];
 467   unsigned char *p, c;
 468   struct slip *sl;
 469   int count;
 470 
 471   DPRINTF((DBG_SLIP, "SLIP: slip_recv(%d) called\n", tty->line));
 472   if ((sl = sl_find(tty)) == NULL) return;      /* not connected */
 473 
 474   /* Suck the bytes out of the TTY queues. */
 475   do {
 476         memset(buff, 0, 128);
 477         count = tty_read_raw_data(tty, buff, 128);
 478         if (count <= 0) break;
 479 
 480         p = buff;
 481         while(count-- > 0) {
 482                 c = *p++;
 483                 switch((c & 0377)) {
 484                         case ESC:
 485                                 sl->escape = 1;
 486                                 break;
 487                         case ESC_ESC:
 488                                 if (sl->escape) sl_enqueue(sl, ESC);
 489                                   else sl_enqueue(sl, c);
 490                                 sl->escape = 0;
 491                                 break;
 492                         case ESC_END:
 493                                 if (sl->escape) sl_enqueue(sl, END);
 494                                   else sl_enqueue(sl, c);
 495                                 sl->escape = 0;
 496                                 break;
 497                         case END:
 498                                 if (sl->rcount > 3) sl_bump(sl);
 499                                 sl_dequeue(sl, sl->rcount);
 500                                 sl->rcount = 0;
 501                                 sl->escape = 0;
 502                                 break;
 503                         default:
 504                                 sl_enqueue(sl, c);
 505                                 sl->escape = 0;
 506                 }
 507         }
 508   } while(1);
 509 }
 510 
 511 
 512 /*
 513  * Open the high-level part of the SLIP channel.  
 514  * This function is called by the TTY module when the
 515  * SLIP line discipline is called for.  Because we are
 516  * sure the tty line exists, we only have to link it to
 517  * a free SLIP channel...
 518  */
 519 static int
 520 slip_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 521 {
 522   struct slip *sl;
 523 
 524   /* First make sure we're not already connected. */
 525   if ((sl = sl_find(tty)) != NULL) {
 526         DPRINTF((DBG_SLIP, "SLIP: TTY %d already connected to %s !\n",
 527                                         tty->line, sl->dev->name));
 528         return(-EEXIST);
 529   }
 530 
 531   /* OK.  Find a free SLIP channel to use. */
 532   if ((sl = sl_alloc()) == NULL) {
 533         DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected: all channels in use!\n",
 534                                                 tty->line));
 535         return(-ENFILE);
 536   }
 537   sl->tty = tty;
 538   tty_read_flush(tty);
 539   tty_write_flush(tty);
 540 
 541   /* Perform the low-level SLIP initialization. */
 542   (void) sl_open(sl->dev);
 543   DPRINTF((DBG_SLIP, "SLIP: TTY %d connected to %s.\n",
 544                                 tty->line, sl->dev->name));
 545 
 546   /* Done.  We have linked the TTY line to a channel. */
 547   return(sl->line);
 548 }
 549 
 550 
 551 /*
 552  * Close down a SLIP channel.
 553  * This means flushing out any pending queues, and then restoring the
 554  * TTY line discipline to what it was before it got hooked to SLIP
 555  * (which usually is TTY again).
 556  */
 557 static void
 558 slip_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 559 {
 560   struct slip *sl;
 561 
 562   /* First make sure we're connected. */
 563   if ((sl = sl_find(tty)) == NULL) {
 564         DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected !\n", tty->line));
 565         return;
 566   }
 567 
 568   (void) dev_close(sl->dev);
 569   DPRINTF((DBG_SLIP, "SLIP: TTY %d disconnected from %s.\n",
 570                                         tty->line, sl->dev->name));
 571 }
 572 
 573 
 574 /* Perform I/O control on an active SLIP channel. */
 575 static int
 576 slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 577 {
 578   struct slip *sl;
 579 
 580   /* First make sure we're connected. */
 581   if ((sl = sl_find(tty)) == NULL) {
 582         DPRINTF((DBG_SLIP, "SLIP: ioctl: TTY %d not connected !\n", tty->line));
 583         return(-EINVAL);
 584   }
 585 
 586   DPRINTF((DBG_SLIP, "SLIP: ioctl(%d, 0x%X, 0x%X)\n", tty->line, cmd, arg));
 587   switch(cmd) {
 588         case SIOCGIFNAME:
 589                 verify_area(VERIFY_WRITE, arg, 16);
 590                 memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);
 591                 return(0);
 592         default:
 593                 return(-EINVAL);
 594   }
 595   return(-EINVAL);
 596 }
 597 
 598 
 599 /* Initialize the SLIP driver.  Called by DDI. */
 600 int
 601 slip_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 602 {
 603   struct slip *sl;
 604   int i;
 605 
 606   sl = &sl_ctrl[dev->base_addr];
 607 
 608   if (already++ == 0) {
 609         printk("SLIP: version %s (%d channels): ",
 610                                 SLIP_VERSION, SL_NRUNIT);
 611 
 612         /* Fill in our LDISC request block. */
 613         sl_ldisc.flags  = 0;
 614         sl_ldisc.open   = slip_open;
 615         sl_ldisc.close  = slip_close;
 616         sl_ldisc.read   = NULL;
 617         sl_ldisc.write  = NULL;
 618         sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
 619                                    unsigned int, unsigned long)) slip_ioctl;
 620         sl_ldisc.handler = slip_recv;
 621         if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) == 0) printk("OK\n");
 622           else printk("ERROR: %d\n", i);
 623   }
 624 
 625   /* Set up the "SLIP Control Block". */
 626   sl_initialize(sl, dev);
 627 
 628   /* Clear all statistics. */
 629   sl->rcount            = 0;                    /* SLIP receiver count  */
 630   sl->rpacket           = 0;                    /* #frames received     */
 631   sl->roverrun          = 0;                    /* "overrun" counter    */
 632   sl->spacket           = 0;                    /* #frames sent out     */
 633   sl->sbusy             = 0;                    /* "xmit busy" counter  */
 634   sl->errors            = 0;                    /* not used at present  */
 635 
 636   /* Finish setting up the DEVICE info. */
 637   dev->mtu              = SL_MTU;
 638   dev->hard_start_xmit  = sl_xmit;
 639   dev->open             = sl_open;
 640   dev->stop             = sl_close;
 641   dev->hard_header      = sl_header;
 642   dev->add_arp          = sl_add_arp;
 643   dev->type_trans       = sl_type_trans;
 644   dev->hard_header_len  = 0;
 645   dev->addr_len         = 0;
 646   dev->type             = 0;
 647   dev->queue_xmit       = dev_queue_xmit;
 648   dev->rebuild_header   = sl_rebuild_header;
 649   for (i = 0; i < DEV_NUMBUFFS; i++)
 650                 dev->buffs[i] = NULL;
 651 
 652   /* New-style flags. */
 653   dev->flags            = 0;
 654   dev->family           = AF_INET;
 655   dev->pa_addr          = 0;
 656   dev->pa_brdaddr       = 0;
 657   dev->pa_mask          = 0;
 658   dev->pa_alen          = sizeof(unsigned long);
 659 
 660   return(0);
 661 }

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