2 * Frame-relay protocol module for the COMX driver
5 * Original author: Tivadar Szemethy <tiv@itc.hu>
6 * Maintainer: Gergely Madarasz <gorgo@itc.hu>
8 * Copyright (C) 1998-1999 ITConsult-Pro Co. <info@itc.hu>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
15 * Version 0.70 (99/06/14):
16 * - cleaned up the source code a bit
17 * - ported back to kernel, now works as builtin code
19 * Version 0.71 (99/06/25):
20 * - use skb priorities and queues for sending keepalive
21 * - use device queues for slave->master data transmit
22 * - set IFF_RUNNING only line protocol up
23 * - fixes on slave device flags
25 * Version 0.72 (99/07/09):
26 * - handle slave tbusy with master tbusy (should be fixed)
27 * - fix the keepalive timer addition/deletion
30 #define VERSION "0.72"
32 #include <linux/module.h>
33 #include <linux/version.h>
34 #include <linux/types.h>
35 #include <linux/sched.h>
36 #include <linux/netdevice.h>
37 #include <linux/proc_fs.h>
38 #include <linux/if_arp.h>
39 #include <linux/inetdevice.h>
40 #include <linux/pkt_sched.h>
41 #include <linux/init.h>
42 #include <asm/uaccess.h>
47 MODULE_AUTHOR("Author: Tivadar Szemethy <tiv@itc.hu>");
48 MODULE_DESCRIPTION("Frame Relay protocol implementation for the COMX drivers"
49 "for Linux kernel 2.2.X");
53 #define NLPID_Q933_LMI 0x08
54 #define NLPID_CISCO_LMI 0x09
56 #define Q933_LINESTAT 0x51
57 #define Q933_COUNTERS 0x53
59 #define MAXALIVECNT 3 /* No. of failures */
63 struct net_device
*master
;
66 char keepalivecnt
, keeploopcnt
;
67 struct timer_list keepa_timer
;
68 u8 local_cnt
, remote_cnt
;
71 static struct comx_protocol fr_master_protocol
;
72 static struct comx_protocol fr_slave_protocol
;
73 static struct comx_hardware fr_dlci
;
75 static void fr_keepalive_send(struct net_device
*dev
)
77 struct comx_channel
*ch
= dev
->priv
;
78 struct fr_data
*fr
= ch
->LINE_privdata
;
82 skb
=alloc_skb(dev
->hard_header_len
+ 13, GFP_ATOMIC
);
87 skb_reserve(skb
, dev
->hard_header_len
);
89 fr_packet
=(u8
*)skb_put(skb
, 13);
91 fr_packet
[0] = (fr
->dlci
& (1024 - 15)) >> 2;
92 fr_packet
[1] = (fr
->dlci
& 15) << 4 | 1; // EA bit 1
93 fr_packet
[2] = FRAD_UI
;
94 fr_packet
[3] = NLPID_Q933_LMI
;
96 fr_packet
[5] = Q933_ENQ
;
97 fr_packet
[6] = Q933_LINESTAT
;
100 fr_packet
[9] = Q933_COUNTERS
;
101 fr_packet
[10] = 0x02;
102 fr_packet
[11] = ++fr
->local_cnt
;
103 fr_packet
[12] = fr
->remote_cnt
;
106 skb
->priority
= TC_PRIO_CONTROL
;
110 static void fr_keepalive_timerfun(unsigned long d
)
112 struct net_device
*dev
= (struct net_device
*)d
;
113 struct comx_channel
*ch
= dev
->priv
;
114 struct fr_data
*fr
= ch
->LINE_privdata
;
115 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
116 struct comx_channel
*sch
;
118 struct net_device
*sdev
;
120 if (ch
->init_status
& LINE_OPEN
) {
121 if (fr
->keepalivecnt
== MAXALIVECNT
) {
122 comx_status(dev
, ch
->line_status
& ~PROTO_UP
);
123 dev
->flags
&= ~IFF_RUNNING
;
124 for (; dir
; dir
= dir
->next
) {
125 if(!S_ISDIR(dir
->mode
)) {
129 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
130 (sdev
->type
== ARPHRD_DLCI
) &&
131 (sfr
= sch
->LINE_privdata
)
132 && (sfr
->master
== dev
) &&
133 (sdev
->flags
& IFF_UP
)) {
134 sdev
->flags
&= ~IFF_RUNNING
;
136 sch
->line_status
& ~PROTO_UP
);
140 if (fr
->keepalivecnt
<= MAXALIVECNT
) {
143 fr_keepalive_send(dev
);
145 mod_timer(&fr
->keepa_timer
, jiffies
+ HZ
* fr
->keepa_freq
);
148 static void fr_rx_lmi(struct net_device
*dev
, struct sk_buff
*skb
,
151 struct comx_channel
*ch
= dev
->priv
;
152 struct fr_data
*fr
= ch
->LINE_privdata
;
153 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
154 struct comx_channel
*sch
;
156 struct net_device
*sdev
;
158 if (dlci
!= fr
->dlci
|| nlpid
!= NLPID_Q933_LMI
|| !fr
->keepa_freq
) {
162 fr
->remote_cnt
= skb
->data
[7];
163 if (skb
->data
[8] == fr
->local_cnt
) { // keepalive UP!
164 fr
->keepalivecnt
= 0;
165 if ((ch
->line_status
& LINE_UP
) &&
166 !(ch
->line_status
& PROTO_UP
)) {
167 comx_status(dev
, ch
->line_status
|= PROTO_UP
);
168 dev
->flags
|= IFF_RUNNING
;
169 for (; dir
; dir
= dir
->next
) {
170 if(!S_ISDIR(dir
->mode
)) {
174 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
175 (sdev
->type
== ARPHRD_DLCI
) &&
176 (sfr
= sch
->LINE_privdata
)
177 && (sfr
->master
== dev
) &&
178 (sdev
->flags
& IFF_UP
)) {
179 sdev
->flags
|= IFF_RUNNING
;
181 sch
->line_status
| PROTO_UP
);
188 static void fr_set_keepalive(struct net_device
*dev
, int keepa
)
190 struct comx_channel
*ch
= dev
->priv
;
191 struct fr_data
*fr
= ch
->LINE_privdata
;
193 if (!keepa
&& fr
->keepa_freq
) { // switch off
195 if (ch
->line_status
& LINE_UP
) {
196 comx_status(dev
, ch
->line_status
| PROTO_UP
);
197 dev
->flags
|= IFF_RUNNING
;
198 del_timer(&fr
->keepa_timer
);
203 if (keepa
) { // bekapcs
204 if(fr
->keepa_freq
&& (ch
->line_status
& LINE_UP
)) {
205 del_timer(&fr
->keepa_timer
);
207 fr
->keepa_freq
= keepa
;
208 fr
->local_cnt
= fr
->remote_cnt
= 0;
209 fr
->keepa_timer
.expires
= jiffies
+ HZ
;
210 fr
->keepa_timer
.function
= fr_keepalive_timerfun
;
211 fr
->keepa_timer
.data
= (unsigned long)dev
;
212 ch
->line_status
&= ~(PROTO_UP
| PROTO_LOOP
);
213 dev
->flags
&= ~IFF_RUNNING
;
214 comx_status(dev
, ch
->line_status
);
215 if(ch
->line_status
& LINE_UP
) {
216 add_timer(&fr
->keepa_timer
);
221 static void fr_rx(struct net_device
*dev
, struct sk_buff
*skb
)
223 struct comx_channel
*ch
= dev
->priv
;
224 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
225 struct net_device
*sdev
= dev
;
226 struct comx_channel
*sch
;
231 if(skb
->len
<= 4 || skb
->data
[2] != FRAD_UI
) {
236 /* Itt majd ki kell talalni, melyik slave kapja a csomagot */
237 dlci
= ((skb
->data
[0] & 0xfc) << 2) | ((skb
->data
[1] & 0xf0) >> 4);
238 if ((nlpid
= skb
->data
[3]) == 0) { // Optional padding
239 nlpid
= skb
->data
[4];
242 skb_pull(skb
, 4); /* DLCI and header throw away */
244 if (ch
->debug_flags
& DEBUG_COMX_DLCI
) {
245 comx_debug(dev
, "Frame received, DLCI: %d, NLPID: 0x%02x\n",
247 comx_debug_skb(dev
, skb
, "Contents");
250 /* Megkeressuk, kihez tartozik */
251 for (; dir
; dir
= dir
->next
) {
252 if(!S_ISDIR(dir
->mode
)) {
255 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
256 (sdev
->type
== ARPHRD_DLCI
) && (sfr
= sch
->LINE_privdata
) &&
257 (sfr
->master
== dev
) && (sfr
->dlci
== dlci
)) {
259 if (ch
->debug_flags
& DEBUG_COMX_DLCI
) {
260 comx_debug(dev
, "Passing it to %s\n",sdev
->name
);
263 sch
->stats
.rx_packets
++;
264 sch
->stats
.rx_bytes
+= skb
->len
;
271 skb
->protocol
= htons(ETH_P_IP
);
272 skb
->mac
.raw
= skb
->data
;
276 fr_rx_lmi(dev
, skb
, dlci
, nlpid
);
283 static int fr_tx(struct net_device
*dev
)
285 struct comx_channel
*ch
= dev
->priv
;
286 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
287 struct net_device
*sdev
;
288 struct comx_channel
*sch
;
292 /* Ha minden igaz, 2 helyen fog allni a tbusy: a masternel,
293 es annal a slave-nel aki eppen kuldott.
294 Egy helyen akkor all, ha a master kuldott.
295 Ez megint jo lesz majd, ha utemezni akarunk */
297 /* This should be fixed, the slave tbusy should be set when
298 the masters queue is full and reset when not */
300 for (; dir
; dir
= dir
->next
) {
301 if(!S_ISDIR(dir
->mode
)) {
304 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
305 (sdev
->type
== ARPHRD_DLCI
) && (sfr
= sch
->LINE_privdata
) &&
306 (sfr
->master
== dev
) && (netif_queue_stopped(sdev
))) {
307 netif_wake_queue(sdev
);
312 netif_wake_queue(dev
);
316 static void fr_status(struct net_device
*dev
, unsigned short status
)
318 struct comx_channel
*ch
= dev
->priv
;
319 struct fr_data
*fr
= ch
->LINE_privdata
;
320 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
321 struct net_device
*sdev
;
322 struct comx_channel
*sch
;
325 if (status
& LINE_UP
) {
326 if (!fr
->keepa_freq
) {
330 status
&= ~(PROTO_UP
| PROTO_LOOP
);
333 if (dev
== fr
->master
&& fr
->keepa_freq
) {
334 if (status
& LINE_UP
) {
335 fr
->keepa_timer
.expires
= jiffies
+ HZ
;
336 add_timer(&fr
->keepa_timer
);
337 fr
->keepalivecnt
= MAXALIVECNT
+ 1;
340 del_timer(&fr
->keepa_timer
);
344 /* Itt a status valtozast vegig kell vinni az osszes slave-n */
345 for (; dir
; dir
= dir
->next
) {
346 if(!S_ISDIR(dir
->mode
)) {
350 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
351 (sdev
->type
== ARPHRD_FRAD
|| sdev
->type
== ARPHRD_DLCI
) &&
352 (sfr
= sch
->LINE_privdata
) && (sfr
->master
== dev
)) {
353 if(status
& LINE_UP
) {
354 netif_wake_queue(sdev
);
356 comx_status(sdev
, status
);
357 if(status
& (PROTO_UP
| PROTO_LOOP
)) {
358 dev
->flags
|= IFF_RUNNING
;
360 dev
->flags
&= ~IFF_RUNNING
;
366 static int fr_open(struct net_device
*dev
)
368 struct comx_channel
*ch
= dev
->priv
;
369 struct fr_data
*fr
= ch
->LINE_privdata
;
370 struct proc_dir_entry
*comxdir
= ch
->procdir
;
371 struct comx_channel
*mch
;
373 if (!(ch
->init_status
& HW_OPEN
)) {
377 if ((ch
->hardware
== &fr_dlci
&& ch
->protocol
!= &fr_slave_protocol
) ||
378 (ch
->protocol
== &fr_slave_protocol
&& ch
->hardware
!= &fr_dlci
)) {
379 printk(KERN_ERR
"Trying to open an improperly set FR interface, giving up\n");
386 mch
= fr
->master
->priv
;
387 if (fr
->master
!= dev
&& (!(mch
->init_status
& LINE_OPEN
)
388 || (mch
->protocol
!= &fr_master_protocol
))) {
389 printk(KERN_ERR
"Master %s is inactive, or incorrectly set up, "
390 "unable to open %s\n", fr
->master
->name
, dev
->name
);
394 ch
->init_status
|= LINE_OPEN
;
395 ch
->line_status
&= ~(PROTO_UP
| PROTO_LOOP
);
396 dev
->flags
&= ~IFF_RUNNING
;
398 if (fr
->master
== dev
) {
399 if (fr
->keepa_freq
) {
400 fr
->keepa_timer
.function
= fr_keepalive_timerfun
;
401 fr
->keepa_timer
.data
= (unsigned long)dev
;
402 add_timer(&fr
->keepa_timer
);
404 if (ch
->line_status
& LINE_UP
) {
405 ch
->line_status
|= PROTO_UP
;
406 dev
->flags
|= IFF_RUNNING
;
410 ch
->line_status
= mch
->line_status
;
411 if(fr
->master
->flags
& IFF_RUNNING
) {
412 dev
->flags
|= IFF_RUNNING
;
416 for (; comxdir
; comxdir
= comxdir
->next
) {
417 if (strcmp(comxdir
->name
, FILENAME_DLCI
) == 0 ||
418 strcmp(comxdir
->name
, FILENAME_MASTER
) == 0 ||
419 strcmp(comxdir
->name
, FILENAME_KEEPALIVE
) == 0) {
420 comxdir
->mode
= S_IFREG
| 0444;
423 // comx_status(dev, ch->line_status);
427 static int fr_close(struct net_device
*dev
)
429 struct comx_channel
*ch
= dev
->priv
;
430 struct fr_data
*fr
= ch
->LINE_privdata
;
431 struct proc_dir_entry
*comxdir
= ch
->procdir
;
433 if (fr
->master
== dev
) { // Ha master
434 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
435 struct net_device
*sdev
= dev
;
436 struct comx_channel
*sch
;
439 if (!(ch
->init_status
& HW_OPEN
)) {
443 if (fr
->keepa_freq
) {
444 del_timer(&fr
->keepa_timer
);
447 for (; dir
; dir
= dir
->next
) {
448 if(!S_ISDIR(dir
->mode
)) {
451 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
452 (sdev
->type
== ARPHRD_DLCI
) &&
453 (sfr
= sch
->LINE_privdata
) &&
454 (sfr
->master
== dev
) &&
455 (sch
->init_status
& LINE_OPEN
)) {
461 ch
->init_status
&= ~LINE_OPEN
;
462 ch
->line_status
&= ~(PROTO_UP
| PROTO_LOOP
);
463 dev
->flags
&= ~IFF_RUNNING
;
465 for (; comxdir
; comxdir
= comxdir
->next
) {
466 if (strcmp(comxdir
->name
, FILENAME_DLCI
) == 0 ||
467 strcmp(comxdir
->name
, FILENAME_MASTER
) == 0 ||
468 strcmp(comxdir
->name
, FILENAME_KEEPALIVE
) == 0) {
469 comxdir
->mode
= S_IFREG
| 0444;
476 static int fr_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
478 struct comx_channel
*ch
= dev
->priv
;
479 struct comx_channel
*sch
, *mch
;
480 struct fr_data
*fr
= ch
->LINE_privdata
;
482 struct net_device
*sdev
;
483 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
486 printk(KERN_ERR
"BUG: fr_xmit without a master!!! dev: %s\n", dev
->name
);
490 mch
= fr
->master
->priv
;
492 /* Ennek majd a slave utemezeskor lesz igazan jelentosege */
493 if (ch
->debug_flags
& DEBUG_COMX_DLCI
) {
494 comx_debug_skb(dev
, skb
, "Sending frame");
497 if (dev
!= fr
->master
) {
498 struct sk_buff
*newskb
=skb_clone(skb
, GFP_ATOMIC
);
499 newskb
->dev
=fr
->master
;
500 dev_queue_xmit(newskb
);
502 ch
->stats
.tx_packets
++;
503 ch
->stats
.tx_bytes
+= skb
->len
;
505 netif_stop_queue(dev
);
506 for (; dir
; dir
= dir
->next
) {
507 if(!S_ISDIR(dir
->mode
)) {
510 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
511 (sdev
->type
== ARPHRD_DLCI
) && (sfr
= sch
->LINE_privdata
) &&
512 (sfr
->master
== dev
) && (netif_queue_stopped(sdev
))) {
513 netif_stop_queue(sdev
);
517 switch(mch
->HW_send_packet(dev
, skb
)) {
519 netif_wake_queue(dev
);
525 printk(KERN_ERR
"%s: Transmit frame error (len %d)\n",
526 dev
->name
, skb
->len
);
533 static int fr_header(struct sk_buff
*skb
, struct net_device
*dev
,
534 unsigned short type
, void *daddr
, void *saddr
, unsigned len
)
536 struct comx_channel
*ch
= dev
->priv
;
537 struct fr_data
*fr
= ch
->LINE_privdata
;
539 skb_push(skb
, dev
->hard_header_len
);
541 skb
->data
[0] = (fr
->dlci
& (1024 - 15)) >> 2;
542 skb
->data
[1] = (fr
->dlci
& 15) << 4 | 1; // EA bit 1
543 skb
->data
[2] = FRAD_UI
;
544 skb
->data
[3] = NLPID_IP
;
546 return dev
->hard_header_len
;
549 static int fr_statistics(struct net_device
*dev
, char *page
)
551 struct comx_channel
*ch
= dev
->priv
;
552 struct fr_data
*fr
= ch
->LINE_privdata
;
555 if (fr
->master
== dev
) {
556 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
557 struct net_device
*sdev
;
558 struct comx_channel
*sch
;
562 len
+= sprintf(page
+ len
,
563 "This is a Frame Relay master device\nSlaves: ");
564 for (; dir
; dir
= dir
->next
) {
565 if(!S_ISDIR(dir
->mode
)) {
568 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
569 (sdev
->type
== ARPHRD_DLCI
) &&
570 (sfr
= sch
->LINE_privdata
) &&
571 (sfr
->master
== dev
) && (sdev
!= dev
)) {
573 len
+= sprintf(page
+ len
, "%s ", sdev
->name
);
576 len
+= sprintf(page
+ len
, "%s\n", slaves
? "" : "(none)");
577 if (fr
->keepa_freq
) {
578 len
+= sprintf(page
+ len
, "Line keepalive (value %d) "
579 "status %s [%d]\n", fr
->keepa_freq
,
580 ch
->line_status
& PROTO_LOOP
? "LOOP" :
581 ch
->line_status
& PROTO_UP
? "UP" : "DOWN",
584 len
+= sprintf(page
+ len
, "Line keepalive protocol "
588 len
+= sprintf(page
+ len
,
589 "This is a Frame Relay slave device, master: %s\n",
590 fr
->master
? fr
->master
->name
: "(not set)");
595 static int fr_read_proc(char *page
, char **start
, off_t off
, int count
,
596 int *eof
, void *data
)
598 struct proc_dir_entry
*file
= (struct proc_dir_entry
*)data
;
599 struct net_device
*dev
= file
->parent
->data
;
600 struct comx_channel
*ch
= dev
->priv
;
601 struct fr_data
*fr
= NULL
;
605 fr
= ch
->LINE_privdata
;
608 if (strcmp(file
->name
, FILENAME_DLCI
) == 0) {
609 len
= sprintf(page
, "%04d\n", fr
->dlci
);
610 } else if (strcmp(file
->name
, FILENAME_MASTER
) == 0) {
611 len
= sprintf(page
, "%-9s\n", fr
->master
? fr
->master
->name
:
613 } else if (strcmp(file
->name
, FILENAME_KEEPALIVE
) == 0) {
614 len
= fr
->keepa_freq
? sprintf(page
, "% 3d\n", fr
->keepa_freq
)
615 : sprintf(page
, "off\n");
617 printk(KERN_ERR
"comxfr: internal error, filename %s\n", file
->name
);
627 if (count
>= len
- off
) *eof
= 1;
628 return ( min(count
, len
- off
) );
631 static int fr_write_proc(struct file
*file
, const char *buffer
,
632 u_long count
, void *data
)
634 struct proc_dir_entry
*entry
= (struct proc_dir_entry
*)data
;
635 struct net_device
*dev
= entry
->parent
->data
;
636 struct comx_channel
*ch
= dev
->priv
;
637 struct fr_data
*fr
= NULL
;
641 fr
= ch
->LINE_privdata
;
644 if (!(page
= (char *)__get_free_page(GFP_KERNEL
))) {
648 copy_from_user(page
, buffer
, count
);
649 if (*(page
+ count
- 1) == '\n') {
650 *(page
+ count
- 1) = 0;
653 if (strcmp(entry
->name
, FILENAME_DLCI
) == 0) {
654 u16 dlci_new
= simple_strtoul(page
, NULL
, 10);
656 if (dlci_new
> 1023) {
657 printk(KERN_ERR
"Invalid DLCI value\n");
659 else fr
->dlci
= dlci_new
;
660 } else if (strcmp(entry
->name
, FILENAME_MASTER
) == 0) {
661 struct net_device
*new_master
= dev_get_by_name(page
);
663 if (new_master
&& new_master
->type
== ARPHRD_FRAD
) {
664 struct comx_channel
*sch
= new_master
->priv
;
665 struct fr_data
*sfr
= sch
->LINE_privdata
;
667 if (sfr
&& sfr
->master
== new_master
) {
670 fr
->master
= new_master
;
671 /* Megorokli a master statuszat */
672 ch
->line_status
= sch
->line_status
;
675 } else if (strcmp(entry
->name
, FILENAME_KEEPALIVE
) == 0) {
678 if (strcmp(page
, KEEPALIVE_OFF
) == 0) {
681 keepa_new
= simple_strtoul(page
, NULL
, 10);
684 if (keepa_new
< 0 || keepa_new
> 100) {
685 printk(KERN_ERR
"invalid keepalive\n");
687 if (fr
->keepa_freq
&& keepa_new
!= fr
->keepa_freq
) {
688 fr_set_keepalive(dev
, 0);
691 fr_set_keepalive(dev
, keepa_new
);
695 printk(KERN_ERR
"comxfr_write_proc: internal error, filename %s\n",
700 free_page((unsigned long)page
);
704 static int fr_exit(struct net_device
*dev
)
706 struct comx_channel
*ch
= dev
->priv
;
707 struct fr_data
*fr
= ch
->LINE_privdata
;
708 struct net_device
*sdev
= dev
;
709 struct comx_channel
*sch
;
711 struct proc_dir_entry
*dir
= ch
->procdir
->parent
->subdir
;
713 /* Ha lezarunk egy master-t, le kell kattintani a slave-eket is */
714 if (fr
->master
&& fr
->master
== dev
) {
715 for (; dir
; dir
= dir
->next
) {
716 if(!S_ISDIR(dir
->mode
)) {
719 if ((sdev
= dir
->data
) && (sch
= sdev
->priv
) &&
720 (sdev
->type
== ARPHRD_DLCI
) &&
721 (sfr
= sch
->LINE_privdata
) && (sfr
->master
== dev
)) {
730 dev
->hard_header_len
= 0;
734 ch
->LINE_status
= NULL
;
735 ch
->LINE_open
= NULL
;
736 ch
->LINE_close
= NULL
;
737 ch
->LINE_xmit
= NULL
;
738 ch
->LINE_header
= NULL
;
739 ch
->LINE_rebuild_header
= NULL
;
740 ch
->LINE_statistics
= NULL
;
744 if (fr
->master
!= dev
) { // if not master, remove dlci
747 remove_proc_entry(FILENAME_DLCI
, ch
->procdir
);
748 remove_proc_entry(FILENAME_MASTER
, ch
->procdir
);
750 if (fr
->keepa_freq
) {
751 fr_set_keepalive(dev
, 0);
753 remove_proc_entry(FILENAME_KEEPALIVE
, ch
->procdir
);
754 remove_proc_entry(FILENAME_DLCI
, ch
->procdir
);
758 ch
->LINE_privdata
= NULL
;
764 static int fr_master_init(struct net_device
*dev
)
766 struct comx_channel
*ch
= dev
->priv
;
768 struct proc_dir_entry
*new_file
;
770 if ((fr
= ch
->LINE_privdata
= kmalloc(sizeof(struct fr_data
),
771 GFP_KERNEL
)) == NULL
) {
774 memset(fr
, 0, sizeof(struct fr_data
));
775 fr
->master
= dev
; // this means master
776 fr
->dlci
= 0; // let's say default
778 dev
->flags
= IFF_POINTOPOINT
| IFF_NOARP
| IFF_MULTICAST
;
779 dev
->type
= ARPHRD_FRAD
;
781 dev
->hard_header_len
= 4;
786 ch
->LINE_status
= fr_status
;
787 ch
->LINE_open
= fr_open
;
788 ch
->LINE_close
= fr_close
;
789 ch
->LINE_xmit
= fr_xmit
;
790 ch
->LINE_header
= fr_header
;
791 ch
->LINE_rebuild_header
= NULL
;
792 ch
->LINE_statistics
= fr_statistics
;
794 if ((new_file
= create_proc_entry(FILENAME_DLCI
, S_IFREG
| 0644,
795 ch
->procdir
)) == NULL
) {
798 new_file
->data
= (void *)new_file
;
799 new_file
->read_proc
= &fr_read_proc
;
800 new_file
->write_proc
= &fr_write_proc
;
804 if ((new_file
= create_proc_entry(FILENAME_KEEPALIVE
, S_IFREG
| 0644,
805 ch
->procdir
)) == NULL
) {
808 new_file
->data
= (void *)new_file
;
809 new_file
->read_proc
= &fr_read_proc
;
810 new_file
->write_proc
= &fr_write_proc
;
814 fr_set_keepalive(dev
, 0);
820 static int fr_slave_init(struct net_device
*dev
)
822 struct comx_channel
*ch
= dev
->priv
;
824 struct proc_dir_entry
*new_file
;
826 if ((fr
= ch
->LINE_privdata
= kmalloc(sizeof(struct fr_data
),
827 GFP_KERNEL
)) == NULL
) {
830 memset(fr
, 0, sizeof(struct fr_data
));
832 dev
->flags
= IFF_POINTOPOINT
| IFF_NOARP
| IFF_MULTICAST
;
833 dev
->type
= ARPHRD_DLCI
;
835 dev
->hard_header_len
= 4;
840 ch
->LINE_status
= fr_status
;
841 ch
->LINE_open
= fr_open
;
842 ch
->LINE_close
= fr_close
;
843 ch
->LINE_xmit
= fr_xmit
;
844 ch
->LINE_header
= fr_header
;
845 ch
->LINE_rebuild_header
= NULL
;
846 ch
->LINE_statistics
= fr_statistics
;
848 if ((new_file
= create_proc_entry(FILENAME_DLCI
, S_IFREG
| 0644,
849 ch
->procdir
)) == NULL
) {
853 new_file
->data
= (void *)new_file
;
854 new_file
->read_proc
= &fr_read_proc
;
855 new_file
->write_proc
= &fr_write_proc
;
859 if ((new_file
= create_proc_entry(FILENAME_MASTER
, S_IFREG
| 0644,
860 ch
->procdir
)) == NULL
) {
863 new_file
->data
= (void *)new_file
;
864 new_file
->read_proc
= &fr_read_proc
;
865 new_file
->write_proc
= &fr_write_proc
;
872 static int dlci_open(struct net_device
*dev
)
874 struct comx_channel
*ch
= dev
->priv
;
876 ch
->init_status
|= HW_OPEN
;
882 static int dlci_close(struct net_device
*dev
)
884 struct comx_channel
*ch
= dev
->priv
;
886 ch
->init_status
&= ~HW_OPEN
;
892 static int dlci_txe(struct net_device
*dev
)
894 struct comx_channel
*ch
= dev
->priv
;
895 struct fr_data
*fr
= ch
->LINE_privdata
;
901 ch
= fr
->master
->priv
;
902 fr
= ch
->LINE_privdata
;
903 return ch
->HW_txe(fr
->master
);
906 static int dlci_statistics(struct net_device
*dev
, char *page
)
911 static int dlci_init(struct net_device
*dev
)
913 struct comx_channel
*ch
= dev
->priv
;
915 ch
->HW_open
= dlci_open
;
916 ch
->HW_close
= dlci_close
;
917 ch
->HW_txe
= dlci_txe
;
918 ch
->HW_statistics
= dlci_statistics
;
920 /* Nincs egyeb hw info, mert ugyis a fr->master-bol fog minden kiderulni */
926 static int dlci_exit(struct net_device
*dev
)
928 struct comx_channel
*ch
= dev
->priv
;
933 ch
->HW_statistics
= NULL
;
939 static int dlci_dump(struct net_device
*dev
)
941 printk(KERN_INFO
"dlci_dump %s, HOGY MI ???\n", dev
->name
);
945 static struct comx_protocol fr_master_protocol
= {
954 static struct comx_protocol fr_slave_protocol
= {
963 static struct comx_hardware fr_dlci
= {
973 #define comx_proto_fr_init init_module
976 int __init
comx_proto_fr_init(void)
980 if ((ret
= comx_register_hardware(&fr_dlci
))) {
983 if ((ret
= comx_register_protocol(&fr_master_protocol
))) {
986 return comx_register_protocol(&fr_slave_protocol
);
990 void cleanup_module(void)
992 comx_unregister_hardware(fr_dlci
.name
);
993 comx_unregister_protocol(fr_master_protocol
.name
);
994 comx_unregister_protocol(fr_slave_protocol
.name
);