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]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
135 {
136 InterruptStatus x;
137 save_flags(x);
138 cli();
139 return(x);
140 }
141
142 extern __inline__ void RestoreInterrupts(InterruptStatus x)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1481 {
1482 return strip_init_ctrl_dev(0);
1483 }
1484
1485 void cleanup_module(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 */