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/config.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/sched.h>
18 #include <linux/smp_lock.h>
19 #include <linux/poll.h>
20 #include <linux/devfs_fs_kernel.h>
21 #include <asm/uaccess.h>
28 static char *main_revision
= "$Revision: 1.32.6.10 $";
32 MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards");
33 MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
34 MODULE_SUPPORTED_DEVICE("DIVA card driver");
35 MODULE_LICENSE("GPL");
37 static int buffer_length
= 128;
38 module_param(buffer_length
, int, 0);
39 static unsigned long diva_dbg_mem
= 0;
40 module_param(diva_dbg_mem
, ulong
, 0);
42 static char *DRIVERNAME
=
43 "Eicon DIVA - MAINT module (http://www.melware.net)";
44 static char *DRIVERLNAME
= "diva_mnt";
45 static char *DEVNAME
= "DivasMAINT";
46 char *DRIVERRELEASE_MNT
= "2.0";
48 static wait_queue_head_t msgwaitq
;
49 static unsigned long opened
;
50 static struct timeval start_time
;
52 extern int mntfunc_init(int *, void **, unsigned long);
53 extern void mntfunc_finit(void);
54 extern int maint_read_write(void __user
*buf
, int count
);
59 static char *getrev(const char *revision
)
64 if ((p
= strchr(revision
, ':'))) {
75 * kernel/user space copy functions
77 int diva_os_copy_to_user(void *os_handle
, void __user
*dst
, const void *src
,
80 return (copy_to_user(dst
, src
, length
));
82 int diva_os_copy_from_user(void *os_handle
, void *dst
, const void __user
*src
,
85 return (copy_from_user(dst
, src
, length
));
91 void diva_os_get_time(dword
* sec
, dword
* usec
)
97 if (tv
.tv_sec
> start_time
.tv_sec
) {
98 if (start_time
.tv_usec
> tv
.tv_usec
) {
100 tv
.tv_usec
+= 1000000;
102 *sec
= (dword
) (tv
.tv_sec
- start_time
.tv_sec
);
103 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
104 } else if (tv
.tv_sec
== start_time
.tv_sec
) {
106 if (start_time
.tv_usec
< tv
.tv_usec
) {
107 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
112 *sec
= (dword
) tv
.tv_sec
;
113 *usec
= (dword
) tv
.tv_usec
;
118 * device node operations
120 static unsigned int maint_poll(struct file
*file
, poll_table
* wait
)
122 unsigned int mask
= 0;
124 poll_wait(file
, &msgwaitq
, wait
);
125 mask
= POLLOUT
| POLLWRNORM
;
126 if (file
->private_data
|| diva_dbg_q_length()) {
127 mask
|= POLLIN
| POLLRDNORM
;
132 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
;
141 return nonseekable_open(ino
, filep
);
144 static int maint_close(struct inode
*ino
, struct file
*filep
)
146 if (filep
->private_data
) {
147 diva_os_free(0, filep
->private_data
);
148 filep
->private_data
= NULL
;
151 /* clear 'used' flag */
152 clear_bit(0, &opened
);
157 static ssize_t
divas_maint_write(struct file
*file
, const char __user
*buf
,
158 size_t count
, loff_t
* ppos
)
160 return (maint_read_write((char __user
*) buf
, (int) count
));
163 static ssize_t
divas_maint_read(struct file
*file
, char __user
*buf
,
164 size_t count
, loff_t
* ppos
)
166 return (maint_read_write(buf
, (int) count
));
169 static struct file_operations divas_maint_fops
= {
170 .owner
= THIS_MODULE
,
172 .read
= divas_maint_read
,
173 .write
= divas_maint_write
,
176 .release
= maint_close
179 static void divas_maint_unregister_chrdev(void)
181 devfs_remove(DEVNAME
);
182 unregister_chrdev(major
, DEVNAME
);
185 static int DIVA_INIT_FUNCTION
divas_maint_register_chrdev(void)
187 if ((major
= register_chrdev(0, DEVNAME
, &divas_maint_fops
)) < 0)
189 printk(KERN_ERR
"%s: failed to create /dev entry.\n",
193 devfs_mk_cdev(MKDEV(major
, 0), S_IFCHR
|S_IRUSR
|S_IWUSR
, DEVNAME
);
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
);