OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [avmb1/] [capi.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * $Id: capi.c,v 1.1.1.1 2001-09-10 07:44:18 simons Exp $
3
 *
4
 * CAPI 2.0 Interface for Linux
5
 *
6
 * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
7
 *
8
 * $Log: not supported by cvs2svn $
9
 * Revision 1.1.1.1  2001/07/02 17:58:32  simons
10
 * Initial revision
11
 *
12
 * Revision 1.4  1997/05/27 15:17:50  fritz
13
 * Added changes for recent 2.1.x kernels:
14
 *   changed return type of isdn_close
15
 *   queue_task_* -> queue_task
16
 *   clear/set_bit -> test_and_... where apropriate.
17
 *   changed type of hard_header_cache parameter.
18
 *
19
 * Revision 1.3  1997/05/18 09:24:14  calle
20
 * added verbose disconnect reason reporting to avmb1.
21
 * some fixes in capi20 interface.
22
 * changed info messages for B1-PCI
23
 *
24
 * Revision 1.2  1997/03/05 21:17:59  fritz
25
 * Added capi_poll for compiling under 2.1.27
26
 *
27
 * Revision 1.1  1997/03/04 21:50:29  calle
28
 * Frirst version in isdn4linux
29
 *
30
 * Revision 2.2  1997/02/12 09:31:39  calle
31
 * new version
32
 *
33
 * Revision 1.1  1997/01/31 10:32:20  calle
34
 * Initial revision
35
 *
36
 */
37
 
38
#include <linux/module.h>
39
#include <linux/errno.h>
40
#include <linux/kernel.h>
41
#include <linux/major.h>
42
#include <linux/sched.h>
43
#include <linux/malloc.h>
44
#include <linux/fcntl.h>
45
#include <linux/fs.h>
46
#include <linux/signal.h>
47
#include <linux/mm.h>
48
#include <linux/timer.h>
49
#include <linux/wait.h>
50
#include <linux/skbuff.h>
51
#if (LINUX_VERSION_CODE >= 0x020117)
52
#include <asm/poll.h>
53
#endif
54
#include <linux/capi.h>
55
#include <linux/kernelcapi.h>
56
 
57
#include "compat.h"
58
#include "capiutil.h"
59
#include "capicmd.h"
60
#include "capidev.h"
61
 
62
#ifdef HAS_NEW_SYMTAB
63
MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");
64
#endif
65
 
66
/* -------- driver information -------------------------------------- */
67
 
68
int capi_major = 68;            /* allocated */
69
 
70
#ifdef HAS_NEW_SYMTAB
71
MODULE_PARM(capi_major, "i");
72
#endif
73
 
74
/* -------- global variables ---------------------------------------- */
75
 
76
static struct capidev capidevs[CAPI_MAXMINOR + 1];
77
struct capi_interface *capifuncs;
78
 
79
/* -------- function called by lower level -------------------------- */
80
 
81
static void capi_signal(__u16 applid, __u32 minor)
82
{
83
        struct capidev *cdev;
84
        struct sk_buff *skb = 0;
85
 
86
        if (minor > CAPI_MAXMINOR || !capidevs[minor].is_registered) {
87
                printk(KERN_ERR "BUG: capi_signal: illegal minor %d\n", minor);
88
                return;
89
        }
90
        cdev = &capidevs[minor];
91
        (void) (*capifuncs->capi_get_message) (applid, &skb);
92
        if (skb) {
93
                skb_queue_tail(&cdev->recv_queue, skb);
94
                wake_up_interruptible(&cdev->recv_wait);
95
        } else {
96
                printk(KERN_ERR "BUG: capi_signal: no skb\n");
97
        }
98
}
99
 
100
/* -------- file_operations ----------------------------------------- */
101
 
102
#if LINUX_VERSION_CODE < 0x020100
103
static int capi_lseek(struct inode *inode, struct file *file,
104
                      off_t offset, int origin)
105
{
106
        return -ESPIPE;
107
}
108
#else
109
static long long capi_llseek(struct inode *inode, struct file *file,
110
                             long long offset, int origin)
111
{
112
        return -ESPIPE;
113
}
114
#endif
115
 
116
#if LINUX_VERSION_CODE < 0x020100
117
static int capi_read(struct inode *inode, struct file *file,
118
                     char *buf, int count)
119
#else
120
static long capi_read(struct inode *inode, struct file *file,
121
                      char *buf, unsigned long count)
122
#endif
123
{
124
        unsigned int minor = MINOR(inode->i_rdev);
125
        struct capidev *cdev;
126
        struct sk_buff *skb;
127
        int retval;
128
        size_t copied;
129
 
130
        if (!minor || minor > CAPI_MAXMINOR || !capidevs[minor].is_registered)
131
                return -ENODEV;
132
 
133
        cdev = &capidevs[minor];
134
 
135
        if ((skb = skb_dequeue(&cdev->recv_queue)) == 0) {
136
 
137
                if (file->f_flags & O_NONBLOCK)
138
                        return -EAGAIN;
139
 
140
                for (;;) {
141
                        interruptible_sleep_on(&cdev->recv_wait);
142
                        if ((skb = skb_dequeue(&cdev->recv_queue)) != 0)
143
                                break;
144
                        if (current->signal & ~current->blocked)
145
                                break;
146
                }
147
                if (skb == 0)
148
                        return -ERESTARTNOHAND;
149
        }
150
        if (skb->len > count) {
151
                skb_queue_head(&cdev->recv_queue, skb);
152
                return -EMSGSIZE;
153
        }
154
        if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
155
            && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND)
156
                CAPIMSG_SETDATA(skb->data, buf + CAPIMSG_LEN(skb->data));
157
        retval = copy_to_user(buf, skb->data, skb->len);
158
        if (retval) {
159
                skb_queue_head(&cdev->recv_queue, skb);
160
                return retval;
161
        }
162
        copied = skb->len;
163
 
164
 
165
        kfree_skb(skb, FREE_READ);
166
 
167
        return copied;
168
}
169
 
