⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capi.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: capi.c,v 1.45 2000/12/02 19:47:29 kai Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ * Revision 1.45  2000/12/02 19:47:29  kai * Change the Makefiles to new style. * There may be problems there that I missed, so this shouldn't go into * an offical kernel any time soon. * However, if I didn't commit it, we wouldn't find the bugs... * * Revision 1.44  2000/11/25 17:00:59  kai * compatibility cleanup - final part for the time being * * Revision 1.43  2000/11/23 20:45:14  kai * fixed module_init/exit stuff * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. * * Revision 1.42  2000/11/19 17:03:55  kai * compatibility cleanup - part 5 * * Revision 1.41  2000/11/01 14:05:02  calle * - use module_init/module_exit from linux/init.h. * - all static struct variables are initialized with "membername:" now. * - avm_cs.c, let it work with newer pcmcia-cs. * * Revision 1.40  2000/10/24 15:15:04  calle * Workaround: pppd calls restoretty before reseting the ldisc and *   ldisc "ppp_sync" didn't support this. So we call n_tty_ioctl *   in the driver ioctl function. (remember: driver ioctl function is *   only called if ldisc ioctl function did not handle the call) * * Revision 1.39  2000/07/24 13:42:50  calle * - lock_kernel/unlock_kernel for _release functions. (from 2.4) * * Revision 1.38  2000/07/24 08:49:09  calle * - Bugfix: capiminor_del_all_ack completely wrong :-( * * Revision 1.37  2000/07/20 10:22:27  calle * - Made procfs function cleaner and removed variable "begin". * * Revision 1.36  2000/06/29 13:59:35  calle * - call to devfs_register was wrong * * Revision 1.35  2000/06/19 15:11:24  keil * avoid use of freed structs * changes from 2.4.0-ac21 * * Revision 1.34  2000/06/18 16:09:54  keil * more changes for 2.4 * * Revision 1.33  2000/05/18 16:35:43  calle * Uaaahh. Bad memory leak fixed. * * Revision 1.32  2000/04/21 12:38:42  calle * Bugfix: error in proc_ functions, begin-off => off-begin * * Revision 1.31  2000/04/03 13:29:24  calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... * * Revision 1.30  2000/03/19 12:31:36  calle * PPP over CAPI raw driver disabled for now, ppp_generic has been changed. * * Revision 1.29  2000/03/13 17:48:13  calle * removed unused variable. * * Revision 1.28  2000/03/08 17:06:33  calle * - changes for devfs and 2.3.49 * - capifs now configurable (no need with devfs) * - New Middleware ioctl CAPI_NCCI_GETUNIT * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) * * Revision 1.27  2000/03/06 18:00:23  calle * - Middleware extention now working with 2.3.49 (capifs). * - Fixed typos in debug section of capi.c * - Bugfix: Makefile corrected for b1pcmcia.c * * Revision 1.26  2000/03/03 16:48:38  calle * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) *   It is now possible to create a connection with a CAPI2.0 applikation *   and than to handle the data connection from /dev/capi/ (capifs) and also *   using async or sync PPP on this connection. *   The two major device number 190 and 191 are not confirmed yet, *   but I want to save the code in cvs, before I go on. * * Revision 1.25  2000/03/03 16:37:11  kai * incorporated some cosmetic changes from the official kernel tree back * into CVS * * Revision 1.24  2000/03/03 15:50:42  calle * - kernel CAPI: *   - Changed parameter "param" in capi_signal from __u32 to void *. *   - rewrote notifier handling in kcapi.c *   - new notifier NCCI_UP and NCCI_DOWN * - User CAPI: *   - /dev/capi20 is now a cloning device. *   - middleware extentions prepared. * - capidrv.c *   - locking of list operations and module count updates. * * Revision 1.23  2000/02/26 01:00:53  keil * changes from 2.3.47 * * Revision 1.22  1999/11/13 21:27:16  keil * remove KERNELVERSION * * Revision 1.21  1999/09/10 17:24:18  calle * Changes for proposed standard for CAPI2.0: * - AK148 "Linux Exention" * * Revision 1.20  1999/09/07 09:02:53  calle * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and * DATA_B3_IND is always directly after the CAPI message. The "Data" member * ist never used inside the kernel. * * Revision 1.19  1999/07/09 15:05:42  keil * compat.h is now isdn_compat.h * * Revision 1.18  1999/07/06 07:42:01  calle * - changes in /proc interface * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. * * Revision 1.17  1999/07/01 15:26:30  calle * complete new version (I love it): * + new hardware independed "capi_driver" interface that will make it easy to: *   - support other controllers with CAPI-2.0 (i.e. USB Controller) *   - write a CAPI-2.0 for the passive cards *   - support serial link CAPI-2.0 boxes. * + wrote "capi_driver" for all supported cards. * + "capi_driver" (supported cards) now have to be configured with *   make menuconfig, in the past all supported cards where included *   at once. * + new and better informations in /proc/capi/ * + new ioctl to switch trace of capi messages per controller *   using "avmcapictrl trace [contr] on|off|...." * + complete testcircle with all supported cards and also the *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. * * Revision 1.16  1999/07/01 08:22:57  keil * compatibility macros now in <linux/isdn_compat.h> * * Revision 1.15  1999/06/21 15:24:11  calle * extend information in /proc. * * Revision 1.14  1999/06/10 16:51:03  calle * Bugfix: open/release of control device was not handled correct. * * Revision 1.13  1998/08/28 04:32:25  calle * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1 * driver running with 2.1.118. * * Revision 1.12  1998/05/26 22:39:34  he * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) * concap typo * cleared dev.tbusy in isdn_net BCONN status callback * * Revision 1.11  1998/03/09 17:46:37  he * merged in 2.1.89 changes * * Revision 1.10  1998/02/13 07:09:13  calle * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * * Revision 1.9  1998/01/31 11:14:44  calle * merged changes to 2.0 tree, prepare 2.1.82 to work. * * Revision 1.8  1997/11/04 06:12:08  calle * capi.c: new read/write in file_ops since 2.1.60 * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware. * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON) * compat.h: added #define LinuxVersionCode * * Revision 1.7  1997/10/11 10:29:34  calle * llseek() parameters changed in 2.1.56. * * Revision 1.6  1997/10/01 09:21:15  fritz * Removed old compatibility stuff for 2.0.X kernels. * From now on, this code is for 2.1.X ONLY! * Old stuff is still in the separate branch. * * Revision 1.5  1997/08/21 23:11:55  fritz * Added changes for kernels >= 2.1.45 * * Revision 1.4  1997/05/27 15:17:50  fritz * Added changes for recent 2.1.x kernels: *   changed return type of isdn_close *   queue_task_* -> queue_task *   clear/set_bit -> test_and_... where apropriate. *   changed type of hard_header_cache parameter. * * Revision 1.3  1997/05/18 09:24:14  calle * added verbose disconnect reason reporting to avmb1. * some fixes in capi20 interface. * changed info messages for B1-PCI * * Revision 1.2  1997/03/05 21:17:59  fritz * Added capi_poll for compiling under 2.1.27 * * Revision 1.1  1997/03/04 21:50:29  calle * Frirst version in isdn4linux * * Revision 2.2  1997/02/12 09:31:39  calle * new version * * Revision 1.1  1997/01/31 10:32:20  calle * Initial revision * */#include <linux/config.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/sched.h>#include <linux/malloc.h>#include <linux/fcntl.h>#include <linux/fs.h>#include <linux/signal.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <linux/timer.h>#include <linux/wait.h>#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE#include <linux/tty.h>#ifdef CONFIG_PPP#include <linux/netdevice.h>#include <linux/ppp_defs.h>#include <linux/if_ppp.h>#undef CAPI_PPP_ON_RAW_DEVICE#endif /* CONFIG_PPP */#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */#include <linux/skbuff.h>#include <linux/proc_fs.h>#include <linux/poll.h>#include <linux/capi.h>#include <linux/kernelcapi.h>#include <linux/init.h>#include <linux/devfs_fs_kernel.h>#include "capiutil.h"#include "capicmd.h"#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)#include "capifs.h"#endif#include <linux/slab.h>static char *revision = "$Revision: 1.45 $";MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");#undef _DEBUG_REFCOUNT		/* alloc/free and open/close debug */#undef _DEBUG_TTYFUNCS		/* call to tty_driver */#undef _DEBUG_DATAFLOW		/* data flow *//* -------- driver information -------------------------------------- */int capi_major = 68;		/* allocated */#ifdef CONFIG_ISDN_CAPI_MIDDLEWAREint capi_rawmajor = 190;int capi_ttymajor = 191;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */MODULE_PARM(capi_major, "i");#ifdef CONFIG_ISDN_CAPI_MIDDLEWAREMODULE_PARM(capi_rawmajor, "i");MODULE_PARM(capi_ttymajor, "i");#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE *//* -------- defines ------------------------------------------------- */#define CAPINC_MAX_RECVQUEUE	10#define CAPINC_MAX_SENDQUEUE	10#define CAPI_MAX_BLKSIZE	2048/* -------- data structures ----------------------------------------- */struct capidev;struct capincci;#ifdef CONFIG_ISDN_CAPI_MIDDLEWAREstruct capiminor;struct capiminor {	struct capiminor *next;	struct capincci  *nccip;	unsigned int      minor;	__u16		 applid;	__u32		 ncci;	__u16		 datahandle;	__u16		 msgid;	struct file      *file;	struct tty_struct *tty;	int                ttyinstop;	int                ttyoutstop;	struct sk_buff    *ttyskb;	atomic_t           ttyopencount;	struct sk_buff_head inqueue;	int                 inbytes;	struct sk_buff_head outqueue;	int                 outbytes;	/* for raw device */	struct sk_buff_head recvqueue;	wait_queue_head_t recvwait;	wait_queue_head_t sendwait;		/* transmit path */	struct datahandle_queue {		    struct datahandle_queue *next;		    __u16                    datahandle;	} *ackqueue;	int nack;};#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */struct capincci {	struct capincci *next;	__u32		 ncci;	struct capidev	*cdev;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	struct capiminor *minorp;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */};struct capidev {	struct capidev *next;	struct file    *file;	__u16		applid;	__u16		errcode;	unsigned int    minor;	unsigned        userflags;	struct sk_buff_head recvqueue;	wait_queue_head_t recvwait;	/* Statistic */	unsigned long	nrecvctlpkt;	unsigned long	nrecvdatapkt;	unsigned long	nsentctlpkt;	unsigned long	nsentdatapkt;		struct capincci *nccis;};/* -------- global variables ---------------------------------------- */static struct capi_interface *capifuncs = 0;static struct capidev *capidev_openlist = 0;#ifdef CONFIG_ISDN_CAPI_MIDDLEWAREstatic struct capiminor *minors = 0;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */static kmem_cache_t *capidev_cachep = 0;static kmem_cache_t *capincci_cachep = 0;#ifdef CONFIG_ISDN_CAPI_MIDDLEWAREstatic kmem_cache_t *capiminor_cachep = 0;static kmem_cache_t *capidh_cachep = 0;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE/* -------- datahandles --------------------------------------------- */int capincci_add_ack(struct capiminor *mp, __u16 datahandle){	struct datahandle_queue *n, **pp;	n = (struct datahandle_queue *)	kmem_cache_alloc(capidh_cachep, GFP_ATOMIC);	if (!n) {	   printk(KERN_ERR "capi: alloc datahandle failed\n");	   return -1;	}	n->next = 0;	n->datahandle = datahandle;	for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ;	*pp = n;	mp->nack++;	return 0;}int capiminor_del_ack(struct capiminor *mp, __u16 datahandle){	struct datahandle_queue **pp, *p;	for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { 		if ((*pp)->datahandle == datahandle) {			p = *pp;			*pp = (*pp)->next;			kmem_cache_free(capidh_cachep, p);			mp->nack--;			return 0;		}	}	return -1;}void capiminor_del_all_ack(struct capiminor *mp){	struct datahandle_queue **pp, *p;	pp = &mp->ackqueue;	while (*pp) {		p = *pp;		*pp = (*pp)->next;		kmem_cache_free(capidh_cachep, p);		mp->nack--;	}}/* -------- struct capiminor ---------------------------------------- */struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci){	struct capiminor *mp, **pp;        unsigned int minor = 0;	MOD_INC_USE_COUNT;	mp = (struct capiminor *)kmem_cache_alloc(capiminor_cachep, GFP_ATOMIC);	if (!mp) {		MOD_DEC_USE_COUNT;		printk(KERN_ERR "capi: can't alloc capiminor\n");		return 0;	}#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capiminor_alloc %d\n", GET_USE_COUNT(THIS_MODULE));#endif	memset(mp, 0, sizeof(struct capiminor));	mp->applid = applid;	mp->ncci = ncci;	mp->msgid = 0;	atomic_set(&mp->ttyopencount,0);	skb_queue_head_init(&mp->inqueue);	skb_queue_head_init(&mp->outqueue);	skb_queue_head_init(&mp->recvqueue);	init_waitqueue_head(&mp->recvwait);	init_waitqueue_head(&mp->sendwait);	for (pp = &minors; *pp; pp = &(*pp)->next) {		if ((*pp)->minor < minor)			continue;		if ((*pp)->minor > minor)			break;		minor++;	}	mp->minor = minor;	mp->next = *pp;	*pp = mp;	return mp;}void capiminor_free(struct capiminor *mp){	struct capiminor **pp;	struct sk_buff *skb;	pp = &minors;	while (*pp) {		if (*pp == mp) {			*pp = (*pp)->next;			if (mp->ttyskb) kfree_skb(mp->ttyskb);			mp->ttyskb = 0;			while ((skb = skb_dequeue(&mp->recvqueue)) != 0)				kfree_skb(skb);			while ((skb = skb_dequeue(&mp->inqueue)) != 0)				kfree_skb(skb);			while ((skb = skb_dequeue(&mp->outqueue)) != 0)				kfree_skb(skb);			capiminor_del_all_ack(mp);			kmem_cache_free(capiminor_cachep, mp);			MOD_DEC_USE_COUNT;#ifdef _DEBUG_REFCOUNT			printk(KERN_DEBUG "capiminor_free %d\n", GET_USE_COUNT(THIS_MODULE));#endif			return;		} else {			pp = &(*pp)->next;		}	}}struct capiminor *capiminor_find(unsigned int minor){	struct capiminor *p;	for (p = minors; p && p->minor != minor; p = p->next)		;	return p;}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE *//* -------- struct capincci ----------------------------------------- */static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci){	struct capincci *np, **pp;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	struct capiminor *mp = 0;	kdev_t kdev;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */	np = (struct capincci *)kmem_cache_alloc(capincci_cachep, GFP_ATOMIC);	if (!np)		return 0;	memset(np, 0, sizeof(struct capincci));	np->ncci = ncci;	np->cdev = cdev;	for (pp=&cdev->nccis; *pp; pp = &(*pp)->next)		;	*pp = np;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	mp = 0;	if (cdev->userflags & CAPIFLAG_HIGHJACKING)		mp = np->minorp = capiminor_alloc(cdev->applid, ncci);	if (mp) {		mp->nccip = np;#ifdef _DEBUG_REFCOUNT		printk(KERN_DEBUG "set mp->nccip\n");#endif#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)		kdev = MKDEV(capi_rawmajor, mp->minor);		capifs_new_ncci('r', mp->minor, kdev);		kdev = MKDEV(capi_ttymajor, mp->minor);		capifs_new_ncci(0, mp->minor, kdev);#endif	}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */        return np;}static void capincci_free(struct capidev *cdev, __u32 ncci){	struct capincci *np, **pp;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	struct capiminor *mp;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */	pp=&cdev->nccis;	while (*pp) {		np = *pp;		if (ncci == 0xffffffff || np->ncci == ncci) {			*pp = (*pp)->next;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE			if ((mp = np->minorp) != 0) {#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)				capifs_free_ncci('r', mp->minor);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -