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