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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [isdn/] [avmb1/] [capi.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: capi.c,v 1.1.1.1 2004-04-15 02:04:14 phoenix Exp $
2
 *
3
 * CAPI 2.0 Interface for Linux
4
 *
5
 * Copyright 1996 by Carsten Paeth <calle@calle.de>
6
 *
7
 * This software may be used and distributed according to the terms
8
 * of the GNU General Public License, incorporated herein by reference.
9
 *
10
 */
11
 
12
#include <linux/config.h>
13
#include <linux/module.h>
14
#include <linux/errno.h>
15
#include <linux/kernel.h>
16
#include <linux/major.h>
17
#include <linux/sched.h>
18
#include <linux/slab.h>
19
#include <linux/fcntl.h>
20
#include <linux/fs.h>
21
#include <linux/signal.h>
22
#include <linux/mm.h>
23
#include <linux/smp_lock.h>
24
#include <linux/timer.h>
25
#include <linux/wait.h>
26
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
27
#include <linux/tty.h>
28
#ifdef CONFIG_PPP
29
#include <linux/netdevice.h>
30
#include <linux/ppp_defs.h>
31
#include <linux/if_ppp.h>
32
#undef CAPI_PPP_ON_RAW_DEVICE
33
#endif /* CONFIG_PPP */
34
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
35
#include <linux/skbuff.h>
36
#include <linux/proc_fs.h>
37
#include <linux/poll.h>
38
#include <linux/capi.h>
39
#include <linux/kernelcapi.h>
40
#include <linux/init.h>
41
#include <linux/devfs_fs_kernel.h>
42
#include "capiutil.h"
43
#include "capicmd.h"
44
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
45
#include "capifs.h"
46
#endif
47
 
48
static char *revision = "$Revision: 1.1.1.1 $";
49
 
50
MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
51
MODULE_AUTHOR("Carsten Paeth");
52
MODULE_LICENSE("GPL");
53
 
54
#undef _DEBUG_REFCOUNT          /* alloc/free and open/close debug */
55
#undef _DEBUG_TTYFUNCS          /* call to tty_driver */
56
#undef _DEBUG_DATAFLOW          /* data flow */
57
 
58
/* -------- driver information -------------------------------------- */
59
 
60
int capi_major = 68;            /* allocated */
61
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
62
int capi_rawmajor = 190;
63
int capi_ttymajor = 191;
64
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
65
 
66
MODULE_PARM(capi_major, "i");
67
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
68
MODULE_PARM(capi_rawmajor, "i");
69
MODULE_PARM(capi_ttymajor, "i");
70
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
71
 
72
/* -------- defines ------------------------------------------------- */
73
 
74
#define CAPINC_MAX_RECVQUEUE    10
75
#define CAPINC_MAX_SENDQUEUE    10
76
#define CAPI_MAX_BLKSIZE        2048
77
 
78
/* -------- data structures ----------------------------------------- */
79
 
80
struct capidev;
81
struct capincci;
82
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
83
struct capiminor;
84
 
85
struct capiminor {
86
        struct capiminor *next;
87
        struct capincci  *nccip;
88
        unsigned int      minor;
89
 
90
        u16              applid;
91
        u32              ncci;
92
        u16              datahandle;
93
        u16              msgid;
94
 
95
        struct file      *file;
96
        struct tty_struct *tty;
97
        int                ttyinstop;
98
        int                ttyoutstop;
99
        struct sk_buff    *ttyskb;
100
        atomic_t           ttyopencount;
101
 
102
        struct sk_buff_head inqueue;
103
        int                 inbytes;
104
        struct sk_buff_head outqueue;
105
        int                 outbytes;
106
 
107
        /* for raw device */
108
        struct sk_buff_head recvqueue;
109
        wait_queue_head_t recvwait;
110
        wait_queue_head_t sendwait;
111
 
112
        /* transmit path */
113
        struct datahandle_queue {
114
                    struct datahandle_queue *next;
115
                    u16                      datahandle;
116
        } *ackqueue;
117
        int nack;
118
 
119
};
120
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
121
 
122
struct capincci {
123
        struct capincci *next;
124
        u32              ncci;
125
        struct capidev  *cdev;
126
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
127
        struct capiminor *minorp;
128
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
129
};
130
 
131
struct capidev {
132
        struct capidev *next;
133
        struct file    *file;
134
        u16             applid;
135
        u16             errcode;
136
        unsigned int    minor;
137
        unsigned        userflags;
138
 
139
        struct sk_buff_head recvqueue;
140
        wait_queue_head_t recvwait;
141
 
142
        /* Statistic */
143
        unsigned long   nrecvctlpkt;
144
        unsigned long   nrecvdatapkt;
145
        unsigned long   nsentctlpkt;
146
        unsigned long   nsentdatapkt;
147
 
148
        struct capincci *nccis;
149
};
150
 
151
/* -------- global variables ---------------------------------------- */
152
 
153
static struct capi_interface *capifuncs = 0;
154
static struct capidev *capidev_openlist = 0;
155
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
156
static struct capiminor *minors = 0;
157
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
158
 
159
static kmem_cache_t *capidev_cachep = 0;
160
static kmem_cache_t *capincci_cachep = 0;
161
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
162
static kmem_cache_t *capiminor_cachep = 0;
163
static kmem_cache_t *capidh_cachep = 0;
164
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
165
 
166
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
167
/* -------- datahandles --------------------------------------------- */
168
 
169
static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
170
{
171
        struct datahandle_queue *n, **pp;
172
 
173
        n = (struct datahandle_queue *)
174
        kmem_cache_alloc(capidh_cachep, GFP_ATOMIC);
175
        if (!n) {
176
           printk(KERN_ERR "capi: alloc datahandle failed\n");
177
           return -1;
178
        }
179
        n->next = 0;
180
        n->datahandle = datahandle;
181
        for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ;
182
        *pp = n;
183
        mp->nack++;
184
        return 0;
185
}
186
 
187
static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
188
{
189
        struct datahandle_queue **pp, *p;
190
 
191
        for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) {
192
                if ((*pp)->datahandle == datahandle) {
193
                        p = *pp;
194
                        *pp = (*pp)->next;
195
                        kmem_cache_free(capidh_cachep, p);
196
                        mp->nack--;
197
                        return 0;
198
                }
199
        }
200
        return -1;
201
}
202
 
203
static void capiminor_del_all_ack(struct capiminor *mp)
204
{
205
        struct datahandle_queue **pp, *p;
206
 
207
        pp = &mp->ackqueue;
208
        while (*pp) {
209
                p = *pp;
210
                *pp = (*pp)->next;
211
                kmem_cache_free(capidh_cachep, p);
212
                mp->nack--;
213
        }
214
}
215
 
216
 
217
/* -------- struct capiminor ---------------------------------------- */
218
 
219
static struct capiminor *capiminor_alloc(u16 applid, u32 ncci)
220
{
221
        struct capiminor *mp, **pp;
222
        unsigned int minor = 0;
223
 
224
        MOD_INC_USE_COUNT;
225
        mp = (struct capiminor *)kmem_cache_alloc(capiminor_cachep, GFP_ATOMIC);
226
        if (!mp) {
227
                MOD_DEC_USE_COUNT;
228
                printk(KERN_ERR "capi: can't alloc capiminor\n");
229
                return 0;
230
        }
231
#ifdef _DEBUG_REFCOUNT
232
        printk(KERN_DEBUG "capiminor_alloc %d\n", GET_USE_COUNT(THIS_MODULE));
233
#endif
234
        memset(mp, 0, sizeof(struct capiminor));
235
        mp->applid = applid;
236
        mp->ncci = ncci;
237
        mp->msgid = 0;
238
        atomic_set(&mp->ttyopencount,0);
239
 
240
        skb_queue_head_init(&mp->inqueue);
241
        skb_queue_head_init(&mp->outqueue);
242
 
243
        skb_queue_head_init(&mp->recvqueue);
244
        init_waitqueue_head(&mp->recvwait);
245
        init_waitqueue_head(&mp->sendwait);
246
 
247
        for (pp = &minors; *pp; pp = &(*pp)->next) {
248
                if ((*pp)->minor < minor)
249
                        continue;
250
                if ((*pp)->minor > minor)
251
                        break;
252
                minor++;
253
        }
254
        mp->minor = minor;
255
        mp->next = *pp;
256
        *pp = mp;
257
        return mp;
258
}
259
 
