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