1 /* $Id: divamnt.c,v 1.32.6.10 2005/02/11 19:40:25 armin Exp $
3 * Driver for Eicon DIVA Server ISDN cards.
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/poll.h>
17 #include <linux/smp_lock.h>
18 #include <asm/uaccess.h>
25 static char *main_revision
= "$Revision: 1.32.6.10 $";
29 MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards");
30 MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
31 MODULE_SUPPORTED_DEVICE("DIVA card driver");
32 MODULE_LICENSE("GPL");
34 static int buffer_length
= 128;
35 module_param(buffer_length
, int, 0);
36 static unsigned long diva_dbg_mem
= 0;
37 module_param(diva_dbg_mem
, ulong
, 0);
39 static char *DRIVERNAME
=
40 "Eicon DIVA - MAINT module (http://www.melware.net)";
41 static char *DRIVERLNAME
= "diva_mnt";
42 static char *DEVNAME
= "DivasMAINT";
43 char *DRIVERRELEASE_MNT
= "2.0";
45 static wait_queue_head_t msgwaitq
;
46 static unsigned long opened
;
47 static struct timeval start_time
;
49 extern int mntfunc_init(int *, void **, unsigned long);
50 extern void mntfunc_finit(void);
51 extern int maint_read_write(void __user
*buf
, int count
);
56 static char *getrev(const char *revision
)
61 if ((p
= strchr(revision
, ':'))) {
72 * kernel/user space copy functions
74 int diva_os_copy_to_user(void *os_handle
, void __user
*dst
, const void *src
,
77 return (copy_to_user(dst
, src
, length
));
79 int diva_os_copy_from_user(void *os_handle
, void *dst
, const void __user
*src
,
82 return (copy_from_user(dst
, src
, length
));
88 void diva_os_get_time(dword
* sec
, dword
* usec
)
94 if (tv
.tv_sec
> start_time
.tv_sec
) {
95 if (start_time
.tv_usec
> tv
.tv_usec
) {
97 tv
.tv_usec
+= 1000000;
99 *sec
= (dword
) (tv
.tv_sec
- start_time
.tv_sec
);
100 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
101 } else if (tv
.tv_sec
== start_time
.tv_sec
) {
103 if (start_time
.tv_usec
< tv
.tv_usec
) {
104 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
109 *sec
= (dword
) tv
.tv_sec
;
110 *usec
= (dword
) tv
.tv_usec
;
115 * device node operations
117 static unsigned int maint_poll(struct file
*file
, poll_table
* wait
)
119 unsigned int mask
= 0;
121 poll_wait(file
, &msgwaitq
, wait
);
122 mask
= POLLOUT
| POLLWRNORM
;
123 if (file
->private_data
|| diva_dbg_q_length()) {
124 mask
|= POLLIN
| POLLRDNORM
;
129 static int maint_open(struct inode
*ino
, struct file
*filep
)
134 /* only one open is allowed, so we test
136 if (test_and_set_bit(0, &opened
))
139 filep
->private_data
= NULL
;
140 ret
= nonseekable_open(ino
, filep
);
146 static int maint_close(struct inode
*ino
, struct file
*filep
)
148 if (filep
->private_data
) {
149 diva_os_free(0, filep
->private_data
);
150 filep
->private_data
= NULL
;
153 /* clear 'used' flag */
154 clear_bit(0, &opened
);
159 static ssize_t
divas_maint_write(struct file
*file
, const char __user
*buf
,
160 size_t count
, loff_t
* ppos
)
162 return (maint_read_write((char __user
*) buf
, (int) count
));
165 static ssize_t
divas_maint_read(struct file
*file
, char __user
*buf
,
166 size_t count
, loff_t
* ppos
)
168 return (maint_read_write(buf
, (int) count
));
171 static const struct file_operations divas_maint_fops
= {
172 .owner
= THIS_MODULE
,
174 .read
= divas_maint_read
,
175 .write
= divas_maint_write
,
178 .release
= maint_close
181 static void divas_maint_unregister_chrdev(void)
183 unregister_chrdev(major
, DEVNAME
);
186 static int DIVA_INIT_FUNCTION
divas_maint_register_chrdev(void)
188 if ((major
= register_chrdev(0, DEVNAME
, &divas_maint_fops
)) < 0)
190 printk(KERN_ERR
"%s: failed to create /dev entry.\n",
201 void diva_maint_wakeup_read(void)
203 wake_up_interruptible(&msgwaitq
);
209 static int DIVA_INIT_FUNCTION
maint_init(void)
215 do_gettimeofday(&start_time
);
216 init_waitqueue_head(&msgwaitq
);
218 printk(KERN_INFO
"%s\n", DRIVERNAME
);
219 printk(KERN_INFO
"%s: Rel:%s Rev:", DRIVERLNAME
, DRIVERRELEASE_MNT
);
220 strcpy(tmprev
, main_revision
);
221 printk("%s Build: %s \n", getrev(tmprev
), DIVA_BUILD
);
223 if (!divas_maint_register_chrdev()) {
228 if (!(mntfunc_init(&buffer_length
, &buffer
, diva_dbg_mem
))) {
229 printk(KERN_ERR
"%s: failed to connect to DIDD.\n",
231 divas_maint_unregister_chrdev();
236 printk(KERN_INFO
"%s: trace buffer = %p - %d kBytes, %s (Major: %d)\n",
237 DRIVERLNAME
, buffer
, (buffer_length
/ 1024),
238 (diva_dbg_mem
== 0) ? "internal" : "external", major
);
247 static void DIVA_EXIT_FUNCTION
maint_exit(void)
249 divas_maint_unregister_chrdev();
252 printk(KERN_INFO
"%s: module unloaded.\n", DRIVERLNAME
);
255 module_init(maint_init
);
256 module_exit(maint_exit
);