260
static void capiminor_free(struct capiminor *mp)
261
{
262
        struct capiminor **pp;
263
 
264
        pp = &minors;
265
        while (*pp) {
266
                if (*pp == mp) {
267
                        *pp = (*pp)->next;
268
                        if (mp->ttyskb) kfree_skb(mp->ttyskb);
269
                        mp->ttyskb = 0;
270
                        skb_queue_purge(&mp->recvqueue);
271
                        skb_queue_purge(&mp->inqueue);
272
                        skb_queue_purge(&mp->outqueue);
273
                        capiminor_del_all_ack(mp);
274
                        kmem_cache_free(capiminor_cachep, mp);
275
                        MOD_DEC_USE_COUNT;
276
#ifdef _DEBUG_REFCOUNT
277
                        printk(KERN_DEBUG "capiminor_free %d\n", GET_USE_COUNT(THIS_MODULE));
278
#endif
279
                        return;
280
                } else {
281
                        pp = &(*pp)->next;
282
                }
283
        }
284
}
285
 
286
static struct capiminor *capiminor_find(unsigned int minor)
287
{
288
        struct capiminor *p;
289
        for (p = minors; p && p->minor != minor; p = p->next)
290
                ;
291
        return p;
292
}
293
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
294
 
295
/* -------- struct capincci ----------------------------------------- */
296
 
297
static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
298
{
299
        struct capincci *np, **pp;
300
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
301
        struct capiminor *mp = 0;
302
        kdev_t kdev;
303
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
304
 
305
        np = (struct capincci *)kmem_cache_alloc(capincci_cachep, GFP_ATOMIC);
306
        if (!np)
307
                return 0;
308
        memset(np, 0, sizeof(struct capincci));
309
        np->ncci = ncci;
310
        np->cdev = cdev;
311
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
312
        mp = 0;
313
        if (cdev->userflags & CAPIFLAG_HIGHJACKING)
314
                mp = np->minorp = capiminor_alloc(cdev->applid, ncci);
315
        if (mp) {
316
                mp->nccip = np;
317
#ifdef _DEBUG_REFCOUNT
318
                printk(KERN_DEBUG "set mp->nccip\n");
319
#endif
320
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
321
                kdev = MKDEV(capi_rawmajor, mp->minor);
322
                capifs_new_ncci('r', mp->minor, kdev);
323
                kdev = MKDEV(capi_ttymajor, mp->minor);
324
                capifs_new_ncci(0, mp->minor, kdev);
325
#endif
326
        }
327
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
328
        for (pp=&cdev->nccis; *pp; pp = &(*pp)->next)
329
                ;
330
        *pp = np;
331
        return np;
332
}
333
 
334
static void capincci_free(struct capidev *cdev, u32 ncci)
335
{
336
        struct capincci *np, **pp;
337
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
338
        struct capiminor *mp;
339
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
340
 
341
        pp=&cdev->nccis;
342
        while (*pp) {
343
                np = *pp;
344
                if (ncci == 0xffffffff || np->ncci == ncci) {
345
                        *pp = (*pp)->next;
346
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
347
                        if ((mp = np->minorp) != 0) {
348
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
349
                                capifs_free_ncci('r', mp->minor);
350
                                capifs_free_ncci(0, mp->minor);
351
#endif
352
                                if (mp->tty) {
353
                                        mp->nccip = 0;
354
#ifdef _DEBUG_REFCOUNT
355
                                        printk(KERN_DEBUG "reset mp->nccip\n");
356
#endif
357
                                        tty_hangup(mp->tty);
358
                                } else if (mp->file) {
359
                                        mp->nccip = 0;
360
#ifdef _DEBUG_REFCOUNT
361
                                        printk(KERN_DEBUG "reset mp->nccip\n");
362
#endif
363
                                        wake_up_interruptible(&mp->recvwait);
364
                                        wake_up_interruptible(&mp->sendwait);
365
                                } else {
366
                                        capiminor_free(mp);
367
                                }
368
                        }
369
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
370
                        kmem_cache_free(capincci_cachep, np);
371
                        if (*pp == 0) return;
372
                } else {
373
                        pp = &(*pp)->next;
374
                }
375
        }
376
}
377
 
378
static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
379
{
380
        struct capincci *p;
381
 
382
        for (p=cdev->nccis; p ; p = p->next) {
383
                if (p->ncci == ncci)
384
                        break;
385
        }
386
        return p;
387
}
388
 
389
/* -------- struct capidev ------------------------------------------ */
390
 
391
static struct capidev *capidev_alloc(struct file *file)
392
{
393
        struct capidev *cdev;
394
        struct capidev **pp;
395
 
396
        cdev = (struct capidev *)kmem_cache_alloc(capidev_cachep, GFP_KERNEL);
397
        if (!cdev)
398
                return 0;
399
        memset(cdev, 0, sizeof(struct capidev));
400
        cdev->file = file;
401
        cdev->minor = MINOR(file->f_dentry->d_inode->i_rdev);
402
 
403
        skb_queue_head_init(&cdev->recvqueue);
404
        init_waitqueue_head(&cdev->recvwait);
405
        pp=&capidev_openlist;
406
        while (*pp) pp = &(*pp)->next;
407
        *pp = cdev;
408
        return cdev;
409
}
410
 
411
static void capidev_free(struct capidev *cdev)
412
{
413
        struct capidev **pp;
414
 
415
        if (cdev->applid)
416
                (*capifuncs->capi_release) (cdev->applid);
417
        cdev->applid = 0;
418
 
419
        skb_queue_purge(&cdev->recvqueue);
420
 
421
        pp=&capidev_openlist;
422
        while (*pp && *pp != cdev) pp = &(*pp)->next;
423
        if (*pp)
424
                *pp = cdev->next;
425
 
426
        kmem_cache_free(capidev_cachep, cdev);
427
}
428
 
429
static struct capidev *capidev_find(u16 applid)
430
{
431
        struct capidev *p;
432
        for (p=capidev_openlist; p; p = p->next) {
433
                if (p->applid == applid)
434
                        break;
435
        }
436
        return p;
437
}
438
 
439
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
440
/* -------- handle data queue --------------------------------------- */
441
 
442
static struct sk_buff *
443
gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
444
{
445
        struct sk_buff *nskb;
446
        nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
447
        if (nskb) {
448
                u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
449
                unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
450
                capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
451
                capimsg_setu16(s, 2, mp->applid);
452
                capimsg_setu8 (s, 4, CAPI_DATA_B3);
453
                capimsg_setu8 (s, 5, CAPI_RESP);
454
                capimsg_setu16(s, 6, mp->msgid++);
455
                capimsg_setu32(s, 8, mp->ncci);
456
                capimsg_setu16(s, 12, datahandle);
457
        }
458
        return nskb;
459
}
460
 
461
static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
462
{
463
        struct sk_buff *nskb;
464
        unsigned int datalen;
465
        u16 errcode, datahandle;
466
 
467
        datalen = skb->len - CAPIMSG_LEN(skb->data);
468
        if (mp->tty) {
469
                if (mp->tty->ldisc.receive_buf == 0) {
470
                        printk(KERN_ERR "capi: ldisc has no receive_buf function\n");
471
                        return -1;
472
                }
473
                if (mp->ttyinstop) {
474
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
475
                        printk(KERN_DEBUG "capi: recv tty throttled\n");
476
#endif
477
                        return -1;
478
                }
479
                if (mp->tty->ldisc.receive_room &&
480
                    mp->tty->ldisc.receive_room(mp->tty) < datalen) {
481
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
482
                        printk(KERN_DEBUG "capi: no room in tty\n");
483
#endif
484
                        return -1;
485
                }
486
                if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
487
                        printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
488
                        return -1;
489
                }
490
                datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
491
                errcode = (*capifuncs->capi_put_message)(mp->applid, nskb);
492
                if (errcode != CAPI_NOERROR) {
493
                        printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
494
                                        errcode);
495
                        kfree_skb(nskb);
496
                        return -1;
497
                }
498
                (void)skb_pull(skb, CAPIMSG_LEN(skb->data));
499
#ifdef _DEBUG_DATAFLOW
500
                printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
501
                                        datahandle, skb->len);
502
#endif
503
                mp->tty->ldisc.receive_buf(mp->tty, skb->data, 0, skb->len);
504
                kfree_skb(skb);
505
                return 0;
506
 
