This source file includes following definitions.
- ip_dump
- sl_initialize
- sl_find
- sl_alloc
- sl_free
- sl_enqueue
- sl_dequeue
- sl_lock
- sl_unlock
- sl_bump
- sl_next
- sl_encaps
- sl_xmit
- sl_type_trans
- sl_header
- sl_add_arp
- sl_rebuild_header
- sl_open
- sl_close
- slip_recv
- slip_open
- slip_close
- slip_ioctl
- slip_init
1
2
3
4
5
6
7
8
9
10
11 #include <asm/segment.h>
12 #include <asm/system.h>
13 #include <linux/types.h>
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/string.h>
17 #include <linux/mm.h>
18 #include <linux/socket.h>
19 #include <linux/termios.h>
20 #include <linux/sockios.h>
21 #include <linux/interrupt.h>
22 #include <linux/tty.h>
23 #include <linux/errno.h>
24 #include <linux/stat.h>
25 #include <linux/tty.h>
26 #include <linux/in.h>
27 #include "inet.h"
28 #include "dev.h"
29 #include "eth.h"
30 #include "timer.h"
31 #include "ip.h"
32 #include "route.h"
33 #include "protocol.h"
34 #include "tcp.h"
35 #include "skbuff.h"
36 #include "sock.h"
37 #include "arp.h"
38 #include "slip.h"
39
40
41 #define SLIP_VERSION "0.7.5"
42
43
44
45 #ifdef SL_DUMP
46 # define IP_VERSION 4
47 # define IPF_F_OFFSET 0x1fff
48 # define IPF_DF 0x4000
49 # define IPF_MF 0x2000
50 # define IP_OF_COPIED 0x80
51 # define IP_OF_CLASS 0x60
52 # define IP_OF_NUMBER 0x1f
53 #endif
54
55
56 static struct slip sl_ctrl[SL_NRUNIT];
57 static struct tty_ldisc sl_ldisc;
58 static int already = 0;
59
60
61
62 static void
63 ip_dump(unsigned char *ptr, int len)
64 {
65 #ifdef SL_DUMP
66 struct iphdr *ip;
67 int dlen, doff;
68
69 if (inet_debug != DBG_SLIP) return;
70
71 ip = (struct iphdr *) ptr;
72 dlen = ntohs(ip->tot_len);
73 doff = ((ntohs(ip->frag_off) & IPF_F_OFFSET) << 3);
74
75 printk("\r*****\n");
76 printk("SLIP: %s->", in_ntoa(ip->saddr));
77 printk("%s\n", in_ntoa(ip->daddr));
78 printk(" len %u ihl %u ver %u ttl %u prot %u",
79 dlen, ip->ihl, ip->version, ip->ttl, ip->protocol);
80
81 if (ip->tos != 0) printk(" tos %u", ip->tos);
82 if (doff != 0 || (ntohs(ip->frag_off) & IPF_MF))
83 printk(" id %u offs %u", ntohs(ip->id), doff);
84
85 if (ntohs(ip->frag_off) & IPF_DF) printk(" DF");
86 if (ntohs(ip->frag_off) & IPF_MF) printk(" MF");
87 printk("\n*****\n");
88 #endif
89 }
90
91
92
93 static void
94 sl_initialize(struct slip *sl, struct device *dev)
95 {
96 sl->inuse = 0;
97 sl->sending = 0;
98 sl->escape = 0;
99
100 sl->line = dev->base_addr;
101 sl->tty = NULL;
102 sl->dev = dev;
103
104
105 sl->rbuff = NULL;
106 sl->xbuff = NULL;
107
108 sl->rhead = NULL;
109 sl->rend = NULL;
110 dev->rmem_end = (unsigned long) NULL;
111 dev->rmem_start = (unsigned long) NULL;
112 dev->mem_end = (unsigned long) NULL;
113 dev->mem_start = (unsigned long) NULL;
114 }
115
116
117
118 static struct slip *
119 sl_find(struct tty_struct *tty)
120 {
121 struct slip *sl;
122 int i;
123
124 if (tty == NULL) return(NULL);
125 for (i = 0; i < SL_NRUNIT; i++) {
126 sl = &sl_ctrl[i];
127 if (sl->tty == tty) return(sl);
128 }
129 return(NULL);
130 }
131
132
133
134 static inline struct slip *
135 sl_alloc(void)
136 {
137 unsigned long flags;
138 struct slip *sl;
139 int i;
140
141 for (i = 0; i < SL_NRUNIT; i++) {
142 sl = &sl_ctrl[i];
143 if (sl->inuse == 0) {
144 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
145 sl->inuse = 1;
146 sl->tty = NULL;
147 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
148 return(sl);
149 }
150 }
151 return(NULL);
152 }
153
154
155
156 static inline void
157 sl_free(struct slip *sl)
158 {
159 unsigned long flags;
160
161 if (sl->inuse) {
162 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
163 sl->inuse = 0;
164 sl->tty = NULL;
165 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
166 }
167 }
168
169
170
171 static inline void
172 sl_enqueue(struct slip *sl, unsigned char c)
173 {
174 unsigned long flags;
175
176 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
177 if (sl->rhead < sl->rend) {
178 *sl->rhead = c;
179 sl->rhead++;
180 sl->rcount++;
181 } else sl->roverrun++;
182 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
183 }
184
185
186
187 static inline void
188 sl_dequeue(struct slip *sl, int i)
189 {
190 unsigned long flags;
191
192 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
193 if (sl->rhead > sl->rbuff) {
194 sl->rhead -= i;
195 sl->rcount -= i;
196 }
197 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
198 }
199
200
201
202 static inline void
203 sl_lock(struct slip *sl)
204 {
205 unsigned long flags;
206
207 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
208 sl->sending = 1;
209 sl->dev->tbusy = 1;
210 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
211 }
212
213
214
215 static inline void
216 sl_unlock(struct slip *sl)
217 {
218 unsigned long flags;
219
220 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
221 sl->sending = 0;
222 sl->dev->tbusy = 0;
223 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
224 }
225
226
227
228 static void
229 sl_bump(struct slip *sl)
230 {
231 int done;
232
233 DPRINTF((DBG_SLIP, "<< \"%s\" recv:\r\n", sl->dev->name));
234 ip_dump(sl->rbuff, sl->rcount);
235
236
237 do {
238 DPRINTF((DBG_SLIP, "SLIP: packet is %d at 0x%X\n",
239 sl->rcount, sl->rbuff));
240 done = dev_rint(sl->rbuff, sl->rcount, 0, sl->dev);
241 if (done == 0 || done == 1) break;
242 } while(1);
243 sl->rpacket++;
244 }
245
246
247
248 static void
249 sl_next(struct slip *sl)
250 {
251 DPRINTF((DBG_SLIP, "SLIP: sl_next(0x%X) called!\n", sl));
252 sl_unlock(sl);
253 }
254
255
256
257 static void
258 sl_encaps(struct slip *sl, unsigned char *p, int len)
259 {
260 unsigned char *bp;
261 unsigned char c;
262 int count;
263
264 DPRINTF((DBG_SLIP, "SLIP: sl_encaps(0x%X, %d) called\n", p, len));
265 DPRINTF((DBG_SLIP, ">> \"%s\" sent:\r\n", sl->dev->name));
266 ip_dump(p, len);
267
268
269
270
271
272
273 bp = (unsigned char *) sl->xbuff;
274 *bp++ = END;
275 count = 1;
276
277
278
279
280
281 while(len-- > 0) {
282 c = *p++;
283 switch((c & 0377)) {
284 case END:
285 *bp++ = ESC;
286 *bp++ = ESC_END;
287 count += 2;
288 break;
289 case ESC:
290 *bp++ = ESC;
291 *bp++ = ESC_ESC;
292 count += 2;
293 break;
294 default:
295 *bp++ = c;
296 count++;
297 }
298 }
299 *bp++ = END;
300 count++;
301 sl->spacket++;
302 bp = (unsigned char *) sl->xbuff;
303
304
305 DPRINTF((DBG_SLIP, "SLIP: kicking TTY for %d bytes at 0x%X\n", count, bp));
306 if (tty_write_data(sl->tty, (char *) bp, count,
307 (void (*)(void *))sl_next, (void *) sl) == 0) {
308 DPRINTF((DBG_SLIP, "SLIP: TTY already done with %d bytes!\n", count));
309 sl_next(sl);
310 }
311 }
312
313
314
315 static int
316 sl_xmit(struct sk_buff *skb, struct device *dev)
317 {
318 struct tty_struct *tty;
319 struct slip *sl;
320
321
322 sl = &sl_ctrl[dev->base_addr];
323 tty = sl->tty;
324 DPRINTF((DBG_SLIP, "SLIP: sl_xmit(\"%s\") skb=0x%X busy=%d\n",
325 dev->name, skb, sl->sending));
326
327
328
329
330
331
332 if (sl->sending) {
333 DPRINTF((DBG_SLIP, "SLIP: sl_xmit: BUSY\r\n"));
334 sl->sbusy++;
335 return(1);
336 }
337
338
339 if (skb != NULL) {
340 sl_lock(sl);
341 sl_encaps(sl, (unsigned char *) (skb + 1), skb->len);
342 if (skb->free) kfree_skb(skb, FREE_WRITE);
343 }
344 return(0);
345 }
346
347
348
349 static unsigned short
350 sl_type_trans (struct sk_buff *skb, struct device *dev)
351 {
352 return(NET16(ETH_P_IP));
353 }
354
355
356
357 static int
358 sl_header(unsigned char *buff, struct device *dev, unsigned short type,
359 unsigned long daddr, unsigned long saddr, unsigned len)
360 {
361 return(0);
362 }
363
364
365
366 static void
367 sl_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
368 {
369 }
370
371
372
373 static int
374 sl_rebuild_header(void *buff, struct device *dev)
375 {
376 return(0);
377 }
378
379
380
381 static int
382 sl_open(struct device *dev)
383 {
384 struct slip *sl;
385 unsigned char *p;
386 unsigned long l;
387
388 sl = &sl_ctrl[dev->base_addr];
389 if (sl->tty == NULL) {
390 DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));
391 return(-ENXIO);
392 }
393 sl->dev = dev;
394
395
396
397
398
399
400
401
402
403 l = (dev->mtu * 2);
404 p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
405 if (p == NULL) {
406 DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP XMIT buffer!\n"));
407 return(-ENOMEM);
408 }
409 sl->dev->mem_start = (unsigned long) p;
410 sl->dev->mem_end = (unsigned long) (sl->dev->mem_start + l);
411
412 p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
413 if (p == NULL) {
414 DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP RECV buffer!\n"));
415 return(-ENOMEM);
416 }
417 sl->dev->rmem_start = (unsigned long) p;
418 sl->dev->rmem_end = (unsigned long) (sl->dev->rmem_start + l);
419
420 sl->xbuff = (unsigned char *) sl->dev->mem_start;
421 sl->rbuff = (unsigned char *) sl->dev->rmem_start;
422 sl->rend = (unsigned char *) sl->dev->rmem_end;
423 sl->rhead = sl->rbuff;
424
425 sl->escape = 0;
426 sl->sending = 0;
427 sl->rcount = 0;
428
429 DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line));
430 return(0);
431 }
432
433
434
435 static int
436 sl_close(struct device *dev)
437 {
438 struct slip *sl;
439
440 sl = &sl_ctrl[dev->base_addr];
441 if (sl->tty == NULL) {
442 DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));
443 return(-EBUSY);
444 }
445 sl_free(sl);
446
447
448 kfree(sl->rbuff);
449 kfree(sl->xbuff);
450 sl_initialize(sl, dev);
451
452 DPRINTF((DBG_SLIP, "SLIP: channel %d closed.\n", sl->line));
453 return(0);
454 }
455
456
457
458
459
460
461
462
463 static void
464 slip_recv(struct tty_struct *tty)
465 {
466 unsigned char buff[128];
467 unsigned char *p, c;
468 struct slip *sl;
469 int count;
470
471 DPRINTF((DBG_SLIP, "SLIP: slip_recv(%d) called\n", tty->line));
472 if ((sl = sl_find(tty)) == NULL) return;
473
474
475 do {
476 memset(buff, 0, 128);
477 count = tty_read_raw_data(tty, buff, 128);
478 if (count <= 0) break;
479
480 p = buff;
481 while(count-- > 0) {
482 c = *p++;
483 switch((c & 0377)) {
484 case ESC:
485 sl->escape = 1;
486 break;
487 case ESC_ESC:
488 if (sl->escape) sl_enqueue(sl, ESC);
489 else sl_enqueue(sl, c);
490 sl->escape = 0;
491 break;
492 case ESC_END:
493 if (sl->escape) sl_enqueue(sl, END);
494 else sl_enqueue(sl, c);
495 sl->escape = 0;
496 break;
497 case END:
498 if (sl->rcount > 3) sl_bump(sl);
499 sl_dequeue(sl, sl->rcount);
500 sl->rcount = 0;
501 sl->escape = 0;
502 break;
503 default:
504 sl_enqueue(sl, c);
505 sl->escape = 0;
506 }
507 }
508 } while(1);
509 }
510
511
512
513
514
515
516
517
518
519 static int
520 slip_open(struct tty_struct *tty)
521 {
522 struct slip *sl;
523
524
525 if ((sl = sl_find(tty)) != NULL) {
526 DPRINTF((DBG_SLIP, "SLIP: TTY %d already connected to %s !\n",
527 tty->line, sl->dev->name));
528 return(-EEXIST);
529 }
530
531
532 if ((sl = sl_alloc()) == NULL) {
533 DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected: all channels in use!\n",
534 tty->line));
535 return(-ENFILE);
536 }
537 sl->tty = tty;
538 tty_read_flush(tty);
539 tty_write_flush(tty);
540
541
542 (void) sl_open(sl->dev);
543 DPRINTF((DBG_SLIP, "SLIP: TTY %d connected to %s.\n",
544 tty->line, sl->dev->name));
545
546
547 return(sl->line);
548 }
549
550
551
552
553
554
555
556
557 static void
558 slip_close(struct tty_struct *tty)
559 {
560 struct slip *sl;
561
562
563 if ((sl = sl_find(tty)) == NULL) {
564 DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected !\n", tty->line));
565 return;
566 }
567
568 (void) dev_close(sl->dev);
569 DPRINTF((DBG_SLIP, "SLIP: TTY %d disconnected from %s.\n",
570 tty->line, sl->dev->name));
571 }
572
573
574
575 static int
576 slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
577 {
578 struct slip *sl;
579
580
581 if ((sl = sl_find(tty)) == NULL) {
582 DPRINTF((DBG_SLIP, "SLIP: ioctl: TTY %d not connected !\n", tty->line));
583 return(-EINVAL);
584 }
585
586 DPRINTF((DBG_SLIP, "SLIP: ioctl(%d, 0x%X, 0x%X)\n", tty->line, cmd, arg));
587 switch(cmd) {
588 case SIOCGIFNAME:
589 verify_area(VERIFY_WRITE, arg, 16);
590 memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);
591 return(0);
592 default:
593 return(-EINVAL);
594 }
595 return(-EINVAL);
596 }
597
598
599
600 int
601 slip_init(struct device *dev)
602 {
603 struct slip *sl;
604 int i;
605
606 sl = &sl_ctrl[dev->base_addr];
607
608 if (already++ == 0) {
609 printk("SLIP: version %s (%d channels): ",
610 SLIP_VERSION, SL_NRUNIT);
611
612
613 sl_ldisc.flags = 0;
614 sl_ldisc.open = slip_open;
615 sl_ldisc.close = slip_close;
616 sl_ldisc.read = NULL;
617 sl_ldisc.write = NULL;
618 sl_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
619 unsigned int, unsigned long)) slip_ioctl;
620 sl_ldisc.handler = slip_recv;
621 if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) == 0) printk("OK\n");
622 else printk("ERROR: %d\n", i);
623 }
624
625
626 sl_initialize(sl, dev);
627
628
629 sl->rcount = 0;
630 sl->rpacket = 0;
631 sl->roverrun = 0;
632 sl->spacket = 0;
633 sl->sbusy = 0;
634 sl->errors = 0;
635
636
637 dev->mtu = SL_MTU;
638 dev->hard_start_xmit = sl_xmit;
639 dev->open = sl_open;
640 dev->stop = sl_close;
641 dev->hard_header = sl_header;
642 dev->add_arp = sl_add_arp;
643 dev->type_trans = sl_type_trans;
644 dev->hard_header_len = 0;
645 dev->addr_len = 0;
646 dev->type = 0;
647 dev->queue_xmit = dev_queue_xmit;
648 dev->rebuild_header = sl_rebuild_header;
649 for (i = 0; i < DEV_NUMBUFFS; i++)
650 dev->buffs[i] = NULL;
651
652
653 dev->flags = 0;
654 dev->family = AF_INET;
655 dev->pa_addr = 0;
656 dev->pa_brdaddr = 0;
657 dev->pa_mask = 0;
658 dev->pa_alen = sizeof(unsigned long);
659
660 return(0);
661 }