root/net/drv/slip/slip.c

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

DEFINITIONS

This source file includes following definitions.
  1. ip_dump
  2. tty_read_data
  3. tty_write_data
  4. tty_flush
  5. sl_find
  6. sl_alloc
  7. sl_free
  8. put_sl_queue
  9. eat_sl_queue
  10. sl_lock
  11. sl_unlock
  12. sl_recv
  13. sl_send
  14. sl_start_xmit
  15. sl_type_trans
  16. sl_open
  17. sl_close
  18. slip_recv
  19. slip_chan
  20. slip_open
  21. slip_close
  22. 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 NET protocol layers (via DDI).
   5  *
   6  * Version:     @(#)slip.c      0.5.0   (02/11/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/tty.h>
  21 #include <linux/errno.h>
  22 #include <linux/stat.h>
  23 #include <linux/tty.h>
  24 #include <linux/slip.h>
  25 #include <netinet/in.h>
  26 
  27 
  28 #define SLIP_VERSION    "0.5.0"
  29 #define SL_DUMP
  30 
  31 
  32 #define SL_DEBUG
  33 #ifdef  SL_DEBUG
  34 #   define PRINTK(x)    printk x
  35 #else
  36 #   define PRINTK(x)    /**/
  37 #endif
  38 
  39 
  40 /* Define some IP layer stuff.  Not all systems have it. */
  41 #ifdef SL_DUMP
  42 #  define       IP_VERSION      4       /* version# of our IP software  */
  43 #  define       IPF_F_OFFSET    0x1fff  /* Offset field                 */
  44 #  define       IPF_DF          0x4000  /* Don't fragment flag          */
  45 #  define       IPF_MF          0x2000  /* More Fragments flag          */
  46 
  47    typedef struct ipheader {
  48         u_char  v_ihl;                  /* Version + IP header length   */
  49         u_char  tos;                    /* Type of service              */
  50         u_short length;                 /* Total length                 */
  51         u_short id;                     /* Identification               */
  52         u_short fl_offs;                /* Flags + fragment offset      */
  53         u_char  ttl;                    /* Time to live                 */
  54         u_char  protocol;               /* Protocol                     */
  55         u_short checksum;               /* Header checksum              */
  56         u_long  source;                 /* Source address               */
  57         u_long  dest;                   /* Destination address          */
  58     } IP;
  59 #   define      IP_OF_COPIED    0x80    /* Copied-on-fragmentation flag */
  60 #   define      IP_OF_CLASS     0x60    /* Option class                 */
  61 #   define      IP_OF_NUMBER    0x1f    /* Option number                */
  62 #   define      IPO_EOL         0       /* End of options list          */
  63 #   define      IPO_NOOP        1       /* No Operation                 */
  64 #   define      IPO_SECURITY    2       /* Security parameters          */
  65 #   define      IPO_LSROUTE     3       /* Loose Source Routing         */
  66 #   define      IPO_TIMESTAMP   4       /* Internet Timestamp           */
  67 #   define      IPO_RROUTE      7       /* Record Route                 */
  68 #   define      IPO_STREAMID    8       /* Stream ID                    */
  69 #   define      IPO_SSROUTE     9       /* Strict Source Routing        */
  70 #   define      IP_TS_ONLY      0       /* Time stamps only             */
  71 #   define      IP_TS_ADDRESS   1       /* Addresses + Time stamps      */
  72 #   define      IP_TS_PRESPEC   3       /* Prespecified addresses only  */
  73 #endif
  74 
  75 
  76 /* This table holds the control blocks for all SLIP channels. */
  77 static struct slip sl_ctrl[SL_NRUNIT];
  78 
  79 
  80 #ifdef SL_DUMP
  81 /* Dump the contents of an IP datagram. */
  82 static void
  83 ip_dump(unsigned char *ptr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85   int hdr_ver, hdr_len, dta_len, dta_off;
  86   IP *ip;
  87   extern char *in_ntoa(long num);
  88 
  89   ip = (IP *) ptr;
  90   hdr_ver = (ip->v_ihl & 0xF0) >> 4;
  91   hdr_len = (ip->v_ihl & 0x0F) * sizeof(long);
  92   dta_len = ntohs(ip->length);
  93   dta_off = (ntohs(ip->fl_offs) & IPF_F_OFFSET) << 3 ;
  94 
  95   printk("\r*****\n");
  96   printk("SLIP: %s->", in_ntoa(ip->source));
  97   printk("%s\n", in_ntoa(ip->dest));
  98   printk(" len %u ihl %u ttl %u prot %u",
  99         dta_len, ip->v_ihl & 0xFF, ip->ttl & 0xFF, ip->protocol & 0xFF);
 100 
 101   if (ip->tos != 0) printk(" tos %u", ip->tos);
 102   if (dta_off != 0 || (ntohs(ip->fl_offs) & IPF_MF))
 103         printk(" id %u offs %u", ntohs(ip->id), dta_off);
 104 
 105   if (ntohs(ip->fl_offs) & IPF_DF) printk(" DF");
 106   if (ntohs(ip->fl_offs) & IPF_MF) printk(" MF");
 107   printk("\n*****\n");
 108 }
 109 #endif
 110 
 111 
 112 /*
 113  * Read data from a TTY queue.  This function will eventually
 114  * be moved into the TTY layer itself, making it available for
 115  * other layers, too.
 116  */
 117 int tty_read_data(struct tty_struct *tty, unsigned char *buf, int max)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         register int count;
 120         register unsigned char c;
 121 
 122         /* Keep fetching characters from TTY until done or full. */
 123         count = 0;
 124         PRINTK (("SLIP: tty_read:"));
 125         while (max-- > 0) {
 126                 if (EMPTY(&tty->read_q)) break;
 127                 c = (get_tty_queue(&tty->read_q) & 0377);
 128                 *buf++ = c;
 129                 PRINTK ((" %02x", (int) (c & 255)));
 130                 count++;
 131         }
 132         PRINTK (("\r\nSLIP: tty_read: read %d bytes\r\n", count));
 133         return(count);
 134 }
 135 
 136 
 137 /*
 138  * Write data to a TTY queue.  This function will eventually
 139  * be moved into the TTY layer itself, making it available for
 140  * other layers, too.
 141  */
 142 void tty_write_data(struct tty_struct *tty, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         /* PRINTK (("SLIP: tty_write: writing %d bytes\r\n", count)); */
 145         while(count--) {
 146                 put_tty_queue(*buf++, &tty->write_q);
 147         }
 148 }
 149 
 150 
 151 /*
 152  * Flush a TTY write queue by calling the TTY layer.  This
 153  * function will eventually be moved into the TTY layer itself,
 154  * making it available for other layers, too.
 155  */
 156 void tty_flush(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         /* PRINTK (("SLIP: tty_flush: flusing the toilet...\r\n")); */
 159         /*
 160          * This should also tell TTY which function to call-back
 161          * when the work is done, allowing us to clean up and
 162          * possibly start another output...
 163          */
 164         tty_write_flush(tty);
 165 }
 166 
 167 
 168 /* Find a SLIP channel from its `tty' link. */
 169 static struct slip *
 170 sl_find(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         int i;
 173         struct slip *sl;
 174 
 175         if (tty == NULL) return(NULL);
 176         for (i = 0; i < SL_NRUNIT; i++) {
 177                 sl = &sl_ctrl[i];
 178                 if (sl->tty == tty) return(sl);
 179         }
 180         return(NULL);
 181 }
 182 
 183 
 184 /* Find a free SLIP channel, and link in this `tty' line. */
 185 static inline struct slip *
 186 sl_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         int i;
 189         struct slip *sl;
 190         unsigned long flags;
 191 
 192         for (i = 0; i < SL_NRUNIT; i++) {
 193                 sl = &sl_ctrl[i];
 194                 if (sl->inuse == 0) {
 195                         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 196                         sl->inuse++;
 197                         sl->tty = NULL;
 198                         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 199                         return(sl);
 200                 }
 201         }
 202         return(NULL);
 203 }
 204 
 205 
 206 /* Free a SLIP channel. */
 207 static inline void
 208 sl_free(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210         unsigned long flags;
 211 
 212         if (sl->inuse == 1) {
 213                 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 214                 sl->inuse--;
 215                 sl->tty = NULL;
 216                 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 217         }
 218 }
 219 
 220 
 221 /* Stuff one byte into a SLIP queue. */
 222 static inline void
 223 put_sl_queue(struct sl_queue * queue, char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         int head;
 226         unsigned long flags;
 227 
 228         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 229         head = (queue->head + 1) & (SL_BUF_SIZE-1);
 230         if (head != queue->tail) {
 231                 queue->buf[queue->head] = c;
 232                 queue->head = head;
 233         }
 234         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 235 }
 236 
 237 
 238 /* Release 'i' bytes from a SLIP queue. */
 239 static inline void
 240 eat_sl_queue(struct sl_queue * queue, int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         unsigned long flags;
 243 
 244         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 245         if (queue->tail != queue->head)
 246                 queue->tail = (queue->tail + i) & (SL_BUF_SIZE-1);
 247         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 248 }
 249 
 250 
 251 /* Set the "sending" flag.  This must be atomic, hence the ASM. */
 252 static inline void
 253 sl_lock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255         unsigned long flags;
 256 
 257         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 258         sl->sending = 1;
 259         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 260 }
 261 
 262 
 263 /* Clear the "sending" flag.  This must be atomic, hence the ASM. */
 264 static inline void
 265 sl_unlock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 266 {
 267         unsigned long flags;
 268 
 269         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 270         sl->sending = 0;
 271         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 272 }
 273 
 274 
 275 /* Send one completely decapsulated IP datagram to the IP layer. */
 276 static void
 277 sl_recv(struct slip *sl, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279 #if 0
 280         struct device *dev;
 281 #endif
 282         register unsigned char *p;
 283         int done;
 284 
 285         PRINTK (("SLIP: sending one dgram to IP (len=%d)\r\n", len));
 286 #ifdef SL_DUMP
 287         printk("<< iface \"sl%d\" recv:\r\n", sl->line);
 288         ip_dump((unsigned char *) &sl->rcv_queue.buf[sl->rcv_queue.tail], len);
 289 #endif
 290 
 291         /* Bump the datagram to the upper layers... */
 292 #if 0
 293         dev = sl->dev;
 294         p = (unsigned char *) &sl->rcv_queue.buf[sl->rcv_queue.tail];
 295         do {
 296                 done = dev_rint(p, len, 0, dev);
 297                 if (done == 1) break;
 298         } while(1);
 299 #endif
 300         eat_sl_queue(&sl->rcv_queue, len);
 301         sl->rcvd++;
 302 }
 303 
 304 
 305 /* Encapsulate one IP datagram and stuff into a TTY queue. */
 306 static void
 307 sl_send(struct slip *sl, unsigned char *p, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309         register unsigned char *bp;
 310         register int count;
 311 
 312         /* PRINTK (("SLIP: sl_send(0x%X, %d) called\n", p, len)); */
 313         bp = (unsigned char *)sl->xbuff;
 314 #ifdef SL_DUMP
 315         printk(">> iface \"sl%d\" sent:\r\n", sl->line);
 316         ip_dump(p, len);
 317 #endif
 318         count = 0;
 319 
 320         /*
 321          * Send an initial END character to flush out any
 322          * data that may have accumulated in the receiver
 323          * due to line noise.
 324          */
 325         *bp++ = END;
 326         count++;
 327 
 328         /*
 329          * For each byte in the packet, send the appropriate
 330          * character sequence, according to the SLIP protocol.
 331          * FIXME: change this to copy blocks of characters between
 332          *        special characters to improve speed.
 333          */
 334         while(len--) {
 335                 switch(*p) {
 336                         case END:
 337                                 *bp++ = ESC;
 338                                 *bp++ = ESC_END;
 339                                 count += 2;
 340                                 break;
 341                         case ESC:
 342                                 *bp++ = ESC;
 343                                 *bp++ = ESC_ESC;
 344                                 count += 2;
 345                                 break;
 346                         default:
 347                                 *bp++ = *p;
 348                                 count++;
 349                 }
 350                 p++;
 351         }
 352         *bp++ = END;
 353         count++;
 354         sl->sent++;
 355         tty_write_data(sl->tty, sl->xbuff, count);      /* stuff into TTY       */
 356 }
 357 
 358 
 359 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 360 static int
 361 sl_start_xmit(void /*struct sk_buff*/ *skb, void /*struct device*/ *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 362 {
 363         struct slip *sl;
 364         struct tty_struct *tty;
 365 
 366 #if 0
 367         /* Find the correct SLIP channel to use. */
 368         sl = &sl_ctrl[dev->base_addr];
 369         tty = sl->tty;
 370         /* PRINTK (("SLIP: sl_start_xmit(\"%s\") skb=0x%X busy=%d\n",
 371                                         dev->name, skb, sl->sending)); */
 372 
 373         /*
 374          * If we are busy already- too bad.  We ought to be able
 375          * to queue things at this point, to allow for a little
 376          * frame buffer.  Oh well...
 377          */
 378         if (sl->sending) {
 379                 PRINTK (("SLIP: sl_start_xmit: BUSY\r\n"));
 380                 return(1);
 381         }
 382 
 383         /* We were not, so we are now... :-) */
 384         sti();
 385         sl_lock(sl);
 386 
 387         if (skb != NULL) {
 388                 /* PRINTK (("SLIP: sl_start_xmit: encaps(0x%X, %d)\r\n",
 389                                         (unsigned) skb, skb->len));     */
 390                 sl_send(sl, (unsigned char *) (skb + 1), skb->len);
 391         }
 392 
 393         /* PRINTK (("SLIP: sl_start_xmit: kicking TTY!\n")); */
 394         tty_flush(tty);                 /* kick TTY in the butt */
 395         sl_unlock(sl);
 396 #endif
 397         return(0);
 398 }
 399 
 400 
 401 /*
 402  * Return the frame type ID.  Shouldn't we pick this up from the
 403  * frame on which we have to operate, like in 'eth' ? - FvK
 404  */
 405 static unsigned short
 406 sl_type_trans (void /*struct sk_buff*/ *skb, void /*struct device*/ *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 407 {
 408 #ifdef notdef
 409         struct slip *sl;
 410 
 411         sl = sl_ctrl[dev->base_addr];
 412         return(sl->type);
 413 #else
 414         return(NET16(ETHERTYPE_IP));
 415 #endif
 416 }
 417 
 418 
 419 /* Open the low-level part of the SLIP channel. Easy! */
 420 static int
 421 sl_open(void /*struct device*/ *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 422 {
 423         struct slip *sl;
 424 
 425 #if 0
 426         sl = &sl_ctrl[dev->base_addr];
 427         if (sl->tty == NULL) {
 428                 PRINTK (("SLIP: channel sl%d not connected!\n", sl->line));
 429                 return(-ENXIO);
 430         }
 431 
 432         sl->escape = 0;                 /* SLIP state machine           */
 433         sl->received = 0;               /* SLIP receiver count          */
 434         PRINTK (("SLIP: channel sl%d opened.\n", sl->line));
 435 #endif
 436         return(0);
 437 }
 438 
 439 
 440 /* Close the low-level part of the SLIP channel. Easy! */
 441 static int
 442 sl_close(void /*struct device*/ *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 443 {
 444         struct slip *sl;
 445 
 446 #if 0
 447         sl = &sl_ctrl[dev->base_addr];
 448         if (sl->tty == NULL) {
 449                 PRINTK (("SLIP: channel sl%d not connected!\n", sl->line));
 450                 return(-EBUSY);
 451         }
 452         sl_free(sl);
 453 
 454         /*
 455          * The next two lines should be handled by a "dev_down()"
 456          * function, which takes care of shutting down an inter-
 457          * face.  It would also be called by the "ip" module when
 458          * an interface is brought down manually.
 459          */
 460         del_devroute(dev);
 461         dev->up = 0;
 462         PRINTK (("SLIP: channel sl%d closed.\n", sl->line));
 463 #endif
 464         return(0);
 465 }
 466 
 467 
 468 /*
 469  * Handle the 'receiver data ready' interrupt.
 470  * This function is called by the 'tty_io' module in the kernel when
 471  * a block of SLIP data has been received, which can now be decapsulated
 472  * and sent on to some IP layer for further processing.
 473  */
 474 static void
 475 slip_recv(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477         unsigned char buff[SL_MTU * 2];
 478         register unsigned char *p;
 479         register int count;
 480         struct slip *sl;
 481         unsigned char c;
 482 
 483 #if 0
 484 PRINTK (("SLIP: slip_recv(%d) called\n", tty->line));
 485         if ((sl = sl_find(tty)) == NULL) return;        /* not connected */
 486 
 487         if (SL_FULL(&sl->rcv_queue)) {
 488                 PRINTK (("SLIP: recv queue full\r\n"));
 489                 return;
 490         }
 491 
 492         while((count = tty_read_data(tty, buff, (SL_MTU * 2))) > 0) {
 493                 p = buff;
 494                 while(count-- > 0) {
 495                         c = *p++;
 496                         switch(c) {
 497                                 case ESC:
 498                                         sl->escape = 1;
 499                                         break;
 500                                 case ESC_ESC:
 501                                         if (sl->escape) c = ESC;
 502                                         put_sl_queue(&sl->rcv_queue, c);
 503                                         sl->escape = 0;
 504                                         sl->received++;
 505                                         break;
 506                                 case ESC_END:
 507                                         if (sl->escape) c = END;
 508                                         put_sl_queue(&sl->rcv_queue, c);
 509                                         sl->escape = 0;
 510                                         sl->received++;
 511                                         break;
 512                                 case END:
 513                                         sl->escape = 0;
 514                                         if (sl->received < 3) {
 515                                                 if (sl->received)
 516                                                         eat_sl_queue(&sl->rcv_queue,
 517                                                                 sl->received);
 518                                                 sl->received = 0;
 519                                         } else {
 520         PRINTK (("SLIP: full frame received!\r\n"));
 521                                                 sl_recv(sl, sl->received);
 522                                                 sl->received = 0;
 523                                         }
 524                                         break;
 525                                 default:
 526                                         put_sl_queue(&sl->rcv_queue, c);
 527                                         sl->escape = 0;
 528                                         sl->received++;
 529                         }
 530                 }
 531         }
 532 #endif
 533 }
 534 
 535 
 536 /* Return the channel number of a SLIP connection. */
 537 static int
 538 slip_chan(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 539 {
 540         struct slip *sl;
 541 
 542         if ((sl = sl_find(tty)) == NULL) return(-ENXIO);  /* not connected */
 543         return(sl->line);
 544 }
 545 
 546 
 547 /*
 548  * Open the high-level part of the SLIP channel.  
 549  * This function is called by the TTY module when the
 550  * SLIP line discipline is called for.  Because we are
 551  * sure the tty line exists, we only have to link it to
 552  * a free SLIP channel...
 553  */
 554 static int
 555 slip_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 556 {
 557         struct slip *sl;
 558 
 559         /* First make sure we're not already connected. */
 560         if ((sl = sl_find(tty)) != NULL) {
 561                 PRINTK (("SLIP: TTY %d already connected to sl%d !\n",
 562                         tty->line, sl->line));
 563                 return(-EEXIST);
 564         }
 565 
 566         /* OK.  Find a free SLIP channel to use. */
 567         if ((sl = sl_alloc()) == NULL) {
 568                 PRINTK (("SLIP: TTY %d not connected: all channels in use!\n",
 569                                                         tty->line));
 570                 return(-ENFILE);
 571         }
 572         sl->tty = tty;
 573 
 574         /* Link the TTY line to this channel. */
 575         (void) sl_open(sl->dev);
 576         PRINTK (("SLIP: TTY %d connected to sl%d.\n", tty->line, sl->line));
 577 
 578         /* Done.  We have linked the TTY line to a channel. */
 579         return(sl->line);
 580 }
 581 
 582 
 583 /*
 584  * Close down a SLIP channel.
 585  * This means flushing out any pending queues, and then restoring the
 586  * TTY line discipline to what it was before it got hooked to SLIP
 587  * (which usually is TTY again).
 588  */
 589 static void
 590 slip_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 591 {
 592         struct slip *sl;
 593 
 594         /* First make sure we're connected. */
 595         if ((sl = sl_find(tty)) == NULL) {
 596                 PRINTK (("SLIP: TTY %d not connected !\n", tty->line));
 597                 return;
 598         }
 599 
 600         (void) sl_close(sl->dev);
 601         PRINTK (("SLIP: TTY %d disconnected from sl%d.\n", tty->line, sl->line));
 602 }
 603 
 604 
 605 /* Initialize the SLIP driver.  Called by DDI. */
 606 int
 607 slip_init(struct ddi *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 608 {
 609         int i;
 610         struct slip *sl;
 611 
 612 #if 1
 613         PRINTK(("SLIP/DDI: version %s (%d channels, buffer=0x%X:%d)\n",
 614                                         ddi->ioaddr, ddi->memaddr, ddi->memsize));
 615 #else
 616         sl = &sl_ctrl[dev->base_addr];
 617 
 618         if (already++ == 0) {
 619                 printk("SLIP: version %s (%d channels): ",
 620                                         SLIP_VERSION, SL_NRUNIT);
 621                 if ((i = tty_set_ldisc(N_SLIP, slip_open, slip_close,
 622                         slip_chan, slip_recv)) == 0) printk("OK\n");
 623                   else printk("ERROR: %d\n", i);
 624         }
 625 
 626         /* Set up the "SLIP Control Block". */
 627         sl->inuse            = 0;               /* not allocated now    */
 628         sl->line             = dev->base_addr;  /* SLIP channel number  */
 629         sl->tty              = NULL;            /* pointer to TTY line  */
 630         sl->dev              = dev;             /* pointer to DEVICE    */
 631         sl->sending          = 0;               /* locked on output     */
 632         sl->rcv_queue.head   = 0;               /* ptr to RECV queue    */
 633         sl->rcv_queue.tail   = 0;               /* ptr to RECV queue    */
 634         sl->escape           = 0;               /* SLIP state machine   */
 635         sl->received         = 0;               /* SLIP receiver count  */
 636         sl->sent             = 0;               /* #frames sent out     */
 637         sl->rcvd             = 0;               /* #frames received     */
 638         sl->errors           = 0;               /* not used at present  */
 639 
 640         /* Finish setting up the DEVICE info. */
 641         dev->mtu             = SL_MTU;
 642         dev->rmem_end        = (unsigned long)&sl->rcv_queue.buf[SL_BUF_SIZE-1];
 643         dev->rmem_start      = (unsigned long)&sl->rcv_queue.buf[0];
 644         dev->mem_end         = (unsigned long)&sl->xbuff[(SL_MTU * 2) -1];
 645         dev->mem_start       = (unsigned long)&sl->xbuff[0];
 646         dev->hard_start_xmit = sl_start_xmit;
 647         dev->open            = sl_open;
 648         dev->stop            = sl_close;
 649         dev->hard_header     = sl_hard_header;
 650         dev->add_arp         = sl_add_arp;
 651         dev->type_trans      = sl_type_trans;
 652         dev->hard_header_len = 0;
 653         dev->addr_len        = 0;
 654         dev->type            = 0;       /* FIXME: ??? */
 655         dev->queue_xmit      = dev_queue_xmit;
 656         dev->rebuild_header  = sl_rebuild_header;
 657         for (i = 0; i < DEV_NUMBUFFS; i++) dev->buffs[i] = NULL;
 658 
 659 #endif
 660         return(0);
 661 }

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