507
        } else if (mp->file) {
508
                if (skb_queue_len(&mp->recvqueue) > CAPINC_MAX_RECVQUEUE) {
509
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
510
                        printk(KERN_DEBUG "capi: no room in raw queue\n");
511
#endif
512
                        return -1;
513
                }
514
                if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
515
                        printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
516
                        return -1;
517
                }
518
                datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
519
                errcode = (*capifuncs->capi_put_message)(mp->applid, nskb);
520
                if (errcode != CAPI_NOERROR) {
521
                        printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
522
                                        errcode);
523
                        kfree_skb(nskb);
524
                        return -1;
525
                }
526
                (void)skb_pull(skb, CAPIMSG_LEN(skb->data));
527
#ifdef _DEBUG_DATAFLOW
528
                printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => raw\n",
529
                                        datahandle, skb->len);
530
#endif
531
                skb_queue_tail(&mp->recvqueue, skb);
532
                wake_up_interruptible(&mp->recvwait);
533
                return 0;
534
        }
535
#ifdef _DEBUG_DATAFLOW
536
        printk(KERN_DEBUG "capi: currently no receiver\n");
537
#endif
538
        return -1;
539
}
540
 
541
static void handle_minor_recv(struct capiminor *mp)
542
{
543
        struct sk_buff *skb;
544
        while ((skb = skb_dequeue(&mp->inqueue)) != 0) {
545
                unsigned int len = skb->len;
546
                mp->inbytes -= len;
547
                if (handle_recv_skb(mp, skb) < 0) {
548
                        skb_queue_head(&mp->inqueue, skb);
549
                        mp->inbytes += len;
550
                        return;
551
                }
552
        }
553
}
554
 
555
static int handle_minor_send(struct capiminor *mp)
556
{
557
        struct sk_buff *skb;
558
        u16 len;
559
        int count = 0;
560
        u16 errcode;
561
        u16 datahandle;
562
 
563
        if (mp->tty && mp->ttyoutstop) {
564
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
565
                printk(KERN_DEBUG "capi: send: tty stopped\n");
566
#endif
567
                return 0;
568
        }
569
 
570
        while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
571
                datahandle = mp->datahandle;
572
                len = (u16)skb->len;
573
                skb_push(skb, CAPI_DATA_B3_REQ_LEN);
574
                memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
575
                capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
576
                capimsg_setu16(skb->data, 2, mp->applid);
577
                capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
578
                capimsg_setu8 (skb->data, 5, CAPI_REQ);
579
                capimsg_setu16(skb->data, 6, mp->msgid++);
580
                capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
581
                capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
582
                capimsg_setu16(skb->data, 16, len);     /* Data length */
583
                capimsg_setu16(skb->data, 18, datahandle);
584
                capimsg_setu16(skb->data, 20, 0);        /* Flags */
585
 
586
                if (capincci_add_ack(mp, datahandle) < 0) {
587
                        skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
588
                        skb_queue_head(&mp->outqueue, skb);
589
                        return count;
590
                }
591
                errcode = (*capifuncs->capi_put_message) (mp->applid, skb);
592
                if (errcode == CAPI_NOERROR) {
593
                        mp->datahandle++;
594
                        count++;
595
                        mp->outbytes -= len;
596
#ifdef _DEBUG_DATAFLOW
597
                        printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n",
598
                                                        datahandle, len);
599
#endif
600
                        continue;
601
                }
602
                capiminor_del_ack(mp, datahandle);
603
 
604
                if (errcode == CAPI_SENDQUEUEFULL) {
605
                        skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
606
                        skb_queue_head(&mp->outqueue, skb);
607
                        break;
608
                }
609
 
610
                /* ups, drop packet */
611
                printk(KERN_ERR "capi: put_message = %x\n", errcode);
612
                mp->outbytes -= len;
613
                kfree_skb(skb);
614
        }
615
        if (count)
616
                wake_up_interruptible(&mp->sendwait);
617
        return count;
618
}
619
 
620
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
621
/* -------- function called by lower level -------------------------- */
622
 
623
static void capi_signal(u16 applid, void *param)
624
{
625
        struct capidev *cdev = (struct capidev *)param;
626
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
627
        struct capiminor *mp;
628
        u16 datahandle;
629
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
630
        struct capincci *np;
631
        struct sk_buff *skb = 0;
632
        u32 ncci;
633
 
634
        (void) (*capifuncs->capi_get_message) (applid, &skb);
635
        if (!skb) {
636
                printk(KERN_ERR "BUG: capi_signal: no skb\n");
637
                return;
638
        }
639
 
640
        if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
641
                skb_queue_tail(&cdev->recvqueue, skb);
642
                wake_up_interruptible(&cdev->recvwait);
643
                return;
644
        }
645
        ncci = CAPIMSG_CONTROL(skb->data);
646
        for (np = cdev->nccis; np && np->ncci != ncci; np = np->next)
647
                ;
648
        if (!np) {
649
                printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
650
                skb_queue_tail(&cdev->recvqueue, skb);
651
                wake_up_interruptible(&cdev->recvwait);
652
                return;
653
        }
654
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
655
        skb_queue_tail(&cdev->recvqueue, skb);
656
        wake_up_interruptible(&cdev->recvwait);
657
#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
658
        mp = np->minorp;
659
        if (!mp) {
660
                skb_queue_tail(&cdev->recvqueue, skb);
661
                wake_up_interruptible(&cdev->recvwait);
662
                return;
663
        }
664
 
665
 
666
        if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
667
                datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
668
#ifdef _DEBUG_DATAFLOW
669
                printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
670
                                datahandle, skb->len-CAPIMSG_LEN(skb->data));
671
#endif
672
                skb_queue_tail(&mp->inqueue, skb);
673
                mp->inbytes += skb->len;
674
                handle_minor_recv(mp);
675
 
676
        } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {
677
 
678
                datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4);
679
#ifdef _DEBUG_DATAFLOW
680
                printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n",
681
                                datahandle,
682
                                CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2));
683
#endif
684
                kfree_skb(skb);
685
                (void)capiminor_del_ack(mp, datahandle);
686
                if (mp->tty) {
687
                        if (mp->tty->ldisc.write_wakeup)
688
                                mp->tty->ldisc.write_wakeup(mp->tty);
689
                } else {
690
                        wake_up_interruptible(&mp->sendwait);
691
                }
692
                (void)handle_minor_send(mp);
693
 
694
        } else {
695
                /* ups, let capi application handle it :-) */
696
                skb_queue_tail(&cdev->recvqueue, skb);
697
                wake_up_interruptible(&cdev->recvwait);
698
        }
699
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
700
}
701
 
702
/* -------- file_operations for capidev ----------------------------- */
703
 
704
static ssize_t
705
capi_read(struct file *file, char *buf, size_t count, loff_t *ppos)
706
{
707
        struct capidev *cdev = (struct capidev *)file->private_data;
708
        struct sk_buff *skb;
709
        int retval;
710
        size_t copied;
711
 
712
        if (ppos != &file->f_pos)
713
                return -ESPIPE;
714
 
715
        if (!cdev->applid)
716
                return -ENODEV;
717
 
718
        if ((skb = skb_dequeue(&cdev->recvqueue)) == 0) {
719
 
720
                if (file->f_flags & O_NONBLOCK)
721
                        return -EAGAIN;
722
 
723
                for (;;) {
724
                        interruptible_sleep_on(&cdev->recvwait);
725
                        if ((skb = skb_dequeue(&cdev->recvqueue)) != 0)
726
                                break;
727
                        if (signal_pending(current))
728
                                break;
729
                }
730
                if (skb == 0)
731
                        return -ERESTARTNOHAND;
732
        }
733
        if (skb->len > count) {
734
                skb_queue_head(&cdev->recvqueue, skb);
735
                return -EMSGSIZE;
736
        }
737
        retval = copy_to_user(buf, skb->data, skb->len);
738
        if (retval) {
739
                skb_queue_head(&cdev->recvqueue, skb);
740
                return retval;
741
        }
742
        copied = skb->len;
743
 
744
        if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND) {
745
                cdev->nrecvdatapkt++;
746
        } else {
747
                cdev->nrecvctlpkt++;
748
        }
749
 
750
        kfree_skb(skb);
751
 
752
        return copied;
753
}
754
 
755
static ssize_t
756
capi_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
757
{
758
        struct capidev *cdev = (struct capidev *)file->private_data;
759
        struct sk_buff *skb;
760
        int retval;
761
        u16 mlen;
762
 
763
        if (ppos != &file->f_pos)
764
                return -ESPIPE;
765
 
766
        if (!cdev->applid)
767
                return -ENODEV;
768
 
769
        skb = alloc_skb(count, GFP_USER);
770
        if (!skb)
771
                return -ENOMEM;
772
 
773
        if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
774
                kfree_skb(skb);
775
                return -EFAULT;
776
        }
