root/net/inet/slip.c

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

DEFINITIONS

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

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