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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [avmb1/] [capi.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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