777
        mlen = CAPIMSG_LEN(skb->data);
778
        if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
779
                if (mlen + CAPIMSG_DATALEN(skb->data) != count) {
780
                        kfree_skb(skb);
781
                        return -EINVAL;
782
                }
783
        } else {
784
                if (mlen != count) {
785
                        kfree_skb(skb);
786
                        return -EINVAL;
787
                }
788
        }
789
        CAPIMSG_SETAPPID(skb->data, cdev->applid);
790
 
791
        cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb);
792
 
793
        if (cdev->errcode) {
794
                kfree_skb(skb);
795
                return -EIO;
796
        }
797
        if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
798
                cdev->nsentdatapkt++;
799
        } else {
800
                cdev->nsentctlpkt++;
801
        }
802
        return count;
803
}
804
 
805
static unsigned int
806
capi_poll(struct file *file, poll_table * wait)
807
{
808
        struct capidev *cdev = (struct capidev *)file->private_data;
809
        unsigned int mask = 0;
810
 
811
        if (!cdev->applid)
812
                return POLLERR;
813
 
814
        poll_wait(file, &(cdev->recvwait), wait);
815
        mask = POLLOUT | POLLWRNORM;
816
        if (!skb_queue_empty(&cdev->recvqueue))
817
                mask |= POLLIN | POLLRDNORM;
818
        return mask;
819
}
820
 
821
static int
822
capi_ioctl(struct inode *inode, struct file *file,
823
                      unsigned int cmd, unsigned long arg)
824
{
825
        struct capidev *cdev = (struct capidev *)file->private_data;
826
        capi_ioctl_struct data;
827
        int retval = -EINVAL;
828
 
829
        switch (cmd) {
830
        case CAPI_REGISTER:
831
                {
832
                        retval = copy_from_user((void *) &data.rparams,
833
                                                (void *) arg, sizeof(struct capi_register_params));
834
                        if (retval)
835
                                return -EFAULT;
836
                        if (cdev->applid)
837
                                return -EEXIST;
838
                        cdev->errcode = (*capifuncs->capi_register) (&data.rparams,
839
                                                          &cdev->applid);
840
                        if (cdev->errcode) {
841
                                cdev->applid = 0;
842
                                return -EIO;
843
                        }
844
                        (void) (*capifuncs->capi_set_signal) (cdev->applid, capi_signal, cdev);
845
                }
846
                return (int)cdev->applid;
847
 
848
        case CAPI_GET_VERSION:
849
                {
850
                        retval = copy_from_user((void *) &data.contr,
851
                                                (void *) arg,
852
                                                sizeof(data.contr));
853
                        if (retval)
854
                                return -EFAULT;
855
                        cdev->errcode = (*capifuncs->capi_get_version) (data.contr, &data.version);
856
                        if (cdev->errcode)
857
                                return -EIO;
858
                        retval = copy_to_user((void *) arg,
859
                                              (void *) &data.version,
860
                                              sizeof(data.version));
861
                        if (retval)
862
                                return -EFAULT;
863
                }
864
                return 0;
865
 
866
        case CAPI_GET_SERIAL:
867
                {
868
                        retval = copy_from_user((void *) &data.contr,
869
                                                (void *) arg,
870
                                                sizeof(data.contr));
871
                        if (retval)
872
                                return -EFAULT;
873
                        cdev->errcode = (*capifuncs->capi_get_serial) (data.contr, data.serial);
874
                        if (cdev->errcode)
875
                                return -EIO;
876
                        retval = copy_to_user((void *) arg,
877
                                              (void *) data.serial,
878
                                              sizeof(data.serial));
879
                        if (retval)
880
                                return -EFAULT;
881
                }
882
                return 0;
883
        case CAPI_GET_PROFILE:
884
                {
885
                        retval = copy_from_user((void *) &data.contr,
886
                                                (void *) arg,
887
                                                sizeof(data.contr));
888
                        if (retval)
889
                                return -EFAULT;
890
 
891
                        if (data.contr == 0) {
892
                                cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile);
893
                                if (cdev->errcode)
894
                                        return -EIO;
895
 
896
                                retval = copy_to_user((void *) arg,
897
                                      (void *) &data.profile.ncontroller,
898
                                       sizeof(data.profile.ncontroller));
899
 
900
                        } else {
901
                                cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile);
902
                                if (cdev->errcode)
903
                                        return -EIO;
904
 
905
                                retval = copy_to_user((void *) arg,
906
                                                  (void *) &data.profile,
907
                                                   sizeof(data.profile));
908
                        }
909
                        if (retval)
910
                                return -EFAULT;
911
                }
912
                return 0;
913
 
914
        case CAPI_GET_MANUFACTURER:
915
                {
916
                        retval = copy_from_user((void *) &data.contr,
917
                                                (void *) arg,
918
                                                sizeof(data.contr));
919
                        if (retval)
920
                                return -EFAULT;
921
                        cdev->errcode = (*capifuncs->capi_get_manufacturer) (data.contr, data.manufacturer);
922
                        if (cdev->errcode)
923
                                return -EIO;
924
 
925
                        retval = copy_to_user((void *) arg, (void *) data.manufacturer,
926
                                              sizeof(data.manufacturer));
927
                        if (retval)
928
                                return -EFAULT;
929
 
930
                }
931
                return 0;
932
        case CAPI_GET_ERRCODE:
933
                data.errcode = cdev->errcode;
934
                cdev->errcode = CAPI_NOERROR;
935
                if (arg) {
936
                        retval = copy_to_user((void *) arg,
937
                                              (void *) &data.errcode,
938
                                              sizeof(data.errcode));
939
                        if (retval)
940
                                return -EFAULT;
941
                }
942
                return data.errcode;
943
 
944
        case CAPI_INSTALLED:
945
                if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR)
946
                        return 0;
947
                return -ENXIO;
948
 
949
        case CAPI_MANUFACTURER_CMD:
950
                {
951
                        struct capi_manufacturer_cmd mcmd;
952
                        if (!capable(CAP_SYS_ADMIN))
953
                                return -EPERM;
954
                        retval = copy_from_user((void *) &mcmd, (void *) arg,
955
                                                sizeof(mcmd));
956
                        if (retval)
957
                                return -EFAULT;
958
                        return (*capifuncs->capi_manufacturer) (mcmd.cmd, mcmd.data);
959
                }
960
                return 0;
961
 
962
        case CAPI_SET_FLAGS:
963
        case CAPI_CLR_FLAGS:
964
                {
965
                        unsigned userflags;
966
                        retval = copy_from_user((void *) &userflags,
967
                                                (void *) arg,
968
                                                sizeof(userflags));
969
                        if (retval)
970
                                return -EFAULT;
971
                        if (cmd == CAPI_SET_FLAGS)
972
                                cdev->userflags |= userflags;
973
                        else
974
                                cdev->userflags &= ~userflags;
975
                }
976
                return 0;
977
 
978
        case CAPI_GET_FLAGS:
979
                {
980
                        retval = copy_to_user((void *) arg,
981
                                              (void *) &cdev->userflags,
982
                                              sizeof(cdev->userflags));
983
                        if (retval)
984
                                return -EFAULT;
985
                }
986
                return 0;
987
 
988
        case CAPI_NCCI_OPENCOUNT:
989
                {
990
                        struct capincci *nccip;
991
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
992
                        struct capiminor *mp;
993
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
994
                        unsigned ncci;
995
                        int count = 0;
996
                        retval = copy_from_user((void *) &ncci,
997
                                                (void *) arg,
998
                                                sizeof(ncci));
999
                        if (retval)
1000
                                return -EFAULT;
1001
                        nccip = capincci_find(cdev, (u32) ncci);
1002
                        if (!nccip)
1003
                                return 0;
1004
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1005
                        if ((mp = nccip->minorp) != 0) {
1006
                                count += atomic_read(&mp->ttyopencount);
1007
                                if (mp->file)
1008
                                        count++;
1009
                        }
1010
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1011
                        return count;
1012
                }
1013
                return 0;
1014
 
1015
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1016
        case CAPI_NCCI_GETUNIT:
