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

📄 capidrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth <calle@calle.de> * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#include <linux/module.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/fcntl.h>#include <linux/fs.h>#include <linux/signal.h>#include <linux/mm.h>#include <linux/timer.h>#include <linux/wait.h>#include <linux/skbuff.h>#include <linux/isdn.h>#include <linux/isdnif.h>#include <linux/proc_fs.h>#include <linux/capi.h>#include <linux/kernelcapi.h>#include <linux/ctype.h>#include <linux/init.h>#include <linux/moduleparam.h>#include <linux/isdn/capiutil.h>#include <linux/isdn/capicmd.h>#include "capidrv.h"static char *revision = "$Revision: 1.1.2.2 $";static int debugmode = 0;MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");MODULE_AUTHOR("Carsten Paeth");MODULE_LICENSE("GPL");module_param(debugmode, uint, 0);/* -------- type definitions ----------------------------------------- */struct capidrv_contr {	struct capidrv_contr *next;	struct module *owner;	u32 contrnr;	char name[20];	/*	 * for isdn4linux	 */	isdn_if interface;	int myid;	/*	 * LISTEN state	 */	int state;	u32 cipmask;	u32 cipmask2;        struct timer_list listentimer;	/*	 * ID of capi message sent	 */	u16 msgid;	/*	 * B-Channels	 */	int nbchan;	struct capidrv_bchan {		struct capidrv_contr *contr;		u8 msn[ISDN_MSNLEN];		int l2;		int l3;		u8 num[ISDN_MSNLEN];		u8 mynum[ISDN_MSNLEN];		int si1;		int si2;		int incoming;		int disconnecting;		struct capidrv_plci {			struct capidrv_plci *next;			u32 plci;			u32 ncci;	/* ncci for CONNECT_ACTIVE_IND */			u16 msgid;	/* to identfy CONNECT_CONF */			int chan;			int state;			int leasedline;			struct capidrv_ncci {				struct capidrv_ncci *next;				struct capidrv_plci *plcip;				u32 ncci;				u16 msgid;	/* to identfy CONNECT_B3_CONF */				int chan;				int state;				int oldstate;				/* */				u16 datahandle;				struct ncci_datahandle_queue {				    struct ncci_datahandle_queue *next;				    u16                         datahandle;				    int                           len;				} *ackqueue;			} *ncci_list;		} *plcip;		struct capidrv_ncci *nccip;	} *bchans;	struct capidrv_plci *plci_list;	/* for q931 data */	u8  q931_buf[4096];	u8 *q931_read;	u8 *q931_write;	u8 *q931_end;};struct capidrv_data {	struct capi20_appl ap;	int ncontr;	struct capidrv_contr *contr_list;};typedef struct capidrv_plci capidrv_plci;typedef struct capidrv_ncci capidrv_ncci;typedef struct capidrv_contr capidrv_contr;typedef struct capidrv_data capidrv_data;typedef struct capidrv_bchan capidrv_bchan;/* -------- data definitions ----------------------------------------- */static capidrv_data global;static DEFINE_SPINLOCK(global_lock);static void handle_dtrace_data(capidrv_contr *card,	int send, int level2, u8 *data, u16 len);/* -------- convert functions ---------------------------------------- */static inline u32 b1prot(int l2, int l3){	switch (l2) {	case ISDN_PROTO_L2_X75I:	case ISDN_PROTO_L2_X75UI:	case ISDN_PROTO_L2_X75BUI:		return 0;	case ISDN_PROTO_L2_HDLC:	default:		return 0;	case ISDN_PROTO_L2_TRANS:		return 1;        case ISDN_PROTO_L2_V11096:        case ISDN_PROTO_L2_V11019:        case ISDN_PROTO_L2_V11038:		return 2;        case ISDN_PROTO_L2_FAX:		return 4;	case ISDN_PROTO_L2_MODEM:		return 8;	}}static inline u32 b2prot(int l2, int l3){	switch (l2) {	case ISDN_PROTO_L2_X75I:	case ISDN_PROTO_L2_X75UI:	case ISDN_PROTO_L2_X75BUI:	default:		return 0;	case ISDN_PROTO_L2_HDLC:	case ISDN_PROTO_L2_TRANS:        case ISDN_PROTO_L2_V11096:        case ISDN_PROTO_L2_V11019:        case ISDN_PROTO_L2_V11038:	case ISDN_PROTO_L2_MODEM:		return 1;        case ISDN_PROTO_L2_FAX:		return 4;	}}static inline u32 b3prot(int l2, int l3){	switch (l2) {	case ISDN_PROTO_L2_X75I:	case ISDN_PROTO_L2_X75UI:	case ISDN_PROTO_L2_X75BUI:	case ISDN_PROTO_L2_HDLC:	case ISDN_PROTO_L2_TRANS:        case ISDN_PROTO_L2_V11096:        case ISDN_PROTO_L2_V11019:        case ISDN_PROTO_L2_V11038:	case ISDN_PROTO_L2_MODEM:	default:		return 0;        case ISDN_PROTO_L2_FAX:		return 4;	}}static _cstruct b1config_async_v110(u16 rate){	/* CAPI-Spec "B1 Configuration" */	static unsigned char buf[9];	buf[0] = 8; /* len */	/* maximum bitrate */	buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;	buf[3] = 8; buf[4] = 0; /* 8 bits per character */	buf[5] = 0; buf[6] = 0; /* parity none */	buf[7] = 0; buf[8] = 0; /* 1 stop bit */	return buf;}static _cstruct b1config(int l2, int l3){	switch (l2) {	case ISDN_PROTO_L2_X75I:	case ISDN_PROTO_L2_X75UI:	case ISDN_PROTO_L2_X75BUI:	case ISDN_PROTO_L2_HDLC:	case ISDN_PROTO_L2_TRANS:	default:		return NULL;        case ISDN_PROTO_L2_V11096:	    return b1config_async_v110(9600);        case ISDN_PROTO_L2_V11019:	    return b1config_async_v110(19200);        case ISDN_PROTO_L2_V11038:	    return b1config_async_v110(38400);	}}static inline u16 si2cip(u8 si1, u8 si2){	static const u8 cip[17][5] =	{	/*  0  1  2  3  4  */		{0, 0, 0, 0, 0},	/*0 */		{16, 16, 4, 26, 16},	/*1 */		{17, 17, 17, 4, 4},	/*2 */		{2, 2, 2, 2, 2},	/*3 */		{18, 18, 18, 18, 18},	/*4 */		{2, 2, 2, 2, 2},	/*5 */		{0, 0, 0, 0, 0},	/*6 */		{2, 2, 2, 2, 2},	/*7 */		{2, 2, 2, 2, 2},	/*8 */		{21, 21, 21, 21, 21},	/*9 */		{19, 19, 19, 19, 19},	/*10 */		{0, 0, 0, 0, 0},	/*11 */		{0, 0, 0, 0, 0},	/*12 */		{0, 0, 0, 0, 0},	/*13 */		{0, 0, 0, 0, 0},	/*14 */		{22, 22, 22, 22, 22},	/*15 */		{27, 27, 27, 28, 27}	/*16 */	};	if (si1 > 16)		si1 = 0;	if (si2 > 4)		si2 = 0;	return (u16) cip[si1][si2];}static inline u8 cip2si1(u16 cipval){	static const u8 si[32] =	{7, 1, 7, 7, 1, 1, 7, 7,	/*0-7 */	 7, 1, 0, 0, 0, 0, 0, 0,	/*8-15 */	 1, 2, 4, 10, 9, 9, 15, 7,	/*16-23 */	 7, 7, 1, 16, 16, 0, 0, 0};	/*24-31 */	if (cipval > 31)		cipval = 0;	/* .... */	return si[cipval];}static inline u8 cip2si2(u16 cipval){	static const u8 si[32] =	{0, 0, 0, 0, 2, 3, 0, 0,	/*0-7 */	 0, 3, 0, 0, 0, 0, 0, 0,	/*8-15 */	 1, 2, 0, 0, 9, 0, 0, 0,	/*16-23 */	 0, 0, 3, 2, 3, 0, 0, 0};	/*24-31 */	if (cipval > 31)		cipval = 0;	/* .... */	return si[cipval];}/* -------- controller management ------------------------------------- */static inline capidrv_contr *findcontrbydriverid(int driverid){    	unsigned long flags;	capidrv_contr *p;	spin_lock_irqsave(&global_lock, flags);	for (p = global.contr_list; p; p = p->next)		if (p->myid == driverid)			break;	spin_unlock_irqrestore(&global_lock, flags);	return p;}static capidrv_contr *findcontrbynumber(u32 contr){	unsigned long flags;	capidrv_contr *p = global.contr_list;	spin_lock_irqsave(&global_lock, flags);	for (p = global.contr_list; p; p = p->next)		if (p->contrnr == contr)			break;	spin_unlock_irqrestore(&global_lock, flags);	return p;}/* -------- plci management ------------------------------------------ */static capidrv_plci *new_plci(capidrv_contr * card, int chan){	capidrv_plci *plcip;	plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC);	if (plcip == 0)		return NULL;	memset(plcip, 0, sizeof(capidrv_plci));	plcip->state = ST_PLCI_NONE;	plcip->plci = 0;	plcip->msgid = 0;	plcip->chan = chan;	plcip->next = card->plci_list;	card->plci_list = plcip;	card->bchans[chan].plcip = plcip;	return plcip;}static capidrv_plci *find_plci_by_plci(capidrv_contr * card, u32 plci){	capidrv_plci *p;	for (p = card->plci_list; p; p = p->next)		if (p->plci == plci)			return p;	return NULL;}static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, u16 msgid){	capidrv_plci *p;	for (p = card->plci_list; p; p = p->next)		if (p->msgid == msgid)			return p;	return NULL;}static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, u32 ncci){	capidrv_plci *p;	for (p = card->plci_list; p; p = p->next)		if (p->plci == (ncci & 0xffff))			return p;	return NULL;}static void free_plci(capidrv_contr * card, capidrv_plci * plcip){	capidrv_plci **pp;	for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {		if (*pp == plcip) {			*pp = (*pp)->next;			card->bchans[plcip->chan].plcip = NULL;			card->bchans[plcip->chan].disconnecting = 0;			card->bchans[plcip->chan].incoming = 0;			kfree(plcip);			return;		}	}	printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",	       card->contrnr, plcip, plcip->plci);}/* -------- ncci management ------------------------------------------ */static inline capidrv_ncci *new_ncci(capidrv_contr * card,				     capidrv_plci * plcip,				     u32 ncci){	capidrv_ncci *nccip;	nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC);	if (nccip == 0)		return NULL;	memset(nccip, 0, sizeof(capidrv_ncci));	nccip->ncci = ncci;	nccip->state = ST_NCCI_NONE;	nccip->plcip = plcip;	nccip->chan = plcip->chan;	nccip->datahandle = 0;	nccip->next = plcip->ncci_list;	plcip->ncci_list = nccip;	card->bchans[plcip->chan].nccip = nccip;	return nccip;}static inline capidrv_ncci *find_ncci(capidrv_contr * card, u32 ncci){	capidrv_plci *plcip;	capidrv_ncci *p;	if ((plcip = find_plci_by_ncci(card, ncci)) == 0)		return NULL;	for (p = plcip->ncci_list; p; p = p->next)		if (p->ncci == ncci)			return p;	return NULL;}static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,					       u32 ncci, u16 msgid){	capidrv_plci *plcip;	capidrv_ncci *p;	if ((plcip = find_plci_by_ncci(card, ncci)) == 0)		return NULL;	for (p = plcip->ncci_list; p; p = p->next)		if (p->msgid == msgid)			return p;	return NULL;}static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip){	struct capidrv_ncci **pp;	for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {		if (*pp == nccip) {			*pp = (*pp)->next;			break;		}

⌨️ 快捷键说明

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