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 <asm/uaccess.h>
24 static char *main_revision
= "$Revision: 1.32.6.10 $";
28 MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards");
29 MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
30 MODULE_SUPPORTED_DEVICE("DIVA card driver");
31 MODULE_LICENSE("GPL");
33 static int buffer_length
= 128;
34 module_param(buffer_length
, int, 0);
35 static unsigned long diva_dbg_mem
= 0;
36 module_param(diva_dbg_mem
, ulong
, 0);
38 static char *DRIVERNAME
=
39 "Eicon DIVA - MAINT module (http://www.melware.net)";
40 static char *DRIVERLNAME
= "diva_mnt";
41 static char *DEVNAME
= "DivasMAINT";
42 char *DRIVERRELEASE_MNT
= "2.0";
44 static wait_queue_head_t msgwaitq
;
45 static unsigned long opened
;
46 static struct timeval start_time
;
48 extern int mntfunc_init(int *, void **, unsigned long);
49 extern void mntfunc_finit(void);
50 extern int maint_read_write(void __user
*buf
, int count
);
55 static char *getrev(const char *revision
)
60 if ((p
= strchr(revision
, ':'))) {
71 * kernel/user space copy functions
73 int diva_os_copy_to_user(void *os_handle
, void __user
*dst
, const void *src
,
76 return (copy_to_user(dst
, src
, length
));
78 int diva_os_copy_from_user(void *os_handle
, void *dst
, const void __user
*src
,
81 return (copy_from_user(dst
, src
, length
));
87 void diva_os_get_time(dword
* sec
, dword
* usec
)
93 if (tv
.tv_sec
> start_time
.tv_sec
) {
94 if (start_time
.tv_usec
> tv
.tv_usec
) {
96 tv
.tv_usec
+= 1000000;
98 *sec
= (dword
) (tv
.tv_sec
- start_time
.tv_sec
);
99 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
100 } else if (tv
.tv_sec
== start_time
.tv_sec
) {
102 if (start_time
.tv_usec
< tv
.tv_usec
) {
103 *usec
= (dword
) (tv
.tv_usec
- start_time
.tv_usec
);
108 *sec
= (dword
) tv
.tv_sec
;
109 *usec
= (dword
) tv
.tv_usec
;
114 * device node operations
116 static unsigned int maint_poll(struct file
*file
, poll_table
* wait
)
118 unsigned int mask
= 0;
120 poll_wait(file
, &msgwaitq
, wait
);
121 mask
= POLLOUT
| POLLWRNORM
;
122 if (file
->private_data
|| diva_dbg_q_length()) {
123 mask
|= POLLIN
| POLLRDNORM
;
128 static int maint_open(struct inode
*ino
, struct file
*filep
)
130 /* only one open is allowed, so we test
132 if (test_and_set_bit(0, &opened
))
135 filep
->private_data
= NULL
;
137 return nonseekable_open(ino
, filep
);
140 static int maint_close(struct inode
*ino
, struct file
*filep
)
142 if (filep
->private_data
) {
143 diva_os_free(0, filep
->private_data
);
144 filep
->private_data
= NULL
;
147 /* clear 'used' flag */
148 clear_bit(0, &opened
);
153 static ssize_t
divas_maint_write(struct file
*file
, const char __user
*buf
,
154 size_t count
, loff_t
* ppos
)
156 return (maint_read_write((char __user
*) buf
, (int) count
));
159 static ssize_t
divas_maint_read(struct file
*file
, char __user
*buf
,
160 size_t count
, loff_t
* ppos
)
162 return (maint_read_write(buf
, (int) count
));
165 static const struct file_operations divas_maint_fops
= {
166 .owner
= THIS_MODULE
,
168 .read
= divas_maint_read
,
169 .write
= divas_maint_write
,
172 .release
= maint_close
175 static void divas_maint_unregister_chrdev(void)
177 unregister_chrdev(major
, DEVNAME
);
180 static int DIVA_INIT_FUNCTION
divas_maint_register_chrdev(void)
182 if ((major
= register_chrdev(0, DEVNAME
, &divas_maint_fops
)) < 0)
184 printk(KERN_ERR
"%s: failed to create /dev entry.\n",
195 void diva_maint_wakeup_read(void)
197 wake_up_interruptible(&msgwaitq
);
203 static int DIVA_INIT_FUNCTION
maint_init(void)
209 do_gettimeofday(&start_time
);
210 init_waitqueue_head(&msgwaitq
);
212 printk(KERN_INFO
"%s\n", DRIVERNAME
);
213 printk(KERN_INFO
"%s: Rel:%s Rev:", DRIVERLNAME
, DRIVERRELEASE_MNT
);
214 strcpy(tmprev
, main_revision
);
215 printk("%s Build: %s \n", getrev(tmprev
), DIVA_BUILD
);
217 if (!divas_maint_register_chrdev()) {
222 if (!(mntfunc_init(&buffer_length
, &buffer
, diva_dbg_mem
))) {
223 printk(KERN_ERR
"%s: failed to connect to DIDD.\n",
225 divas_maint_unregister_chrdev();
230 printk(KERN_INFO
"%s: trace buffer = %p - %d kBytes, %s (Major: %d)\n",
231 DRIVERLNAME
, buffer
, (buffer_length
/ 1024),
232 (diva_dbg_mem
== 0) ? "internal" : "external", major
);
241 static void DIVA_EXIT_FUNCTION
maint_exit(void)
243 divas_maint_unregister_chrdev();
246 printk(KERN_INFO
"%s: module unloaded.\n", DRIVERLNAME
);
249 module_init(maint_init
);
250 module_exit(maint_exit
);