1017
                {
1018
                        struct capincci *nccip;
1019
                        struct capiminor *mp;
1020
                        unsigned ncci;
1021
                        retval = copy_from_user((void *) &ncci,
1022
                                                (void *) arg,
1023
                                                sizeof(ncci));
1024
                        if (retval)
1025
                                return -EFAULT;
1026
                        nccip = capincci_find(cdev, (u32) ncci);
1027
                        if (!nccip || (mp = nccip->minorp) == 0)
1028
                                return -ESRCH;
1029
                        return mp->minor;
1030
                }
1031
                return 0;
1032
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1033
        }
1034
        return -EINVAL;
1035
}
1036
 
1037
static int
1038
capi_open(struct inode *inode, struct file *file)
1039
{
1040
        if (file->private_data)
1041
                return -EEXIST;
1042
 
1043
        if ((file->private_data = capidev_alloc(file)) == 0)
1044
                return -ENOMEM;
1045
 
1046
        MOD_INC_USE_COUNT;
1047
#ifdef _DEBUG_REFCOUNT
1048
        printk(KERN_DEBUG "capi_open %d\n", GET_USE_COUNT(THIS_MODULE));
1049
#endif
1050
        return 0;
1051
}
1052
 
1053
static int
1054
capi_release(struct inode *inode, struct file *file)
1055
{
1056
        struct capidev *cdev = (struct capidev *)file->private_data;
1057
 
1058
        lock_kernel();
1059
        capincci_free(cdev, 0xffffffff);
1060
        capidev_free(cdev);
1061
        file->private_data = NULL;
1062
 
1063
        MOD_DEC_USE_COUNT;
1064
#ifdef _DEBUG_REFCOUNT
1065
        printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE));
1066
#endif
1067
        unlock_kernel();
1068
        return 0;
1069
}
1070
 
1071
static struct file_operations capi_fops =
1072
{
1073
        owner:          THIS_MODULE,
1074
        llseek:         no_llseek,
1075
        read:           capi_read,
1076
        write:          capi_write,
1077
        poll:           capi_poll,
1078
        ioctl:          capi_ioctl,
1079
        open:           capi_open,
1080
        release:        capi_release,
1081
};
1082
 
1083
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1084
/* -------- file_operations for capincci ---------------------------- */
1085
 
1086
static int
1087
capinc_raw_open(struct inode *inode, struct file *file)
1088
{
1089
        struct capiminor *mp;
1090
 
1091
        if (file->private_data)
1092
                return -EEXIST;
1093
        if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
1094
                return -ENXIO;
1095
        if (mp->nccip == 0)
1096
                return -ENXIO;
1097
        if (mp->file)
1098
                return -EBUSY;
1099
 
1100
#ifdef _DEBUG_REFCOUNT
1101
        printk(KERN_DEBUG "capi_raw_open %d\n", GET_USE_COUNT(THIS_MODULE));
1102
#endif
1103
 
1104
        mp->datahandle = 0;
1105
        mp->file = file;
1106
        file->private_data = (void *)mp;
1107
        handle_minor_recv(mp);
1108
        return 0;
1109
}
1110
 
1111
static ssize_t
1112
capinc_raw_read(struct file *file, char *buf, size_t count, loff_t *ppos)
1113
{
1114
        struct capiminor *mp = (struct capiminor *)file->private_data;
1115
        struct sk_buff *skb;
1116
        int retval;
1117
        size_t copied = 0;
1118
 
1119
        if (ppos != &file->f_pos)
1120
                return -ESPIPE;
1121
 
1122
        if (!mp || !mp->nccip)
1123
                return -EINVAL;
1124
 
1125
        if ((skb = skb_dequeue(&mp->recvqueue)) == 0) {
1126
 
1127
                if (file->f_flags & O_NONBLOCK)
1128
                        return -EAGAIN;
1129
 
1130
                for (;;) {
1131
                        interruptible_sleep_on(&mp->recvwait);
1132
                        if (mp->nccip == 0)
1133
                                return 0;
1134
                        if ((skb = skb_dequeue(&mp->recvqueue)) != 0)
1135
                                break;
1136
                        if (signal_pending(current))
1137
                                break;
1138
                }
1139
                if (skb == 0)
1140
                        return -ERESTARTNOHAND;
1141
        }
1142
        do {
1143
                if (count < skb->len) {
1144
                        retval = copy_to_user(buf, skb->data, count);
1145
                        if (retval) {
1146
                                skb_queue_head(&mp->recvqueue, skb);
1147
                                return retval;
1148
                        }
1149
                        skb_pull(skb, count);
1150
                        skb_queue_head(&mp->recvqueue, skb);
1151
                        copied += count;
1152
                        return copied;
1153
                } else {
1154
                        retval = copy_to_user(buf, skb->data, skb->len);
1155
                        if (retval) {
1156
                                skb_queue_head(&mp->recvqueue, skb);
1157
                                return copied;
1158
                        }
1159
                        copied += skb->len;
1160
                        count -= skb->len;
1161
                        buf += skb->len;
1162
                        kfree_skb(skb);
1163
                }
1164
        } while ((skb = skb_dequeue(&mp->recvqueue)) != 0);
1165
 
1166
        return copied;
1167
}
1168
 
1169
static ssize_t
1170
capinc_raw_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
1171
{
1172
        struct capiminor *mp = (struct capiminor *)file->private_data;
1173
        struct sk_buff *skb;
1174
        int retval;
1175
 
1176
        if (ppos != &file->f_pos)
1177
                return -ESPIPE;
1178
 
1179
        if (!mp || !mp->nccip)
1180
                return -EINVAL;
1181
 
1182
        skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_USER);
1183
        if (!skb)
1184
                return -ENOMEM;
1185
 
1186
        skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1187
        if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
1188
                kfree_skb(skb);
1189
                return -EFAULT;
1190
        }
1191
 
1192
        while (skb_queue_len(&mp->outqueue) > CAPINC_MAX_SENDQUEUE) {
1193
                if (file->f_flags & O_NONBLOCK)
1194
                        return -EAGAIN;
1195
                interruptible_sleep_on(&mp->sendwait);
1196
                if (mp->nccip == 0) {
1197
                        kfree_skb(skb);
1198
                        return -EIO;
1199
                }
1200
                if (signal_pending(current))
1201
                        return -ERESTARTNOHAND;
1202
        }
1203
        skb_queue_tail(&mp->outqueue, skb);
1204
        mp->outbytes += skb->len;
1205
        (void)handle_minor_send(mp);
1206
        return count;
1207
}
1208
 
1209
static unsigned int
1210
capinc_raw_poll(struct file *file, poll_table * wait)
1211
{
1212
        struct capiminor *mp = (struct capiminor *)file->private_data;
1213
        unsigned int mask = 0;
1214
 
1215
        if (!mp || !mp->nccip)
1216
                return POLLERR|POLLHUP;
1217
 
1218
        poll_wait(file, &(mp->recvwait), wait);
1219
        if (!skb_queue_empty(&mp->recvqueue))
1220
                mask |= POLLIN | POLLRDNORM;
1221
        poll_wait(file, &(mp->sendwait), wait);
1222
        if (skb_queue_len(&mp->outqueue) > CAPINC_MAX_SENDQUEUE)
1223
                mask = POLLOUT | POLLWRNORM;
1224
        return mask;
1225
}
1226
 
1227
static int
1228
capinc_raw_ioctl(struct inode *inode, struct file *file,
1229
                      unsigned int cmd, unsigned long arg)
1230
{
1231
        struct capiminor *mp = (struct capiminor *)file->private_data;
1232
        if (!mp || !mp->nccip)
1233
                return -EINVAL;
1234
 
1235
        switch (cmd) {
1236
        }
1237
        return -EINVAL;
1238
}
1239
 
1240
static int
1241
capinc_raw_release(struct inode *inode, struct file *file)
1242
{
1243
        struct capiminor *mp = (struct capiminor *)file->private_data;
1244
 
1245
        if (mp) {
1246
                lock_kernel();
1247
                mp->file = 0;
1248
                if (mp->nccip == 0) {
1249
                        capiminor_free(mp);
1250
                        file->private_data = NULL;
1251
                }
1252
                unlock_kernel();
1253
        }
1254
 
1255
#ifdef _DEBUG_REFCOUNT
1256
        printk(KERN_DEBUG "capinc_raw_release %d\n", GET_USE_COUNT(THIS_MODULE));
1257
#endif
1258
        return 0;
1259
}
1260
 
