~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/isdn/hardware/eicon/divamnt.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: divamnt.c,v 1.32.6.10 2005/02/11 19:40:25 armin Exp $
 
2
 *
 
3
 * Driver for Eicon DIVA Server ISDN cards.
 
4
 * Maint module
 
5
 *
 
6
 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
 
7
 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
 
8
 *
 
9
 * This software may be used and distributed according to the terms
 
10
 * of the GNU General Public License, incorporated herein by reference.
 
11
 */
 
12
 
 
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>
 
19
 
 
20
#include "platform.h"
 
21
#include "di_defs.h"
 
22
#include "divasync.h"
 
23
#include "debug_if.h"
 
24
 
 
25
static DEFINE_MUTEX(maint_mutex);
 
26
static char *main_revision = "$Revision: 1.32.6.10 $";
 
27
 
 
28
static int major;
 
29
 
 
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");
 
34
 
 
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);
 
39
 
 
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";
 
45
 
 
46
static wait_queue_head_t msgwaitq;
 
47
static unsigned long opened;
 
48
static struct timeval start_time;
 
49
 
 
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);
 
53
 
 
54
/*
 
55
 *  helper functions
 
56
 */
 
57
static char *getrev(const char *revision)
 
58
{
 
59
        char *rev;
 
60
        char *p;
 
61
 
 
62
        if ((p = strchr(revision, ':'))) {
 
63
                rev = p + 2;
 
64
                p = strchr(rev, '$');
 
65
                *--p = 0;
 
66
        } else
 
67
                rev = "1.0";
 
68
 
 
69
        return rev;
 
70
}
 
71
 
 
72
/*
 
73
 * kernel/user space copy functions
 
74
 */
 
75
int diva_os_copy_to_user(void *os_handle, void __user *dst, const void *src,
 
76
                         int length)
 
77
{
 
78
        return (copy_to_user(dst, src, length));
 
79
}
 
80
int diva_os_copy_from_user(void *os_handle, void *dst, const void __user *src,
 
81
                           int length)
 
82
{
 
83
        return (copy_from_user(dst, src, length));
 
84
}
 
85
 
 
86
/*
 
87
 * get time
 
88
 */
 
89
void diva_os_get_time(dword * sec, dword * usec)
 
90
{
 
91
        struct timeval tv;
 
92
 
 
93
        do_gettimeofday(&tv);
 
94
 
 
95
        if (tv.tv_sec > start_time.tv_sec) {
 
96
                if (start_time.tv_usec > tv.tv_usec) {
 
97
                        tv.tv_sec--;
 
98
                        tv.tv_usec += 1000000;
 
99
                }
 
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) {
 
103
                *sec = 0;
 
104
                if (start_time.tv_usec < tv.tv_usec) {
 
105
                        *usec = (dword) (tv.tv_usec - start_time.tv_usec);
 
106
                } else {
 
107
                        *usec = 0;
 
108
                }
 
109
        } else {
 
110
                *sec = (dword) tv.tv_sec;
 
111
                *usec = (dword) tv.tv_usec;
 
112
        }
 
113
}
 
114
 
 
115
/*
 
116
 * device node operations
 
117
 */
 
118
static unsigned int maint_poll(struct file *file, poll_table * wait)
 
119
{
 
120
        unsigned int mask = 0;
 
121
 
 
122
        poll_wait(file, &msgwaitq, wait);
 
123
        mask = POLLOUT | POLLWRNORM;
 
124
        if (file->private_data || diva_dbg_q_length()) {
 
125
                mask |= POLLIN | POLLRDNORM;
 
126
        }
 
127
        return (mask);
 
128
}
 
129
 
 
130
static int maint_open(struct inode *ino, struct file *filep)
 
131
{
 
132
        int ret;
 
133
 
 
134
        mutex_lock(&maint_mutex);
 
135
        /* only one open is allowed, so we test
 
136
           it atomically */
 
137
        if (test_and_set_bit(0, &opened))
 
138
                ret = -EBUSY;
 
139
        else {
 
140
                filep->private_data = NULL;
 
141
                ret = nonseekable_open(ino, filep);
 
142
        }
 
143
        mutex_unlock(&maint_mutex);
 
144
        return ret;
 
145
}
 
146
 
 
147
static int maint_close(struct inode *ino, struct file *filep)
 
148
{
 
149
        if (filep->private_data) {
 
150
                diva_os_free(0, filep->private_data);
 
151
                filep->private_data = NULL;
 
152
        }
 
153
 
 
154
        /* clear 'used' flag */
 
155
        clear_bit(0, &opened);
 
156
        
 
157
        return (0);
 
158
}
 
159
 
 
160
static ssize_t divas_maint_write(struct file *file, const char __user *buf,
 
161
                                 size_t count, loff_t * ppos)
 
162
{
 
163
        return (maint_read_write((char __user *) buf, (int) count));
 
164
}
 
165
 
 
166
static ssize_t divas_maint_read(struct file *file, char __user *buf,
 
167
                                size_t count, loff_t * ppos)
 
168
{
 
169
        return (maint_read_write(buf, (int) count));
 
170
}
 
171
 
 
172
static const struct file_operations divas_maint_fops = {
 
173
        .owner   = THIS_MODULE,
 
174
        .llseek  = no_llseek,
 
175
        .read    = divas_maint_read,
 
176
        .write   = divas_maint_write,
 
177
        .poll    = maint_poll,
 
178
        .open    = maint_open,
 
179
        .release = maint_close
 
180
};
 
181
 
 
182
static void divas_maint_unregister_chrdev(void)
 
183
{
 
184
        unregister_chrdev(major, DEVNAME);
 
185
}
 
186
 
 
187
static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
 
188
{
 
189
        if ((major = register_chrdev(0, DEVNAME, &divas_maint_fops)) < 0)
 
190
        {
 
191
                printk(KERN_ERR "%s: failed to create /dev entry.\n",
 
192
                       DRIVERLNAME);
 
193
                return (0);
 
194
        }
 
195
 
 
196
        return (1);
 
197
}
 
198
 
 
199
/*
 
200
 * wake up reader
 
201
 */
 
202
void diva_maint_wakeup_read(void)
 
203
{
 
204
        wake_up_interruptible(&msgwaitq);
 
205
}
 
206
 
 
207
/*
 
208
 *  Driver Load
 
209
 */
 
210
static int DIVA_INIT_FUNCTION maint_init(void)
 
211
{
 
212
        char tmprev[50];
 
213
        int ret = 0;
 
214
        void *buffer = NULL;
 
215
 
 
216
        do_gettimeofday(&start_time);
 
217
        init_waitqueue_head(&msgwaitq);
 
218
 
 
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);
 
223
 
 
224
        if (!divas_maint_register_chrdev()) {
 
225
                ret = -EIO;
 
226
                goto out;
 
227
        }
 
228
 
 
229
        if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
 
230
                printk(KERN_ERR "%s: failed to connect to DIDD.\n",
 
231
                       DRIVERLNAME);
 
232
                divas_maint_unregister_chrdev();
 
233
                ret = -EIO;
 
234
                goto out;
 
235
        }
 
236
 
 
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);
 
240
 
 
241
      out:
 
242
        return (ret);
 
243
}
 
244
 
 
245
/*
 
246
**  Driver Unload
 
247
*/
 
248
static void DIVA_EXIT_FUNCTION maint_exit(void)
 
249
{
 
250
        divas_maint_unregister_chrdev();
 
251
        mntfunc_finit();
 
252
 
 
253
        printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
 
254
}
 
255
 
 
256
module_init(maint_init);
 
257
module_exit(maint_exit);
 
258