170
#if LINUX_VERSION_CODE < 0x020100
171
static int capi_write(struct inode *inode, struct file *file,
172
                      const char *buf, int count)
173
#else
174
static long capi_write(struct inode *inode, struct file *file,
175
                       const char *buf, unsigned long count)
176
#endif
177
{
178
        unsigned int minor = MINOR(inode->i_rdev);
179
        struct capidev *cdev;
180
        struct sk_buff *skb;
181
        int retval;
182
        __u8 cmd;
183
        __u8 subcmd;
184
        __u16 mlen;
185
 
186
        if (!minor || minor > CAPI_MAXMINOR || !capidevs[minor].is_registered)
187
                return -ENODEV;
188
 
189
        cdev = &capidevs[minor];
190
 
191
        skb = alloc_skb(count, GFP_USER);
192
 
193
        if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
194
                dev_kfree_skb(skb, FREE_WRITE);
195
                return retval;
196
        }
197
        cmd = CAPIMSG_COMMAND(skb->data);
198
        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
199
        mlen = CAPIMSG_LEN(skb->data);
200
        if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
201
                __u16 dlen = CAPIMSG_DATALEN(skb->data);
202
                if (mlen + dlen != count) {
203
                        dev_kfree_skb(skb, FREE_WRITE);
204
                        return -EINVAL;
205
                }
206
        } else if (mlen != count) {
207
                dev_kfree_skb(skb, FREE_WRITE);
208
                return -EINVAL;
209
        }
210
        CAPIMSG_SETAPPID(skb->data, cdev->applid);
211
 
212
        cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb);
213
 
214
        if (cdev->errcode) {
215
                dev_kfree_skb(skb, FREE_WRITE);
216
                return -EIO;
217
        }
218
        return count;
219
}
220
 
221
#if (LINUX_VERSION_CODE < 0x020117)
222
static int capi_select(struct inode *inode, struct file *file,
223
                       int sel_type, select_table * wait)
224
{
225
        unsigned int minor = MINOR(inode->i_rdev);
226
        struct capidev *cdev;
227
 
228
        if (!minor || minor > CAPI_MAXMINOR || !capidevs[minor].is_registered)
229
                return -ENODEV;
230
 
231
        cdev = &capidevs[minor];
232
 
233
        switch (sel_type) {
234
        case SEL_IN:
235
                if (!skb_queue_empty(&cdev->recv_queue))
236
                        return 1;
237
                /* fall througth */
238
        case SEL_EX:
239
                /* error conditions ? */
240
 
241
                select_wait(&cdev->recv_wait, wait);
242
                return 0;
243
        case SEL_OUT:
244
                /*
245
                   if (!queue_full())
246
                   return 1;
247
                   select_wait(&cdev->send_wait, wait);
248
                   return 0;
249
                 */
250
                return 1;
251
        }
252
        return 1;
253
}
254
#else
255
static unsigned int
256
capi_poll(struct file *file, poll_table * wait)
257
{
258
        unsigned int mask = 0;
259
        unsigned int minor = MINOR(file->f_inode->i_rdev);
260
        struct capidev *cdev;
261
 
262
        if (!minor || minor > CAPI_MAXMINOR || !capidevs[minor].is_registered)
263
                return POLLERR;
264
 
265
        cdev = &capidevs[minor];
266
        poll_wait(&(cdev->recv_wait), wait);
267
        mask = POLLOUT | POLLWRNORM;
268
        if (!skb_queue_empty(&cdev->recv_queue))
269
                mask |= POLLIN | POLLRDNORM;
270
        return mask;
271
}
272
#endif
273
 
