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

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