root/drivers/net/strip.c

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

DEFINITIONS

This source file includes following definitions.
  1. DisableInterrupts
  2. RestoreInterrupts
  3. StuffData
  4. UnStuffData
  5. strip_changedmtu
  6. strip_unlock
  7. ResetRadio
  8. strip_write_some_more
  9. strip_stuff
  10. strip_send
  11. strip_xmit
  12. strip_IdleTask
  13. strip_receive_room
  14. strip_bump
  15. RecvErr
  16. RecvErr_Message
  17. process_packet
  18. strip_receive_buf
  19. strip_header
  20. strip_rebuild_header
  21. strip_set_dev_mac_address
  22. strip_get_stats
  23. strip_open_low
  24. strip_close_low
  25. strip_dev_init
  26. strip_free
  27. strip_alloc
  28. strip_open
  29. strip_close
  30. strip_ioctl
  31. strip_init_ctrl_dev
  32. init_module
  33. cleanup_module

   1 /*
   2  * Copyright 1996 The Board of Trustees of The Leland Stanford
   3  * Junior University. All Rights Reserved.
   4  *
   5  * Permission to use, copy, modify, and distribute this
   6  * software and its documentation for any purpose and without
   7  * fee is hereby granted, provided that the above copyright
   8  * notice appear in all copies.  Stanford University
   9  * makes no representations about the suitability of this
  10  * software for any purpose.  It is provided "as is" without
  11  * express or implied warranty.
  12  *
  13  * strip.c      This module implements Starmode Radio IP (STRIP)
  14  *              for kernel-based devices like TTY.  It interfaces between a
  15  *              raw TTY, and the kernel's INET protocol layers (via DDI).
  16  *
  17  * Version:     @(#)strip.c     0.9.1   3/6/95
  18  *
  19  * Author:      Stuart Cheshire <cheshire@cs.stanford.edu>
  20  *
  21  * Fixes:
  22  *              Stuart Cheshire:
  23  *                      Original version converted from SLIP driver
  24  *              Jonathan Stone:
  25  *                      change to 1.3 calling conventions
  26  *              Stuart Cheshire:
  27  *                      v0.9 12th Feb 1996.
  28  *                      New byte stuffing (2+6 run-length encoding)
  29  *                      New watchdog timer task
  30  *                      New Protocol key (SIP0)
  31  *                      v0.9.1 3rd March 1996
  32  *                      Changed to dynamic device allocation
  33  */
  34 
  35 #include <linux/config.h>
  36 #ifdef MODULE
  37 #include <linux/module.h>
  38 #include <linux/version.h>
  39 #endif
  40 
  41 #include <asm/system.h>
  42 #include <asm/segment.h>
  43 #include <asm/bitops.h>
  44 #include <linux/string.h>
  45 #include <linux/mm.h>
  46 #include <linux/interrupt.h>
  47 #include <linux/in.h>
  48 #include <linux/tty.h>
  49 #include <linux/errno.h>
  50 #include <linux/netdevice.h>
  51 #include <linux/etherdevice.h>
  52 #include <linux/skbuff.h>
  53 #include <linux/if_arp.h>
  54 #include <linux/if_strip.h>
  55 #include <net/arp.h>
  56 #ifdef CONFIG_INET
  57 #include <linux/ip.h>
  58 #include <linux/tcp.h>
  59 #endif
  60 
  61 #ifdef MODULE
  62 #define STRIP_VERSION    "0.9.1-STUART.CHESHIRE-MODULAR"
  63 #else
  64 #define STRIP_VERSION    "0.9.1-STUART.CHESHIRE"
  65 #endif
  66 
  67 #define STRIP_MTU 1024
  68 #define STRIP_MAGIC 0x5303
  69 
  70 /*
  71  *      Do we still needs all these flags? 
  72  */
  73 
  74 enum 
  75 {
  76         STR_INUSE = 0,          /* Channel in use       */
  77         STR_ESCAPE,                     /* ESC received         */
  78         STR_ERROR                       /* Parity, etc. error   */
  79 }
  80 STRIP_FLAGS;
  81 
  82 struct strip 
  83 {
  84         int magic;
  85         /*
  86          *      Other useful structures. 
  87          */
  88 
  89         /*
  90          *      These are pointers to the malloc()ed frame buffers.
  91          */
  92 
  93         unsigned char     *rx_buff;             /* buffer for received IP packet*/
  94         unsigned char     *sx_buff;             /* buffer for received serial data*/
  95         int                sx_count;            /* received serial data counter */
  96         unsigned char     *tx_buff;             /* transmitter buffer  */
  97         unsigned char     *tx_head;             /* pointer to next byte to XMIT */
  98         int                tx_left;             /* bytes left in XMIT queue     */
  99 
 100         /*
 101          *      STRIP interface statistics.
 102          */
 103          
 104         unsigned long      rx_packets;          /* inbound frames counter       */
 105         unsigned long      tx_packets;          /* outbound frames counter      */
 106         unsigned long      rx_errors;           /* Parity, etc. errors          */
 107         unsigned long      tx_errors;           /* Planned stuff                */
 108         unsigned long      rx_dropped;          /* No memory for skb            */
 109         unsigned long      tx_dropped;          /* When MTU change              */
 110         unsigned long      rx_over_errors;      /* Frame bigger then STRIP buf. */
 111 
 112         /*
 113          *      Internal variables.
 114          */
 115          
 116         struct strip      *next;                /* The next struct in the list  */
 117         struct strip     **referrer;            /* The pointer that points to us */
 118         unsigned char      flags;               /* Flag values/ mode etc        */
 119         int                mtu;                 /* Our mtu (to spot changes!)   */
 120         int                buffsize;            /* Max buffers sizes            */
 121         long               watchdog_doprobe;    /* Next time to test the radio  */
 122         long               watchdog_doreset;    /* Time to do next reset        */
 123         struct timer_list  idle_timer;
 124 
 125         struct tty_struct *tty;                 /* ptr to TTY structure         */
 126         char               if_name[8];          /* Dynamically generated name   */
 127         struct device       dev;                /* Our device structure         */
 128 };
 129 /************************************************************************/
 130 /* Utility routines for disabling and restoring interrupts              */
 131 
 132 typedef unsigned long InterruptStatus;
 133 
 134 extern __inline__ InterruptStatus DisableInterrupts(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136     InterruptStatus x;
 137     save_flags(x);
 138     cli();
 139     return(x);
 140 }
 141 
 142 extern __inline__ void RestoreInterrupts(InterruptStatus x)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144     restore_flags(x);
 145 }
 146 
 147 /************************************************************************/
 148 /* Useful structures and definitions                                    */
 149 
 150 typedef struct {
 151     __u8 c[32];
 152 } RadioName;
 153 
 154 typedef struct {
 155     __u8 c[ 4];
 156 } MetricomKey;
 157 
 158 typedef union {
 159     __u8 b[ 4];
 160     __u32 l;
 161 } IPaddr;
 162 
 163 static const MetricomKey ProtocolKey = 
 164 {
 165     {
 166         "SIP0"
 167     }
 168 };
 169 
 170 enum 
 171 {
 172     FALSE = 0,
 173     TRUE = 1
 174 };
 175 
 176 #define LONG_TIME 0x7FFFFFFF
 177 
 178 typedef struct 
 179 {
 180         RadioName   name;       /* The address, with delimiters eg. *0000-1164* */
 181         MetricomKey key;        /* Protocol type */
 182 } STRIP_Header;
 183 
 184 typedef struct 
 185 {
 186         STRIP_Header h;
 187         __u8 data[4];           /* Placeholder for payload (The IP packet) */
 188 } STRIP_Packet;
 189 
 190 /*
 191  *      STRIP_ENCAP_SIZE of an IP packet is the STRIP header at the front,
 192  *      byte-stuffing overhead of the payload, plus the CR at the end
 193  */
 194  
 195 #define STRIP_ENCAP_SIZE(X) (sizeof(STRIP_Header) + (X)*65L/64L + 2)
 196 
 197 /*
 198  *      Note: A Metricom packet looks like this: *<address>*<key><payload><CR>
 199  *      eg. *0000-1164*SIP0<payload><CR>
 200  */
 201 
 202 static struct strip *struct_strip_list = NULL;
 203 
 204 /************************************************************************/
 205 /* Byte stuffing/unstuffing routines                                    */
 206 
 207 /* Stuffing scheme:
 208  * 00    Unused (reserved character)
 209  * 01-3F Run of 2-64 different characters
 210  * 40-7F Run of 1-64 different characters plus a single zero at the end
 211  * 80-BF Run of 1-64 of the same character
 212  * C0-FF Run of 1-64 zeroes (ASCII 0)
 213  */
 214 
 215 typedef enum 
 216 {
 217     Stuff_Diff      = 0x00,
 218     Stuff_DiffZero  = 0x40,
 219     Stuff_Same      = 0x80,
 220     Stuff_Zero      = 0xC0,
 221     Stuff_NoCode    = 0xFF,     /* Special code, meaning no code selected */
 222     
 223     Stuff_CodeMask  = 0xC0,
 224     Stuff_CountMask = 0x3F,
 225     Stuff_MaxCount  = 0x3F,
 226     Stuff_Magic     = 0x0D      /* The value we are eliminating */
 227 } StuffingCode;
 228 
 229 /* StuffData encodes the data starting at "src" for "length" bytes.
 230  * It writes it to the buffer pointed to by "dst" (which must be at least
 231  * as long as 1 + 65/64 of the input length). The output may be up to 1.6%
 232  * larger than the input for pathological input, but will usually be smaller.
 233  * StuffData returns the new value of the dst pointer as its result.
 234  * "code_ptr_ptr" points to a "__u8 *" which is used to hold encoding state
 235  * between calls, allowing an encoded packet to be incrementally built up
 236  * from small parts. On the first call, the "__u8 *" pointed to should be
 237  * initialized to NULL; between subsequent calls the calling routine should
 238  * leave the value alone and simply pass it back unchanged so that the
 239  * encoder can recover its current state.
 240  */
 241 
 242 #define StuffData_FinishBlock(X) \
 243 (*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode)
 244 
 245 static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247         __u8 *end = src + length;
 248         __u8 *code_ptr = *code_ptr_ptr;
 249         __u8 code = Stuff_NoCode, count = 0;
 250     
 251         if (!length) 
 252                 return(dst);
 253     
 254         if (code_ptr) 
 255         {
 256                 /*
 257                  *      Recover state from last call, if applicable 
 258                  */
 259                 code  = (*code_ptr ^ Stuff_Magic) & Stuff_CodeMask;
 260                 count = (*code_ptr ^ Stuff_Magic) & Stuff_CountMask;
 261         }
 262 
 263         while (src < end) 
 264         {
 265                 switch (code) 
 266                 {
 267                         /* Stuff_NoCode: If no current code, select one */
 268                         case Stuff_NoCode:
 269                                 /* Record where we're going to put this code */
 270                                 code_ptr = dst++;
 271                                 count = 0;      /* Reset the count (zero means one instance) */
 272                                 /* Tentatively start a new block */
 273                                 if (*src == 0) 
 274                                 {
 275                                         code = Stuff_Zero;
 276                                         src++;
 277                                 }
 278                                 else
 279                                 {
 280                                         code = Stuff_Same;
 281                                         *dst++ = *src++ ^ Stuff_Magic;
 282                                 }
 283                                 /* Note: We optimistically assume run of same -- */
 284                                 /* which will be fixed later in Stuff_Same */
 285                                 /* if it turns out not to be true. */
 286                                 break;
 287 
 288                         /* Stuff_Zero: We already have at least one zero encoded */
 289                         case Stuff_Zero:
 290                                 /* If another zero, count it, else finish this code block */
 291                                 if (*src == 0) 
 292                                 {
 293                                         count++;
 294                                         src++;
 295                                 }
 296                                 else 
 297                                 {
 298                                         StuffData_FinishBlock(Stuff_Zero + count);
 299                                 }
 300                                 break;
 301 
 302                         /* Stuff_Same: We already have at least one byte encoded */
 303                         case Stuff_Same:
 304                                 /* If another one the same, count it */
 305                                 if ((*src ^ Stuff_Magic) == code_ptr[1]) 
 306                                 {
 307                                         count++;
 308                                         src++;
 309                                         break;
 310                                 }
 311                                 /* else, this byte does not match this block. */
 312                                 /* If we already have two or more bytes encoded, */
 313                                 /* finish this code block */
 314                                 if (count) 
 315                                 {
 316                                         StuffData_FinishBlock(Stuff_Same + count);
 317                                         break;
 318                                 }
 319                                 /* else, we only have one so far, */
 320                                 /* so switch to Stuff_Diff code */
 321                                 code = Stuff_Diff;
 322                                 /* and fall through to Stuff_Diff case below */
 323                          /* Stuff_Diff: We have at least two *different* bytes encoded */
 324                         case Stuff_Diff:
 325                                 /* If this is a zero, must encode a Stuff_DiffZero, */
 326                                 /* and begin a new block */
 327                                 if (*src == 0) 
 328                                 {
 329                                         StuffData_FinishBlock(Stuff_DiffZero + count);
 330                                 }
 331                                 /* else, if we have three in a row, it is worth starting */
 332                                 /* a Stuff_Same block */
 333                                 else if ((*src ^ Stuff_Magic)==dst[-1] && dst[-1]==dst[-2]) 
 334                                 {
 335                                 /* Back off the last two characters we encoded */
 336                                 code += count-2;
 337                                 /* Note: "Stuff_Diff + 0" is an illegal code */
 338                                 if (code == Stuff_Diff + 0) 
 339                                 {
 340                                         code = Stuff_Same + 0;
 341                                 }
 342                                 StuffData_FinishBlock(code);
 343                                 code_ptr = dst-2;
 344                                 /* dst[-1] already holds the correct value */
 345                                 count = 2;              /* 2 means three bytes encoded */
 346                                 code = Stuff_Same;
 347                         }
 348                         /* else, another different byte, so add it to the block */
 349                         else 
 350                         {
 351                                 *dst++ = *src ^ Stuff_Magic;
 352                                 count++;
 353                         }
 354                         src++;  /* Consume the byte */
 355                         break;
 356                 }
 357                 if (count == Stuff_MaxCount) 
 358                 {
 359                         StuffData_FinishBlock(code + count);
 360                 }
 361         }
 362         if (code == Stuff_NoCode) 
 363         {
 364                 *code_ptr_ptr = NULL;
 365         }
 366         else 
 367         {
 368                 *code_ptr_ptr = code_ptr;
 369                 StuffData_FinishBlock(code + count);
 370         }       
 371         return(dst);
 372 }
 373 
 374 /* UnStuffData decodes the data at "src", up to (but not including) "end".
 375 It writes the decoded data into the buffer pointed to by "dst", up to a
 376 maximum of "dst_length", and returns the new value of "src" so that a
 377 follow-on call can read more data, continuing from where the first left off.
 378 
 379 There are three types of results:
 380 1. The source data runs out before extracting "dst_length" bytes:
 381    UnStuffData returns NULL to indicate failure.
 382 2. The source data produces exactly "dst_length" bytes:
 383    UnStuffData returns new_src = end to indicate that all bytes were consumed.
 384 3. "dst_length" bytes are extracted, with more remaining.
 385    UnStuffData returns new_src < end to indicate that there are more bytes
 386    to be read.
 387 
 388 Note: The decoding may be destructive, in that it may alter the source
 389 data in the process of decoding it (this is necessary to allow a follow-on
 390 call to resume correctly). */
 391 
 392 static __u8 *UnStuffData(__u8 *src, __u8 *end, __u8 *dst, __u32 dst_length)
     /* [previous][next][first][last][top][bottom][index][help] */
 393 {
 394         __u8 *dst_end = dst + dst_length;
 395         /* Sanity check */
 396         if (!src || !end || !dst || !dst_length) 
 397                 return(NULL);
 398         while (src < end && dst < dst_end) 
 399         {
 400                 int count = (*src ^ Stuff_Magic) & Stuff_CountMask;
 401                 switch ((*src ^ Stuff_Magic) & Stuff_CodeMask) 
 402                 {
 403                         case Stuff_Diff:
 404                                 if (src+1+count >= end) 
 405                                         return(NULL);
 406                                 do 
 407                                 {
 408                                         *dst++ = *++src ^ Stuff_Magic;
 409                                 }
 410                                 while(--count >= 0 && dst < dst_end);
 411                                 if (count < 0) 
 412                                         src += 1;
 413                                 else 
 414                                 {
 415                                         if (count == 0)
 416                                                 *src = Stuff_Same ^ Stuff_Magic;
 417                                         else
 418                                                 *src = (Stuff_Diff + count) ^ Stuff_Magic;
 419                                 }
 420                                 break;
 421                         case Stuff_DiffZero:
 422                                 if (src+1+count >= end) 
 423                                         return(NULL);
 424                                 do 
 425                                 {
 426                                         *dst++ = *++src ^ Stuff_Magic;
 427                                 }
 428                                 while(--count >= 0 && dst < dst_end);
 429                                 if (count < 0)
 430                                         *src = Stuff_Zero ^ Stuff_Magic;
 431                                 else
 432                                         *src = (Stuff_DiffZero + count) ^ Stuff_Magic;
 433                                 break;
 434                         case Stuff_Same:
 435                                 if (src+1 >= end)
 436                                         return(NULL);
 437                                 do 
 438                                 {
 439                                         *dst++ = src[1] ^ Stuff_Magic;
 440                                 }
 441                                 while(--count >= 0 && dst < dst_end);
 442                                 if (count < 0)
 443                                         src += 2;
 444                                 else
 445                                         *src = (Stuff_Same + count) ^ Stuff_Magic;
 446                                 break;
 447                         case Stuff_Zero:
 448                                 do 
 449                                 {
 450                                         *dst++ = 0;
 451                                 }
 452                                 while(--count >= 0 && dst < dst_end);
 453                                 if (count < 0)
 454                                         src += 1;
 455                                 else
 456                                         *src = (Stuff_Zero + count) ^ Stuff_Magic;
 457                                 break;
 458                 }
 459         }
 460         if (dst < dst_end) 
 461                 return(NULL);
 462         else
 463                 return(src);
 464 }
 465 
 466 /************************************************************************/
 467 /* General routines for STRIP                                           */
 468 
 469 /* MTU has been changed by the IP layer. Unfortunately we are not told
 470  * about this, but we spot it ourselves and fix things up. We could be in
 471  * an upcall from the tty driver, or in an ip packet queue.
 472  */
 473 
 474 static void strip_changedmtu(struct strip *strip_info)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476         struct device *dev = &strip_info->dev;
 477         unsigned char *tbuff, *rbuff, *sbuff, *otbuff, *orbuff, *osbuff;
 478         int len;
 479         InterruptStatus intstat;
 480 
 481         len = STRIP_ENCAP_SIZE(dev->mtu);
 482         if (len < STRIP_ENCAP_SIZE(576)) 
 483                 len = STRIP_ENCAP_SIZE(576);
 484 
 485         tbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 486         rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 487         sbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 488         if (!tbuff || !rbuff || !sbuff) 
 489         {
 490                 printk("%s: unable to grow strip buffers, MTU change cancelled.\n",
 491                         strip_info->dev.name);
 492                 dev->mtu = strip_info->mtu;
 493                 if (tbuff)
 494                         kfree(tbuff);
 495                 if (rbuff)
 496                         kfree(rbuff);
 497                 if (sbuff)
 498                         kfree(sbuff);
 499                 return;
 500         }
 501 
 502         intstat = DisableInterrupts();
 503         otbuff = strip_info->tx_buff; strip_info->tx_buff = tbuff;
 504         orbuff = strip_info->rx_buff; strip_info->rx_buff = rbuff;
 505         osbuff = strip_info->sx_buff; strip_info->sx_buff = sbuff;
 506         if (strip_info->tx_left) 
 507         {
 508                 if (strip_info->tx_left <= len)
 509                         memcpy(strip_info->tx_buff, strip_info->tx_head, strip_info->tx_left);
 510                 else 
 511                 {
 512                         strip_info->tx_left = 0;
 513                         strip_info->tx_dropped++;
 514                 }
 515         }
 516         strip_info->tx_head = strip_info->tx_buff;
 517 
 518         if (strip_info->sx_count) 
 519         {
 520                 if (strip_info->sx_count <= len)
 521                         memcpy(strip_info->sx_buff, osbuff, strip_info->sx_count);
 522                 else
 523                 {
 524                         strip_info->sx_count = 0;
 525                         strip_info->rx_over_errors++;
 526                         set_bit(STR_ERROR, &strip_info->flags);
 527                 }
 528         }
 529 
 530         strip_info->mtu      = STRIP_ENCAP_SIZE(dev->mtu);
 531         strip_info->buffsize = len;
 532 
 533         RestoreInterrupts(intstat);
 534 
 535         if (otbuff != NULL)
 536                  kfree(otbuff);
 537         if (orbuff != NULL)
 538                 kfree(orbuff);
 539         if (osbuff != NULL)
 540                 kfree(osbuff);
 541 }
 542 
 543 static void strip_unlock(struct strip *strip_info)
     /* [previous][next][first][last][top][bottom][index][help] */
 544 {
 545         strip_info->idle_timer.expires  = jiffies + 2 * HZ;
 546         add_timer(&strip_info->idle_timer);
 547         if (!clear_bit(0, (void *)&strip_info->dev.tbusy))
 548                 printk("%s: trying to unlock already unlocked device!\n",
 549                         strip_info->dev.name);
 550 }
 551 
 552 /************************************************************************/
 553 /* Sending routines                                                     */
 554 
 555 static void ResetRadio(struct strip *strip_info)
     /* [previous][next][first][last][top][bottom][index][help] */
 556 {       
 557         static const char InitString[] = "ate0dt**starmode\r**";
 558         strip_info->watchdog_doprobe = jiffies + 10 * HZ;
 559         strip_info->watchdog_doreset = jiffies + 1 * HZ;
 560         strip_info->tty->driver.write(strip_info->tty, 0,
 561                 (char *)InitString, sizeof(InitString)-1);
 562 }
 563 
 564 /*
 565  * Called by the driver when there's room for more data.  If we have
 566  * more packets to send, we send them here.
 567  */
 568 
 569 static void strip_write_some_more(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 570 {
 571         InterruptStatus intstat;
 572         int num_written;
 573         struct strip *strip_info = (struct strip *) tty->disc_data;
 574 
 575         /* First make sure we're connected. */
 576         if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start)
 577                 return;
 578 
 579         if (strip_info->tx_left > 0) 
 580         {       /* If some data left, send it */
 581                 /* Must disable interrupts because otherwise the write_wakeup might
 582                  * happen before we've had a chance to update the tx_left and
 583                  *  tx_head fields
 584                  */
 585                 intstat = DisableInterrupts();
 586                 num_written = tty->driver.write(tty, 0, strip_info->tx_head, strip_info->tx_left);
 587                 strip_info->tx_left -= num_written;
 588                 strip_info->tx_head += num_written;
 589                 RestoreInterrupts(intstat);
 590         }
 591         else                    /* Else start transmission of another packet */
 592         {
 593                 tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 594                 strip_unlock(strip_info);
 595                 mark_bh(NET_BH);
 596         }
 597 }
 598 
 599 
 600 /* Encapsulate one IP datagram. */
 601 
 602 static unsigned char *strip_stuff(unsigned char *ptr, struct strip *strip_info, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 603 {
 604     __u8         *start;
 605     __u8         *stuffstate = NULL;
 606     unsigned char  *icp        = skb->data;
 607     int             len        = skb->len;
 608     MetricomAddress haddr;
 609 
 610     if (len > strip_info->mtu) {                /* Sigh, shouldn't occur BUT ... */
 611         printk("%s: Dropping oversized transmit packet!\n", strip_info->dev.name);
 612         strip_info->tx_dropped++;
 613         return(NULL);
 614     }
 615 
 616     if (!arp_query(haddr.c, skb->raddr, &strip_info->dev)) {
 617         IPaddr a,b,c;
 618         a.l = skb->raddr;
 619         b.l = skb->saddr;
 620         c.l = skb->daddr;
 621         printk("%s: Unknown dest %d.%d.%d.%d s=%d.%d.%d.%d d=%d.%d.%d.%d\n",
 622             strip_info->dev.name,
 623             a.b[0], a.b[1], a.b[2], a.b[3],
 624             b.b[0], b.b[1], b.b[2], b.b[3],
 625             c.b[0], c.b[1], c.b[2], c.b[3]);
 626         strip_info->tx_dropped++;
 627         return(NULL);
 628     }
 629 
 630     *ptr++ = '*';
 631     ptr[3] = '0' + haddr.s[0] % 10; haddr.s[0] /= 10;
 632     ptr[2] = '0' + haddr.s[0] % 10; haddr.s[0] /= 10;
 633     ptr[1] = '0' + haddr.s[0] % 10; haddr.s[0] /= 10;
 634     ptr[0] = '0' + haddr.s[0] % 10;
 635     ptr+=4;
 636     *ptr++ = '-';
 637     ptr[3] = '0' + haddr.s[1] % 10; haddr.s[1] /= 10;
 638     ptr[2] = '0' + haddr.s[1] % 10; haddr.s[1] /= 10;
 639     ptr[1] = '0' + haddr.s[1] % 10; haddr.s[1] /= 10;
 640     ptr[0] = '0' + haddr.s[1] % 10;
 641     ptr+=4;
 642     *ptr++ = '*';
 643     *ptr++ = ProtocolKey.c[0];                          /* Protocol key */
 644     *ptr++ = ProtocolKey.c[1];
 645     *ptr++ = ProtocolKey.c[2];
 646     *ptr++ = ProtocolKey.c[3];
 647 
 648     start = ptr;
 649     ptr = StuffData(icp, len, ptr, &stuffstate);        /* Make payload */
 650 
 651     *ptr++ = 0x0D;                                      /* Put on final delimiter */
 652     return(ptr);
 653 }
 654 
 655 /* Encapsulate one IP datagram and stuff into a TTY queue. */
 656 static void strip_send(struct strip *strip_info, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 657 {
 658     unsigned char *ptr;
 659 
 660     /* See if someone has been ifconfigging */
 661     if (strip_info->mtu != STRIP_ENCAP_SIZE(strip_info->dev.mtu))
 662         strip_changedmtu(strip_info);
 663 
 664     ptr = strip_info->tx_buff;
 665 
 666     /* If we have a packet, encapsulate it and put it in the buffer */
 667     if (skb) {
 668         ptr = strip_stuff(ptr, strip_info, skb);
 669         /* If error, unlock and return */
 670         if (!ptr) { strip_unlock(strip_info); return; }
 671         strip_info->tx_packets++;       /* Count another successful packet */
 672     }
 673 
 674     /* Set up the strip_info ready to send the data */
 675     strip_info->tx_head =       strip_info->tx_buff;
 676     strip_info->tx_left = ptr - strip_info->tx_buff;
 677     strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 678 
 679     /* If watchdog has expired, reset the radio */
 680     if ((long)jiffies - strip_info->watchdog_doreset >= 0) {
 681         printk("%s: No response: Resetting radio.\n", strip_info->dev.name);
 682         ResetRadio(strip_info);
 683         /* Note: if there's a packet to send, strip_write_some_more
 684                  will do it after the reset has finished */
 685         return;
 686     }
 687     
 688     /* No reset.
 689      * If it is time for another tickle, tack it on the end of the packet
 690      */
 691     if ((long)jiffies - strip_info->watchdog_doprobe >= 0) {
 692         /* printk("%s: Routine radio test.\n", strip_info->dev.name); */
 693         *ptr++ = '*';                   /* Tickle to make radio protest */
 694         *ptr++ = '*';
 695         strip_info->tx_left += 2;
 696         strip_info->watchdog_doprobe = jiffies + 10 * HZ;
 697         strip_info->watchdog_doreset = jiffies + 1 * HZ;
 698     }
 699     
 700     /* All ready. Start the transmission */
 701     strip_write_some_more(strip_info->tty);
 702 }
 703 
 704 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 705 static int strip_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 706 {
 707     struct strip *strip_info = (struct strip *)(dev->priv);
 708 
 709     if (!dev->start) {
 710         printk("%s: xmit call when iface is down\n", dev->name);
 711         return(1);
 712     }
 713     if (set_bit(0, (void *) &strip_info->dev.tbusy)) return(1);
 714     del_timer(&strip_info->idle_timer);
 715     strip_send(strip_info, skb);
 716     if (skb) dev_kfree_skb(skb, FREE_WRITE);
 717     return(0);
 718 }
 719 
 720 /* IdleTask periodically calls strip_xmit, so even when we have no IP packets
 721    to send for an extended period of time, the watchdog processing still gets
 722    done to ensure that the radio stays in Starmode */
 723 
 724 static void strip_IdleTask(unsigned long parameter)
     /* [previous][next][first][last][top][bottom][index][help] */
 725 {
 726         strip_xmit(NULL, (struct device *)parameter);
 727 }
 728 
 729 /************************************************************************/
 730 /* Receiving routines                                                   */
 731 
 732 static int strip_receive_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 733 {
 734         return 65536;  /* We can handle an infinite amount of data. :-) */
 735 }
 736 
 737 /* Send one completely decapsulated IP datagram to the IP layer. */
 738 
 739 static void strip_bump(struct strip *strip_info, __u16 packetlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 740 {
 741         int count = sizeof(STRIP_Header) + packetlen;
 742         struct sk_buff *skb = dev_alloc_skb(count);
 743         if (skb == NULL) 
 744         {
 745                 printk("%s: memory squeeze, dropping packet.\n", 
 746                         strip_info->dev.name);
 747                 strip_info->rx_dropped++;
 748                 return;
 749         }
 750         skb->dev = &strip_info->dev;
 751         memcpy(skb_put(skb, count), strip_info->rx_buff, count);
 752         skb->mac.raw=skb->data;
 753         skb->protocol = htons(ETH_P_IP);
 754         netif_rx(skb);
 755         strip_info->rx_packets++;
 756 }
 757 
 758 static void RecvErr(char *msg, struct strip *strip_info)
     /* [previous][next][first][last][top][bottom][index][help] */
 759 {
 760         static const int MAX_RecvErr = 80;
 761         __u8 *ptr = strip_info->sx_buff;
 762         __u8 *end = strip_info->sx_buff + strip_info->sx_count;
 763         __u8 pkt_text[MAX_RecvErr], *p = pkt_text;
 764         *p++ = '\"';
 765         while (ptr<end && p < &pkt_text[MAX_RecvErr-4]) 
 766         {
 767                 if (*ptr == '\\') 
 768                 {
 769                         *p++ = '\\';
 770                         *p++ = '\\';
 771                 }
 772                 else 
 773                 {
 774                         if (*ptr >= 32 && *ptr <= 126) 
 775                                 *p++ = *ptr;
 776                         else
 777                         {
 778                                 sprintf(p, "\\%02X", *ptr);
 779                                 p+= 3;
 780                         }
 781                 }
 782                 ptr++;
 783         }
 784         if (ptr == end)
 785                 *p++ = '\"';
 786         *p++ = 0;
 787         printk("%-13s%s\n", msg, pkt_text);
 788         set_bit(STR_ERROR, &strip_info->flags);
 789         strip_info->rx_errors++;
 790 }
 791 
 792 static void RecvErr_Message(struct strip *strip_info, __u8 *sendername, __u8 *msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 793 {
 794         static const char ERR_001[] = "ERR_001 Not in StarMode!";
 795         static const char ERR_002[] = "ERR_002 Remap handle";
 796         static const char ERR_003[] = "ERR_003 Can't resolve name";
 797         static const char ERR_004[] = "ERR_004 Name too small or missing";
 798         static const char ERR_007[] = "ERR_007 Body too big";
 799         static const char ERR_008[] = "ERR_008 Bad character in name";
 800 
 801         if (!strncmp(msg, ERR_001, sizeof(ERR_001)-1))
 802                 printk("Radio %s is not in StarMode\n", sendername);
 803         else if (!strncmp(msg, ERR_002, sizeof(ERR_002)-1)) 
 804         {
 805 #ifdef notyet           /*Kernel doesn't have scanf!*/
 806                 int handle;
 807                 __u8 newname[64];
 808                 sscanf(msg, "ERR_002 Remap handle &%d to name %s", &handle, newname);
 809                 printk("Radio name %s is handle %d\n", newname, handle);
 810 #endif
 811         }
 812         else if (!strncmp(msg, ERR_003, sizeof(ERR_003)-1)) 
 813                 printk("Radio name <unspecified> is unknown (\"Can't resolve name\" error)\n");
 814         else if (!strncmp(msg, ERR_004, sizeof(ERR_004)-1)) 
 815                 strip_info->watchdog_doreset = jiffies + LONG_TIME;
 816          else if (!strncmp(msg, ERR_007, sizeof(ERR_007)-1)) 
 817          {
 818                 /*
 819                  *      Note: This error knocks the radio back into 
 820                  *      command mode. 
 821                  */
 822                 printk("Error! Packet size <unspecified> is too big for radio.");
 823                 strip_info->watchdog_doreset = jiffies;         /* Do reset ASAP */
 824         }
 825         else if (!strncmp(msg, ERR_008, sizeof(ERR_008)-1)) 
 826                 printk("Name <unspecified> contains illegal character\n");
 827         else 
 828                 RecvErr("Error Msg:", strip_info);
 829 }
 830 
 831 static void process_packet(struct strip *strip_info)
     /* [previous][next][first][last][top][bottom][index][help] */
 832 {
 833     __u8 *ptr = strip_info->sx_buff;
 834     __u8 *end = strip_info->sx_buff + strip_info->sx_count;
 835     __u8 *name, *name_end;
 836     __u16 packetlen;
 837 
 838     /* Ignore empty lines */
 839     if (strip_info->sx_count == 0) return;
 840 
 841     /* Catch 'OK' responses which show radio has fallen out of starmode */
 842     if (strip_info->sx_count == 2 && ptr[0] == 'O' && ptr[1] == 'K') {
 843         printk("%s: Radio is back in AT command mode: Will Reset\n",
 844             strip_info->dev.name);
 845         strip_info->watchdog_doreset = jiffies;         /* Do reset ASAP */
 846         return;
 847     }
 848 
 849     /* Check for start of address marker, and then skip over it */
 850     if (*ptr != '*') {
 851         /* Catch other error messages */
 852         if (ptr[0] == 'E' && ptr[1] == 'R' && ptr[2] == 'R' && ptr[3] == '_')
 853             RecvErr_Message(strip_info, NULL, strip_info->sx_buff);
 854         else RecvErr("No initial *", strip_info);
 855         return;
 856     }
 857     ptr++;
 858 
 859     /* Skip the return address */
 860     name = ptr;
 861     while (ptr < end && *ptr != '*') ptr++;
 862 
 863     /* Check for end of address marker, and skip over it */
 864     if (ptr == end) {
 865         RecvErr("No second *", strip_info);
 866         return;
 867     }
 868     name_end = ptr++;
 869 
 870     /* Check for STRIP key, and skip over it */
 871     if (ptr[0] != ProtocolKey.c[0] ||
 872         ptr[1] != ProtocolKey.c[1] ||
 873         ptr[2] != ProtocolKey.c[2] ||
 874         ptr[3] != ProtocolKey.c[3]) {
 875         if (ptr[0] == 'E' && ptr[1] == 'R' && ptr[2] == 'R' && ptr[3] == '_') { *name_end = 0; RecvErr_Message(strip_info, name, ptr); }
 876         else RecvErr("Unrecognized protocol key", strip_info);
 877         return;
 878     }
 879     ptr += 4;
 880 
 881     /* Decode start of the IP packet header */
 882     ptr = UnStuffData(ptr, end, strip_info->rx_buff, 4);
 883     if (!ptr) {
 884         RecvErr("Runt packet", strip_info);
 885         return;
 886     }
 887 
 888     packetlen = ((__u16)strip_info->rx_buff[2] << 8) | strip_info->rx_buff[3];
 889 /*      printk("Packet %02X.%02X.%02X.%02X\n",
 890         strip_info->rx_buff[0], strip_info->rx_buff[1],
 891         strip_info->rx_buff[2], strip_info->rx_buff[3]);
 892     printk("Got %d byte packet\n", packetlen);*/
 893 
 894     /* Decode remainder of the IP packer */
 895     ptr = UnStuffData(ptr, end, strip_info->rx_buff+4, packetlen-4);
 896     if (!ptr) {
 897         RecvErr("Runt packet", strip_info);
 898         return;
 899     }
 900     strip_bump(strip_info, packetlen);
 901 
 902     /* This turns out to be a mistake. Taking receipt of a valid packet as
 903      * evidence that the radio is correctly in Starmode (and resetting the
 904      * watchdog_doreset timer) is wrong.  It turns out that if the radio is
 905      * in command mode, with character echo on, then the echo of the packet
 906      * you sent coming back looks like a valid packet and fools this test.
 907      * We should only accept the "ERR_004 Name too small or missing" message
 908      * as evidence that the radio is correctly in Starmode.
 909     strip_info->watchdog_doprobe = jiffies + 10 * HZ;
 910     strip_info->watchdog_doreset = jiffies + LONG_TIME;
 911      */
 912 }
 913 
 914 /*
 915  * Handle the 'receiver data ready' interrupt.
 916  * This function is called by the 'tty_io' module in the kernel when
 917  * a block of STRIP data has been received, which can now be decapsulated
 918  * and sent on to some IP layer for further processing.
 919  */
 920 static void
 921 strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 922 {
 923 /*      struct timeval tv;*/
 924     struct strip *strip_info = (struct strip *) tty->disc_data;
 925     const unsigned char *end = cp + count;
 926 
 927     if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start)
 928         return;
 929 
 930     /* Argh! mtu change time! - costs us the packet part received at the change */
 931     if (strip_info->mtu != STRIP_ENCAP_SIZE(strip_info->dev.mtu))
 932         strip_changedmtu(strip_info);
 933 
 934 /*      do_gettimeofday(&tv);
 935     printk("**** strip_receive_buf: %3d bytes at %d.%06d\n",
 936         count, tv.tv_sec % 100, tv.tv_usec);*/
 937     /* Read the characters out of the buffer */
 938     while (cp < end) {
 939         if (fp && *fp++) {
 940             if (!set_bit(STR_ERROR, &strip_info->flags)) strip_info->rx_errors++;
 941         }
 942         else if (*cp == 0x0D) {
 943             /*printk("Cut a %d byte packet (%d bytes remaining)\n",
 944                 strip_info->sx_count, end-cp-1);*/
 945             if (!clear_bit(STR_ERROR, &strip_info->flags))
 946                 process_packet(strip_info);
 947             strip_info->sx_count = 0;
 948         }
 949         else if (!test_bit(STR_ERROR, &strip_info->flags) &&
 950             (strip_info->sx_count > 0 || *cp != 0x0A))
 951         {
 952             /* (leading newline characters are ignored) */
 953             if (strip_info->sx_count < strip_info->buffsize)
 954                 strip_info->sx_buff[strip_info->sx_count++] = *cp;
 955             else
 956             {
 957                 set_bit(STR_ERROR, &strip_info->flags);
 958                 strip_info->rx_over_errors++;
 959             }
 960         }
 961         cp++;
 962     }
 963 }
 964 
 965 /************************************************************************/
 966 /* General control routines                                             */
 967 
 968 /*
 969  *       Create the Ethernet MAC header for an arbitrary protocol layer 
 970  *
 971  *      saddr=NULL      means use device source address
 972  *      daddr=NULL      means leave destination address (eg unresolved arp)
 973  */
 974 
 975 static int strip_header(struct sk_buff *skb, struct device *dev, 
     /* [previous][next][first][last][top][bottom][index][help] */
 976         unsigned short type, void *daddr, void *saddr, unsigned len)
 977 {
 978         return(-dev->hard_header_len);
 979 }
 980 
 981 /*
 982  *      Rebuild the Ethernet MAC header. This is called after an ARP
 983  *      (or in future other address resolution) has completed on this
 984  *      sk_buff. We now let ARP fill in the other fields.
 985  */
 986 
 987 /* I think this should return zero if packet is ready to send, */
 988 /* or non-zero if it needs more time to do an address lookup   */
 989 
 990 static int strip_rebuild_header(void *buff, struct device *dev, 
     /* [previous][next][first][last][top][bottom][index][help] */
 991         unsigned long dst, struct sk_buff *skb)
 992 {
 993 /*      STRIP_Header *h = (STRIP_Header *)buff;*/
 994 
 995 #ifdef CONFIG_INET
 996         /* I'll use arp_find when I understand it */
 997         /* Arp find returns zero if if knows the address, or if it doesn't */
 998         /* know the address it sends an ARP packet and returns non-zero */
 999         /*return arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb)? 1 : 0;*/
1000         return(0);
1001 #else
1002         return(0);
1003 #endif  
1004 }
1005 
1006 static int strip_set_dev_mac_address(struct device *dev, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
1007 {
1008         memcpy(dev->dev_addr, addr, 7);
1009         return 0;
1010 }
1011 
1012 static struct enet_statistics *strip_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1013 {
1014         static struct enet_statistics stats;
1015         struct strip *strip_info = (struct strip *)(dev->priv);
1016 
1017         memset(&stats, 0, sizeof(struct enet_statistics));
1018 
1019         stats.rx_packets     = strip_info->rx_packets;
1020         stats.tx_packets     = strip_info->tx_packets;
1021         stats.rx_dropped     = strip_info->rx_dropped;
1022         stats.tx_dropped     = strip_info->tx_dropped;
1023         stats.tx_errors      = strip_info->tx_errors;
1024         stats.rx_errors      = strip_info->rx_errors;
1025         stats.rx_over_errors = strip_info->rx_over_errors;
1026         return(&stats);
1027 }
1028 
1029 /************************************************************************/
1030 /* Opening and closing                                                  */
1031 
1032 /*
1033  * Here's the order things happen:
1034  * When the user runs "slattach -p strip ..."
1035  *  1. The TTY module calls strip_open
1036  *  2. strip_open calls strip_alloc
1037  *  3.                  strip_alloc calls register_netdev
1038  *  4.                  register_netdev calls strip_dev_init
1039  *  5. then strip_open finishes setting up the strip_info
1040  *
1041  * When the user runs "ifconfig st<x> up address netmask ..."
1042  *  6. strip_open_low gets called
1043  *
1044  * When the user runs "ifconfig st<x> down"
1045  *  7. strip_close_low gets called
1046  *
1047  * When the user kills the slattach process
1048  *  8. strip_close gets called
1049  *  9. strip_close calls dev_close
1050  * 10. if the device is still up, then dev_close calls strip_close_low
1051  * 11. strip_close calls strip_free
1052  */
1053 
1054 /* Open the low-level part of the STRIP channel. Easy! */
1055 
1056 static int strip_open_low(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1057 {
1058         struct strip *strip_info = (struct strip *)(dev->priv);
1059         unsigned long len;
1060 
1061         if (strip_info->tty == NULL) 
1062                 return(-ENODEV);
1063 
1064         /*
1065          * Allocate the STRIP frame buffers:
1066          *
1067          * rbuff        Receive buffer.
1068          * tbuff        Transmit buffer.
1069          * cbuff        Temporary compression buffer.
1070          */
1071 
1072         len = STRIP_ENCAP_SIZE(dev->mtu);
1073         if (len < STRIP_ENCAP_SIZE(576)) 
1074                 len = STRIP_ENCAP_SIZE(576);
1075         strip_info->rx_buff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
1076         if (strip_info->rx_buff == NULL) 
1077                 goto norbuff;
1078         strip_info->sx_buff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
1079         if (strip_info->sx_buff == NULL) 
1080                 goto nosbuff;
1081         strip_info->tx_buff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
1082         if (strip_info->tx_buff == NULL) 
1083                 goto notbuff;
1084 
1085         strip_info->flags   &= (1 << STR_INUSE); /* Clear ESCAPE & ERROR flags */
1086         strip_info->mtu  = STRIP_ENCAP_SIZE(dev->mtu);
1087         strip_info->buffsize = len;
1088         strip_info->sx_count = 0;
1089         strip_info->tx_left  = 0;
1090 
1091         /*
1092          *      Needed because address '0' is special 
1093          */
1094          
1095         if (dev->pa_addr == 0) 
1096                 dev->pa_addr=ntohl(0xC0A80001);
1097         dev->tbusy  = 0;
1098         dev->start  = 1;
1099 
1100         printk("%s: Initializing Radio.\n", strip_info->dev.name);
1101         ResetRadio(strip_info);
1102         strip_info->idle_timer.expires  = jiffies + 2 * HZ;
1103         add_timer(&strip_info->idle_timer);
1104         return(0);
1105 
1106 notbuff:
1107         kfree(strip_info->sx_buff);
1108 nosbuff:
1109         kfree(strip_info->rx_buff);
1110 norbuff:
1111         return(-ENOMEM);
1112 }
1113 
1114 
1115 /*
1116  *      Close the low-level part of the STRIP channel. Easy! 
1117  */
1118  
1119 static int strip_close_low(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1120 {
1121         struct strip *strip_info = (struct strip *)(dev->priv);
1122 
1123         if (strip_info->tty == NULL) 
1124                 return -EBUSY;
1125         strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
1126         dev->tbusy = 1;
1127         dev->start = 0;
1128     
1129         /*
1130          *      Free all STRIP frame buffers.
1131          */
1132         if (strip_info->rx_buff) 
1133         {
1134                 kfree(strip_info->rx_buff);
1135                 strip_info->rx_buff = NULL;
1136         }
1137         if (strip_info->sx_buff) 
1138         {
1139                 kfree(strip_info->sx_buff); 
1140                 strip_info->sx_buff = NULL;
1141         }
1142         if (strip_info->tx_buff) 
1143         {
1144                 kfree(strip_info->tx_buff); 
1145                 strip_info->tx_buff = NULL; 
1146         }
1147         del_timer(&strip_info->idle_timer);
1148         return 0;
1149 }
1150 
1151 /* 
1152  *      This routine is called by DDI when the
1153  *      (dynamically assigned) device is registered
1154  */
1155  
1156 static int strip_dev_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1157 {
1158         int i;
1159         
1160         /*
1161          *      Finish setting up the DEVICE info. 
1162          */
1163 
1164         dev->trans_start        = 0;
1165         dev->last_rx            = 0;
1166         dev->tx_queue_len       = 30;   /* Drop after 30 frames queued */
1167 
1168         dev->flags              = 0;
1169         dev->family             = AF_INET;
1170         dev->metric             = 0;
1171         dev->mtu                = STRIP_MTU;
1172         dev->type               = ARPHRD_METRICOM;        /* dtang */
1173         dev->hard_header_len    = 8; /*sizeof(STRIP_Header);*/
1174         /*
1175          *  dev->priv                 Already holds a pointer to our struct strip 
1176          */
1177 
1178         dev->broadcast[0]       = 0;
1179         dev->dev_addr[0]        = 0;
1180         dev->addr_len           = sizeof(MetricomAddress);
1181         dev->pa_addr            = 0;
1182         dev->pa_brdaddr         = 0;
1183         dev->pa_mask            = 0;
1184         dev->pa_alen            = sizeof(unsigned long);
1185 
1186         /*
1187          *      Pointer to the interface buffers. 
1188          */
1189          
1190         for (i = 0; i < DEV_NUMBUFFS; i++) 
1191                 skb_queue_head_init(&dev->buffs[i]);
1192 
1193         /*
1194          *      Pointers to interface service routines. 
1195          */
1196 
1197         dev->open               = strip_open_low;
1198         dev->stop               = strip_close_low;
1199         dev->hard_start_xmit    = strip_xmit;
1200         dev->hard_header        = strip_header;
1201         dev->rebuild_header     = strip_rebuild_header;
1202         /*  dev->type_trans            unused */
1203         /*  dev->set_multicast_list   unused */
1204         dev->set_mac_address    = strip_set_dev_mac_address;
1205         /*  dev->do_ioctl             unused */
1206         /*  dev->set_config           unused */
1207         dev->get_stats          = strip_get_stats;
1208         return 0;
1209 }
1210 
1211 /*
1212  *      Free a STRIP channel. 
1213  */
1214  
1215 static void strip_free(struct strip *strip_info)
     /* [previous][next][first][last][top][bottom][index][help] */
1216 {
1217         *(strip_info->referrer) = strip_info->next;
1218         if (strip_info->next) 
1219                 strip_info->next->referrer = strip_info->referrer;
1220         strip_info->magic = 0;
1221         kfree(strip_info);
1222 }
1223 
1224 /* 
1225  *      Allocate a new free STRIP channel 
1226  */
1227  
1228 static struct strip *strip_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1229 {
1230         int channel_id = 0;
1231         struct strip **s = &struct_strip_list;
1232         struct strip *strip_info = (struct strip *)
1233                 kmalloc(sizeof(struct strip), GFP_KERNEL);
1234 
1235         if (!strip_info) 
1236                 return(NULL);   /* If no more memory, return */
1237 
1238         /*
1239          *      Clear the allocated memory 
1240          */
1241          
1242         memset(strip_info, 0, sizeof(struct strip));
1243 
1244         /*
1245          *      Search the list to find where to put our new entry
1246          *      (and in the process decide what channel number it is
1247          *      going to be) 
1248          */
1249          
1250         while (*s && (*s)->dev.base_addr == channel_id) 
1251         {
1252                 channel_id++;
1253                 s = &(*s)->next;
1254         }
1255 
1256         /*
1257          *      Fill in the link pointers 
1258          */
1259          
1260         strip_info->next = *s;
1261         if (*s) 
1262                 (*s)->referrer = &strip_info->next;
1263         strip_info->referrer = s;
1264         *s = strip_info;
1265 
1266         set_bit(STR_INUSE, &strip_info->flags);
1267         strip_info->magic = STRIP_MAGIC;
1268         strip_info->tty   = NULL;
1269 
1270         init_timer(&strip_info->idle_timer);
1271         strip_info->idle_timer.data     = (long)&strip_info->dev;
1272         strip_info->idle_timer.function = strip_IdleTask;
1273 
1274         sprintf(strip_info->if_name, "st%d", channel_id);
1275         strip_info->dev.name         = strip_info->if_name;
1276         strip_info->dev.base_addr    = channel_id;
1277         strip_info->dev.priv         = (void*)strip_info;
1278         strip_info->dev.next         = NULL;
1279         strip_info->dev.init         = strip_dev_init;
1280 
1281         return(strip_info);
1282 }
1283 
1284 /*
1285  *      Open the high-level part of the STRIP channel.
1286  *      This function is called by the TTY module when the
1287  *      STRIP line discipline is called for.  Because we are
1288  *      sure the tty line exists, we only have to link it to
1289  *      a free STRIP channel...
1290  */
1291 
1292 static int strip_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1293 {
1294         struct strip *strip_info = (struct strip *) tty->disc_data;
1295 
1296         /*
1297          *      First make sure we're not already connected.
1298          */
1299         
1300         if (strip_info && strip_info->magic == STRIP_MAGIC) 
1301                 return -EEXIST;
1302 
1303         /*
1304          *      OK.  Find a free STRIP channel to use. 
1305          */
1306          
1307         if ((strip_info = strip_alloc()) == NULL) 
1308                 return -ENFILE;
1309 
1310         /*
1311          *      Register our newly created device so it can be ifconfig'd
1312          * strip_dev_init() will be called as a side-effect
1313          */
1314      
1315         if (register_netdev(&strip_info->dev) != 0) 
1316         {
1317                 printk("strip: register_netdev() failed.\n");
1318                 strip_free(strip_info);
1319                 return -ENFILE;
1320         }
1321 
1322         strip_info->tty = tty;
1323         tty->disc_data = strip_info;
1324         if (tty->driver.flush_buffer) 
1325                 tty->driver.flush_buffer(tty);
1326         if (tty->ldisc.flush_buffer) 
1327                 tty->ldisc.flush_buffer(tty);
1328 
1329         /*
1330          *      Restore default settings 
1331          */
1332          
1333         strip_info->dev.type = ARPHRD_METRICOM; /* dtang */
1334 
1335         /*
1336          *      Set tty options 
1337          */
1338 
1339         tty->termios->c_iflag |= IGNBRK |IGNPAR;/* Ignore breaks and parity errors. */
1340         tty->termios->c_cflag |= CLOCAL;        /* Ignore modem control signals. */
1341         tty->termios->c_cflag &= ~HUPCL;        /* Don't close on hup */
1342 
1343 #ifdef MODULE
1344         MOD_INC_USE_COUNT;
1345 #endif
1346         /*
1347          *      Done.  We have linked the TTY line to a channel. 
1348          */
1349         return(strip_info->dev.base_addr);
1350 }
1351 
1352 /*
1353  * Close down a STRIP channel.
1354  * This means flushing out any pending queues, and then restoring the
1355  * TTY line discipline to what it was before it got hooked to STRIP
1356  * (which usually is TTY again).
1357  */
1358 static void strip_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1359 {
1360         struct strip *strip_info = (struct strip *) tty->disc_data;
1361 
1362         /*
1363          *      First make sure we're connected. 
1364          */
1365          
1366         if (!strip_info || strip_info->magic != STRIP_MAGIC) 
1367                 return;
1368 
1369         dev_close(&strip_info->dev);
1370         unregister_netdev(&strip_info->dev);
1371     
1372         tty->disc_data = 0;
1373         strip_info->tty = NULL;
1374         strip_free(strip_info);
1375         tty->disc_data = NULL;
1376 #ifdef MODULE
1377         MOD_DEC_USE_COUNT;
1378 #endif
1379 }
1380 
1381 
1382 /************************************************************************/
1383 /* Perform I/O control calls on an active STRIP channel.                */
1384 
1385 static int strip_ioctl(struct tty_struct *tty, struct file *file, 
     /* [previous][next][first][last][top][bottom][index][help] */
1386         unsigned int cmd, unsigned long arg)
1387 {
1388         struct strip *strip_info = (struct strip *) tty->disc_data;
1389         int err;
1390 
1391         /*
1392          *      First make sure we're connected. 
1393          */
1394          
1395         if (!strip_info || strip_info->magic != STRIP_MAGIC) 
1396                 return -EINVAL;
1397 
1398         switch(cmd) 
1399         {
1400                 case SIOCGIFNAME:
1401                         err = verify_area(VERIFY_WRITE, (void*)arg, 16);
1402                         if (err)
1403                                 return -err;
1404                         memcpy_tofs((void*)arg, strip_info->dev.name, 
1405                                 strlen(strip_info->dev.name) + 1);
1406                         return 0;
1407 
1408                 case SIOCSIFHWADDR:
1409                         return -EINVAL;
1410 
1411                 /*
1412                  *      Allow stty to read, but not set, the serial port 
1413                  */
1414          
1415                 case TCGETS:
1416                 case TCGETA:
1417                         return n_tty_ioctl(tty, (struct file *) file, cmd, 
1418                                 (unsigned long) arg);
1419 
1420                 default:
1421                         return -ENOIOCTLCMD;
1422         }
1423 }
1424 
1425 /************************************************************************/
1426 /* Initialization                                                       */
1427 
1428 /*
1429  *      Initialize the STRIP driver.
1430  *      This routine is called at boot time, to bootstrap the multi-channel
1431  *      STRIP driver
1432  */
1433 
1434 #ifdef MODULE
1435 static
1436 #endif
1437 int strip_init_ctrl_dev(struct device *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
1438 {
1439         static struct tty_ldisc strip_ldisc;
1440         int status;
1441         printk("STRIP: version %s (unlimited channels)\n", STRIP_VERSION);
1442 
1443         /*
1444          *      Fill in our line protocol discipline, and register it
1445          */
1446          
1447         memset(&strip_ldisc, 0, sizeof(strip_ldisc));
1448         strip_ldisc.magic       = TTY_LDISC_MAGIC;
1449         strip_ldisc.flags       = 0;
1450         strip_ldisc.open        = strip_open;
1451         strip_ldisc.close       = strip_close;
1452         strip_ldisc.read        = NULL;
1453         strip_ldisc.write       = NULL;
1454         strip_ldisc.ioctl       = strip_ioctl;
1455         strip_ldisc.select       = NULL;
1456         strip_ldisc.receive_buf  = strip_receive_buf;
1457         strip_ldisc.receive_room = strip_receive_room;
1458         strip_ldisc.write_wakeup = strip_write_some_more;
1459         status = tty_register_ldisc(N_STRIP, &strip_ldisc);
1460         if (status != 0) 
1461         {
1462                 printk("STRIP: can't register line discipline (err = %d)\n", status);
1463         }
1464 
1465 #ifdef MODULE
1466          return status;
1467 #else
1468         /* Return "not found", so that dev_init() will unlink
1469          * the placeholder device entry for us.
1470          */
1471         return ENODEV;
1472 #endif
1473 }
1474 
1475 /************************************************************************/
1476 /* From here down is only used when compiled as an external module        */
1477 
1478 #ifdef MODULE
1479 
1480 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1481 {
1482     return strip_init_ctrl_dev(0);
1483 }
1484 
1485 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1486 {
1487         int i;
1488         while (struct_strip_list) 
1489                 strip_free(struct_strip_list);
1490 
1491         if ((i = tty_register_ldisc(N_STRIP, NULL)))  
1492                 printk("STRIP: can't unregister line discipline (err = %d)\n", i);
1493 }
1494 #endif /* MODULE */

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