274
static int capi_ioctl(struct inode *inode, struct file *file,
275
                      unsigned int cmd, unsigned long arg)
276
{
277
        unsigned int minor = MINOR(inode->i_rdev);
278
        struct capidev *cdev;
279
        capi_ioctl_struct data;
280
        int retval;
281
 
282
 
283
        if (minor >= CAPI_MAXMINOR || !capidevs[minor].is_open)
284
                return -ENODEV;
285
 
286
        cdev = &capidevs[minor];
287
 
288
        switch (cmd) {
289
        case CAPI_REGISTER:
290
                {
291
                        if (!minor)
292
                                return -EINVAL;
293
                        retval = copy_from_user((void *) &data.rparams,
294
                                                (void *) arg, sizeof(struct capi_register_params));
295
                        if (retval)
296
                                return -EFAULT;
297
                        if (cdev->is_registered)
298
                                return -EEXIST;
299
                        cdev->errcode = (*capifuncs->capi_register) (&data.rparams,
300
                                                          &cdev->applid);
301
                        if (cdev->errcode)
302
                                return -EIO;
303
                        (void) (*capifuncs->capi_set_signal) (cdev->applid, capi_signal, minor);
304
                        cdev->is_registered = 1;
305
                }
306
                return 0;
307
 
308
        case CAPI_GET_VERSION:
309
                {
310
                        retval = copy_from_user((void *) &data.contr,
311
                                                (void *) arg,
312
                                                sizeof(data.contr));
313
                        if (retval)
314
                                return -EFAULT;
315
                        cdev->errcode = (*capifuncs->capi_get_version) (data.contr, &data.version);
316
                        if (cdev->errcode)
317
                                return -EIO;
318
                        retval = copy_to_user((void *) arg,
319
                                              (void *) &data.version,
320
                                              sizeof(data.version));
321
                        if (retval)
322
                                return -EFAULT;
323
                }
324
                return 0;
325
 
326
        case CAPI_GET_SERIAL:
327
                {
328
                        retval = copy_from_user((void *) &data.contr,
329
                                                (void *) arg,
330
                                                sizeof(data.contr));
331
                        if (retval)
332
                                return -EFAULT;
333
                        cdev->errcode = (*capifuncs->capi_get_serial) (data.contr, data.serial);
334
                        if (cdev->errcode)
335
                                return -EIO;
336
                        retval = copy_to_user((void *) arg,
337
                                              (void *) data.serial,
338
                                              sizeof(data.serial));
339
                        if (retval)
340
                                return -EFAULT;
341
                }
342
                return 0;
343
        case CAPI_GET_PROFILE:
344
                {
345
                        retval = copy_from_user((void *) &data.contr,
346
                                                (void *) arg,
347
                                                sizeof(data.contr));
348
                        if (retval)
349
                                return -EFAULT;
350
 
351
                        if (data.contr == 0) {
352
                                cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile);
353
                                if (cdev->errcode)
354
                                        return -EIO;
355
 
356
                                retval = copy_to_user((void *) arg,
357
                                      (void *) &data.profile.ncontroller,
358
                                       sizeof(data.profile.ncontroller));
359
 
360
                        } else {
361
                                cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile);
362
                                if (cdev->errcode)
363
                                        return -EIO;
364
 
365
                                retval = copy_to_user((void *) arg,
366
                                                  (void *) &data.profile,
367
                                                   sizeof(data.profile));
368
                        }
369
                        if (retval)
370
                                return -EFAULT;
371
                }
372
                return 0;
373
 
374
        case CAPI_GET_MANUFACTURER:
375
                {
376
                        retval = copy_from_user((void *) &data.contr,
377
                                                (void *) arg,
378
                                                sizeof(data.contr));
379
                        if (retval)
380
                                return -EFAULT;
381
                        cdev->errcode = (*capifuncs->capi_get_manufacturer) (data.contr, data.manufacturer);
382
                        if (cdev->errcode)
383
                                return -EIO;
384
 
385
                        retval = copy_to_user((void *) arg, (void *) data.manufacturer,
386
                                              sizeof(data.manufacturer));
387
                        if (retval)
388
                                return -EFAULT;
389
 
390
                }
391
                return 0;
392
        case CAPI_GET_ERRCODE:
