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

📄 capidrv.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: capidrv.c,v 1.1.1.1 1999/11/15 13:42:17 vadim Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ * Revision 1.1.1.1  1999/11/15 13:42:17  vadim * Initial import * * Revision 1.3.2.12  1998/09/11 15:37:11  calle * Started with support for CAPI channel allocation/bundling. * * Revision 1.3.2.11  1998/04/02 10:27:59  calle * version check for D2 trace was wrong :-( * * Revision 1.3.2.10  1998/03/20 14:38:24  calle * capidrv: prepared state machines for suspend/resume/hold * capidrv: fix bug in state machine if B1/T1 is out of nccis * b1capi: changed some errno returns. * b1capi: detect if you try to add same T1 to different io address. * b1capi: change number of nccis depending on number of channels. * b1lli: cosmetics * * Revision 1.3.2.9  1998/03/20 09:01:12  calle * Changes capi_register handling to get full support for 30 bchannels. * * Revision 1.3.2.8  1998/03/18 17:51:28  calle * added controller number to error messages * * Revision 1.3.2.7  1998/02/27 15:40:47  calle * T1 running with slow link. bugfix in capi_release. * * Revision 1.3.2.6  1998/02/02 19:51:13  calle * Fixed vbox (audio) acceptb. * * Revision 1.3.2.5  1997/10/29 09:35:29  calle * correct byteorder problem with new isdnlog interface. * * Revision 1.3.2.4  1997/10/26 15:04:24  calle * prepared isdnlog interface for d2-trace in newer firmware. * * Revision 1.3.2.3  1997/10/24 06:37:00  calle * changed LISTEN cipmask, now we can distinguish voice, fax und data calls. * * Revision 1.3.2.2  1997/10/08 05:42:25  calle * Added isdnlog support. patch to isdnlog needed. * * Revision 1.3.2.1  1997/07/13 12:16:48  calle * bug fix for more than one controller in connect_req. * * Revision 1.3  1997/05/18 09:24:15  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:19:59  fritz * Removed include of config.h (mkdep stated this is unneded). * * Revision 1.1  1997/03/04 21:50:31  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/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/timer.h>#include <linux/wait.h>#include <linux/skbuff.h>#include <linux/isdn.h>#include <linux/isdnif.h>#include <linux/capi.h>#include <linux/kernelcapi.h>#include <linux/ctype.h>#include "compat.h"#include "capiutil.h"#include "capicmd.h"#include "capidrv.h"static char *revision = "$Revision: 1.1.1.1 $";int debugmode = 0;#ifdef HAS_NEW_SYMTABMODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");MODULE_PARM(debugmode, "i");#endif/* -------- type definitions ----------------------------------------- */struct capidrv_contr {	struct capidrv_contr *next;	__u32 contrnr;	char name[20];	/*	 * for isdn4linux	 */	isdn_if interface;	int myid;	/*	 * LISTEN state	 */	int state;	__u32 cipmask;	__u32 cipmask2;	/*	 * 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;			} *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 {	__u16 appid;	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 struct capi_interface *capifuncs;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;	}}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:		return 1;	}}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:	default:		return 0;	}}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 managment ------------------------------------- */static inline capidrv_contr *findcontrbydriverid(int driverid){	capidrv_contr *p = global.contr_list;	while (p) {		if (p->myid == driverid)			return p;		p = p->next;	}	return (capidrv_contr *) 0;}static capidrv_contr *findcontrbynumber(__u32 contr){	capidrv_contr *p = global.contr_list;	while (p) {		if (p->contrnr == contr)			return p;		p = p->next;	}	return (capidrv_contr *) 0;}/* -------- 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 0;	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 0;}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 0;}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 0;}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 = 0;			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 0;	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 0;	for (p = plcip->ncci_list; p; p = p->next)		if (p->ncci == ncci)			return p;	return 0;}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 0;	for (p = plcip->ncci_list; p; p = p->next)		if (p->msgid == msgid)			return p;	return 0;}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;		}	}	card->bchans[nccip->chan].nccip = 0;	kfree(nccip);}/* -------- convert and send capi message ---------------------------- */static void send_message(capidrv_contr * card, _cmsg * cmsg){	struct sk_buff *skb;	size_t len;	capi_cmsg2message(cmsg, cmsg->buf);	len = CAPIMSG_LEN(cmsg->buf);	skb = dev_alloc_skb(len);        SET_SKB_FREE(skb);	memcpy(skb_put(skb, len), cmsg->buf, len);	(*capifuncs->capi_put_message) (global.appid, skb);}/* -------- state machine -------------------------------------------- */struct listenstatechange {	int actstate;	int nextstate;	int event;};static struct listenstatechange listentable[] ={  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},  {},};static void listen_change_state(capidrv_contr * card, int event){	struct listenstatechange *p = listentable;	while (p->event) {		if (card->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",				       card->contrnr, card->state, p->nextstate);			card->state = p->nextstate;			return;		}		p++;	}	printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",	       card->contrnr, card->state, event);}/* ------------------------------------------------------------------ */static void p0(capidrv_contr * card, capidrv_plci * plci){	isdn_ctrl cmd;	card->bchans[plci->chan].contr = 0;	cmd.command = ISDN_STAT_DHUP;	cmd.driver = card->myid;	cmd.arg = plci->chan;	card->interface.statcallb(&cmd);	free_plci(card, plci);}/* ------------------------------------------------------------------ */struct plcistatechange {	int actstate;	int nextstate;	int event;	void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);};

⌨️ 快捷键说明

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