CAPI: Drop capiminor's unused inbytes counter
[deliverable/linux.git] / drivers / isdn / capi / capi.c
CommitLineData
1da177e4
LT
1/* $Id: capi.c,v 1.1.2.7 2004/04/28 09:48:59 armin 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
1da177e4
LT
12#include <linux/module.h>
13#include <linux/errno.h>
14#include <linux/kernel.h>
15#include <linux/major.h>
16#include <linux/sched.h>
17#include <linux/slab.h>
18#include <linux/fcntl.h>
19#include <linux/fs.h>
20#include <linux/signal.h>
9ea6e5d8 21#include <linux/mutex.h>
1da177e4 22#include <linux/mm.h>
a237f3bb 23#include <linux/smp_lock.h>
1da177e4
LT
24#include <linux/timer.h>
25#include <linux/wait.h>
1da177e4 26#include <linux/tty.h>
1da177e4
LT
27#include <linux/netdevice.h>
28#include <linux/ppp_defs.h>
29#include <linux/if_ppp.h>
1da177e4
LT
30#include <linux/skbuff.h>
31#include <linux/proc_fs.h>
9a58a80a 32#include <linux/seq_file.h>
1da177e4
LT
33#include <linux/poll.h>
34#include <linux/capi.h>
35#include <linux/kernelcapi.h>
36#include <linux/init.h>
37#include <linux/device.h>
38#include <linux/moduleparam.h>
1da177e4
LT
39#include <linux/isdn/capiutil.h>
40#include <linux/isdn/capicmd.h>
90926f0e 41
1da177e4 42#include "capifs.h"
1da177e4 43
1da177e4
LT
44MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
45MODULE_AUTHOR("Carsten Paeth");
46MODULE_LICENSE("GPL");
47
1da177e4
LT
48#undef _DEBUG_TTYFUNCS /* call to tty_driver */
49#undef _DEBUG_DATAFLOW /* data flow */
50
51/* -------- driver information -------------------------------------- */
52
56b22935 53static struct class *capi_class;
408b664a 54static int capi_major = 68; /* allocated */
501c87a9
JK
55
56module_param_named(major, capi_major, uint, 0);
57
1da177e4 58#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
501c87a9 59#define CAPINC_NR_PORTS 32
1da177e4 60#define CAPINC_MAX_PORTS 256
501c87a9 61
408b664a 62static int capi_ttyminors = CAPINC_NR_PORTS;
1da177e4 63
1da177e4
LT
64module_param_named(ttyminors, capi_ttyminors, uint, 0);
65#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
66
67/* -------- defines ------------------------------------------------- */
68
69#define CAPINC_MAX_RECVQUEUE 10
70#define CAPINC_MAX_SENDQUEUE 10
71#define CAPI_MAX_BLKSIZE 2048
72
73/* -------- data structures ----------------------------------------- */
74
75struct capidev;
76struct capincci;
1da177e4
LT
77struct capiminor;
78
42651b5c 79struct ackqueue_entry {
6aa65472
MB
80 struct list_head list;
81 u16 datahandle;
82};
83
1da177e4 84struct capiminor {
0159d549
JK
85 struct kref kref;
86
1da177e4 87 unsigned int minor;
90926f0e 88 struct dentry *capifs_dentry;
1da177e4 89
42792713
JK
90 struct capi20_appl *ap;
91 u32 ncci;
92 atomic_t datahandle;
93 atomic_t msgid;
1da177e4 94
fb4b4881 95 struct tty_port port;
1da177e4
LT
96 int ttyinstop;
97 int ttyoutstop;
98 struct sk_buff *ttyskb;
1da177e4
LT
99
100 struct sk_buff_head inqueue;
1da177e4
LT
101 struct sk_buff_head outqueue;
102 int outbytes;
103
104 /* transmit path */
6aa65472 105 struct list_head ackqueue;
1da177e4 106 int nack;
6aa65472 107 spinlock_t ackqlock;
1da177e4 108};
1da177e4 109
053b47ff
MB
110/* FIXME: The following lock is a sledgehammer-workaround to a
111 * locking issue with the capiminor (and maybe other) data structure(s).
112 * Access to this data is done in a racy way and crashes the machine with
113 * a FritzCard DSL driver; sooner or later. This is a workaround
114 * which trades scalability vs stability, so it doesn't crash the kernel anymore.
115 * The correct (and scalable) fix for the issue seems to require
116 * an API change to the drivers... . */
117static DEFINE_SPINLOCK(workaround_lock);
118
1da177e4 119struct capincci {
884f5c44 120 struct list_head list;
1da177e4
LT
121 u32 ncci;
122 struct capidev *cdev;
123#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
124 struct capiminor *minorp;
125#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
126};
127
128struct capidev {
129 struct list_head list;
130 struct capi20_appl ap;
131 u16 errcode;
132 unsigned userflags;
133
134 struct sk_buff_head recvqueue;
135 wait_queue_head_t recvwait;
136
884f5c44 137 struct list_head nccis;
1da177e4 138
05b41494 139 struct mutex lock;
1da177e4
LT
140};
141
142/* -------- global variables ---------------------------------------- */
143
b8f433dc 144static DEFINE_MUTEX(capidev_list_lock);
1da177e4
LT
145static LIST_HEAD(capidev_list);
146
147#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
501c87a9 148
3d5d30fe 149static DEFINE_SPINLOCK(capiminors_lock);
81d17fe5 150static struct capiminor **capiminors;
1da177e4 151
40fb2d0d
JK
152static struct tty_driver *capinc_tty_driver;
153
1da177e4
LT
154/* -------- datahandles --------------------------------------------- */
155
501c87a9 156static int capiminor_add_ack(struct capiminor *mp, u16 datahandle)
1da177e4 157{
42651b5c 158 struct ackqueue_entry *n;
6aa65472 159 unsigned long flags;
1da177e4
LT
160
161 n = kmalloc(sizeof(*n), GFP_ATOMIC);
6aa65472
MB
162 if (unlikely(!n)) {
163 printk(KERN_ERR "capi: alloc datahandle failed\n");
164 return -1;
1da177e4 165 }
1da177e4 166 n->datahandle = datahandle;
6aa65472
MB
167 INIT_LIST_HEAD(&n->list);
168 spin_lock_irqsave(&mp->ackqlock, flags);
169 list_add_tail(&n->list, &mp->ackqueue);
1da177e4 170 mp->nack++;
6aa65472 171 spin_unlock_irqrestore(&mp->ackqlock, flags);
1da177e4
LT
172 return 0;
173}
174
175static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
176{
42651b5c 177 struct ackqueue_entry *p, *tmp;
6aa65472 178 unsigned long flags;
1da177e4 179
6aa65472
MB
180 spin_lock_irqsave(&mp->ackqlock, flags);
181 list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
182 if (p->datahandle == datahandle) {
183 list_del(&p->list);
1da177e4
LT
184 kfree(p);
185 mp->nack--;
6aa65472 186 spin_unlock_irqrestore(&mp->ackqlock, flags);
1da177e4
LT
187 return 0;
188 }
189 }
6aa65472 190 spin_unlock_irqrestore(&mp->ackqlock, flags);
1da177e4
LT
191 return -1;
192}
193
194static void capiminor_del_all_ack(struct capiminor *mp)
195{
42651b5c 196 struct ackqueue_entry *p, *tmp;
6aa65472 197 unsigned long flags;
1da177e4 198
6aa65472
MB
199 spin_lock_irqsave(&mp->ackqlock, flags);
200 list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
201 list_del(&p->list);
1da177e4
LT
202 kfree(p);
203 mp->nack--;
204 }
6aa65472 205 spin_unlock_irqrestore(&mp->ackqlock, flags);
1da177e4
LT
206}
207
208
209/* -------- struct capiminor ---------------------------------------- */
210
fb4b4881
JK
211static const struct tty_port_operations capiminor_port_ops; /* we have none */
212
1da177e4
LT
213static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
214{
81d17fe5 215 struct capiminor *mp;
40fb2d0d 216 struct device *dev;
81d17fe5 217 unsigned int minor;
1da177e4 218
54f0fad3 219 mp = kzalloc(sizeof(*mp), GFP_KERNEL);
1da177e4
LT
220 if (!mp) {
221 printk(KERN_ERR "capi: can't alloc capiminor\n");
222 return NULL;
223 }
224
0159d549
JK
225 kref_init(&mp->kref);
226
1da177e4
LT
227 mp->ap = ap;
228 mp->ncci = ncci;
6aa65472
MB
229 INIT_LIST_HEAD(&mp->ackqueue);
230 spin_lock_init(&mp->ackqlock);
1da177e4
LT
231
232 skb_queue_head_init(&mp->inqueue);
233 skb_queue_head_init(&mp->outqueue);
234
fb4b4881
JK
235 tty_port_init(&mp->port);
236 mp->port.ops = &capiminor_port_ops;
237
81d17fe5 238 /* Allocate the least unused minor number. */
3d5d30fe 239 spin_lock(&capiminors_lock);
81d17fe5
JK
240 for (minor = 0; minor < capi_ttyminors; minor++)
241 if (!capiminors[minor]) {
242 capiminors[minor] = mp;
243 break;
1da177e4 244 }
3d5d30fe 245 spin_unlock(&capiminors_lock);
1da177e4 246
81d17fe5 247 if (minor == capi_ttyminors) {
1da177e4 248 printk(KERN_NOTICE "capi: out of minors\n");
40fb2d0d 249 goto err_out1;
1da177e4
LT
250 }
251
81d17fe5
JK
252 mp->minor = minor;
253
40fb2d0d
JK
254 dev = tty_register_device(capinc_tty_driver, minor, NULL);
255 if (IS_ERR(dev))
256 goto err_out2;
257
1da177e4 258 return mp;
40fb2d0d
JK
259
260err_out2:
3d5d30fe 261 spin_lock(&capiminors_lock);
40fb2d0d 262 capiminors[minor] = NULL;
3d5d30fe 263 spin_unlock(&capiminors_lock);
40fb2d0d
JK
264
265err_out1:
266 kfree(mp);
267 return NULL;
1da177e4
LT
268}
269
0159d549 270static void capiminor_destroy(struct kref *kref)
1da177e4 271{
0159d549 272 struct capiminor *mp = container_of(kref, struct capiminor, kref);
1da177e4 273
d46604e1 274 kfree_skb(mp->ttyskb);
1da177e4
LT
275 skb_queue_purge(&mp->inqueue);
276 skb_queue_purge(&mp->outqueue);
277 capiminor_del_all_ack(mp);
278 kfree(mp);
279}
280
40fb2d0d 281static struct capiminor *capiminor_get(unsigned int minor)
1da177e4 282{
81d17fe5 283 struct capiminor *mp;
1da177e4 284
3d5d30fe 285 spin_lock(&capiminors_lock);
81d17fe5 286 mp = capiminors[minor];
0159d549
JK
287 if (mp)
288 kref_get(&mp->kref);
3d5d30fe 289 spin_unlock(&capiminors_lock);
81d17fe5
JK
290
291 return mp;
1da177e4 292}
1da177e4 293
0159d549
JK
294static inline void capiminor_put(struct capiminor *mp)
295{
296 kref_put(&mp->kref, capiminor_destroy);
297}
298
299static void capiminor_free(struct capiminor *mp)
300{
0159d549
JK
301 tty_unregister_device(capinc_tty_driver, mp->minor);
302
3d5d30fe 303 spin_lock(&capiminors_lock);
0159d549 304 capiminors[mp->minor] = NULL;
3d5d30fe 305 spin_unlock(&capiminors_lock);
0159d549
JK
306
307 capiminor_put(mp);
308}
309
1da177e4
LT
310/* -------- struct capincci ----------------------------------------- */
311
501c87a9 312static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)
1da177e4 313{
501c87a9 314 struct capiminor *mp;
e95ac143 315 dev_t device;
1da177e4 316
501c87a9
JK
317 if (!(cdev->userflags & CAPIFLAG_HIGHJACKING))
318 return;
319
320 mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci);
1da177e4 321 if (mp) {
e95ac143
JK
322 device = MKDEV(capinc_tty_driver->major, mp->minor);
323 mp->capifs_dentry = capifs_new_ncci(mp->minor, device);
1da177e4 324 }
501c87a9
JK
325}
326
327static void capincci_free_minor(struct capincci *np)
328{
329 struct capiminor *mp = np->minorp;
fb4b4881 330 struct tty_struct *tty;
501c87a9
JK
331
332 if (mp) {
333 capifs_free_ncci(mp->capifs_dentry);
fb4b4881
JK
334
335 tty = tty_port_tty_get(&mp->port);
336 if (tty) {
30bced91 337 tty_vhangup(tty);
fb4b4881 338 tty_kref_put(tty);
501c87a9 339 }
fb4b4881
JK
340
341 capiminor_free(mp);
501c87a9
JK
342 }
343}
344
345static inline unsigned int capincci_minor_opencount(struct capincci *np)
346{
347 struct capiminor *mp = np->minorp;
a84fdf41
JK
348 unsigned int count = 0;
349 struct tty_struct *tty;
501c87a9 350
a84fdf41
JK
351 if (mp) {
352 tty = tty_port_tty_get(&mp->port);
353 if (tty) {
354 count = tty->count;
355 tty_kref_put(tty);
356 }
357 }
358 return count;
501c87a9
JK
359}
360
361#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
362
363static inline void
364capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { }
365static inline void capincci_free_minor(struct capincci *np) { }
366
367static inline unsigned int capincci_minor_opencount(struct capincci *np)
368{
369 return 0;
370}
371
372#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
373
374static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
375{
884f5c44 376 struct capincci *np;
501c87a9 377
54f0fad3 378 np = kzalloc(sizeof(*np), GFP_KERNEL);
501c87a9
JK
379 if (!np)
380 return NULL;
381 np->ncci = ncci;
382 np->cdev = cdev;
383
384 capincci_alloc_minor(cdev, np);
385
884f5c44
JK
386 list_add_tail(&np->list, &cdev->nccis);
387
388 return np;
1da177e4
LT
389}
390
391static void capincci_free(struct capidev *cdev, u32 ncci)
392{
884f5c44 393 struct capincci *np, *tmp;
1da177e4 394
884f5c44 395 list_for_each_entry_safe(np, tmp, &cdev->nccis, list)
1da177e4 396 if (ncci == 0xffffffff || np->ncci == ncci) {
501c87a9 397 capincci_free_minor(np);
884f5c44 398 list_del(&np->list);
1da177e4 399 kfree(np);
1da177e4 400 }
1da177e4
LT
401}
402
403static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
404{
884f5c44 405 struct capincci *np;
1da177e4 406
884f5c44
JK
407 list_for_each_entry(np, &cdev->nccis, list)
408 if (np->ncci == ncci)
409 return np;
410 return NULL;
1da177e4
LT
411}
412
1da177e4
LT
413#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
414/* -------- handle data queue --------------------------------------- */
415
416static struct sk_buff *
417gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
418{
419 struct sk_buff *nskb;
420 nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
421 if (nskb) {
422 u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
423 unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
424 capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
425 capimsg_setu16(s, 2, mp->ap->applid);
426 capimsg_setu8 (s, 4, CAPI_DATA_B3);
427 capimsg_setu8 (s, 5, CAPI_RESP);
42792713 428 capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid));
1da177e4
LT
429 capimsg_setu32(s, 8, mp->ncci);
430 capimsg_setu16(s, 12, datahandle);
431 }
432 return nskb;
433}
434
435static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
436{
a11ef7be 437 unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data);
fb4b4881 438 struct tty_struct *tty;
1da177e4 439 struct sk_buff *nskb;
1da177e4
LT
440 u16 errcode, datahandle;
441 struct tty_ldisc *ld;
fb4b4881
JK
442 int ret = -1;
443
fb4b4881
JK
444 tty = tty_port_tty_get(&mp->port);
445 if (!tty) {
1da177e4
LT
446#ifdef _DEBUG_DATAFLOW
447 printk(KERN_DEBUG "capi: currently no receiver\n");
448#endif
449 return -1;
450 }
451
fb4b4881 452 ld = tty_ldisc_ref(tty);
a11ef7be
JK
453 if (!ld) {
454 /* fatal error, do not requeue */
455 ret = 0;
456 kfree_skb(skb);
457 goto deref_tty;
458 }
fb4b4881 459
a352def2 460 if (ld->ops->receive_buf == NULL) {
1da177e4
LT
461#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
462 printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
463#endif
a11ef7be
JK
464 /* fatal error, do not requeue */
465 goto free_skb;
1da177e4
LT
466 }
467 if (mp->ttyinstop) {
468#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
469 printk(KERN_DEBUG "capi: recv tty throttled\n");
470#endif
a11ef7be 471 goto deref_ldisc;
1da177e4 472 }
a11ef7be 473
fb4b4881 474 if (tty->receive_room < datalen) {
1da177e4
LT
475#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
476 printk(KERN_DEBUG "capi: no room in tty\n");
477#endif
a11ef7be 478 goto deref_ldisc;
1da177e4 479 }
a11ef7be
JK
480
481 nskb = gen_data_b3_resp_for(mp, skb);
482 if (!nskb) {
1da177e4 483 printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
a11ef7be 484 goto deref_ldisc;
1da177e4 485 }
a11ef7be
JK
486
487 datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);
488
1da177e4 489 errcode = capi20_put_message(mp->ap, nskb);
a11ef7be
JK
490
491 if (errcode == CAPI_NOERROR) {
492 skb_pull(skb, CAPIMSG_LEN(skb->data));
493#ifdef _DEBUG_DATAFLOW
494 printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
495 datahandle, skb->len);
496#endif
497 ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
498 } else {
1da177e4
LT
499 printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
500 errcode);
501 kfree_skb(nskb);
a11ef7be
JK
502
503 if (errcode == CAPI_SENDQUEUEFULL)
504 goto deref_ldisc;
1da177e4 505 }
a11ef7be
JK
506
507free_skb:
fb4b4881 508 ret = 0;
a11ef7be
JK
509 kfree_skb(skb);
510
511deref_ldisc:
1da177e4 512 tty_ldisc_deref(ld);
a11ef7be
JK
513
514deref_tty:
fb4b4881
JK
515 tty_kref_put(tty);
516 return ret;
1da177e4
LT
517}
518
519static void handle_minor_recv(struct capiminor *mp)
520{
521 struct sk_buff *skb;
68d7347b
JK
522
523 while ((skb = skb_dequeue(&mp->inqueue)) != NULL)
1da177e4
LT
524 if (handle_recv_skb(mp, skb) < 0) {
525 skb_queue_head(&mp->inqueue, skb);
1da177e4
LT
526 return;
527 }
1da177e4
LT
528}
529
530static int handle_minor_send(struct capiminor *mp)
531{
fb4b4881 532 struct tty_struct *tty;
1da177e4
LT
533 struct sk_buff *skb;
534 u16 len;
535 int count = 0;
536 u16 errcode;
537 u16 datahandle;
538
fb4b4881
JK
539 tty = tty_port_tty_get(&mp->port);
540 if (!tty)
541 return 0;
542
543 if (mp->ttyoutstop) {
1da177e4
LT
544#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
545 printk(KERN_DEBUG "capi: send: tty stopped\n");
546#endif
fb4b4881 547 tty_kref_put(tty);
1da177e4
LT
548 return 0;
549 }
550
2f9e9b6d 551 while ((skb = skb_dequeue(&mp->outqueue)) != NULL) {
42792713 552 datahandle = atomic_inc_return(&mp->datahandle);
1da177e4
LT
553 len = (u16)skb->len;
554 skb_push(skb, CAPI_DATA_B3_REQ_LEN);
555 memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
556 capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
557 capimsg_setu16(skb->data, 2, mp->ap->applid);
558 capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
559 capimsg_setu8 (skb->data, 5, CAPI_REQ);
42792713 560 capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid));
1da177e4 561 capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
5e6c20a9 562 capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
1da177e4
LT
563 capimsg_setu16(skb->data, 16, len); /* Data length */
564 capimsg_setu16(skb->data, 18, datahandle);
565 capimsg_setu16(skb->data, 20, 0); /* Flags */
566
501c87a9 567 if (capiminor_add_ack(mp, datahandle) < 0) {
1da177e4
LT
568 skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
569 skb_queue_head(&mp->outqueue, skb);
fb4b4881 570 tty_kref_put(tty);
1da177e4
LT
571 return count;
572 }
573 errcode = capi20_put_message(mp->ap, skb);
574 if (errcode == CAPI_NOERROR) {
1da177e4
LT
575 count++;
576 mp->outbytes -= len;
577#ifdef _DEBUG_DATAFLOW
578 printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n",
579 datahandle, len);
580#endif
581 continue;
582 }
583 capiminor_del_ack(mp, datahandle);
584
585 if (errcode == CAPI_SENDQUEUEFULL) {
586 skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
587 skb_queue_head(&mp->outqueue, skb);
588 break;
589 }
590
591 /* ups, drop packet */
592 printk(KERN_ERR "capi: put_message = %x\n", errcode);
593 mp->outbytes -= len;
594 kfree_skb(skb);
595 }
fb4b4881 596 tty_kref_put(tty);
1da177e4
LT
597 return count;
598}
599
600#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
601/* -------- function called by lower level -------------------------- */
602
603static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
604{
605 struct capidev *cdev = ap->private;
606#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
fb4b4881 607 struct tty_struct *tty;
1da177e4
LT
608 struct capiminor *mp;
609 u16 datahandle;
610#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
611 struct capincci *np;
053b47ff 612 unsigned long flags;
1da177e4 613
05b41494
JK
614 mutex_lock(&cdev->lock);
615
1da177e4
LT
616 if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
617 u16 info = CAPIMSG_U16(skb->data, 12); // Info field
05b41494 618 if ((info & 0xff00) == 0)
1da177e4 619 capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
1da177e4 620 }
05b41494 621 if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND)
1da177e4 622 capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
05b41494 623
053b47ff 624 spin_lock_irqsave(&workaround_lock, flags);
1da177e4
LT
625 if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
626 skb_queue_tail(&cdev->recvqueue, skb);
627 wake_up_interruptible(&cdev->recvwait);
05b41494 628 goto unlock_out;
1da177e4 629 }
05b41494
JK
630
631 np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data));
1da177e4
LT
632 if (!np) {
633 printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
634 skb_queue_tail(&cdev->recvqueue, skb);
635 wake_up_interruptible(&cdev->recvwait);
05b41494 636 goto unlock_out;
1da177e4 637 }
501c87a9 638
1da177e4
LT
639#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
640 skb_queue_tail(&cdev->recvqueue, skb);
641 wake_up_interruptible(&cdev->recvwait);
501c87a9 642
1da177e4 643#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
501c87a9 644
1da177e4
LT
645 mp = np->minorp;
646 if (!mp) {
647 skb_queue_tail(&cdev->recvqueue, skb);
648 wake_up_interruptible(&cdev->recvwait);
05b41494 649 goto unlock_out;
1da177e4 650 }
1da177e4 651 if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
1da177e4
LT
652 datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
653#ifdef _DEBUG_DATAFLOW
654 printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
655 datahandle, skb->len-CAPIMSG_LEN(skb->data));
656#endif
657 skb_queue_tail(&mp->inqueue, skb);
68d7347b 658
1da177e4
LT
659 handle_minor_recv(mp);
660
661 } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {
662
663 datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4);
664#ifdef _DEBUG_DATAFLOW
665 printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n",
666 datahandle,
667 CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2));
668#endif
669 kfree_skb(skb);
670 (void)capiminor_del_ack(mp, datahandle);
fb4b4881
JK
671 tty = tty_port_tty_get(&mp->port);
672 if (tty) {
673 tty_wakeup(tty);
674 tty_kref_put(tty);
675 }
1da177e4
LT
676 (void)handle_minor_send(mp);
677
678 } else {
679 /* ups, let capi application handle it :-) */
680 skb_queue_tail(&cdev->recvqueue, skb);
681 wake_up_interruptible(&cdev->recvwait);
682 }
683#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
501c87a9 684
05b41494 685unlock_out:
053b47ff 686 spin_unlock_irqrestore(&workaround_lock, flags);
05b41494 687 mutex_unlock(&cdev->lock);
1da177e4
LT
688}
689
690/* -------- file_operations for capidev ----------------------------- */
691
692static ssize_t
693capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
694{
695 struct capidev *cdev = (struct capidev *)file->private_data;
696 struct sk_buff *skb;
697 size_t copied;
28a1dbb6 698 int err;
1da177e4
LT
699
700 if (!cdev->ap.applid)
701 return -ENODEV;
702
28a1dbb6
JK
703 skb = skb_dequeue(&cdev->recvqueue);
704 if (!skb) {
1da177e4
LT
705 if (file->f_flags & O_NONBLOCK)
706 return -EAGAIN;
28a1dbb6
JK
707 err = wait_event_interruptible(cdev->recvwait,
708 (skb = skb_dequeue(&cdev->recvqueue)));
709 if (err)
710 return err;
1da177e4
LT
711 }
712 if (skb->len > count) {
713 skb_queue_head(&cdev->recvqueue, skb);
714 return -EMSGSIZE;
715 }
716 if (copy_to_user(buf, skb->data, skb->len)) {
717 skb_queue_head(&cdev->recvqueue, skb);
718 return -EFAULT;
719 }
720 copied = skb->len;
721
722 kfree_skb(skb);
723
724 return copied;
725}
726
727static ssize_t
728capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
729{
730 struct capidev *cdev = (struct capidev *)file->private_data;
731 struct sk_buff *skb;
732 u16 mlen;
733
734 if (!cdev->ap.applid)
735 return -ENODEV;
736
737 skb = alloc_skb(count, GFP_USER);
738 if (!skb)
739 return -ENOMEM;
740
741 if (copy_from_user(skb_put(skb, count), buf, count)) {
742 kfree_skb(skb);
743 return -EFAULT;
744 }
745 mlen = CAPIMSG_LEN(skb->data);
746 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
747 if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
748 kfree_skb(skb);
749 return -EINVAL;
750 }
751 } else {
752 if (mlen != count) {
753 kfree_skb(skb);
754 return -EINVAL;
755 }
756 }
757 CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
758
759 if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
05b41494 760 mutex_lock(&cdev->lock);
1da177e4 761 capincci_free(cdev, CAPIMSG_NCCI(skb->data));
05b41494 762 mutex_unlock(&cdev->lock);
1da177e4
LT
763 }
764
765 cdev->errcode = capi20_put_message(&cdev->ap, skb);
766
767 if (cdev->errcode) {
768 kfree_skb(skb);
769 return -EIO;
770 }
771 return count;
772}
773
774static unsigned int
775capi_poll(struct file *file, poll_table * wait)
776{
777 struct capidev *cdev = (struct capidev *)file->private_data;
778 unsigned int mask = 0;
779
780 if (!cdev->ap.applid)
781 return POLLERR;
782
783 poll_wait(file, &(cdev->recvwait), wait);
784 mask = POLLOUT | POLLWRNORM;
785 if (!skb_queue_empty(&cdev->recvqueue))
786 mask |= POLLIN | POLLRDNORM;
787 return mask;
788}
789
790static int
791capi_ioctl(struct inode *inode, struct file *file,
792 unsigned int cmd, unsigned long arg)
793{
794 struct capidev *cdev = file->private_data;
1da177e4
LT
795 capi_ioctl_struct data;
796 int retval = -EINVAL;
797 void __user *argp = (void __user *)arg;
798
799 switch (cmd) {
800 case CAPI_REGISTER:
05b41494 801 mutex_lock(&cdev->lock);
1da177e4 802
05b41494
JK
803 if (cdev->ap.applid) {
804 retval = -EEXIST;
805 goto register_out;
806 }
807 if (copy_from_user(&cdev->ap.rparam, argp,
808 sizeof(struct capi_register_params))) {
809 retval = -EFAULT;
810 goto register_out;
811 }
812 cdev->ap.private = cdev;
813 cdev->ap.recv_message = capi_recv_message;
814 cdev->errcode = capi20_register(&cdev->ap);
815 retval = (int)cdev->ap.applid;
816 if (cdev->errcode) {
817 cdev->ap.applid = 0;
818 retval = -EIO;
1da177e4 819 }
05b41494
JK
820
821register_out:
822 mutex_unlock(&cdev->lock);
823 return retval;
1da177e4
LT
824
825 case CAPI_GET_VERSION:
826 {
827 if (copy_from_user(&data.contr, argp,
828 sizeof(data.contr)))
829 return -EFAULT;
830 cdev->errcode = capi20_get_version(data.contr, &data.version);
831 if (cdev->errcode)
832 return -EIO;
833 if (copy_to_user(argp, &data.version,
834 sizeof(data.version)))
835 return -EFAULT;
836 }
837 return 0;
838
839 case CAPI_GET_SERIAL:
840 {
841 if (copy_from_user(&data.contr, argp,
842 sizeof(data.contr)))
843 return -EFAULT;
844 cdev->errcode = capi20_get_serial (data.contr, data.serial);
845 if (cdev->errcode)
846 return -EIO;
847 if (copy_to_user(argp, data.serial,
848 sizeof(data.serial)))
849 return -EFAULT;
850 }
851 return 0;
852 case CAPI_GET_PROFILE:
853 {
854 if (copy_from_user(&data.contr, argp,
855 sizeof(data.contr)))
856 return -EFAULT;
857
858 if (data.contr == 0) {
859 cdev->errcode = capi20_get_profile(data.contr, &data.profile);
860 if (cdev->errcode)
861 return -EIO;
862
863 retval = copy_to_user(argp,
864 &data.profile.ncontroller,
865 sizeof(data.profile.ncontroller));
866
867 } else {
868 cdev->errcode = capi20_get_profile(data.contr, &data.profile);
869 if (cdev->errcode)
870 return -EIO;
871
872 retval = copy_to_user(argp, &data.profile,
873 sizeof(data.profile));
874 }
875 if (retval)
876 return -EFAULT;
877 }
878 return 0;
879
880 case CAPI_GET_MANUFACTURER:
881 {
882 if (copy_from_user(&data.contr, argp,
883 sizeof(data.contr)))
884 return -EFAULT;
885 cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer);
886 if (cdev->errcode)
887 return -EIO;
888
889 if (copy_to_user(argp, data.manufacturer,
890 sizeof(data.manufacturer)))
891 return -EFAULT;
892
893 }
894 return 0;
895 case CAPI_GET_ERRCODE:
896 data.errcode = cdev->errcode;
897 cdev->errcode = CAPI_NOERROR;
898 if (arg) {
899 if (copy_to_user(argp, &data.errcode,
900 sizeof(data.errcode)))
901 return -EFAULT;
902 }
903 return data.errcode;
904
905 case CAPI_INSTALLED:
906 if (capi20_isinstalled() == CAPI_NOERROR)
907 return 0;
908 return -ENXIO;
909
910 case CAPI_MANUFACTURER_CMD:
911 {
912 struct capi_manufacturer_cmd mcmd;
913 if (!capable(CAP_SYS_ADMIN))
914 return -EPERM;
915 if (copy_from_user(&mcmd, argp, sizeof(mcmd)))
916 return -EFAULT;
917 return capi20_manufacturer(mcmd.cmd, mcmd.data);
918 }
919 return 0;
920
921 case CAPI_SET_FLAGS:
05b41494
JK
922 case CAPI_CLR_FLAGS: {
923 unsigned userflags;
924
925 if (copy_from_user(&userflags, argp, sizeof(userflags)))
926 return -EFAULT;
1da177e4 927
05b41494
JK
928 mutex_lock(&cdev->lock);
929 if (cmd == CAPI_SET_FLAGS)
930 cdev->userflags |= userflags;
931 else
932 cdev->userflags &= ~userflags;
933 mutex_unlock(&cdev->lock);
934 return 0;
935 }
1da177e4
LT
936 case CAPI_GET_FLAGS:
937 if (copy_to_user(argp, &cdev->userflags,
938 sizeof(cdev->userflags)))
939 return -EFAULT;
940 return 0;
941
05b41494
JK
942 case CAPI_NCCI_OPENCOUNT: {
943 struct capincci *nccip;
944 unsigned ncci;
945 int count = 0;
1da177e4 946
05b41494
JK
947 if (copy_from_user(&ncci, argp, sizeof(ncci)))
948 return -EFAULT;
949
950 mutex_lock(&cdev->lock);
951 nccip = capincci_find(cdev, (u32)ncci);
952 if (nccip)
953 count = capincci_minor_opencount(nccip);
954 mutex_unlock(&cdev->lock);
955 return count;
956 }
1da177e4
LT
957
958#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
05b41494
JK
959 case CAPI_NCCI_GETUNIT: {
960 struct capincci *nccip;
961 struct capiminor *mp;
962 unsigned ncci;
963 int unit = -ESRCH;
964
965 if (copy_from_user(&ncci, argp, sizeof(ncci)))
966 return -EFAULT;
967
968 mutex_lock(&cdev->lock);
969 nccip = capincci_find(cdev, (u32)ncci);
970 if (nccip) {
971 mp = nccip->minorp;
972 if (mp)
973 unit = mp->minor;
1da177e4 974 }
05b41494
JK
975 mutex_unlock(&cdev->lock);
976 return unit;
977 }
1da177e4 978#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
05b41494
JK
979
980 default:
981 return -EINVAL;
1da177e4 982 }
1da177e4
LT
983}
984
eca39dd8 985static int capi_open(struct inode *inode, struct file *file)
1da177e4 986{
eca39dd8
JK
987 struct capidev *cdev;
988
989 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
990 if (!cdev)
991 return -ENOMEM;
992
05b41494 993 mutex_init(&cdev->lock);
eca39dd8
JK
994 skb_queue_head_init(&cdev->recvqueue);
995 init_waitqueue_head(&cdev->recvwait);
884f5c44 996 INIT_LIST_HEAD(&cdev->nccis);
eca39dd8
JK
997 file->private_data = cdev;
998
999 mutex_lock(&capidev_list_lock);
1000 list_add_tail(&cdev->list, &capidev_list);
1001 mutex_unlock(&capidev_list_lock);
1002
1003 return nonseekable_open(inode, file);
1da177e4
LT
1004}
1005
eca39dd8 1006static int capi_release(struct inode *inode, struct file *file)
1da177e4 1007{
eca39dd8 1008 struct capidev *cdev = file->private_data;
1da177e4 1009
eca39dd8
JK
1010 mutex_lock(&capidev_list_lock);
1011 list_del(&cdev->list);
1012 mutex_unlock(&capidev_list_lock);
1013
05b41494 1014 if (cdev->ap.applid)
eca39dd8 1015 capi20_release(&cdev->ap);
eca39dd8 1016 skb_queue_purge(&cdev->recvqueue);
eca39dd8 1017 capincci_free(cdev, 0xffffffff);
eca39dd8
JK
1018
1019 kfree(cdev);
1da177e4
LT
1020 return 0;
1021}
1022
2b8693c0 1023static const struct file_operations capi_fops =
1da177e4
LT
1024{
1025 .owner = THIS_MODULE,
1026 .llseek = no_llseek,
1027 .read = capi_read,
1028 .write = capi_write,
1029 .poll = capi_poll,
1030 .ioctl = capi_ioctl,
1031 .open = capi_open,
1032 .release = capi_release,
1033};
1034
1035#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1036/* -------- tty_operations for capincci ----------------------------- */
1037
46324511
JK
1038static int
1039capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
1da177e4 1040{
46324511
JK
1041 int idx = tty->index;
1042 struct capiminor *mp = capiminor_get(idx);
1043 int ret = tty_init_termios(tty);
1044
1045 if (ret == 0) {
1046 tty_driver_kref_get(driver);
1047 tty->count++;
1048 tty->driver_data = mp;
1049 driver->ttys[idx] = tty;
1050 } else
1051 capiminor_put(mp);
1052 return ret;
1053}
1da177e4 1054
46324511
JK
1055static void capinc_tty_cleanup(struct tty_struct *tty)
1056{
1057 struct capiminor *mp = tty->driver_data;
1058 tty->driver_data = NULL;
1059 capiminor_put(mp);
1060}
1da177e4 1061
fb4b4881 1062static int capinc_tty_open(struct tty_struct *tty, struct file *filp)
46324511
JK
1063{
1064 struct capiminor *mp = tty->driver_data;
1065 unsigned long flags;
fb4b4881
JK
1066 int err;
1067
1068 err = tty_port_open(&mp->port, tty, filp);
1069 if (err)
1070 return err;
1da177e4 1071
053b47ff 1072 spin_lock_irqsave(&workaround_lock, flags);
1da177e4 1073 handle_minor_recv(mp);
053b47ff 1074 spin_unlock_irqrestore(&workaround_lock, flags);
1da177e4
LT
1075 return 0;
1076}
1077
fb4b4881 1078static void capinc_tty_close(struct tty_struct *tty, struct file *filp)
1da177e4 1079{
46324511 1080 struct capiminor *mp = tty->driver_data;
1da177e4 1081
fb4b4881 1082 tty_port_close(&mp->port, tty, filp);
1da177e4
LT
1083}
1084
6576c289 1085static int capinc_tty_write(struct tty_struct *tty,
1da177e4
LT
1086 const unsigned char *buf, int count)
1087{
2c8df722 1088 struct capiminor *mp = tty->driver_data;
1da177e4 1089 struct sk_buff *skb;
053b47ff 1090 unsigned long flags;
1da177e4
LT
1091
1092#ifdef _DEBUG_TTYFUNCS
1093 printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count);
1094#endif
1095
053b47ff 1096 spin_lock_irqsave(&workaround_lock, flags);
1da177e4
LT
1097 skb = mp->ttyskb;
1098 if (skb) {
1099 mp->ttyskb = NULL;
1100 skb_queue_tail(&mp->outqueue, skb);
1101 mp->outbytes += skb->len;
1102 }
1103
1104 skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);
1105 if (!skb) {
1106 printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
053b47ff 1107 spin_unlock_irqrestore(&workaround_lock, flags);
1da177e4
LT
1108 return -ENOMEM;
1109 }
1110
1111 skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1112 memcpy(skb_put(skb, count), buf, count);
1113
1114 skb_queue_tail(&mp->outqueue, skb);
1115 mp->outbytes += skb->len;
1116 (void)handle_minor_send(mp);
053b47ff 1117 spin_unlock_irqrestore(&workaround_lock, flags);
1da177e4
LT
1118 return count;
1119}
1120
f2545a75 1121static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4 1122{
2c8df722 1123 struct capiminor *mp = tty->driver_data;
1da177e4 1124 struct sk_buff *skb;
053b47ff 1125 unsigned long flags;
f2545a75 1126 int ret = 1;
1da177e4
LT
1127
1128#ifdef _DEBUG_TTYFUNCS
1129 printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
1130#endif
1131
053b47ff 1132 spin_lock_irqsave(&workaround_lock, flags);
1da177e4
LT
1133 skb = mp->ttyskb;
1134 if (skb) {
1135 if (skb_tailroom(skb) > 0) {
1136 *(skb_put(skb, 1)) = ch;
053b47ff 1137 spin_unlock_irqrestore(&workaround_lock, flags);
f2545a75 1138 return 1;
1da177e4
LT
1139 }
1140 mp->ttyskb = NULL;
1141 skb_queue_tail(&mp->outqueue, skb);
1142 mp->outbytes += skb->len;
1143 (void)handle_minor_send(mp);
1144 }
1145 skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC);
1146 if (skb) {
1147 skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1148 *(skb_put(skb, 1)) = ch;
1149 mp->ttyskb = skb;
1150 } else {
1151 printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
f2545a75 1152 ret = 0;
1da177e4 1153 }
053b47ff 1154 spin_unlock_irqrestore(&workaround_lock, flags);
f2545a75 1155 return ret;
1da177e4
LT
1156}
1157
1158static void capinc_tty_flush_chars(struct tty_struct *tty)
1159{
2c8df722 1160 struct capiminor *mp = tty->driver_data;
1da177e4 1161 struct sk_buff *skb;
053b47ff 1162 unsigned long flags;
1da177e4
LT
1163
1164#ifdef _DEBUG_TTYFUNCS
1165 printk(KERN_DEBUG "capinc_tty_flush_chars\n");
1166#endif
1167
053b47ff 1168 spin_lock_irqsave(&workaround_lock, flags);
1da177e4
LT
1169 skb = mp->ttyskb;
1170 if (skb) {
1171 mp->ttyskb = NULL;
1172 skb_queue_tail(&mp->outqueue, skb);
1173 mp->outbytes += skb->len;
1174 (void)handle_minor_send(mp);
1175 }
1176 (void)handle_minor_recv(mp);
053b47ff 1177 spin_unlock_irqrestore(&workaround_lock, flags);
1da177e4
LT
1178}
1179
1180static int capinc_tty_write_room(struct tty_struct *tty)
1181{
2c8df722 1182 struct capiminor *mp = tty->driver_data;
1da177e4 1183 int room;
2c8df722 1184
1da177e4
LT
1185 room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);
1186 room *= CAPI_MAX_BLKSIZE;
1187#ifdef _DEBUG_TTYFUNCS
1188 printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room);
1189#endif
1190 return room;
1191}
1192
408b664a 1193static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
1da177e4 1194{
2c8df722
JK
1195 struct capiminor *mp = tty->driver_data;
1196
1da177e4
LT
1197#ifdef _DEBUG_TTYFUNCS
1198 printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
1199 mp->outbytes, mp->nack,
1200 skb_queue_len(&mp->outqueue),
1201 skb_queue_len(&mp->inqueue));
1202#endif
1203 return mp->outbytes;
1204}
1205
1206static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
1207 unsigned int cmd, unsigned long arg)
1208{
1209 int error = 0;
1210 switch (cmd) {
1211 default:
53e86317 1212 error = n_tty_ioctl_helper(tty, file, cmd, arg);
1da177e4
LT
1213 break;
1214 }
1215 return error;
1216}
1217
606d099c 1218static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
1da177e4
LT
1219{
1220#ifdef _DEBUG_TTYFUNCS
1221 printk(KERN_DEBUG "capinc_tty_set_termios\n");
1222#endif
1223}
1224
2c8df722 1225static void capinc_tty_throttle(struct tty_struct *tty)
1da177e4 1226{
2c8df722 1227 struct capiminor *mp = tty->driver_data;
1da177e4
LT
1228#ifdef _DEBUG_TTYFUNCS
1229 printk(KERN_DEBUG "capinc_tty_throttle\n");
1230#endif
2c8df722 1231 mp->ttyinstop = 1;
1da177e4
LT
1232}
1233
2c8df722 1234static void capinc_tty_unthrottle(struct tty_struct *tty)
1da177e4 1235{
2c8df722 1236 struct capiminor *mp = tty->driver_data;
053b47ff 1237 unsigned long flags;
2c8df722 1238
1da177e4
LT
1239#ifdef _DEBUG_TTYFUNCS
1240 printk(KERN_DEBUG "capinc_tty_unthrottle\n");
1241#endif
2c8df722
JK
1242 spin_lock_irqsave(&workaround_lock, flags);
1243 mp->ttyinstop = 0;
1244 handle_minor_recv(mp);
1245 spin_unlock_irqrestore(&workaround_lock, flags);
1da177e4
LT
1246}
1247
1248static void capinc_tty_stop(struct tty_struct *tty)
1249{
2c8df722
JK
1250 struct capiminor *mp = tty->driver_data;
1251
1da177e4
LT
1252#ifdef _DEBUG_TTYFUNCS
1253 printk(KERN_DEBUG "capinc_tty_stop\n");
1254#endif
2c8df722 1255 mp->ttyoutstop = 1;
1da177e4
LT
1256}
1257
1258static void capinc_tty_start(struct tty_struct *tty)
1259{
2c8df722 1260 struct capiminor *mp = tty->driver_data;
053b47ff 1261 unsigned long flags;
2c8df722 1262
1da177e4
LT
1263#ifdef _DEBUG_TTYFUNCS
1264 printk(KERN_DEBUG "capinc_tty_start\n");
1265#endif
2c8df722
JK
1266 spin_lock_irqsave(&workaround_lock, flags);
1267 mp->ttyoutstop = 0;
1268 (void)handle_minor_send(mp);
1269 spin_unlock_irqrestore(&workaround_lock, flags);
1da177e4
LT
1270}
1271
1272static void capinc_tty_hangup(struct tty_struct *tty)
1273{
fb4b4881
JK
1274 struct capiminor *mp = tty->driver_data;
1275
1da177e4
LT
1276#ifdef _DEBUG_TTYFUNCS
1277 printk(KERN_DEBUG "capinc_tty_hangup\n");
1278#endif
fb4b4881 1279 tty_port_hangup(&mp->port);
1da177e4
LT
1280}
1281
9e98966c 1282static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
1da177e4
LT
1283{
1284#ifdef _DEBUG_TTYFUNCS
1285 printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
1286#endif
9e98966c 1287 return 0;
1da177e4
LT
1288}
1289
1290static void capinc_tty_flush_buffer(struct tty_struct *tty)
1291{
1292#ifdef _DEBUG_TTYFUNCS
1293 printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
1294#endif
1295}
1296
1297static void capinc_tty_set_ldisc(struct tty_struct *tty)
1298{
1299#ifdef _DEBUG_TTYFUNCS
1300 printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
1301#endif
1302}
1303
1304static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
1305{
1306#ifdef _DEBUG_TTYFUNCS
1307 printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
1308#endif
1309}
1310
b68e31d0 1311static const struct tty_operations capinc_ops = {
1da177e4
LT
1312 .open = capinc_tty_open,
1313 .close = capinc_tty_close,
1314 .write = capinc_tty_write,
1315 .put_char = capinc_tty_put_char,
1316 .flush_chars = capinc_tty_flush_chars,
1317 .write_room = capinc_tty_write_room,
1318 .chars_in_buffer = capinc_tty_chars_in_buffer,
1319 .ioctl = capinc_tty_ioctl,
1320 .set_termios = capinc_tty_set_termios,
1321 .throttle = capinc_tty_throttle,
1322 .unthrottle = capinc_tty_unthrottle,
1323 .stop = capinc_tty_stop,
1324 .start = capinc_tty_start,
1325 .hangup = capinc_tty_hangup,
1326 .break_ctl = capinc_tty_break_ctl,
1327 .flush_buffer = capinc_tty_flush_buffer,
1328 .set_ldisc = capinc_tty_set_ldisc,
1329 .send_xchar = capinc_tty_send_xchar,
46324511
JK
1330 .install = capinc_tty_install,
1331 .cleanup = capinc_tty_cleanup,
1da177e4
LT
1332};
1333
e76b1544 1334static int __init capinc_tty_init(void)
1da177e4
LT
1335{
1336 struct tty_driver *drv;
e76b1544
JK
1337 int err;
1338
1da177e4
LT
1339 if (capi_ttyminors > CAPINC_MAX_PORTS)
1340 capi_ttyminors = CAPINC_MAX_PORTS;
1341 if (capi_ttyminors <= 0)
1342 capi_ttyminors = CAPINC_NR_PORTS;
1343
81d17fe5
JK
1344 capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors,
1345 GFP_KERNEL);
1346 if (!capiminors)
1da177e4
LT
1347 return -ENOMEM;
1348
81d17fe5
JK
1349 drv = alloc_tty_driver(capi_ttyminors);
1350 if (!drv) {
1351 kfree(capiminors);
1352 return -ENOMEM;
1353 }
1da177e4
LT
1354 drv->owner = THIS_MODULE;
1355 drv->driver_name = "capi_nc";
1da177e4 1356 drv->name = "capi";
e95ac143 1357 drv->major = 0;
1da177e4
LT
1358 drv->minor_start = 0;
1359 drv->type = TTY_DRIVER_TYPE_SERIAL;
1360 drv->subtype = SERIAL_TYPE_NORMAL;
1361 drv->init_termios = tty_std_termios;
1362 drv->init_termios.c_iflag = ICRNL;
1363 drv->init_termios.c_oflag = OPOST | ONLCR;
1364 drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1365 drv->init_termios.c_lflag = 0;
40fb2d0d
JK
1366 drv->flags =
1367 TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
1368 TTY_DRIVER_DYNAMIC_DEV;
1da177e4 1369 tty_set_operations(drv, &capinc_ops);
e76b1544
JK
1370
1371 err = tty_register_driver(drv);
1372 if (err) {
1da177e4 1373 put_tty_driver(drv);
81d17fe5 1374 kfree(capiminors);
1da177e4 1375 printk(KERN_ERR "Couldn't register capi_nc driver\n");
e76b1544 1376 return err;
1da177e4
LT
1377 }
1378 capinc_tty_driver = drv;
1379 return 0;
1380}
1381
e76b1544 1382static void __exit capinc_tty_exit(void)
1da177e4 1383{
e76b1544
JK
1384 tty_unregister_driver(capinc_tty_driver);
1385 put_tty_driver(capinc_tty_driver);
81d17fe5 1386 kfree(capiminors);
1da177e4
LT
1387}
1388
501c87a9
JK
1389#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
1390
1391static inline int capinc_tty_init(void)
1392{
1393 return 0;
1394}
1395
1396static inline void capinc_tty_exit(void) { }
1397
1398#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
1da177e4
LT
1399
1400/* -------- /proc functions ----------------------------------------- */
1401
1402/*
1403 * /proc/capi/capi20:
1404 * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
1405 */
9a58a80a 1406static int capi20_proc_show(struct seq_file *m, void *v)
1da177e4
LT
1407{
1408 struct capidev *cdev;
1409 struct list_head *l;
1da177e4 1410
b8f433dc 1411 mutex_lock(&capidev_list_lock);
1da177e4
LT
1412 list_for_each(l, &capidev_list) {
1413 cdev = list_entry(l, struct capidev, list);
9a58a80a 1414 seq_printf(m, "0 %d %lu %lu %lu %lu\n",
1da177e4
LT
1415 cdev->ap.applid,
1416 cdev->ap.nrecvctlpkt,
1417 cdev->ap.nrecvdatapkt,
1418 cdev->ap.nsentctlpkt,
1419 cdev->ap.nsentdatapkt);
1da177e4 1420 }
b8f433dc 1421 mutex_unlock(&capidev_list_lock);
9a58a80a 1422 return 0;
1da177e4
LT
1423}
1424
9a58a80a
AD
1425static int capi20_proc_open(struct inode *inode, struct file *file)
1426{
1427 return single_open(file, capi20_proc_show, NULL);
1428}
1429
1430static const struct file_operations capi20_proc_fops = {
1431 .owner = THIS_MODULE,
1432 .open = capi20_proc_open,
1433 .read = seq_read,
1434 .llseek = seq_lseek,
1435 .release = single_release,
1436};
1437
1da177e4
LT
1438/*
1439 * /proc/capi/capi20ncci:
1440 * applid ncci
1441 */
9a58a80a 1442static int capi20ncci_proc_show(struct seq_file *m, void *v)
1da177e4 1443{
884f5c44
JK
1444 struct capidev *cdev;
1445 struct capincci *np;
1da177e4 1446
b8f433dc 1447 mutex_lock(&capidev_list_lock);
884f5c44 1448 list_for_each_entry(cdev, &capidev_list, list) {
05b41494 1449 mutex_lock(&cdev->lock);
884f5c44
JK
1450 list_for_each_entry(np, &cdev->nccis, list)
1451 seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci);
05b41494 1452 mutex_unlock(&cdev->lock);
1da177e4 1453 }
b8f433dc 1454 mutex_unlock(&capidev_list_lock);
9a58a80a 1455 return 0;
1da177e4
LT
1456}
1457
9a58a80a
AD
1458static int capi20ncci_proc_open(struct inode *inode, struct file *file)
1459{
1460 return single_open(file, capi20ncci_proc_show, NULL);
1461}
1462
1463static const struct file_operations capi20ncci_proc_fops = {
1464 .owner = THIS_MODULE,
1465 .open = capi20ncci_proc_open,
1466 .read = seq_read,
1467 .llseek = seq_lseek,
1468 .release = single_release,
1da177e4
LT
1469};
1470
1471static void __init proc_init(void)
1472{
9a58a80a
AD
1473 proc_create("capi/capi20", 0, NULL, &capi20_proc_fops);
1474 proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops);
1da177e4
LT
1475}
1476
1477static void __exit proc_exit(void)
1478{
9a58a80a
AD
1479 remove_proc_entry("capi/capi20", NULL);
1480 remove_proc_entry("capi/capi20ncci", NULL);
1da177e4
LT
1481}
1482
1483/* -------- init function and module interface ---------------------- */
1484
1485
1da177e4
LT
1486static int __init capi_init(void)
1487{
88549d6b 1488 const char *compileinfo;
6d9eac34 1489 int major_ret;
1da177e4 1490
6d9eac34
AM
1491 major_ret = register_chrdev(capi_major, "capi20", &capi_fops);
1492 if (major_ret < 0) {
1da177e4 1493 printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
6d9eac34 1494 return major_ret;
1da177e4 1495 }
56b22935 1496 capi_class = class_create(THIS_MODULE, "capi");
1da177e4
LT
1497 if (IS_ERR(capi_class)) {
1498 unregister_chrdev(capi_major, "capi20");
1499 return PTR_ERR(capi_class);
1500 }
1501
a9b12619 1502 device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
1da177e4 1503
1da177e4 1504 if (capinc_tty_init() < 0) {
d78b0368 1505 device_destroy(capi_class, MKDEV(capi_major, 0));
56b22935 1506 class_destroy(capi_class);
1da177e4
LT
1507 unregister_chrdev(capi_major, "capi20");
1508 return -ENOMEM;
1509 }
1da177e4
LT
1510
1511 proc_init();
1512
1da177e4
LT
1513#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
1514 compileinfo = " (middleware+capifs)";
501c87a9 1515#elif defined(CONFIG_ISDN_CAPI_MIDDLEWARE)
1da177e4 1516 compileinfo = " (no capifs)";
1da177e4
LT
1517#else
1518 compileinfo = " (no middleware)";
1519#endif
88549d6b
JK
1520 printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n",
1521 capi_major, compileinfo);
1da177e4
LT
1522
1523 return 0;
1524}
1525
1526static void __exit capi_exit(void)
1527{
1528 proc_exit();
1529
d78b0368 1530 device_destroy(capi_class, MKDEV(capi_major, 0));
56b22935 1531 class_destroy(capi_class);
1da177e4 1532 unregister_chrdev(capi_major, "capi20");
1da177e4 1533
1da177e4 1534 capinc_tty_exit();
1da177e4
LT
1535}
1536
1537module_init(capi_init);
1538module_exit(capi_exit);
This page took 0.63698 seconds and 5 git commands to generate.