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/mutex.h>
18 #include <asm/uaccess.h>
25 static DEFINE_MUTEX(maint_mutex
);
26 static char *main_revision
= "$Revision: 1.32.6.10 $";
30 MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards");
31 MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
32 MODULE_SUPPORTED_DEVICE("DIVA card driver");
33 MODULE_LICENSE("GPL");
35 static int buffer_length
= 128;
36 module_param(buffer_length
, int, 0);
37 static unsigned long diva_dbg_mem
= 0;
38 module_param(diva_dbg_mem
, ulong
, 0);
40 static char *DRIVERNAME
=
41 "Eicon DIVA - MAINT module (http://www.melware.net)";
42 static char *DRIVERLNAME
= "diva_mnt";
43 static char *DEVNAME
= "DivasMAINT";
44 char *DRIVERRELEASE_MNT
= "2.0";
46 static wait_queue_head_t msgwaitq
;
47 static unsigned long opened
;
48 static struct timeval start_time
;
50 extern int mntfunc_init(int *, void **, unsigned long);
51 extern void mntfunc_finit(void);
52 extern int maint_read_write(void __user
*buf
, int count
);
57 static char *getrev(const char *revision
)
62 if ((p
= strchr(revision
, ':'))) {
73 * kernel/user space copy functions
75 int diva_os_copy_to_user(void *os_handle
, void __user
*dst
, const void *src
,
78 return (copy_to_user(dst
, src
, length
));
80 int diva_os_copy_from_user(void *os_handle
, void *dst
, const void __user
*src
,
83 return (copy_from_user(dst
, src
, length
));
89 void diva_os_get_time(dword
* sec
, dword
* usec
)
95 if (tv
.tv_sec
> start_time
.tv_sec
) {
96 if (start_time
.tv_usec
> tv
.tv_usec
) {
98 tv
.tv_usec
+= 1000000;
100 *sec
= (dword
) (tv
.tv_sec
- start_time
.tv_sec
);
101 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
102 } else if (tv
.tv_sec
== start_time
.tv_sec
) {
104 if (start_time
.tv_usec
< tv
.tv_usec
) {
105 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
110 *sec
= (dword
) tv
.tv_sec
;
111 *usec
= (dword
) tv
.tv_usec
;
116 * device node operations
118 static unsigned int maint_poll(struct file
*file
, poll_table
* wait
)
120 unsigned int mask
= 0;
122 poll_wait(file
, &msgwaitq
, wait
);
123 mask
= POLLOUT
| POLLWRNORM
;
124 if (file
->private_data
|| diva_dbg_q_length()) {
125 mask
|= POLLIN
| POLLRDNORM
;
130 static int maint_open(struct inode
*ino
, struct file
*filep
)
134 mutex_lock(&maint_mutex
);
135 /* only one open is allowed, so we test
137 if (test_and_set_bit(0, &opened
))
140 filep
->private_data
= NULL
;
141 ret
= nonseekable_open(ino
, filep
);
143 mutex_unlock(&maint_mutex
);
147 static int maint_close(struct inode
*ino
, struct file
*filep
)
149 if (filep
->private_data
) {
150 diva_os_free(0, filep
->private_data
);
151 filep
->private_data
= NULL
;
154 /* clear 'used' flag */
155 clear_bit(0, &opened
);
160 static ssize_t
divas_maint_write(struct file
*file
, const char __user
*buf
,
161 size_t count
, loff_t
* ppos
)
163 return (maint_read_write((char __user
*) buf
, (int) count
));
166 static ssize_t
divas_maint_read(struct file
*file
, char __user
*buf
,
167 size_t count
, loff_t
* ppos
)
169 return (maint_read_write(buf
, (int) count
));
172 static const struct file_operations divas_maint_fops
= {
173 .owner
= THIS_MODULE
,
175 .read
= divas_maint_read
,
176 .write
= divas_maint_write
,
179 .release
= maint_close
182 static void divas_maint_unregister_chrdev(void)
184 unregister_chrdev(major
, DEVNAME
);
187 static int DIVA_INIT_FUNCTION
divas_maint_register_chrdev(void)
189 if ((major
= register_chrdev(0, DEVNAME
, &divas_maint_fops
)) < 0)
191 printk(KERN_ERR
"%s: failed to create /dev entry.\n",
202 void diva_maint_wakeup_read(void)
204 wake_up_interruptible(&msgwaitq
);
210 static int DIVA_INIT_FUNCTION
maint_init(void)
216 do_gettimeofday(&start_time
);
217 init_waitqueue_head(&msgwaitq
);
219 printk(KERN_INFO
"%s\n", DRIVERNAME
);
220 printk(KERN_INFO
"%s: Rel:%s Rev:", DRIVERLNAME
, DRIVERRELEASE_MNT
);
221 strcpy(tmprev
, main_revision
);
222 printk("%s Build: %s \n", getrev(tmprev
), DIVA_BUILD
);
224 if (!divas_maint_register_chrdev()) {
229 if (!(mntfunc_init(&buffer_length
, &buffer
, diva_dbg_mem
))) {
230 printk(KERN_ERR
"%s: failed to connect to DIDD.\n",
232 divas_maint_unregister_chrdev();
237 printk(KERN_INFO
"%s: trace buffer = %p - %d kBytes, %s (Major: %d)\n",
238 DRIVERLNAME
, buffer
, (buffer_length
/ 1024),
239 (diva_dbg_mem
== 0) ? "internal" : "external", major
);
248 static void DIVA_EXIT_FUNCTION
maint_exit(void)
250 divas_maint_unregister_chrdev();
253 printk(KERN_INFO
"%s: module unloaded.\n", DRIVERLNAME
);
256 module_init(maint_init
);
257 module_exit(maint_exit
);