2 * Device driver framework for the COMX line of synchronous serial boards
4 * for Linux kernel 2.2.X
6 * Original authors: Arpad Bakay <bakay.arpad@synergon.hu>,
7 * Peter Bajan <bajan.peter@synergon.hu>,
8 * Previous maintainer: Tivadar Szemethy <tiv@itc.hu>
9 * Current maintainer: Gergely Madarasz <gorgo@itc.hu>
11 * Copyright (C) 1995-1999 ITConsult-Pro Co.
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
18 * Version 0.80 (99/06/11):
19 * - clean up source code (playing a bit of indent)
20 * - port back to kernel, add support for non-module versions
21 * - add support for board resets when channel protocol is down
22 * - reset the device structure after protocol exit
23 * the syncppp driver needs it
24 * - add support for /proc/comx/protocols and
25 * /proc/comx/boardtypes
27 * Version 0.81 (99/06/21):
28 * - comment out the board reset support code, the locomx
29 * driver seems not buggy now
30 * - printk() levels fixed
32 * Version 0.82 (99/07/08):
33 * - Handle stats correctly if the lowlevel driver is
34 * is not a comx one (locomx - z85230)
36 * Version 0.83 (99/07/15):
37 * - reset line_status when interface is down
39 * Version 0.84 (99/12/01):
40 * - comx_status should not check for IFF_UP (to report
41 * line status from dev->open())
44 #define VERSION "0.84"
46 #include <linux/config.h>
47 #include <linux/module.h>
48 #include <linux/version.h>
50 #include <linux/types.h>
51 #include <linux/sched.h>
52 #include <linux/netdevice.h>
53 #include <linux/proc_fs.h>
54 #include <asm/uaccess.h>
55 #include <linux/ctype.h>
56 #include <linux/init.h>
59 #include <linux/kmod.h>
62 #ifndef CONFIG_PROC_FS
63 #error For now, COMX really needs the /proc filesystem
69 MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
70 MODULE_DESCRIPTION("Common code for the COMX synchronous serial adapters");
72 extern int comx_hw_comx_init(void);
73 extern int comx_hw_locomx_init(void);
74 extern int comx_hw_mixcom_init(void);
75 extern int comx_proto_hdlc_init(void);
76 extern int comx_proto_ppp_init(void);
77 extern int comx_proto_syncppp_init(void);
78 extern int comx_proto_lapb_init(void);
79 extern int comx_proto_fr_init(void);
81 static struct comx_hardware
*comx_channels
= NULL
;
82 static struct comx_protocol
*comx_lines
= NULL
;
84 static struct inode_operations comx_root_inode_ops
= {
90 static int comx_delete_dentry(struct dentry
*dentry
);
91 static struct proc_dir_entry
*create_comx_proc_entry(char *name
, int mode
,
92 int size
, struct proc_dir_entry
*dir
);
94 static struct dentry_operations comx_dentry_operations
= {
95 d_delete
: comx_delete_dentry
,
99 static struct proc_dir_entry
* comx_root_dir
;
101 struct comx_debugflags_struct comx_debugflags
[] = {
102 { "comx_rx", DEBUG_COMX_RX
},
103 { "comx_tx", DEBUG_COMX_TX
},
104 { "hw_tx", DEBUG_HW_TX
},
105 { "hw_rx", DEBUG_HW_RX
},
106 { "hdlc_keepalive", DEBUG_HDLC_KEEPALIVE
},
107 { "comxppp", DEBUG_COMX_PPP
},
108 { "comxlapb", DEBUG_COMX_LAPB
},
109 { "dlci", DEBUG_COMX_DLCI
},
114 int comx_debug(struct net_device
*dev
, char *fmt
, ...)
116 struct comx_channel
*ch
= dev
->priv
;
121 if (!ch
->debug_area
) return 0;
123 if (!(page
= (char *)__get_free_page(GFP_ATOMIC
))) return -ENOMEM
;
126 len
= vsprintf(str
= page
, fmt
, args
);
129 if (len
>= PAGE_SIZE
) {
130 printk(KERN_ERR
"comx_debug: PANIC! len = %d !!!\n", len
);
131 free_page((unsigned long)page
);
137 int free
= (ch
->debug_start
- ch
->debug_end
+ ch
->debug_size
)
140 to_copy
= min( free
? free
: ch
->debug_size
,
141 min (ch
->debug_size
- ch
->debug_end
, len
) );
142 memcpy(ch
->debug_area
+ ch
->debug_end
, str
, to_copy
);
145 ch
->debug_end
= (ch
->debug_end
+ to_copy
) % ch
->debug_size
;
146 if (ch
->debug_start
== ch
->debug_end
) // Full ? push start away
147 ch
->debug_start
= (ch
->debug_start
+ len
+ 1) %
149 ch
->debug_file
->size
= (ch
->debug_end
- ch
->debug_start
+
150 ch
->debug_size
) % ch
->debug_size
;
153 free_page((unsigned long)page
);
157 int comx_debug_skb(struct net_device
*dev
, struct sk_buff
*skb
, char *msg
)
159 struct comx_channel
*ch
= dev
->priv
;
161 if (!ch
->debug_area
) return 0;
162 if (!skb
) comx_debug(dev
, "%s: %s NULL skb\n\n", dev
->name
, msg
);
163 if (!skb
->len
) comx_debug(dev
, "%s: %s empty skb\n\n", dev
->name
, msg
);
165 return comx_debug_bytes(dev
, skb
->data
, skb
->len
, msg
);
168 int comx_debug_bytes(struct net_device
*dev
, unsigned char *bytes
, int len
,
172 struct comx_channel
*ch
= dev
->priv
;
174 if (!ch
->debug_area
) return 0;
176 comx_debug(dev
, "%s: %s len %d\n", dev
->name
, msg
, len
);
183 sprintf(line
,"%04d ", pos
);
185 sprintf(line
+ 5 + (pos
% 16) * 3, "%02x", bytes
[pos
]);
186 sprintf(line
+ 60 + (pos
% 16), "%c",
187 isprint(bytes
[pos
]) ? bytes
[pos
] : '.');
189 } while (pos
!= len
&& pos
% 16);
191 while ( i
++ != 78 ) if (line
[i
] == 0) line
[i
] = ' ';
195 comx_debug(dev
, "%s", line
);
197 comx_debug(dev
, "\n");
201 static void comx_loadavg_timerfun(unsigned long d
)
203 struct net_device
*dev
= (struct net_device
*)d
;
204 struct comx_channel
*ch
= dev
->priv
;
206 ch
->avg_bytes
[ch
->loadavg_counter
] = ch
->current_stats
->rx_bytes
;
207 ch
->avg_bytes
[ch
->loadavg_counter
+ ch
->loadavg_size
] =
208 ch
->current_stats
->tx_bytes
;
210 ch
->loadavg_counter
= (ch
->loadavg_counter
+ 1) % ch
->loadavg_size
;
212 mod_timer(&ch
->loadavg_timer
,jiffies
+ HZ
* ch
->loadavg
[0]);
216 static void comx_reset_timerfun(unsigned long d
)
218 struct net_device
*dev
= (struct net_device
*)d
;
219 struct comx_channel
*ch
= dev
->priv
;
221 if(!(ch
->line_status
& (PROTO_LOOP
| PROTO_UP
))) {
222 if(test_and_set_bit(0,&ch
->reset_pending
) && ch
->HW_reset
) {
227 mod_timer(&ch
->reset_timer
, jiffies
+ HZ
* ch
->reset_timeout
);
231 static int comx_open(struct net_device
*dev
)
233 struct comx_channel
*ch
= dev
->priv
;
234 struct proc_dir_entry
*comxdir
= ch
->procdir
->subdir
;
237 if (!ch
->protocol
|| !ch
->hardware
) return -ENODEV
;
239 if ((ret
= ch
->HW_open(dev
))) return ret
;
240 if ((ret
= ch
->LINE_open(dev
))) {
245 for (; comxdir
; comxdir
= comxdir
->next
) {
246 if (strcmp(comxdir
->name
, FILENAME_HARDWARE
) == 0 ||
247 strcmp(comxdir
->name
, FILENAME_PROTOCOL
) == 0)
248 comxdir
->mode
= S_IFREG
| 0444;
252 ch
->reset_pending
= 1;
253 ch
->reset_timeout
= 30;
254 ch
->reset_timer
.function
= comx_reset_timerfun
;
255 ch
->reset_timer
.data
= (unsigned long)dev
;
256 ch
->reset_timer
.expires
= jiffies
+ HZ
* ch
->reset_timeout
;
257 add_timer(&ch
->reset_timer
);
263 static int comx_close(struct net_device
*dev
)
265 struct comx_channel
*ch
= dev
->priv
;
266 struct proc_dir_entry
*comxdir
= ch
->procdir
->subdir
;
269 if (test_and_clear_bit(0, &ch
->lineup_pending
)) {
270 del_timer(&ch
->lineup_timer
);
274 del_timer(&ch
->reset_timer
);
277 if (ch
->init_status
& LINE_OPEN
&& ch
->protocol
&& ch
->LINE_close
) {
278 ret
= ch
->LINE_close(dev
);
283 if (ch
->init_status
& HW_OPEN
&& ch
->hardware
&& ch
->HW_close
) {
284 ret
= ch
->HW_close(dev
);
289 for (; comxdir
; comxdir
= comxdir
->next
) {
290 if (strcmp(comxdir
->name
, FILENAME_HARDWARE
) == 0 ||
291 strcmp(comxdir
->name
, FILENAME_PROTOCOL
) == 0)
292 comxdir
->mode
= S_IFREG
| 0644;
298 void comx_status(struct net_device
*dev
, int status
)
300 struct comx_channel
*ch
= dev
->priv
;
303 if(status
& (PROTO_UP
| PROTO_LOOP
)) {
304 clear_bit(0,&ch
->reset_pending
);
308 printk(KERN_NOTICE
"Interface %s: modem status %s, line protocol %s\n",
309 dev
->name
, status
& LINE_UP
? "UP" : "DOWN",
310 status
& PROTO_LOOP
? "LOOP" : status
& PROTO_UP
?
313 ch
->line_status
= status
;
316 static int comx_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
318 struct comx_channel
*ch
= dev
->priv
;
321 if (skb
->len
> dev
->mtu
+ dev
->hard_header_len
) {
322 printk(KERN_ERR
"comx_xmit: %s: skb->len %d > dev->mtu %d\n", dev
->name
,
323 (int)skb
->len
, dev
->mtu
);
326 if (ch
->debug_flags
& DEBUG_COMX_TX
) {
327 comx_debug_skb(dev
, skb
, "comx_xmit skb");
330 rc
=ch
->LINE_xmit(skb
, dev
);
331 // if (!rc) dev_kfree_skb(skb);
336 static int comx_header(struct sk_buff
*skb
, struct net_device
*dev
,
337 unsigned short type
, void *daddr
, void *saddr
, unsigned len
)
339 struct comx_channel
*ch
= dev
->priv
;
341 if (ch
->LINE_header
) {
342 return (ch
->LINE_header(skb
, dev
, type
, daddr
, saddr
, len
));
348 static int comx_rebuild_header(struct sk_buff
*skb
)
350 struct net_device
*dev
= skb
->dev
;
351 struct comx_channel
*ch
= dev
->priv
;
353 if (ch
->LINE_rebuild_header
) {
354 return(ch
->LINE_rebuild_header(skb
));
360 int comx_rx(struct net_device
*dev
, struct sk_buff
*skb
)
362 struct comx_channel
*ch
= dev
->priv
;
364 if (ch
->debug_flags
& DEBUG_COMX_RX
) {
365 comx_debug_skb(dev
, skb
, "comx_rx skb");
373 static struct net_device_stats
*comx_stats(struct net_device
*dev
)
375 struct comx_channel
*ch
= (struct comx_channel
*)dev
->priv
;
377 return ch
->current_stats
;
380 void comx_lineup_func(unsigned long d
)
382 struct net_device
*dev
= (struct net_device
*)d
;
383 struct comx_channel
*ch
= dev
->priv
;
385 del_timer(&ch
->lineup_timer
);
386 clear_bit(0, &ch
->lineup_pending
);
388 if (ch
->LINE_status
) {
389 ch
->LINE_status(dev
, ch
->line_status
|= LINE_UP
);
393 #define LOADAVG(avg, off) (int) \
394 ((ch->avg_bytes[(ch->loadavg_counter - 1 + ch->loadavg_size * 2) \
395 % ch->loadavg_size + off] - ch->avg_bytes[(ch->loadavg_counter - 1 \
396 - ch->loadavg[avg] / ch->loadavg[0] + ch->loadavg_size * 2) \
397 % ch->loadavg_size + off]) / ch->loadavg[avg] * 8)
399 static int comx_statistics(struct net_device
*dev
, char *page
)
401 struct comx_channel
*ch
= dev
->priv
;
408 len
+= sprintf(page
+ len
, "Interface administrative status is %s, "
409 "modem status is %s, protocol is %s\n",
410 dev
->flags
& IFF_UP
? "UP" : "DOWN",
411 ch
->line_status
& LINE_UP
? "UP" : "DOWN",
412 ch
->line_status
& PROTO_LOOP
? "LOOP" :
413 ch
->line_status
& PROTO_UP
? "UP" : "DOWN");
414 len
+= sprintf(page
+ len
, "Modem status changes: %lu, Transmitter status "
415 "is %s, tbusy: %d\n", ch
->current_stats
->tx_carrier_errors
, ch
->HW_txe
?
416 ch
->HW_txe(dev
) ? "IDLE" : "BUSY" : "NOT READY", netif_running(dev
));
417 len
+= sprintf(page
+ len
, "Interface load (input): %d / %d / %d bits/s (",
418 LOADAVG(0,0), LOADAVG(1, 0), LOADAVG(2, 0));
420 for (i
=0; i
!= 3; i
++) {
423 tf
= ch
->loadavg
[i
] % 60 == 0 &&
424 ch
->loadavg
[i
] / 60 > 0 ? 'm' : 's';
425 tmpstrlen
+= sprintf(tmpstr
+ tmpstrlen
, "%d%c%s",
426 ch
->loadavg
[i
] / (tf
== 'm' ? 60 : 1), tf
,
427 i
== 2 ? ")\n" : "/");
429 len
+= sprintf(page
+ len
,
430 "%s (output): %d / %d / %d bits/s (%s", tmpstr
,
431 LOADAVG(0,ch
->loadavg_size
), LOADAVG(1, ch
->loadavg_size
),
432 LOADAVG(2, ch
->loadavg_size
), tmpstr
);
434 len
+= sprintf(page
+ len
, "Debug flags: ");
436 while (comx_debugflags
[i
].name
) {
437 if (ch
->debug_flags
& comx_debugflags
[i
].value
)
438 len
+= sprintf(page
+ len
, "%s ",
439 comx_debugflags
[i
].name
);
442 len
+= sprintf(page
+ len
, "%s\n", tmp
== len
? "none" : "");
444 len
+= sprintf(page
+ len
, "RX errors: len: %lu, overrun: %lu, crc: %lu, "
445 "aborts: %lu\n buffer overrun: %lu, pbuffer overrun: %lu\n"
446 "TX errors: underrun: %lu\n",
447 ch
->current_stats
->rx_length_errors
, ch
->current_stats
->rx_over_errors
,
448 ch
->current_stats
->rx_crc_errors
, ch
->current_stats
->rx_frame_errors
,
449 ch
->current_stats
->rx_missed_errors
, ch
->current_stats
->rx_fifo_errors
,
450 ch
->current_stats
->tx_fifo_errors
);
452 if (ch
->LINE_statistics
&& (ch
->init_status
& LINE_OPEN
)) {
453 len
+= ch
->LINE_statistics(dev
, page
+ len
);
455 len
+= sprintf(page
+len
, "Line status: driver not initialized\n");
457 if (ch
->HW_statistics
&& (ch
->init_status
& HW_OPEN
)) {
458 len
+= ch
->HW_statistics(dev
, page
+ len
);
460 len
+= sprintf(page
+len
, "Board status: driver not initialized\n");
466 static int comx_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
)
468 struct comx_channel
*ch
= dev
->priv
;
470 if (ch
->LINE_ioctl
) {
471 return(ch
->LINE_ioctl(dev
, ifr
, cmd
));
476 static void comx_reset_dev(struct net_device
*dev
)
478 dev
->open
= comx_open
;
479 dev
->stop
= comx_close
;
480 dev
->hard_start_xmit
= comx_xmit
;
481 dev
->hard_header
= comx_header
;
482 dev
->rebuild_header
= comx_rebuild_header
;
483 dev
->get_stats
= comx_stats
;
484 dev
->do_ioctl
= comx_ioctl
;
485 dev
->change_mtu
= NULL
;
486 dev
->tx_queue_len
= 20;
487 dev
->flags
= IFF_NOARP
;
490 static int comx_init_dev(struct net_device
*dev
)
492 struct comx_channel
*ch
;
494 if ((ch
= kmalloc(sizeof(struct comx_channel
), GFP_KERNEL
)) == NULL
) {
497 memset(ch
, 0, sizeof(struct comx_channel
));
500 ch
->loadavg
[1] = 300;
501 ch
->loadavg
[2] = 900;
502 ch
->loadavg_size
= ch
->loadavg
[2] / ch
->loadavg
[0] + 1;
503 if ((ch
->avg_bytes
= kmalloc(ch
->loadavg_size
*
504 sizeof(unsigned long) * 2, GFP_KERNEL
)) == NULL
) {
508 memset(ch
->avg_bytes
, 0, ch
->loadavg_size
* sizeof(unsigned long) * 2);
509 ch
->loadavg_counter
= 0;
510 ch
->loadavg_timer
.function
= comx_loadavg_timerfun
;
511 ch
->loadavg_timer
.data
= (unsigned long)dev
;
512 ch
->loadavg_timer
.expires
= jiffies
+ HZ
* ch
->loadavg
[0];
513 add_timer(&ch
->loadavg_timer
);
515 dev
->priv
= (void *)ch
;
517 ch
->line_status
&= ~LINE_UP
;
519 ch
->current_stats
= &ch
->stats
;
525 static int comx_read_proc(char *page
, char **start
, off_t off
, int count
,
526 int *eof
, void *data
)
528 struct proc_dir_entry
*file
= (struct proc_dir_entry
*)data
;
529 struct net_device
*dev
= file
->parent
->data
;
530 struct comx_channel
*ch
=(struct comx_channel
*)dev
->priv
;
533 if (strcmp(file
->name
, FILENAME_STATUS
) == 0) {
534 len
= comx_statistics(dev
, page
);
535 } else if (strcmp(file
->name
, FILENAME_HARDWARE
) == 0) {
536 len
= sprintf(page
, "%s\n", ch
->hardware
?
537 ch
->hardware
->name
: HWNAME_NONE
);
538 } else if (strcmp(file
->name
, FILENAME_PROTOCOL
) == 0) {
539 len
= sprintf(page
, "%s\n", ch
->protocol
?
540 ch
->protocol
->name
: PROTONAME_NONE
);
541 } else if (strcmp(file
->name
, FILENAME_LINEUPDELAY
) == 0) {
542 len
= sprintf(page
, "%01d\n", ch
->lineup_delay
);
551 if (count
>= len
- off
) {
554 return( min(count
, len
- off
) );
558 static int comx_root_read_proc(char *page
, char **start
, off_t off
, int count
,
559 int *eof
, void *data
)
561 struct proc_dir_entry
*file
= (struct proc_dir_entry
*)data
;
562 struct comx_hardware
*hw
;
563 struct comx_protocol
*line
;
567 if (strcmp(file
->name
, FILENAME_HARDWARELIST
) == 0) {
568 for(hw
=comx_channels
;hw
;hw
=hw
->next
)
569 len
+=sprintf(page
+len
, "%s\n", hw
->name
);
570 } else if (strcmp(file
->name
, FILENAME_PROTOCOLLIST
) == 0) {
571 for(line
=comx_lines
;line
;line
=line
->next
)
572 len
+=sprintf(page
+len
, "%s\n", line
->name
);
581 if (count
>= len
- off
) {
584 return( min(count
, len
- off
) );
589 static int comx_write_proc(struct file
*file
, const char *buffer
, u_long count
,
592 struct proc_dir_entry
*entry
= (struct proc_dir_entry
*)data
;
593 struct net_device
*dev
= (struct net_device
*)entry
->parent
->data
;
594 struct comx_channel
*ch
=(struct comx_channel
*)dev
->priv
;
596 struct comx_hardware
*hw
= comx_channels
;
597 struct comx_protocol
*line
= comx_lines
;
601 if (count
> PAGE_SIZE
) {
602 printk(KERN_ERR
"count is %lu > %d!!!\n", count
, (int)PAGE_SIZE
);
606 if (!(page
= (char *)__get_free_page(GFP_KERNEL
))) return -ENOMEM
;
608 copy_from_user(page
, buffer
, count
);
610 if (*(page
+ count
- 1) == '\n') *(page
+ count
- 1) = 0;
612 if (strcmp(entry
->name
, FILENAME_DEBUG
) == 0) {
616 if ((i
= simple_strtoul(page
, NULL
, 10)) != 0) {
619 save_flags(flags
); cli();
620 if (ch
->debug_area
) kfree(ch
->debug_area
);
621 if ((ch
->debug_area
= kmalloc(ch
->debug_size
= i
,
622 GFP_KERNEL
)) == NULL
) {
625 ch
->debug_start
= ch
->debug_end
= 0;
626 restore_flags(flags
);
627 free_page((unsigned long)page
);
631 if (*page
!= '+' && *page
!= '-') {
632 free_page((unsigned long)page
);
635 while (comx_debugflags
[i
].value
&&
636 strncmp(comx_debugflags
[i
].name
, page
+ 1,
637 strlen(comx_debugflags
[i
].name
))) {
641 if (comx_debugflags
[i
].value
== 0) {
642 printk(KERN_ERR
"Invalid debug option\n");
643 free_page((unsigned long)page
);
647 ch
->debug_flags
|= comx_debugflags
[i
].value
;
649 ch
->debug_flags
&= ~comx_debugflags
[i
].value
;
651 } else if (strcmp(entry
->name
, FILENAME_HARDWARE
) == 0) {
652 if(strlen(page
)>10) {
653 free_page((unsigned long)page
);
657 if (strcmp(hw
->name
, page
) == 0) {
664 if(!hw
&& comx_strcasecmp(HWNAME_NONE
,page
) != 0){
665 sprintf(str
,"comx-hw-%s",page
);
670 if (comx_strcasecmp(hw
->name
, page
) == 0) {
678 if (comx_strcasecmp(HWNAME_NONE
, page
) != 0 && !hw
) {
679 free_page((unsigned long)page
);
682 if (ch
->init_status
& HW_OPEN
) {
683 free_page((unsigned long)page
);
686 if (ch
->hardware
&& ch
->hardware
->hw_exit
&&
687 (ret
=ch
->hardware
->hw_exit(dev
))) {
688 free_page((unsigned long)page
);
692 entry
->size
= strlen(page
) + 1;
693 if (hw
&& hw
->hw_init
) hw
->hw_init(dev
);
694 } else if (strcmp(entry
->name
, FILENAME_PROTOCOL
) == 0) {
695 if(strlen(page
)>10) {
696 free_page((unsigned long)page
);
700 if (comx_strcasecmp(line
->name
, page
) == 0) {
707 if(!line
&& comx_strcasecmp(PROTONAME_NONE
, page
) != 0) {
708 sprintf(str
,"comx-proto-%s",page
);
713 if (comx_strcasecmp(line
->name
, page
) == 0) {
721 if (comx_strcasecmp(PROTONAME_NONE
, page
) != 0 && !line
) {
722 free_page((unsigned long)page
);
726 if (ch
->init_status
& LINE_OPEN
) {
727 free_page((unsigned long)page
);
731 if (ch
->protocol
&& ch
->protocol
->line_exit
&&
732 (ret
=ch
->protocol
->line_exit(dev
))) {
733 free_page((unsigned long)page
);
737 entry
->size
= strlen(page
) + 1;
739 if (line
&& line
->line_init
) line
->line_init(dev
);
740 } else if (strcmp(entry
->name
, FILENAME_LINEUPDELAY
) == 0) {
743 if ((i
= simple_strtoul(page
, NULL
, 10)) != 0) {
744 if (i
>=0 && i
< 10) {
745 ch
->lineup_delay
= i
;
747 printk(KERN_ERR
"comx: invalid lineup_delay value\n");
752 free_page((unsigned long)page
);
756 static int comx_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
758 struct proc_dir_entry
*new_dir
, *debug_file
;
759 struct net_device
*dev
;
760 struct comx_channel
*ch
;
762 if ((new_dir
= create_proc_entry(dentry
->d_name
.name
, mode
| S_IFDIR
,
763 comx_root_dir
)) == NULL
) {
768 new_dir
->data
= NULL
; // ide jon majd a struct dev
771 if (!create_comx_proc_entry(FILENAME_HARDWARE
, 0644,
772 strlen(HWNAME_NONE
) + 1, new_dir
)) {
775 if (!create_comx_proc_entry(FILENAME_PROTOCOL
, 0644,
776 strlen(PROTONAME_NONE
) + 1, new_dir
)) {
779 if (!create_comx_proc_entry(FILENAME_STATUS
, 0444, 0, new_dir
)) {
782 if (!create_comx_proc_entry(FILENAME_LINEUPDELAY
, 0644, 2, new_dir
)) {
786 if ((debug_file
= create_proc_entry(FILENAME_DEBUG
,
787 S_IFREG
| 0644, new_dir
)) == NULL
) {
790 debug_file
->data
= (void *)debug_file
;
791 debug_file
->read_proc
= NULL
; // see below
792 debug_file
->write_proc
= &comx_write_proc
;
793 debug_file
->nlink
= 1;
795 if ((dev
= kmalloc(sizeof(struct net_device
), GFP_KERNEL
)) == NULL
) {
798 memset(dev
, 0, sizeof(struct net_device
));
799 strcpy(dev
->name
, (char *)new_dir
->name
);
800 dev
->init
= comx_init_dev
;
802 if (register_netdevice(dev
)) {
806 if((ch
->if_ptr
= (void *)kmalloc(sizeof(struct ppp_device
),
807 GFP_KERNEL
)) == NULL
) {
810 memset(ch
->if_ptr
, 0, sizeof(struct ppp_device
));
811 ch
->debug_file
= debug_file
;
812 ch
->procdir
= new_dir
;
815 ch
->debug_start
= ch
->debug_end
= 0;
816 if ((ch
->debug_area
= kmalloc(ch
->debug_size
= DEFAULT_DEBUG_SIZE
,
817 GFP_KERNEL
)) == NULL
) {
821 ch
->lineup_delay
= DEFAULT_LINEUP_DELAY
;
827 static int comx_rmdir(struct inode
*dir
, struct dentry
*dentry
)
829 struct proc_dir_entry
*entry
= dentry
->d_inode
->u
.generic_ip
;
830 struct net_device
*dev
= entry
->data
;
831 struct comx_channel
*ch
= dev
->priv
;
834 if (dev
->flags
& IFF_UP
) {
835 printk(KERN_ERR
"%s: down interface before removing it\n", dev
->name
);
839 if (ch
->protocol
&& ch
->protocol
->line_exit
&&
840 (ret
=ch
->protocol
->line_exit(dev
))) {
843 if (ch
->hardware
&& ch
->hardware
->hw_exit
&&
844 (ret
=ch
->hardware
->hw_exit(dev
))) {
845 if(ch
->protocol
&& ch
->protocol
->line_init
) {
846 ch
->protocol
->line_init(dev
);
853 del_timer(&ch
->loadavg_timer
);
854 kfree(ch
->avg_bytes
);
856 unregister_netdev(dev
);
857 if (ch
->debug_area
) {
858 kfree(ch
->debug_area
);
865 remove_proc_entry(FILENAME_DEBUG
, entry
);
866 remove_proc_entry(FILENAME_LINEUPDELAY
, entry
);
867 remove_proc_entry(FILENAME_STATUS
, entry
);
868 remove_proc_entry(FILENAME_HARDWARE
, entry
);
869 remove_proc_entry(FILENAME_PROTOCOL
, entry
);
870 remove_proc_entry(dentry
->d_name
.name
, comx_root_dir
);
876 static struct dentry
*comx_lookup(struct inode
*dir
, struct dentry
*dentry
)
878 struct proc_dir_entry
*de
;
879 struct inode
*inode
= NULL
;
881 if ((de
= (struct proc_dir_entry
*) dir
->u
.generic_ip
) != NULL
) {
882 for (de
= de
->subdir
; de
; de
= de
->next
) {
883 if ((de
&& de
->low_ino
) &&
884 (de
->namelen
== dentry
->d_name
.len
) &&
885 (memcmp(dentry
->d_name
.name
, de
->name
,
886 de
->namelen
) == 0)) {
887 if ((inode
= proc_get_inode(dir
->i_sb
,
888 de
->low_ino
, de
)) == NULL
) {
889 printk(KERN_ERR
"COMX: lookup error\n");
890 return ERR_PTR(-EINVAL
);
896 dentry
->d_op
= &comx_dentry_operations
;
897 d_add(dentry
, inode
);
901 int comx_strcasecmp(const char *cs
, const char *ct
)
903 register signed char __res
;
906 if ((__res
= toupper(*cs
) - toupper(*ct
++)) != 0 || !*cs
++) {
913 static int comx_delete_dentry(struct dentry
*dentry
)
918 static struct proc_dir_entry
*create_comx_proc_entry(char *name
, int mode
,
919 int size
, struct proc_dir_entry
*dir
)
921 struct proc_dir_entry
*new_file
;
923 if ((new_file
= create_proc_entry(name
, S_IFREG
| mode
, dir
)) != NULL
) {
924 new_file
->data
= (void *)new_file
;
925 new_file
->read_proc
= &comx_read_proc
;
926 new_file
->write_proc
= &comx_write_proc
;
927 new_file
->size
= size
;
933 int comx_register_hardware(struct comx_hardware
*comx_hw
)
935 struct comx_hardware
*hw
= comx_channels
;
938 comx_channels
= comx_hw
;
940 while (hw
->next
!= NULL
&& strcmp(comx_hw
->name
, hw
->name
) != 0) {
943 if (strcmp(comx_hw
->name
, hw
->name
) == 0) {
949 printk(KERN_INFO
"COMX: driver for hardware type %s, version %s\n", comx_hw
->name
, comx_hw
->version
);
953 int comx_unregister_hardware(char *name
)
955 struct comx_hardware
*hw
= comx_channels
;
961 if (strcmp(hw
->name
, name
) == 0) {
962 comx_channels
= comx_channels
->next
;
966 while (hw
->next
!= NULL
&& strcmp(hw
->next
->name
,name
) != 0) {
970 if (hw
->next
!= NULL
&& strcmp(hw
->next
->name
, name
) == 0) {
971 hw
->next
= hw
->next
->next
;
977 int comx_register_protocol(struct comx_protocol
*comx_line
)
979 struct comx_protocol
*pr
= comx_lines
;
982 comx_lines
= comx_line
;
984 while (pr
->next
!= NULL
&& strcmp(comx_line
->name
, pr
->name
) !=0) {
987 if (strcmp(comx_line
->name
, pr
->name
) == 0) {
990 pr
->next
= comx_line
;
993 printk(KERN_INFO
"COMX: driver for protocol type %s, version %s\n", comx_line
->name
, comx_line
->version
);
997 int comx_unregister_protocol(char *name
)
999 struct comx_protocol
*pr
= comx_lines
;
1005 if (strcmp(pr
->name
, name
) == 0) {
1006 comx_lines
= comx_lines
->next
;
1010 while (pr
->next
!= NULL
&& strcmp(pr
->next
->name
,name
) != 0) {
1014 if (pr
->next
!= NULL
&& strcmp(pr
->next
->name
, name
) == 0) {
1015 pr
->next
= pr
->next
->next
;
1022 #define comx_init init_module
1025 int __init
comx_init(void)
1027 struct proc_dir_entry
*new_file
;
1029 comx_root_dir
= create_proc_entry("comx",
1030 S_IFDIR
| S_IWUSR
| S_IRUGO
| S_IXUGO
, &proc_root
);
1033 comx_root_dir
->proc_iops
= &comx_root_inode_ops
;
1035 if ((new_file
= create_proc_entry(FILENAME_HARDWARELIST
,
1036 S_IFREG
| 0444, comx_root_dir
)) == NULL
) {
1040 new_file
->data
= new_file
;
1041 new_file
->read_proc
= &comx_root_read_proc
;
1042 new_file
->write_proc
= NULL
;
1043 new_file
->nlink
= 1;
1045 if ((new_file
= create_proc_entry(FILENAME_PROTOCOLLIST
,
1046 S_IFREG
| 0444, comx_root_dir
)) == NULL
) {
1050 new_file
->data
= new_file
;
1051 new_file
->read_proc
= &comx_root_read_proc
;
1052 new_file
->write_proc
= NULL
;
1053 new_file
->nlink
= 1;
1056 printk(KERN_INFO
"COMX: driver version %s (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>\n",
1060 #ifdef CONFIG_COMX_HW_COMX
1061 comx_hw_comx_init();
1063 #ifdef CONFIG_COMX_HW_LOCOMX
1064 comx_hw_locomx_init();
1066 #ifdef CONFIG_COMX_HW_MIXCOM
1067 comx_hw_mixcom_init();
1069 #ifdef CONFIG_COMX_PROTO_HDLC
1070 comx_proto_hdlc_init();
1072 #ifdef CONFIG_COMX_PROTO_PPP
1073 comx_proto_ppp_init();
1075 #ifdef CONFIG_COMX_PROTO_LAPB
1076 comx_proto_lapb_init();
1078 #ifdef CONFIG_COMX_PROTO_FR
1079 comx_proto_fr_init();
1087 void cleanup_module(void)
1089 remove_proc_entry(FILENAME_HARDWARELIST
, comx_root_dir
);
1090 remove_proc_entry(FILENAME_PROTOCOLLIST
, comx_root_dir
);
1091 remove_proc_entry(comx_root_dir
->name
, &proc_root
);
1095 EXPORT_SYMBOL(comx_register_hardware
);
1096 EXPORT_SYMBOL(comx_unregister_hardware
);
1097 EXPORT_SYMBOL(comx_register_protocol
);
1098 EXPORT_SYMBOL(comx_unregister_protocol
);
1099 EXPORT_SYMBOL(comx_debug_skb
);
1100 EXPORT_SYMBOL(comx_debug_bytes
);
1101 EXPORT_SYMBOL(comx_debug
);
1102 EXPORT_SYMBOL(comx_lineup_func
);
1103 EXPORT_SYMBOL(comx_status
);
1104 EXPORT_SYMBOL(comx_rx
);
1105 EXPORT_SYMBOL(comx_strcasecmp
);
1106 EXPORT_SYMBOL(comx_root_dir
);