393
                data.errcode = cdev->errcode;
394
                cdev->errcode = CAPI_NOERROR;
395
                if (arg) {
396
                        retval = copy_to_user((void *) arg,
397
                                              (void *) &data.errcode,
398
                                              sizeof(data.errcode));
399
                        if (retval)
400
                                return -EFAULT;
401
                }
402
                return data.errcode;
403
 
404
        case CAPI_INSTALLED:
405
                if ((*capifuncs->capi_installed) ())
406
                        return 0;
407
                return -ENXIO;
408
 
409
        case CAPI_MANUFACTURER_CMD:
410
                {
411
                        struct capi_manufacturer_cmd mcmd;
412
                        if (minor)
413
                                return -EINVAL;
414
                        if (!suser())
415
                                return -EPERM;
416
                        retval = copy_from_user((void *) &mcmd, (void *) arg,
417
                                                sizeof(mcmd));
418
                        if (retval)
419
                                return -EFAULT;
420
                        return (*capifuncs->capi_manufacturer) (mcmd.cmd, mcmd.data);
421
                }
422
                return 0;
423
        }
424
        return -EINVAL;
425
}
426
 
427
static int capi_open(struct inode *inode, struct file *file)
428
{
429
        unsigned int minor = MINOR(inode->i_rdev);
430
 
431
        if (minor >= CAPI_MAXMINOR)
432
                return -ENXIO;
433
 
434
        if (minor) {
435
                if (capidevs[minor].is_open)
436
                        return -EEXIST;
437
 
438
                capidevs[minor].is_open = 1;
439
                skb_queue_head_init(&capidevs[minor].recv_queue);
440
                MOD_INC_USE_COUNT;
441
 
442
        } else {
443
 
444
                if (!capidevs[minor].is_open) {
445
                        capidevs[minor].is_open = 1;
446
                        MOD_INC_USE_COUNT;
447
                }
448
        }
449
 
450
 
451
        return 0;
452
}
453
 
454
static CLOSETYPE
455
capi_release(struct inode *inode, struct file *file)
456
{
457
        unsigned int minor = MINOR(inode->i_rdev);
458
        struct capidev *cdev;
459
        struct sk_buff *skb;
460
 
461
        if (minor >= CAPI_MAXMINOR || !capidevs[minor].is_open) {
462
                printk(KERN_ERR "capi20: release minor %d ???\n", minor);
463
                return CLOSEVAL;
464
        }
465
        cdev = &capidevs[minor];
466
 
467
        if (minor) {
468
 
469
                if (cdev->is_registered)
470
                        (*capifuncs->capi_release) (cdev->applid);
471
 
472
                cdev->is_registered = 0;
473
                cdev->applid = 0;
474
 
475
                while ((skb = skb_dequeue(&cdev->recv_queue)) != 0)
476
                        kfree_skb(skb, FREE_READ);
477
        }
478
        cdev->is_open = 0;
479
 
480
        MOD_DEC_USE_COUNT;
481
        return CLOSEVAL;
482
}
483
 
484
static struct file_operations capi_fops =
485
{
486
#if LINUX_VERSION_CODE < 0x020100
487
        capi_lseek,
488
#else
489
        capi_llseek,
490
#endif
491
        capi_read,
492
        capi_write,
493
        NULL,                   /* capi_readdir */
494
#if (LINUX_VERSION_CODE < 0x020117)
495
        capi_select,
496
#else
497
        capi_poll,
498
#endif
499
        capi_ioctl,
500
        NULL,                   /* capi_mmap */
501
        capi_open,
502
        capi_release,
503
        NULL,                   /* capi_fsync */
504
        NULL,                   /* capi_fasync */
505
};
506
 
507
 
508
/* -------- init function and module interface ---------------------- */
509
 
510
#ifdef MODULE
511
#define  capi_init      init_module
512
#endif
513
 
514
static struct capi_interface_user cuser = {
515
        "capi20",
516
        0,
517
};
518
 
519
int capi_init(void)
520
{
521
        memset(capidevs, 0, sizeof(capidevs));
522
 
523
        if (register_chrdev(capi_major, "capi20", &capi_fops)) {
524
                printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
525
                return -EIO;
526
        }
527
        printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
528
 
529
        if ((capifuncs = attach_capi_interface(&cuser)) == 0) {
530
                unregister_chrdev(capi_major, "capi20");
531
                return -EIO;
532
        }
533
        return 0;
534
}
535
 
536
#ifdef MODULE
537
void cleanup_module(void)
538
{
539
        unregister_chrdev(capi_major, "capi20");
540
        (void) detach_capi_interface(&cuser);
541
}
542
 
543
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.