1261
static struct file_operations capinc_raw_fops =
1262
{
1263
        owner:          THIS_MODULE,
1264
        llseek:         no_llseek,
1265
        read:           capinc_raw_read,
1266
        write:          capinc_raw_write,
1267
        poll:           capinc_raw_poll,
1268
        ioctl:          capinc_raw_ioctl,
1269
        open:           capinc_raw_open,
1270
        release:        capinc_raw_release,
1271
};
1272
 
1273
/* -------- tty_operations for capincci ----------------------------- */
1274
 
1275
static int capinc_tty_open(struct tty_struct * tty, struct file * file)
1276
{
1277
        struct capiminor *mp;
1278
 
1279
        if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
1280
                return -ENXIO;
1281
        if (mp->nccip == 0)
1282
                return -ENXIO;
1283
        if (mp->file)
1284
                return -EBUSY;
1285
 
1286
        skb_queue_head_init(&mp->recvqueue);
1287
        init_waitqueue_head(&mp->recvwait);
1288
        init_waitqueue_head(&mp->sendwait);
1289
        tty->driver_data = (void *)mp;
1290
#ifdef _DEBUG_REFCOUNT
1291
        printk(KERN_DEBUG "capi_tty_open %d\n", GET_USE_COUNT(THIS_MODULE));
1292
#endif
1293
        if (atomic_read(&mp->ttyopencount) == 0)
1294
                mp->tty = tty;
1295
        atomic_inc(&mp->ttyopencount);
1296
#ifdef _DEBUG_REFCOUNT
1297
        printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount));
1298
#endif
1299
        handle_minor_recv(mp);
1300
        return 0;
1301
}
1302
 
1303
static void capinc_tty_close(struct tty_struct * tty, struct file * file)
1304
{
1305
        struct capiminor *mp;
1306
 
1307
        mp = (struct capiminor *)tty->driver_data;
1308
        if (mp) {
1309
                if (atomic_dec_and_test(&mp->ttyopencount)) {
1310
#ifdef _DEBUG_REFCOUNT
1311
                        printk(KERN_DEBUG "capinc_tty_close lastclose\n");
1312
#endif
1313
                        tty->driver_data = (void *)0;
1314
                        mp->tty = 0;
1315
                }
1316
#ifdef _DEBUG_REFCOUNT
1317
                printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount));
1318
#endif
1319
                if (mp->nccip == 0)
1320
                        capiminor_free(mp);
1321
        }
1322
 
1323
#ifdef _DEBUG_REFCOUNT
1324
        printk(KERN_DEBUG "capinc_tty_close\n");
1325
#endif
1326
}
1327
 
1328
static int capinc_tty_write(struct tty_struct * tty, int from_user,
1329
                            const unsigned char *buf, int count)
1330
{
1331
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1332
        struct sk_buff *skb;
1333
        int retval;
1334
 
1335
#ifdef _DEBUG_TTYFUNCS
1336
        printk(KERN_DEBUG "capinc_tty_write(from_user=%d,count=%d)\n",
1337
                                from_user, count);
1338
#endif
1339
 
1340
        if (!mp || !mp->nccip) {
1341
#ifdef _DEBUG_TTYFUNCS
1342
                printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n");
1343
#endif
1344
                return 0;
1345
        }
1346
 
1347
        skb = mp->ttyskb;
1348
        if (skb) {
1349
                mp->ttyskb = 0;
1350
                skb_queue_tail(&mp->outqueue, skb);
1351
                mp->outbytes += skb->len;
1352
        }
1353
 
1354
        skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);
1355
        if (!skb) {
1356
                printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
1357
                return -ENOMEM;
1358
        }
1359
 
1360
        skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1361
        if (from_user) {
1362
                if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
1363
                        kfree_skb(skb);
1364
#ifdef _DEBUG_TTYFUNCS
1365
                        printk(KERN_DEBUG "capinc_tty_write: copy_from_user=%d\n", retval);
1366
#endif
1367
                        return -EFAULT;
1368
                }
1369
        } else {
1370
                memcpy(skb_put(skb, count), buf, count);
1371
        }
1372
 
1373
        skb_queue_tail(&mp->outqueue, skb);
1374
        mp->outbytes += skb->len;
1375
        (void)handle_minor_send(mp);
1376
        (void)handle_minor_recv(mp);
1377
        return count;
1378
}
1379
 
1380
static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
1381
{
1382
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1383
        struct sk_buff *skb;
1384
 
1385
#ifdef _DEBUG_TTYFUNCS
1386
        printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
1387
#endif
1388
 
1389
        if (!mp || !mp->nccip) {
1390
#ifdef _DEBUG_TTYFUNCS
1391
                printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n");
1392
#endif
1393
                return;
1394
        }
1395
 
1396
        skb = mp->ttyskb;
1397
        if (skb) {
1398
                if (skb_tailroom(skb) > 0) {
1399
                        *(skb_put(skb, 1)) = ch;
1400
                        return;
1401
                }
1402
                mp->ttyskb = 0;
1403
                skb_queue_tail(&mp->outqueue, skb);
1404
                mp->outbytes += skb->len;
1405
                (void)handle_minor_send(mp);
1406
        }
1407
        skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC);
1408
        if (skb) {
1409
                skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1410
                *(skb_put(skb, 1)) = ch;
1411
                mp->ttyskb = skb;
1412
        } else {
1413
                printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
1414
        }
1415
}
1416
 
1417
static void capinc_tty_flush_chars(struct tty_struct *tty)
1418
{
1419
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1420
        struct sk_buff *skb;
1421
 
1422
#ifdef _DEBUG_TTYFUNCS
1423
        printk(KERN_DEBUG "capinc_tty_flush_chars\n");
1424
#endif
1425
 
1426
        if (!mp || !mp->nccip) {
1427
#ifdef _DEBUG_TTYFUNCS
1428
                printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n");
1429
#endif
1430
                return;
1431
        }
1432
 
1433
        skb = mp->ttyskb;
1434
        if (skb) {
1435
                mp->ttyskb = 0;
1436
                skb_queue_tail(&mp->outqueue, skb);
1437
                mp->outbytes += skb->len;
1438
                (void)handle_minor_send(mp);
1439
        }
1440
        (void)handle_minor_recv(mp);
1441
}
1442
 
1443
static int capinc_tty_write_room(struct tty_struct *tty)
1444
{
1445
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1446
        int room;
1447
        if (!mp || !mp->nccip) {
1448
#ifdef _DEBUG_TTYFUNCS
1449
                printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n");
1450
#endif
1451
                return 0;
1452
        }
1453
        room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);
1454
        room *= CAPI_MAX_BLKSIZE;
1455
#ifdef _DEBUG_TTYFUNCS
1456
        printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room);
1457
#endif
1458
        return room;
1459
}
1460
 
1461
static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
1462
{
1463
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1464
        if (!mp || !mp->nccip) {
1465
#ifdef _DEBUG_TTYFUNCS
1466
                printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n");
1467
#endif
1468
                return 0;
1469
        }
1470
#ifdef _DEBUG_TTYFUNCS
1471
        printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
1472
                        mp->outbytes, mp->nack,
1473
                        skb_queue_len(&mp->outqueue),
1474
                        skb_queue_len(&mp->inqueue));
1475
#endif
1476
        return mp->outbytes;
1477
}
1478
 
1479
static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
1480
                    unsigned int cmd, unsigned long arg)
1481
{
1482
        int error = 0;
1483
        switch (cmd) {
1484
        default:
1485
                error = n_tty_ioctl (tty, file, cmd, arg);
1486
                break;
1487
        }
1488
        return error;
1489
}
1490
 
1491
static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
1492
{
1493
#ifdef _DEBUG_TTYFUNCS
1494
        printk(KERN_DEBUG "capinc_tty_set_termios\n");
1495
#endif
1496
}
1497
 
1498
static void capinc_tty_throttle(struct tty_struct * tty)
1499
{
1500
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1501
#ifdef _DEBUG_TTYFUNCS
1502
        printk(KERN_DEBUG "capinc_tty_throttle\n");
1503
#endif
1504
        if (mp)
1505
                mp->ttyinstop = 1;
1506
}
1507
 
1508
static void capinc_tty_unthrottle(struct tty_struct * tty)
1509
{
1510
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1511
#ifdef _DEBUG_TTYFUNCS
1512
        printk(KERN_DEBUG "capinc_tty_unthrottle\n");
1513
#endif
1514
        if (mp) {
1515
                mp->ttyinstop = 0;
1516
                handle_minor_recv(mp);
1517
        }
1518
}
1519
 
1520
static void capinc_tty_stop(struct tty_struct *tty)
1521
{
1522
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1523
#ifdef _DEBUG_TTYFUNCS
1524
        printk(KERN_DEBUG "capinc_tty_stop\n");
1525
#endif
1526
        if (mp) {
1527
                mp->ttyoutstop = 1;
1528
        }
1529
}
1530
 
1531
static void capinc_tty_start(struct tty_struct *tty)
1532
{
1533
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1534
#ifdef _DEBUG_TTYFUNCS
1535
        printk(KERN_DEBUG "capinc_tty_start\n");
1536
#endif
1537
        if (mp) {
1538
                mp->ttyoutstop = 0;
1539
                (void)handle_minor_send(mp);
1540
        }
1541
}
1542
 
1543
static void capinc_tty_hangup(struct tty_struct *tty)
1544
{
1545
#ifdef _DEBUG_TTYFUNCS
1546
        printk(KERN_DEBUG "capinc_tty_hangup\n");
1547
#endif
1548
}
1549
 
1550
static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
1551
{
1552
#ifdef _DEBUG_TTYFUNCS
1553
        printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
1554
#endif
1555
}
1556
 
1557
static void capinc_tty_flush_buffer(struct tty_struct *tty)
1558
{
1559
#ifdef _DEBUG_TTYFUNCS
1560
        printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
1561
#endif
1562
}
1563
 
1564
static void capinc_tty_set_ldisc(struct tty_struct *tty)
1565
{
1566
#ifdef _DEBUG_TTYFUNCS
1567
        printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
1568
#endif
1569
}
1570
 
1571
static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
1572
{
1573
#ifdef _DEBUG_TTYFUNCS
1574
        printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
1575
#endif
1576
}
1577
 
1578
static int capinc_tty_read_proc(char *page, char **start, off_t off,
1579
                                int count, int *eof, void *data)
1580
{
1581
        return 0;
1582
}
1583
 
1584
#define CAPINC_NR_PORTS 256
1585
static struct tty_driver capinc_tty_driver;
1586
static int capinc_tty_refcount;
1587
static struct tty_struct *capinc_tty_table[CAPINC_NR_PORTS];
1588
static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];
1589
static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];
1590
 
1591
static int capinc_tty_init(void)
1592
{
1593
        struct tty_driver *drv = &capinc_tty_driver;
1594
 
1595
        /* Initialize the tty_driver structure */
1596
 
1597
        memset(drv, 0, sizeof(struct tty_driver));
1598
        drv->magic = TTY_DRIVER_MAGIC;
1599
#if (LINUX_VERSION_CODE > 0x20100)
1600
        drv->driver_name = "capi_nc";
1601
#endif
1602
        drv->name = "capi/%d";
1603
        drv->major = capi_ttymajor;
1604
        drv->minor_start = 0;
1605
        drv->num = CAPINC_NR_PORTS;
1606
        drv->type = TTY_DRIVER_TYPE_SERIAL;
1607
        drv->subtype = SERIAL_TYPE_NORMAL;
1608
        drv->init_termios = tty_std_termios;
1609
        drv->init_termios.c_iflag = ICRNL;
1610
        drv->init_termios.c_oflag = OPOST | ONLCR;
1611
        drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1612
        drv->init_termios.c_lflag = 0;
1613
        drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS;
1614
        drv->refcount = &capinc_tty_refcount;
1615
        drv->table = capinc_tty_table;
1616
        drv->termios = capinc_tty_termios;
1617
        drv->termios_locked = capinc_tty_termios_locked;
1618
 
1619
        drv->open = capinc_tty_open;
1620
        drv->close = capinc_tty_close;
1621
        drv->write = capinc_tty_write;
1622
        drv->put_char = capinc_tty_put_char;
1623
        drv->flush_chars = capinc_tty_flush_chars;
1624
        drv->write_room = capinc_tty_write_room;
1625
        drv->chars_in_buffer = capinc_tty_chars_in_buffer;
1626
        drv->ioctl = capinc_tty_ioctl;
1627
        drv->set_termios = capinc_tty_set_termios;
1628
        drv->throttle = capinc_tty_throttle;
1629
        drv->unthrottle = capinc_tty_unthrottle;
1630
        drv->stop = capinc_tty_stop;
1631
        drv->start = capinc_tty_start;
1632
        drv->hangup = capinc_tty_hangup;
1633
#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
1634
        drv->break_ctl = capinc_tty_break_ctl;
1635
#endif
1636
        drv->flush_buffer = capinc_tty_flush_buffer;
1637
        drv->set_ldisc = capinc_tty_set_ldisc;
1638
#if (LINUX_VERSION_CODE >= 131343)
1639
        drv->send_xchar = capinc_tty_send_xchar;
1640
        drv->read_proc = capinc_tty_read_proc;
1641
#endif
1642
        if (tty_register_driver(drv)) {
1643
                printk(KERN_ERR "Couldn't register capi_nc driver\n");
1644
                return -1;
1645
        }
1646
        return 0;
1647
}
1648
 
1649
static void capinc_tty_exit(void)
1650
{
1651
        struct tty_driver *drv = &capinc_tty_driver;
1652
        int retval;
1653
        if ((retval = tty_unregister_driver(drv)))
1654
                printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval);
1655
}
1656
 
1657
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1658
 
1659
/* -------- /proc functions ----------------------------------------- */
1660
 
1661
/*
1662
 * /proc/capi/capi20:
1663
 *  minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
1664
 */
1665
static int proc_capidev_read_proc(char *page, char **start, off_t off,
1666
                                       int count, int *eof, void *data)
1667
{
1668
        struct capidev *cdev;
1669
        int len = 0;
1670
 
1671
        for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
1672
                len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n",
1673
                        cdev->minor,
1674
                        cdev->applid,
1675
                        cdev->nrecvctlpkt,
1676
                        cdev->nrecvdatapkt,
1677
                        cdev->nsentctlpkt,
1678
                        cdev->nsentdatapkt);
1679
                if (len <= off) {
1680
                        off -= len;
1681
                        len = 0;
1682
                } else {
1683
                        if (len-off > count)
1684
                                goto endloop;
1685
                }
1686
        }
1687
endloop:
1688
        if (len < count)
1689
                *eof = 1;
1690
        if (len>count) len = count;
1691
        if (len<0) len = 0;
1692
        return len;
1693
}
1694
 
1695
/*
1696
 * /proc/capi/capi20ncci:
1697
 *  applid ncci
1698
 */
1699
static int proc_capincci_read_proc(char *page, char **start, off_t off,
1700
                                       int count, int *eof, void *data)
1701
{
1702
        struct capidev *cdev;
1703
        struct capincci *np;
1704
        int len = 0;
1705
 
1706
        for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
1707
                for (np=cdev->nccis; np; np = np->next) {
1708
                        len += sprintf(page+len, "%d 0x%x%s\n",
1709
                                cdev->applid,
1710
                                np->ncci,
1711
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
1712
                                "");
1713
#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1714
                                np->minorp && np->minorp->file ? " open" : "");
1715
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1716
                        if (len <= off) {
1717
                                off -= len;
1718
                                len = 0;
1719
                        } else {
1720
                                if (len-off > count)
1721
                                        goto endloop;
1722
                        }
1723
                }
1724
        }
1725
endloop:
1726
        *start = page+off;
1727
        if (len < count)
1728
                *eof = 1;
1729
        if (len>count) len = count;
1730
        if (len<0) len = 0;
1731
        return len;
1732
}
1733
 
1734
static struct procfsentries {
1735
  char *name;
1736
  mode_t mode;
1737
  int (*read_proc)(char *page, char **start, off_t off,
1738
                                       int count, int *eof, void *data);
1739
  struct proc_dir_entry *procent;
1740
} procfsentries[] = {
1741
   /* { "capi",           S_IFDIR, 0 }, */
1742
   { "capi/capi20",       0       , proc_capidev_read_proc },
1743
   { "capi/capi20ncci",   0       , proc_capincci_read_proc },
1744
};
1745
 
1746
static void __init proc_init(void)
1747
{
1748
    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
1749
    int i;
1750
 
1751
    for (i=0; i < nelem; i++) {
1752
        struct procfsentries *p = procfsentries + i;
1753
        p->procent = create_proc_entry(p->name, p->mode, 0);
1754
        if (p->procent) p->procent->read_proc = p->read_proc;
1755
    }
1756
}
1757
 
