root/drivers/net/slip.c

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

DEFINITIONS

This source file includes following definitions.
  1. sl_alloc
  2. sl_free
  3. sl_changedmtu
  4. sl_lock
  5. sl_unlock
  6. sl_bump
  7. sl_encaps
  8. slip_write_wakeup
  9. sl_xmit
  10. sl_header
  11. sl_rebuild_header
  12. sl_open
  13. sl_close
  14. slip_receive_room
  15. slip_receive_buf
  16. slip_open
  17. slip_close
  18. sl_get_stats
  19. slip_esc
  20. slip_unesc
  21. slip_esc6
  22. slip_unesc6
  23. sl_set_mac_address
  24. sl_set_dev_mac_address
  25. slip_ioctl
  26. sl_open_dev
  27. slip_init
  28. init_module
  29. cleanup_module

   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.8.3   12/24/94
   7  *
   8  * Authors:     Laurence Culhane, <loz@holmes.demon.co.uk>
   9  *              Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  10  *
  11  * Fixes:
  12  *              Alan Cox        :       Sanity checks and avoid tx overruns.
  13  *                                      Has a new sl->mtu field.
  14  *              Alan Cox        :       Found cause of overrun. ifconfig sl0 mtu upwards.
  15  *                                      Driver now spots this and grows/shrinks its buffers(hack!).
  16  *                                      Memory leak if you run out of memory setting up a slip driver fixed.
  17  *              Matt Dillon     :       Printable slip (borrowed from NET2E)
  18  *      Pauline Middelink       :       Slip driver fixes.
  19  *              Alan Cox        :       Honours the old SL_COMPRESSED flag
  20  *              Alan Cox        :       KISS AX.25 and AXUI IP support
  21  *              Michael Riepe   :       Automatic CSLIP recognition added
  22  *              Charles Hedrick :       CSLIP header length problem fix.
  23  *              Alan Cox        :       Corrected non-IP cases of the above.
  24  *              Alan Cox        :       Now uses hardware type as per FvK.
  25  *              Alan Cox        :       Default to 192.168.0.0 (RFC 1597)
  26  *              A.N.Kuznetsov   :       dev_tint() recursion fix.
  27  *      Dmitry Gorodchanin      :       SLIP memory leaks
  28  *      Dmitry Gorodchanin      :       Code cleanup. Reduce tty driver
  29  *                                      buffering from 4096 to 256 bytes.
  30  *                                      Improving SLIP response time.
  31  *                                      CONFIG_SLIP_MODE_SLIP6.
  32  *                                      ifconfig sl? up & down now works correctly.
  33  *                                      Modularization.
  34  *              Alan Cox        :       Oops - fix AX.25 buffer lengths
  35  *      Dmitry Gorodchanin      :       Even more cleanups. Preserve CSLIP
  36  *                                      statistics. Include CSLIP code only
  37  *                                      if it really needed.
  38  *              Alan Cox        :       Free slhc buffers in the right place.
  39  *
  40  *
  41  *
  42  *      FIXME:  This driver still makes some IP'ish assumptions. It should build cleanly KISS TNC only without
  43  *      CONFIG_INET defined.
  44  *      I hope now it is fixed ;)
  45  */
  46 
  47 #define SL_CHECK_TRANSMIT
  48 #include <linux/config.h>
  49 #ifdef MODULE
  50 #include <linux/module.h>
  51 #include <linux/version.h>
  52 #endif
  53 
  54 /* Undef this, if you don't need 6bit encapsulation code in the driver */
  55 #define CONFIG_SLIP_MODE_SLIP6
  56 
  57 #include <asm/system.h>
  58 #include <asm/segment.h>
  59 #include <asm/bitops.h>
  60 #include <linux/string.h>
  61 #include <linux/mm.h>
  62 #include <linux/interrupt.h>
  63 #include <linux/in.h>
  64 #include <linux/tty.h>
  65 #include <linux/errno.h>
  66 #include <linux/netdevice.h>
  67 #ifdef CONFIG_AX25
  68 #include <linux/timer.h>
  69 #include <net/ax25.h>
  70 #endif
  71 #include <linux/etherdevice.h>
  72 #include <linux/skbuff.h>
  73 #include <linux/if_arp.h>
  74 #include "slip.h"
  75 #ifdef CONFIG_INET
  76 #include <linux/ip.h>
  77 #include <linux/tcp.h>
  78 #include "slhc.h"
  79 #endif
  80 
  81 #ifdef MODULE
  82 #define SLIP_VERSION    "0.8.3-NET3.019-NEWTTY-MODULAR"
  83 #else
  84 #define SLIP_VERSION    "0.8.3-NET3.019-NEWTTY"
  85 #endif
  86 
  87 
  88 static struct slip      sl_ctrl[SL_NRUNIT];
  89 static struct tty_ldisc sl_ldisc;
  90 static int              already = 0;
  91 
  92 static int slip_esc(unsigned char *p, unsigned char *d, int len);
  93 static void slip_unesc(struct slip *sl, unsigned char c);
  94 #ifdef CONFIG_SLIP_MODE_SLIP6
  95 static int slip_esc6(unsigned char *p, unsigned char *d, int len);
  96 static void slip_unesc6(struct slip *sl, unsigned char c);
  97 #endif
  98 
  99 
 100 /* Find a free SLIP channel, and link in this `tty' line. */
 101 static inline struct slip *
 102 sl_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104         struct slip *sl;
 105         int i;
 106 
 107         for (i = 0; i < SL_NRUNIT; i++) {
 108                 sl = &sl_ctrl[i];
 109                 if (!set_bit(SLF_INUSE, &sl->flags)) {
 110                         return sl;
 111                 }
 112         }
 113         return NULL;
 114 }
 115 
 116 
 117 /* Free a SLIP channel. */
 118 static inline void
 119 sl_free(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121         /* Free all SLIP frame buffers. */
 122         if (sl->rbuff)  {
 123                 kfree(sl->rbuff);
 124         }
 125         sl->rbuff = NULL;
 126         if (sl->xbuff)  {
 127                 kfree(sl->xbuff);
 128         }
 129         sl->xbuff = NULL;
 130 #ifdef SL_INCLUDE_CSLIP
 131         /* Save CSLIP statistics */
 132         if (sl->slcomp)  {
 133                 sl->rx_compressed += sl->slcomp->sls_i_compressed;
 134                 sl->rx_dropped    += sl->slcomp->sls_i_tossed;
 135                 sl->tx_compressed += sl->slcomp->sls_o_compressed;
 136                 sl->tx_misses     += sl->slcomp->sls_o_misses;
 137         }
 138         if (sl->cbuff)  {
 139                 kfree(sl->cbuff);
 140         }
 141         sl->cbuff = NULL;
 142         if(sl->slcomp)
 143                 slhc_free(sl->slcomp);
 144         sl->slcomp = NULL;
 145 #endif
 146 
 147         if (!clear_bit(SLF_INUSE, &sl->flags)) {
 148                 printk("%s: sl_free for already free unit.\n", sl->dev->name);
 149         }
 150 }
 151 
 152 /* MTU has been changed by the IP layer. Unfortunately we are not told about this, but
 153    we spot it ourselves and fix things up. We could be in an upcall from the tty
 154    driver, or in an ip packet queue. */
 155 
 156 static void sl_changedmtu(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         struct device *dev = sl->dev;
 159         unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
 160 #ifdef SL_INCLUDE_CSLIP
 161         unsigned char *cbuff, *ocbuff;
 162 #endif
 163         int len;
 164         unsigned long flags;
 165 
 166         len = dev->mtu * 2;
 167 /*
 168  * allow for arrival of larger UDP packets, even if we say not to
 169  * also fixes a bug in which SunOS sends 512-byte packets even with
 170  * an MSS of 128
 171  */
 172         if (len < 576 * 2)  {
 173                 len = 576 * 2;
 174         }
 175 
 176         xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 177         rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 178 #ifdef SL_INCLUDE_CSLIP
 179         cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 180 #endif
 181 
 182 #ifdef SL_INCLUDE_CSLIP
 183         if (xbuff == NULL || rbuff == NULL || cbuff == NULL)  {
 184 #else
 185         if (xbuff == NULL || rbuff == NULL)  {
 186 #endif
 187                 printk("%s: unable to grow slip buffers, MTU change cancelled.\n",
 188                        sl->dev->name);
 189                 dev->mtu = sl->mtu;
 190                 if (xbuff != NULL)  {
 191                         kfree(xbuff);
 192                 }
 193                 if (rbuff != NULL)  {
 194                         kfree(rbuff);
 195                 }
 196 #ifdef SL_INCLUDE_CSLIP
 197                 if (cbuff != NULL)  {
 198                         kfree(cbuff);
 199                 }
 200 #endif
 201                 return;
 202         }
 203 
 204         save_flags(flags); cli();
 205 
 206         oxbuff    = sl->xbuff;
 207         sl->xbuff = xbuff;
 208         orbuff    = sl->rbuff;
 209         sl->rbuff = rbuff;
 210 #ifdef SL_INCLUDE_CSLIP
 211         ocbuff    = sl->cbuff;
 212         sl->cbuff = cbuff;
 213 #endif
 214         if (sl->xleft)  {
 215                 if (sl->xleft <= len)  {
 216                         memcpy(sl->xbuff, sl->xhead, sl->xleft);
 217                 } else  {
 218                         sl->xleft = 0;
 219                         sl->tx_dropped++;
 220                 }
 221         }
 222         sl->xhead = sl->xbuff;
 223 
 224         if (sl->rcount)  {
 225                 if (sl->rcount <= len) {
 226                         memcpy(sl->rbuff, orbuff, sl->rcount);
 227                 } else  {
 228                         sl->rcount = 0;
 229                         sl->rx_over_errors++;
 230                         set_bit(SLF_ERROR, &sl->flags);
 231                 }
 232         }
 233 #ifdef CONFIG_AX25
 234         sl->mtu      = dev->mtu + 73;
 235 #else
 236         sl->mtu      = dev->mtu;
 237 #endif
 238         sl->buffsize = len;
 239 
 240         restore_flags(flags);
 241 
 242         if (oxbuff != NULL)   {
 243                 kfree(oxbuff);
 244         }
 245         if (orbuff != NULL)    {
 246                 kfree(orbuff);
 247         }
 248 #ifdef SL_INCLUDE_CSLIP
 249         if (ocbuff != NULL)  {
 250                 kfree(ocbuff);
 251         }
 252 #endif
 253 }
 254 
 255 
 256 /* Set the "sending" flag.  This must be atomic, hence the ASM. */
 257 static inline void
 258 sl_lock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260         if (set_bit(0, (void *) &sl->dev->tbusy))  {
 261                 printk("%s: trying to lock already locked device!\n", sl->dev->name);
 262         }
 263 }
 264 
 265 
 266 /* Clear the "sending" flag.  This must be atomic, hence the ASM. */
 267 static inline void
 268 sl_unlock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 269 {
 270         if (!clear_bit(0, (void *)&sl->dev->tbusy))  {
 271                 printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
 272         }
 273 }
 274 
 275 /* Send one completely decapsulated IP datagram to the IP layer. */
 276 static void
 277 sl_bump(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279         struct sk_buff *skb;
 280         int count;
 281 
 282         count = sl->rcount;
 283 #ifdef SL_INCLUDE_CSLIP
 284         if (sl->mode & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) {
 285                 unsigned char c;
 286                 if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) {
 287                         /* ignore compressed packets when CSLIP is off */
 288                         if (!(sl->mode & SL_MODE_CSLIP)) {
 289                                 printk("%s: compressed packet ignored\n", sl->dev->name);
 290                                 return;
 291                         }
 292                         /* make sure we've reserved enough space for uncompress to use */
 293                         if (count + 80 > sl->buffsize) {
 294                                 sl->rx_over_errors++;
 295                                 return;
 296                         }
 297                         count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
 298                         if (count <= 0) {
 299                                 return;
 300                         }
 301                 } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
 302                         if (!(sl->mode & SL_MODE_CSLIP)) {
 303                                 /* turn on header compression */
 304                                 sl->mode |= SL_MODE_CSLIP;
 305                                 sl->mode &= ~SL_MODE_ADAPTIVE;
 306                                 printk("%s: header compression turned on\n", sl->dev->name);
 307                         }
 308                         sl->rbuff[0] &= 0x4f;
 309                         if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) {
 310                                 return;
 311                         }
 312                 }
 313         }
 314 #endif  /* SL_INCLUDE_CSLIP */
 315 
 316         skb = alloc_skb(count, GFP_ATOMIC);
 317         if (skb == NULL)  {
 318                 printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
 319                 sl->rx_dropped++;
 320                 return;
 321         }
 322         skb->len = count;
 323         skb->dev = sl->dev;
 324         memcpy(skb->data, sl->rbuff, count);
 325         if(sl->mode&(SL_MODE_AX25|SL_MODE_AX25VC))
 326                 skb->protocol=htons(ETH_P_AX25);
 327         else
 328                 skb->protocol=htons(ETH_P_IP);
 329         netif_rx(skb);
 330         sl->rx_packets++;
 331 }
 332 
 333 /* Encapsulate one IP datagram and stuff into a TTY queue. */
 334 static void
 335 sl_encaps(struct slip *sl, unsigned char *icp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 336 {
 337         unsigned char *p;
 338         int actual, count;
 339 
 340 
 341 #ifdef CONFIG_AX25
 342         if (sl->mtu != sl->dev->mtu + 73) {     /* Someone has been ifconfigging */
 343 #else
 344         if (sl->mtu != sl->dev->mtu) {  /* Someone has been ifconfigging */
 345 #endif
 346                 sl_changedmtu(sl);
 347         }
 348 
 349         if (len > sl->mtu) {            /* Sigh, shouldn't occur BUT ... */
 350                 len = sl->mtu;
 351                 printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
 352                 sl->tx_dropped++;
 353                 sl_unlock(sl);
 354                 return;
 355         }
 356 
 357         p = icp;
 358 #ifdef SL_INCLUDE_CSLIP
 359         if (sl->mode & SL_MODE_CSLIP)  {
 360                 len = slhc_compress(sl->slcomp, p, len, sl->cbuff, &p, 1);
 361         }
 362 #endif
 363 #ifdef CONFIG_SLIP_MODE_SLIP6
 364         if(sl->mode & SL_MODE_SLIP6)
 365                 count = slip_esc6(p, (unsigned char *) sl->xbuff, len);
 366         else
 367 #endif
 368                 count = slip_esc(p, (unsigned char *) sl->xbuff, len);
 369 
 370         /* Order of next two lines is *very* important.
 371          * When we are sending a little amount of data,
 372          * the transfer may be completed inside driver.write()
 373          * routine, because it's running with interrupts enabled.
 374          * In this case we *never* got WRITE_WAKEUP event,
 375          * if we did not request it before write operation.
 376          *       14 Oct 1994  Dmitry Gorodchanin.
 377          */
 378         sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 379         actual = sl->tty->driver.write(sl->tty, 0, sl->xbuff, count);
 380 #ifdef SL_CHECK_TRANSMIT
 381         sl->dev->trans_start = jiffies;
 382 #endif
 383         sl->xleft = count - actual;
 384         sl->xhead = sl->xbuff + actual;
 385 }
 386 
 387 /*
 388  * Called by the driver when there's room for more data.  If we have
 389  * more packets to send, we send them here.
 390  */
 391 static void slip_write_wakeup(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 392 {
 393         int actual;
 394         struct slip *sl = (struct slip *) tty->disc_data;
 395 
 396         /* First make sure we're connected. */
 397         if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start) {
 398                 return;
 399         }
 400 
 401         if (sl->xleft <= 0)  {
 402                 /* Now serial buffer is almost free & we can start
 403                  * transmission of another packet */
 404                 sl->tx_packets++;
 405                 tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 406                 sl_unlock(sl);
 407                 mark_bh(NET_BH);
 408                 return;
 409         }
 410 
 411         actual = tty->driver.write(tty, 0, sl->xhead, sl->xleft);
 412         sl->xleft -= actual;
 413         sl->xhead += actual;
 414 }
 415 
 416 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 417 static int
 418 sl_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 419 {
 420         struct slip *sl = &sl_ctrl[dev->base_addr];
 421 
 422         if (!dev->start)  {
 423                 printk("%s: xmit call when iface is down\n", dev->name);
 424                 return 1;
 425         }
 426         /*
 427          * If we are busy already- too bad.  We ought to be able
 428          * to queue things at this point, to allow for a little
 429          * frame buffer.  Oh well...
 430          * -----------------------------------------------------
 431          * I hate queues in SLIP driver. May be it's efficient,
 432          * but for me latency is more important. ;)
 433          * So, no queues !
 434          *        14 Oct 1994  Dmitry Gorodchanin.
 435          */
 436         if (dev->tbusy) {
 437                 /* May be we must check transmitter timeout here ?
 438                  *      14 Oct 1994 Dmitry Gorodchanin.
 439                  */
 440 #ifdef SL_CHECK_TRANSMIT
 441                 if (jiffies - dev->trans_start  < 20 * HZ)  {
 442                         /* 20 sec timeout not reached */
 443                         return 1;
 444                 }
 445                 printk("%s: transmit timed out, %s?\n", dev->name,
 446                        (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
 447                        "bad line quality" : "driver error");
 448                 sl->xleft = 0;
 449                 sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 450                 sl_unlock(sl);
 451 #else
 452                 return 1;
 453 #endif
 454         }
 455 
 456 #ifdef CONFIG_AX25
 457 #ifdef CONFIG_INET
 458         /*
 459          * This code is not very intelligent. Fix me.
 460          */
 461         if (skb->data[15] == LAPB_UI && skb->data[16] == AX25_P_IP) {
 462                 struct sk_buff *skbn;
 463                 char mode;
 464                 
 465                 mode = ax25_ip_mode_get((ax25_address *)(skb->data + 1), dev);
 466 
 467                 if (mode == 'V' || mode == 'v' || (mode == ' ' && sl->mode & SL_MODE_AX25VC)) {
 468                         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 469                                 sl->tx_errors++;
 470                                 return 1;
 471                         }
 472 
 473                         ax25_send_frame(skbn, (ax25_address *)dev->dev_addr, (ax25_address *)(skbn->data + 1), dev);
 474                         dev_kfree_skb(skb, FREE_WRITE);
 475                         mark_bh(NET_BH);
 476                         return 0;
 477                 }
 478         }
 479 #endif
 480 #endif
 481 
 482         /* We were not busy, so we are now... :-) */
 483         if (skb != NULL) {
 484                 sl_lock(sl);
 485                 sl_encaps(sl, skb->data, skb->len);
 486                 dev_kfree_skb(skb, FREE_WRITE);
 487         }
 488         return 0;
 489 }
 490 
 491 
 492 /* Return the frame type ID.  This is normally IP but maybe be AX.25. */
 493 
 494 /* Fill in the MAC-level header. Not used by SLIP. */
 495 static int
 496 sl_header(unsigned char *buff, struct device *dev, unsigned short type,
     /* [previous][next][first][last][top][bottom][index][help] */
 497           void *daddr, void *saddr, unsigned len, struct sk_buff *skb)
 498 {
 499 #ifdef CONFIG_AX25
 500 #ifdef CONFIG_INET
 501         struct slip *sl = &sl_ctrl[dev->base_addr];
 502 
 503         if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25))  {
 504                 return ax25_encapsulate(buff, dev, type, daddr, saddr, len, skb);
 505         }
 506 #endif
 507 #endif
 508         return 0;
 509 }
 510 
 511 
 512 /* Rebuild the MAC-level header.  Not used by SLIP. */
 513 static int
 514 sl_rebuild_header(void *buff, struct device *dev, unsigned long raddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 515                   struct sk_buff *skb)
 516 {
 517 #ifdef CONFIG_AX25
 518 #ifdef CONFIG_INET
 519         struct slip *sl = &sl_ctrl[dev->base_addr];
 520 
 521         if ((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) {
 522                 return ax25_rebuild_header(buff, dev, raddr, skb);
 523         }
 524 #endif
 525 #endif
 526         return 0;
 527 }
 528 
 529 
 530 /* Open the low-level part of the SLIP channel. Easy! */
 531 static int
 532 sl_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 533 {
 534         struct slip *sl = &sl_ctrl[dev->base_addr];
 535         unsigned long len;
 536 
 537         if (sl->tty == NULL) {
 538                 return -ENODEV;
 539         }
 540 
 541         /*
 542          * Allocate the SLIP frame buffers:
 543          *
 544          * rbuff        Receive buffer.
 545          * xbuff        Transmit buffer.
 546          * cbuff        Temporary compression buffer.
 547          */
 548         len = dev->mtu * 2;
 549         /*
 550          * allow for arrival of larger UDP packets, even if we say not to
 551          * also fixes a bug in which SunOS sends 512-byte packets even with
 552          * an MSS of 128
 553          */
 554         if (len < 576 * 2)  {
 555                 len = 576 * 2;
 556         }
 557         sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
 558         if (sl->rbuff == NULL)   {
 559                 goto norbuff;
 560         }
 561         sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
 562         if (sl->xbuff == NULL)   {
 563                 goto noxbuff;
 564         }
 565 #ifdef SL_INCLUDE_CSLIP
 566         sl->cbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
 567         if (sl->cbuff == NULL)   {
 568                 goto nocbuff;
 569         }
 570         sl->slcomp = slhc_init(16, 16);
 571         if (sl->slcomp == NULL)  {
 572                 goto noslcomp;
 573         }
 574 #endif
 575 
 576 #ifdef CONFIG_AX25
 577         sl->mtu      = dev->mtu + 73;
 578 #else
 579         sl->mtu      = dev->mtu;
 580 #endif
 581         sl->buffsize = len;
 582         sl->rcount   = 0;
 583         sl->xleft    = 0;
 584 #ifdef CONFIG_SLIP_MODE_SLIP6
 585         sl->xdata    = 0;
 586         sl->xbits    = 0;
 587 #endif
 588         sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */
 589 
 590         /* Needed because address '0' is special */
 591         if (dev->pa_addr == 0)  {
 592                 dev->pa_addr=ntohl(0xC0A80001);
 593         }
 594         dev->tbusy  = 0;
 595 /*      dev->flags |= IFF_UP; */
 596         dev->start  = 1;
 597 
 598         return 0;
 599 
 600         /* Cleanup */
 601 #ifdef SL_INCLUDE_CSLIP
 602 noslcomp:
 603         kfree(sl->cbuff);
 604 nocbuff:
 605 #endif
 606         kfree(sl->xbuff);
 607 noxbuff:
 608         kfree(sl->rbuff);
 609 norbuff:
 610         return -ENOMEM;
 611 }
 612 
 613 
 614 /* Close the low-level part of the SLIP channel. Easy! */
 615 static int
 616 sl_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 617 {
 618         struct slip *sl = &sl_ctrl[dev->base_addr];
 619 
 620         if (sl->tty == NULL) {
 621                 return -EBUSY;
 622         }
 623         sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 624         dev->tbusy = 1;
 625         dev->start = 0;
 626         
 627 /*      dev->flags &= ~IFF_UP; */
 628 
 629         return 0;
 630 }
 631 
 632 static int
 633 slip_receive_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 634 {
 635         return 65536;  /* We can handle an infinite amount of data. :-) */
 636 }
 637 
 638 /*
 639  * Handle the 'receiver data ready' interrupt.
 640  * This function is called by the 'tty_io' module in the kernel when
 641  * a block of SLIP data has been received, which can now be decapsulated
 642  * and sent on to some IP layer for further processing.
 643  */
 644 static void
 645 slip_receive_buf(struct tty_struct *tty, unsigned char *cp, char *fp, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 646 {
 647         struct slip *sl = (struct slip *) tty->disc_data;
 648 
 649         if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start)
 650                 return;
 651 
 652         /*
 653          * Argh! mtu change time! - costs us the packet part received
 654          * at the change
 655          */
 656 #ifdef CONFIG_AX25
 657         if (sl->mtu != sl->dev->mtu + 73)  {
 658 #else
 659         if (sl->mtu != sl->dev->mtu)  {
 660 #endif
 661                 sl_changedmtu(sl);
 662         }
 663 
 664         /* Read the characters out of the buffer */
 665         while (count--) {
 666                 if (fp && *fp++) {
 667                         if (!set_bit(SLF_ERROR, &sl->flags))  {
 668                                 sl->rx_errors++;
 669                         }
 670                         cp++;
 671                         continue;
 672                 }
 673 #ifdef CONFIG_SLIP_MODE_SLIP6
 674                 if (sl->mode & SL_MODE_SLIP6)
 675                         slip_unesc6(sl, *cp++);
 676                 else
 677 #endif
 678                         slip_unesc(sl, *cp++);
 679         }
 680 }
 681 
 682 /*
 683  * Open the high-level part of the SLIP channel.
 684  * This function is called by the TTY module when the
 685  * SLIP line discipline is called for.  Because we are
 686  * sure the tty line exists, we only have to link it to
 687  * a free SLIP channel...
 688  */
 689 static int
 690 slip_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 691 {
 692         struct slip *sl = (struct slip *) tty->disc_data;
 693         int err;
 694 
 695         /* First make sure we're not already connected. */
 696         if (sl && sl->magic == SLIP_MAGIC) {
 697                 return -EEXIST;
 698         }
 699 
 700         /* OK.  Find a free SLIP channel to use. */
 701         if ((sl = sl_alloc()) == NULL) {
 702                 return -ENFILE;
 703         }
 704 
 705         sl->tty = tty;
 706         tty->disc_data = sl;
 707         if (tty->driver.flush_buffer)  {
 708                 tty->driver.flush_buffer(tty);
 709         }
 710         if (tty->ldisc.flush_buffer)  {
 711                 tty->ldisc.flush_buffer(tty);
 712         }
 713 
 714         /* Restore default settings */
 715         sl->mode      = SL_MODE_DEFAULT;
 716         sl->dev->type = ARPHRD_SLIP + sl->mode;
 717 #ifdef CONFIG_AX25      
 718         if (sl->dev->type == 260 || sl->dev->type == 272) {     /* KISS */
 719                 sl->dev->type = ARPHRD_AX25;
 720         }
 721 #endif  
 722         /* Perform the low-level SLIP initialization. */
 723         if ((err = sl_open(sl->dev)))  {
 724                 return err;
 725         }
 726         
 727 #ifdef MODULE
 728         MOD_INC_USE_COUNT;
 729 #endif
 730 
 731         /* Done.  We have linked the TTY line to a channel. */
 732         return sl->dev->base_addr;
 733 }
 734 
 735 
 736 /*
 737  * Close down a SLIP channel.
 738  * This means flushing out any pending queues, and then restoring the
 739  * TTY line discipline to what it was before it got hooked to SLIP
 740  * (which usually is TTY again).
 741  */
 742 static void
 743 slip_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 744 {
 745         struct slip *sl = (struct slip *) tty->disc_data;
 746 
 747         /* First make sure we're connected. */
 748         if (!sl || sl->magic != SLIP_MAGIC) {
 749                 return;
 750         }
 751 
 752         (void) dev_close(sl->dev);
 753         
 754         tty->disc_data = 0;
 755         sl->tty = NULL;
 756         sl_free(sl);
 757 #ifdef MODULE
 758         MOD_DEC_USE_COUNT;
 759 #endif
 760 }
 761 
 762 
 763 static struct enet_statistics *
 764 sl_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 765 {
 766         static struct enet_statistics stats;
 767         struct slip *sl = &sl_ctrl[dev->base_addr];
 768 #ifdef SL_INCLUDE_CSLIP
 769         struct slcompress *comp;
 770 #endif
 771 
 772         memset(&stats, 0, sizeof(struct enet_statistics));
 773 
 774         stats.rx_packets     = sl->rx_packets;
 775         stats.tx_packets     = sl->tx_packets;
 776         stats.rx_dropped     = sl->rx_dropped;
 777         stats.tx_dropped     = sl->tx_dropped;
 778         stats.tx_errors      = sl->tx_errors;
 779         stats.rx_errors      = sl->rx_errors;
 780         stats.rx_over_errors = sl->rx_over_errors;
 781 #ifdef SL_INCLUDE_CSLIP
 782         stats.rx_fifo_errors = sl->rx_compressed;
 783         stats.tx_fifo_errors = sl->tx_compressed;
 784         stats.collisions     = sl->tx_misses;
 785         comp = sl->slcomp;
 786         if (comp) {
 787                 stats.rx_fifo_errors += comp->sls_i_compressed;
 788                 stats.rx_dropped     += comp->sls_i_tossed;
 789                 stats.tx_fifo_errors += comp->sls_o_compressed;
 790                 stats.collisions     += comp->sls_o_misses;
 791         }
 792 #endif /* CONFIG_INET */
 793         return (&stats);
 794 }
 795 
 796 
 797  /************************************************************************
 798   *                     STANDARD SLIP ENCAPSULATION                      *
 799   ************************************************************************/
 800 
 801 int
 802 slip_esc(unsigned char *s, unsigned char *d, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 803 {
 804         unsigned char *ptr = d;
 805         unsigned char c;
 806 
 807         /*
 808          * Send an initial END character to flush out any
 809          * data that may have accumulated in the receiver
 810          * due to line noise.
 811          */
 812 
 813         *ptr++ = END;
 814 
 815         /*
 816          * For each byte in the packet, send the appropriate
 817          * character sequence, according to the SLIP protocol.
 818          */
 819 
 820         while (len-- > 0) {
 821                 switch(c = *s++) {
 822                  case END:
 823                         *ptr++ = ESC;
 824                         *ptr++ = ESC_END;
 825                         break;
 826                  case ESC:
 827                         *ptr++ = ESC;
 828                         *ptr++ = ESC_ESC;
 829                         break;
 830                  default:
 831                         *ptr++ = c;
 832                         break;
 833                 }
 834         }
 835         *ptr++ = END;
 836         return (ptr - d);
 837 }
 838 
 839 static void
 840 slip_unesc(struct slip *sl, unsigned char s)
     /* [previous][next][first][last][top][bottom][index][help] */
 841 {
 842 
 843         switch(s) {
 844          case END:
 845                 if (!clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  {
 846                         sl_bump(sl);
 847                 }
 848                 clear_bit(SLF_ESCAPE, &sl->flags);
 849                 sl->rcount = 0;
 850                 return;
 851 
 852          case ESC:
 853                 set_bit(SLF_ESCAPE, &sl->flags);
 854                 return;
 855          case ESC_ESC:
 856                 if (clear_bit(SLF_ESCAPE, &sl->flags))  {
 857                         s = ESC;
 858                 }
 859                 break;
 860          case ESC_END:
 861                 if (clear_bit(SLF_ESCAPE, &sl->flags))  {
 862                         s = END;
 863                 }
 864                 break;
 865         }
 866         if (!test_bit(SLF_ERROR, &sl->flags))  {
 867                 if (sl->rcount < sl->buffsize)  {
 868                         sl->rbuff[sl->rcount++] = s;
 869                         return;
 870                 }
 871                 sl->rx_over_errors++;
 872                 set_bit(SLF_ERROR, &sl->flags);
 873         }
 874 }
 875 
 876 
 877 #ifdef CONFIG_SLIP_MODE_SLIP6
 878 /************************************************************************
 879  *                       6 BIT SLIP ENCAPSULATION                       *
 880  ************************************************************************/
 881 
 882 int
 883 slip_esc6(unsigned char *s, unsigned char *d, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 884 {
 885         unsigned char *ptr = d;
 886         unsigned char c;
 887         int i;
 888         unsigned short v = 0;
 889         short bits = 0;
 890 
 891         /*
 892          * Send an initial END character to flush out any
 893          * data that may have accumulated in the receiver
 894          * due to line noise.
 895          */
 896 
 897         *ptr++ = 0x70;
 898 
 899         /*
 900          * Encode the packet into printable ascii characters
 901          */
 902 
 903         for (i = 0; i < len; ++i) {
 904                 v = (v << 8) | s[i];
 905                 bits += 8;
 906                 while (bits >= 6) {
 907                         bits -= 6;
 908                         c = 0x30 + ((v >> bits) & 0x3F);
 909                         *ptr++ = c;
 910                 }
 911         }
 912         if (bits) {
 913                 c = 0x30 + ((v << (6 - bits)) & 0x3F);
 914                 *ptr++ = c;
 915         }
 916         *ptr++ = 0x70;
 917         return ptr - d;
 918 }
 919 
 920 void
 921 slip_unesc6(struct slip *sl, unsigned char s)
     /* [previous][next][first][last][top][bottom][index][help] */
 922 {
 923         unsigned char c;
 924 
 925         if (s == 0x70) {
 926                 if (!clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  {
 927                         sl_bump(sl);
 928                 }
 929                 sl->rcount = 0;
 930                 sl->xbits = 0;
 931                 sl->xdata = 0;
 932         } else if (s >= 0x30 && s < 0x70) {
 933                 sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);
 934                 sl->xbits += 6;
 935                 if (sl->xbits >= 8) {
 936                         sl->xbits -= 8;
 937                         c = (unsigned char)(sl->xdata >> sl->xbits);
 938                         if (!test_bit(SLF_ERROR, &sl->flags))  {
 939                                 if (sl->rcount < sl->buffsize)  {
 940                                         sl->rbuff[sl->rcount++] = c;
 941                                         return;
 942                                 }
 943                                 sl->rx_over_errors++;
 944                                 set_bit(SLF_ERROR, &sl->flags);
 945                         }
 946                 }
 947         }
 948 }
 949 #endif /* CONFIG_SLIP_MODE_SLIP6 */
 950 
 951 #ifdef CONFIG_AX25
 952 int
 953 sl_set_mac_address(struct device *dev, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 954 {
 955         int err;
 956 
 957         err = verify_area(VERIFY_READ, addr, 7);
 958         if (err)  {
 959                 return err;
 960         }
 961 
 962         memcpy_fromfs(dev->dev_addr, addr, 7);  /* addr is an AX.25 shifted ASCII mac address */
 963 
 964         return 0;
 965 }
 966 
 967 static int
 968 sl_set_dev_mac_address(struct device *dev, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 969 {
 970         memcpy(dev->dev_addr, addr, 7);
 971         return 0;
 972 }
 973 #endif /* CONFIG_AX25 */
 974 
 975 
 976 /* Perform I/O control on an active SLIP channel. */
 977 static int
 978 slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 979 {
 980         struct slip *sl = (struct slip *) tty->disc_data;
 981         int err;
 982         unsigned int tmp;
 983 
 984         /* First make sure we're connected. */
 985         if (!sl || sl->magic != SLIP_MAGIC) {
 986                 return -EINVAL;
 987         }
 988 
 989         switch(cmd) {
 990          case SIOCGIFNAME:
 991                 err = verify_area(VERIFY_WRITE, arg, 16);
 992                 if (err)  {
 993                         return -err;
 994                 }
 995                 memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);
 996                 return 0;
 997 
 998         case SIOCGIFENCAP:
 999                 err = verify_area(VERIFY_WRITE, arg, sizeof(int));
1000                 if (err)  {
1001                         return -err;
1002                 }
1003                 put_user(sl->mode, (int *)arg);
1004                 return 0;
1005 
1006         case SIOCSIFENCAP:
1007                 err = verify_area(VERIFY_READ, arg, sizeof(int));
1008                 if (err)  {
1009                         return -err;
1010                 }
1011                 tmp = get_user((int *)arg);
1012 #ifndef SL_INCLUDE_CSLIP
1013                 if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))  {
1014                         return -EINVAL;
1015                 }
1016 #else
1017                 if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==
1018                     (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))  {
1019                         /* return -EINVAL; */
1020                         tmp &= ~SL_MODE_ADAPTIVE;
1021                 }
1022 #endif
1023 #ifndef CONFIG_SLIP_MODE_SLIP6
1024                 if (tmp & SL_MODE_SLIP6)  {
1025                         return -EINVAL;
1026                 }
1027 #endif
1028 #ifndef CONFIG_AX25
1029                 if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
1030                         return -EINVAL;
1031                 }
1032 #else
1033                 if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
1034                         sl->dev->addr_len=7;    /* sizeof an AX.25 addr */
1035                         sl->dev->hard_header_len=17;    /* We don't do digipeaters */
1036                 } else  {
1037                         sl->dev->addr_len=0;    /* No mac addr in slip mode */
1038                         sl->dev->hard_header_len=0;
1039                 }
1040 #endif
1041                 sl->mode = tmp;
1042                 sl->dev->type = ARPHRD_SLIP+sl->mode;
1043 #ifdef CONFIG_AX25              
1044                 if (sl->dev->type == 260 || sl->dev->type == 272)  {
1045                         sl->dev->type = ARPHRD_AX25;
1046                 }
1047 #endif          
1048                 return 0;
1049 
1050          case SIOCSIFHWADDR:
1051 #ifdef CONFIG_AX25
1052                 return sl_set_mac_address(sl->dev, arg);
1053 #else
1054                 return -EINVAL;
1055 #endif
1056 
1057         /* Allow stty to read, but not set, the serial port */
1058         case TCGETS:
1059         case TCGETA:
1060                 return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
1061 
1062         default:
1063                 return -ENOIOCTLCMD;
1064         }
1065 }
1066 
1067 static int sl_open_dev(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1068 {
1069         struct slip *sl = &sl_ctrl[dev->base_addr];
1070         if(sl->tty==NULL)
1071                 return -ENODEV;
1072         return 0;
1073 }
1074 
1075 /* Initialize the SLIP driver.  Called by DDI. */
1076 int
1077 slip_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1078 {
1079         struct slip *sl = &sl_ctrl[dev->base_addr];
1080         int i;
1081 #ifdef CONFIG_AX25
1082         static char ax25_bcast[7] =
1083                 {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
1084         static char ax25_test[7] =
1085                 {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
1086 #endif
1087 
1088         if (already++ == 0) {
1089                 printk("SLIP: version %s (%d channels) %s\n",
1090                        SLIP_VERSION, SL_NRUNIT,
1091 #ifdef CONFIG_SLIP_MODE_SLIP6
1092                        "(6 bit encapsulation enabled)"
1093 #else
1094                        ""
1095 #endif
1096                        );
1097 #if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
1098                 printk("CSLIP: code copyright 1989 Regents of the University of California\n");
1099 #endif
1100 #ifdef CONFIG_AX25
1101                 printk("AX25: KISS encapsulation enabled\n");
1102 #endif
1103                 /* Fill in our LDISC request block. */
1104                 memset(&sl_ldisc, 0, sizeof(sl_ldisc));
1105                 sl_ldisc.magic  = TTY_LDISC_MAGIC;
1106                 sl_ldisc.flags  = 0;
1107                 sl_ldisc.open   = slip_open;
1108                 sl_ldisc.close  = slip_close;
1109                 sl_ldisc.read   = NULL;
1110                 sl_ldisc.write  = NULL;
1111                 sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
1112                                            unsigned int, unsigned long)) slip_ioctl;
1113                 sl_ldisc.select = NULL;
1114                 sl_ldisc.receive_buf = slip_receive_buf;
1115                 sl_ldisc.receive_room = slip_receive_room;
1116                 sl_ldisc.write_wakeup = slip_write_wakeup;
1117                 if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
1118                         printk("SLIP: can't register line discipline (err = %d)\n", i);
1119                 }
1120         }
1121 
1122         /* Set up the "SLIP Control Block". (And clear statistics) */
1123         
1124         memset(sl, 0, sizeof (struct slip));
1125         sl->magic  = SLIP_MAGIC;
1126         sl->dev    = dev;
1127         
1128         /* Finish setting up the DEVICE info. */
1129         dev->mtu                = SL_MTU;
1130         dev->hard_start_xmit    = sl_xmit;
1131         dev->open               = sl_open_dev;
1132         dev->stop               = sl_close;
1133         dev->hard_header        = sl_header;
1134         dev->get_stats          = sl_get_stats;
1135 #ifdef HAVE_SET_MAC_ADDR
1136 #ifdef CONFIG_AX25
1137         dev->set_mac_address    = sl_set_dev_mac_address;
1138 #endif
1139 #endif
1140         dev->hard_header_len    = 0;
1141         dev->addr_len           = 0;
1142         dev->type               = ARPHRD_SLIP + SL_MODE_DEFAULT;
1143 #ifdef CONFIG_AX25
1144         if (sl->dev->type == 260 || sl->dev->type == 272)  {
1145                 sl->dev->type = ARPHRD_AX25;
1146         }
1147         memcpy(dev->broadcast, ax25_bcast, 7); /* Only activated in AX.25 mode */
1148         memcpy(dev->dev_addr, ax25_test, 7);   /*    ""      ""       ""    "" */
1149 #endif
1150         dev->rebuild_header     = sl_rebuild_header;
1151 
1152         for (i = 0; i < DEV_NUMBUFFS; i++)  {
1153                 skb_queue_head_init(&dev->buffs[i]);
1154         }
1155 
1156         /* New-style flags. */
1157         dev->flags              = 0;
1158         dev->family             = AF_INET;
1159         dev->pa_addr            = 0;
1160         dev->pa_brdaddr         = 0;
1161         dev->pa_mask            = 0;
1162         dev->pa_alen            = sizeof(unsigned long);
1163 
1164         return 0;
1165 }
1166 #ifdef MODULE
1167 char kernel_version[] = UTS_RELEASE;
1168 
1169 static struct device dev_slip[SL_NRUNIT] =  {
1170         {
1171                 "sl0",          /* slip */
1172                 0, 0, 0, 0,     /* memory */
1173                 0, 0,           /* base, irq */
1174                 0, 0, 0, NULL, slip_init,
1175         },
1176         { "sl1" , 0, 0, 0, 0,  1, 0, 0, 0, 0, NULL, slip_init },
1177         { "sl2" , 0, 0, 0, 0,  2, 0, 0, 0, 0, NULL, slip_init },
1178         { "sl3" , 0, 0, 0, 0,  3, 0, 0, 0, 0, NULL, slip_init },
1179 #ifdef SL_SLIP_LOTS
1180         { "sl4" , 0, 0, 0, 0,  4, 0, 0, 0, 0, NULL, slip_init },
1181         { "sl5" , 0, 0, 0, 0,  5, 0, 0, 0, 0, NULL, slip_init },
1182         { "sl6" , 0, 0, 0, 0,  6, 0, 0, 0, 0, NULL, slip_init },
1183         { "sl7" , 0, 0, 0, 0,  7, 0, 0, 0, 0, NULL, slip_init },
1184         { "sl8" , 0, 0, 0, 0,  8, 0, 0, 0, 0, NULL, slip_init },
1185         { "sl9" , 0, 0, 0, 0,  9, 0, 0, 0, 0, NULL, slip_init },
1186         { "sl10", 0, 0, 0, 0, 10, 0, 0, 0, 0, NULL, slip_init },
1187         { "sl11", 0, 0, 0, 0, 11, 0, 0, 0, 0, NULL, slip_init },
1188         { "sl12", 0, 0, 0, 0, 12, 0, 0, 0, 0, NULL, slip_init },
1189         { "sl13", 0, 0, 0, 0, 13, 0, 0, 0, 0, NULL, slip_init },
1190         { "sl14", 0, 0, 0, 0, 14, 0, 0, 0, 0, NULL, slip_init },
1191         { "sl15", 0, 0, 0, 0, 15, 0, 0, 0, 0, NULL, slip_init },
1192 #endif /* SL_SLIP_LOTS */
1193 };
1194 
1195 int
1196 init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1197 {
1198         int err;
1199         int i;
1200 
1201         for (i = 0; i < SL_NRUNIT; i++)  {
1202                 if ((err = register_netdev(&dev_slip[i])))  {
1203                         if (err == -EEXIST)  {
1204                                 printk("SLIP: devices already present. Module not loaded.\n");
1205                         }
1206                         return err;
1207                 }
1208         }
1209         return 0;
1210 }
1211 
1212 void
1213 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1214 {
1215         int i;
1216 
1217         if (MOD_IN_USE)  {
1218                 printk("SLIP: device busy, remove delayed\n");
1219                 return;
1220         }
1221         for (i = 0; i < SL_NRUNIT; i++)  {
1222                 unregister_netdev(&dev_slip[i]);
1223         }
1224         if ((i = tty_register_ldisc(N_SLIP, NULL)))  {
1225                 printk("SLIP: can't unregister line discipline (err = %d)\n", i);
1226         }
1227         already = 0;
1228 }
1229 #endif /* MODULE */

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