1758
static void __exit proc_exit(void)
1759
{
1760
    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
1761
    int i;
1762
 
1763
    for (i=nelem-1; i >= 0; i--) {
1764
        struct procfsentries *p = procfsentries + i;
1765
        if (p->procent) {
1766
           remove_proc_entry(p->name, 0);
1767
           p->procent = 0;
1768
        }
1769
    }
1770
}
1771
 
1772
/* -------- init function and module interface ---------------------- */
1773
 
1774
 
1775
static void alloc_exit(void)
1776
{
1777
        if (capidev_cachep) {
1778
                (void)kmem_cache_destroy(capidev_cachep);
1779
                capidev_cachep = 0;
1780
        }
1781
        if (capincci_cachep) {
1782
                (void)kmem_cache_destroy(capincci_cachep);
1783
                capincci_cachep = 0;
1784
        }
1785
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1786
        if (capidh_cachep) {
1787
                (void)kmem_cache_destroy(capidh_cachep);
1788
                capidh_cachep = 0;
1789
        }
1790
        if (capiminor_cachep) {
1791
                (void)kmem_cache_destroy(capiminor_cachep);
1792
                capiminor_cachep = 0;
1793
        }
1794
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1795
}
1796
 
1797
static int __init alloc_init(void)
1798
{
1799
        capidev_cachep = kmem_cache_create("capi20_dev",
1800
                                         sizeof(struct capidev),
1801
                                         0,
1802
                                         SLAB_HWCACHE_ALIGN,
1803
                                         NULL, NULL);
1804
        if (!capidev_cachep) {
1805
                alloc_exit();
1806
                return -ENOMEM;
1807
        }
1808
 
1809
        capincci_cachep = kmem_cache_create("capi20_ncci",
1810
                                         sizeof(struct capincci),
1811
                                         0,
1812
                                         SLAB_HWCACHE_ALIGN,
1813
                                         NULL, NULL);
1814
        if (!capincci_cachep) {
1815
                alloc_exit();
1816
                return -ENOMEM;
1817
        }
1818
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1819
        capidh_cachep = kmem_cache_create("capi20_dh",
1820
                                         sizeof(struct datahandle_queue),
1821
                                         0,
1822
                                         SLAB_HWCACHE_ALIGN,
1823
                                         NULL, NULL);
1824
        if (!capidh_cachep) {
1825
                alloc_exit();
1826
                return -ENOMEM;
1827
        }
1828
        capiminor_cachep = kmem_cache_create("capi20_minor",
1829
                                         sizeof(struct capiminor),
1830
                                         0,
1831
                                         SLAB_HWCACHE_ALIGN,
1832
                                         NULL, NULL);
1833
        if (!capiminor_cachep) {
1834
                alloc_exit();
1835
                return -ENOMEM;
1836
        }
1837
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1838
        return 0;
1839
}
1840
 
1841
static void lower_callback(unsigned int cmd, u32 contr, void *data)
1842
{
1843
        struct capi_ncciinfo *np;
1844
        struct capidev *cdev;
1845
 
1846
        switch (cmd) {
1847
        case KCI_CONTRUP:
1848
                printk(KERN_INFO "capi: controller %hu up\n", contr);
1849
                break;
1850
        case KCI_CONTRDOWN:
1851
                printk(KERN_INFO "capi: controller %hu down\n", contr);
1852
                break;
1853
        case KCI_NCCIUP:
1854
                np = (struct capi_ncciinfo *)data;
1855
                if ((cdev = capidev_find(np->applid)) == 0)
1856
                        return;
1857
                (void)capincci_alloc(cdev, np->ncci);
1858
                break;
1859
        case KCI_NCCIDOWN:
1860
                np = (struct capi_ncciinfo *)data;
1861
                if ((cdev = capidev_find(np->applid)) == 0)
1862
                        return;
1863
                (void)capincci_free(cdev, np->ncci);
1864
                break;
1865
        }
1866
}
1867
 
1868
static struct capi_interface_user cuser = {
1869
        name: "capi20",
1870
        callback: lower_callback,
1871
};
1872
 
1873
static char rev[32];
1874
 
1875
static int __init capi_init(void)
1876
{
1877
        char *p;
1878
        char *compileinfo;
1879
 
1880
        MOD_INC_USE_COUNT;
1881
 
1882
        if ((p = strchr(revision, ':')) != 0 && p[1]) {
1883
                strncpy(rev, p + 2, sizeof(rev));
1884
                rev[sizeof(rev)-1] = 0;
1885
                if ((p = strchr(rev, '$')) != 0 && p > rev)
1886
                   *(p-1) = 0;
1887
        } else
1888
                strcpy(rev, "1.0");
1889
 
1890
        if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) {
1891
                printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
1892
                MOD_DEC_USE_COUNT;
1893
                return -EIO;
1894
        }
1895
 
1896
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1897
        if (devfs_register_chrdev(capi_rawmajor, "capi/r%d", &capinc_raw_fops)) {
1898
                devfs_unregister_chrdev(capi_major, "capi20");
1899
                printk(KERN_ERR "capi20: unable to get major %d\n", capi_rawmajor);
1900
                MOD_DEC_USE_COUNT;
1901
                return -EIO;
1902
        }
1903
        devfs_register_series (NULL, "capi/r%u", CAPINC_NR_PORTS,
1904
                              DEVFS_FL_DEFAULT,
1905
                              capi_rawmajor, 0,
1906
                              S_IFCHR | S_IRUSR | S_IWUSR,
1907
                              &capinc_raw_fops, NULL);
1908
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1909
        devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT,
1910
                        capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
1911
                        &capi_fops, NULL);
1912
        printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
1913
 
1914
        if ((capifuncs = attach_capi_interface(&cuser)) == 0) {
1915
 
1916
                MOD_DEC_USE_COUNT;
1917
                devfs_unregister_chrdev(capi_major, "capi20");
1918
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1919
                devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
1920
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1921
                devfs_unregister(devfs_find_handle(NULL, "capi20",
1922
                                                   capi_major, 0,
1923
                                                   DEVFS_SPECIAL_CHR, 0));
1924
                return -EIO;
1925
        }
1926
 
1927
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1928
        if (capinc_tty_init() < 0) {
1929
                (void) detach_capi_interface(&cuser);
1930
                devfs_unregister_chrdev(capi_major, "capi20");
1931
                devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
1932
                MOD_DEC_USE_COUNT;
1933
                return -ENOMEM;
1934
        }
1935
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1936
 
1937
        if (alloc_init() < 0) {
1938
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1939
                unsigned int j;
1940
                devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
1941
                for (j = 0; j < CAPINC_NR_PORTS; j++) {
1942
                        char devname[32];
1943
                        sprintf(devname, "capi/r%u", j);
1944
                        devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));
1945
                }
1946
                capinc_tty_exit();
1947
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1948
                (void) detach_capi_interface(&cuser);
1949
                devfs_unregister_chrdev(capi_major, "capi20");
1950
                devfs_unregister(devfs_find_handle(NULL, "capi20",
1951
                                                   capi_major, 0,
1952
                                                   DEVFS_SPECIAL_CHR, 0));
1953
                MOD_DEC_USE_COUNT;
1954
                return -ENOMEM;
1955
        }
1956
 
1957
        (void)proc_init();
1958
 
1959
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1960
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
1961
        compileinfo = " (middleware+capifs)";
1962
#else
1963
        compileinfo = " (no capifs)";
1964
#endif
1965
#else
1966
        compileinfo = " (no middleware)";
1967
#endif
1968
        printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n",
1969
                                rev, capi_major, compileinfo);
1970
 
1971
        MOD_DEC_USE_COUNT;
1972
        return 0;
1973
}
1974
 
1975
static void __exit capi_exit(void)
1976
{
1977
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1978
        unsigned int j;
1979
#endif
1980
        alloc_exit();
1981
        (void)proc_exit();
1982
 
1983
        devfs_unregister_chrdev(capi_major, "capi20");
1984
        devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0));
1985
 
1986
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1987
        capinc_tty_exit();
1988
        devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
1989
        for (j = 0; j < CAPINC_NR_PORTS; j++) {
1990
                char devname[32];
1991
                sprintf(devname, "capi/r%u", j);
1992
                devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));
1993
        }
1994
#endif
1995
        (void) detach_capi_interface(&cuser);
1996
        printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev);
1997
}
1998
 
1999
module_init(capi_init);
2000
module_exit(capi_exit);

powered by: WebSVN 2.1.0

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