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

📄 b1capi.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * $Id: b1capi.c,v 1.1.1.1 1999/11/15 13:42:16 vadim Exp $ *  * CAPI 2.0 Module for AVM B1-card. *  * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) *  * $Log: b1capi.c,v $ * Revision 1.1.1.1  1999/11/15 13:42:16  vadim * Initial import * * Revision 1.4.2.19  1998/10/25 14:36:14  fritz * Backported from MIPS (Cobalt). * * Revision 1.4.2.18  1998/03/20 20:34:37  calle * port valid check now only for T1, because of the PCI and PCMCIA cards. * * Revision 1.4.2.17  1998/03/20 14:38:17  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.4.2.16  1998/03/20 09:01:08  calle * Changes capi_register handling to get full support for 30 bchannels. * * Revision 1.4.2.15  1998/03/18 17:43:26  calle * T1 with fastlink, bugfix for multicontroller support in capidrv.c * * Revision 1.4.2.14  1998/03/04 17:33:47  calle * Changes for T1. * * Revision 1.4.2.13  1998/02/27 15:40:41  calle * T1 running with slow link. bugfix in capi_release. * * Revision 1.4.2.12  1998/02/24 17:58:25  calle * changes for T1. * * Revision 1.4.2.11  1998/01/27 16:12:49  calle * Support for PCMCIA B1/M1/M2 ready. * * Revision 1.4.2.10  1998/01/26 14:53:30  calle * interface change for pcmcia cards * * Revision 1.4.2.9  1998/01/23 16:49:27  calle * added functions for pcmcia cards, * avmb1_addcard returns now the controller number. * * Revision 1.4.2.8  1998/01/16 14:04:15  calle * Decoding of manufacturer part of capi_profile, now show linetype and * protocol if possible. * * Revision 1.4.2.7  1998/01/15 15:33:34  calle * print cardtype, d2 protocol and linetype after load. * * Revision 1.4.2.6  1997/12/08 06:58:41  calle * correct typo. * * Revision 1.4.2.5  1997/12/07 19:59:54  calle * more changes for M1/T1/B1 + config * * Revision 1.4.2.4  1997/11/26 16:57:20  calle * more changes for B1/M1/T1. * * Revision 1.4.2.3  1997/11/26 10:46:52  calle * prepared for M1 (Mobile) and T1 (PMX) cards. * prepared to set configuration after load to support other D-channel * protocols, point-to-point and leased lines. * * Revision 1.4.2.2  1997/10/19 14:44:36  calle * fixed capi_get_version. * * Revision 1.4.2.1  1997/07/12 08:18:59  calle * Correct bug in CARD_NR macro, so now more than one card will work. * Allow card reset, even if card is in running state. * * Revision 1.4  1997/05/27 15:17:45  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:09  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:20:41  fritz * Removed include of config.h (mkdep stated this is unneded). * * Revision 1.1  1997/03/04 21:50:27  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/kernel.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <asm/segment.h>#include <linux/skbuff.h>#include <linux/tqueue.h>#include <linux/capi.h>#include <linux/b1lli.h>#include <linux/kernelcapi.h>#include "compat.h"#include "capicmd.h"#include "capiutil.h"static char *revision = "$Revision: 1.1.1.1 $";/* ------------------------------------------------------------- */int showcapimsgs = 0;		/* used in lli.c */int loaddebug = 0;#ifdef HAS_NEW_SYMTABMODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");MODULE_PARM(showcapimsgs, "0-5i");MODULE_PARM(loaddebug, "0-1i");#endif/* ------------------------------------------------------------- */struct msgidqueue {	struct msgidqueue *next;	__u16 msgid;};typedef struct avmb1_ncci {	struct avmb1_ncci *next;	__u16 applid;	__u32 ncci;	__u32 winsize;	struct msgidqueue *msgidqueue;	struct msgidqueue *msgidlast;	struct msgidqueue *msgidfree;	struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];} avmb1_ncci;typedef struct avmb1_appl {	__u16 applid;	capi_register_params rparam;	int releasing;	__u32 param;	void (*signal) (__u16 applid, __u32 param);	struct sk_buff_head recv_queue;	struct avmb1_ncci *nccilist;} avmb1_appl;/* ------------------------------------------------------------- */static struct capi_version driver_version = {2, 0, 1, 1<<4};static char driver_serial[CAPI_SERIAL_LEN] = "4711";static char capi_manufakturer[64] = "AVM Berlin";#define APPL(a)		   (&applications[(a)-1])#define	VALID_APPLID(a)	   ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)#define APPL_IS_FREE(a)    (APPL(a)->applid == 0)#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)#define VALID_CARD(c)	   ((c) > 0 && (c) <= CAPI_MAXCONTR)#define CARD(c)		   (&cards[(c)-1])#define CARDNR(cp)	   (((cp)-cards)+1)static avmb1_appl applications[CAPI_MAXAPPL];static avmb1_card cards[CAPI_MAXCONTR];static int ncards = 0;static struct sk_buff_head recv_queue;static struct capi_interface_user *capi_users = 0;static long notify_up_set = 0;static long notify_down_set = 0;static struct tq_struct tq_state_notify;static struct tq_struct tq_recv_notify;/* -------- util functions ------------------------------------ */static char *cardtype2str(int cardtype){	switch (cardtype) {		default:		case AVM_CARDTYPE_B1: return "B1";		case AVM_CARDTYPE_M1: return "M1";		case AVM_CARDTYPE_M2: return "M2";		case AVM_CARDTYPE_T1: return "T1";	}}static inline int capi_cmd_valid(__u8 cmd){	switch (cmd) {	case CAPI_ALERT:	case CAPI_CONNECT:	case CAPI_CONNECT_ACTIVE:	case CAPI_CONNECT_B3_ACTIVE:	case CAPI_CONNECT_B3:	case CAPI_CONNECT_B3_T90_ACTIVE:	case CAPI_DATA_B3:	case CAPI_DISCONNECT_B3:	case CAPI_DISCONNECT:	case CAPI_FACILITY:	case CAPI_INFO:	case CAPI_LISTEN:	case CAPI_MANUFACTURER:	case CAPI_RESET_B3:	case CAPI_SELECT_B_PROTOCOL:		return 1;	}	return 0;}static inline int capi_subcmd_valid(__u8 subcmd){	switch (subcmd) {	case CAPI_REQ:	case CAPI_CONF:	case CAPI_IND:	case CAPI_RESP:		return 1;	}	return 0;}/* -------- NCCI Handling ------------------------------------- */static inline void mq_init(avmb1_ncci * np){	int i;	np->msgidqueue = 0;	np->msgidlast = 0;	memset(np->msgidpool, 0, sizeof(np->msgidpool));	np->msgidfree = &np->msgidpool[0];	for (i = 1; i < np->winsize; i++) {		np->msgidpool[i].next = np->msgidfree;		np->msgidfree = &np->msgidpool[i];	}}static inline int mq_enqueue(avmb1_ncci * np, __u16 msgid){	struct msgidqueue *mq;	if ((mq = np->msgidfree) == 0)		return 0;	np->msgidfree = mq->next;	mq->msgid = msgid;	mq->next = 0;	if (np->msgidlast)		np->msgidlast->next = mq;	np->msgidlast = mq;	if (!np->msgidqueue)		np->msgidqueue = mq;	return 1;}static inline int mq_dequeue(avmb1_ncci * np, __u16 msgid){	struct msgidqueue **pp;	for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {		if ((*pp)->msgid == msgid) {			struct msgidqueue *mq = *pp;			*pp = mq->next;			if (mq == np->msgidlast)				np->msgidlast = 0;			mq->next = np->msgidfree;			np->msgidfree = mq;			return 1;		}	}	return 0;}void avmb1_handle_new_ncci(avmb1_card * card,			   __u16 appl, __u32 ncci, __u32 winsize){	avmb1_ncci *np;	if (!VALID_APPLID(appl)) {		printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);		return;	}	if ((np = (avmb1_ncci *) kmalloc(sizeof(avmb1_ncci), GFP_ATOMIC)) == 0) {		printk(KERN_ERR "avmb1_handle_new_ncci: alloc failed ncci 0x%x\n", ncci);		return;	}	if (winsize > CAPI_MAXDATAWINDOW) {		printk(KERN_ERR "avmb1_handle_new_ncci: winsize %d too big, set to %d\n",		       winsize, CAPI_MAXDATAWINDOW);		winsize = CAPI_MAXDATAWINDOW;	}	np->applid = appl;	np->ncci = ncci;	np->winsize = winsize;	mq_init(np);	np->next = APPL(appl)->nccilist;	APPL(appl)->nccilist = np;	printk(KERN_INFO "b1capi: appl %d ncci 0x%x up\n", appl, ncci);}void avmb1_handle_free_ncci(avmb1_card * card,			    __u16 appl, __u32 ncci){	if (!VALID_APPLID(appl)) {		printk(KERN_ERR "avmb1_handle_free_ncci: illegal appl %d\n", appl);		return;	}	if (ncci != 0xffffffff) {		avmb1_ncci **pp;		for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {			if ((*pp)->ncci == ncci) {				avmb1_ncci *np = *pp;				*pp = np->next;				kfree(np);				printk(KERN_INFO "b1capi: appl %d ncci 0x%x down\n", appl, ncci);				return;			}		}		printk(KERN_ERR "avmb1_handle_free_ncci: ncci 0x%x not found\n", ncci);	} else {		avmb1_ncci **pp, **nextpp;		for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {			if (NCCI2CTRL((*pp)->ncci) == card->cnr) {				avmb1_ncci *np = *pp;				*pp = np->next;				printk(KERN_INFO "b1capi: appl %d ncci 0x%x down!\n", appl, np->ncci);				kfree(np);				nextpp = pp;			} else {				nextpp = &(*pp)->next;			}		}		APPL(appl)->releasing--;		if (APPL(appl)->releasing <= 0) {	                APPL(appl)->signal = 0;			APPL_MARK_FREE(appl);			printk(KERN_INFO "b1capi: appl %d down\n", appl);		}	}}static avmb1_ncci *find_ncci(avmb1_appl * app, __u32 ncci){	avmb1_ncci *np;	for (np = app->nccilist; np; np = np->next) {		if (np->ncci == ncci)			return np;	}	return 0;}/* -------- Receiver ------------------------------------------ */static void recv_handler(void *dummy){	struct sk_buff *skb;	while ((skb = skb_dequeue(&recv_queue)) != 0) {		__u16 appl = CAPIMSG_APPID(skb->data);		struct avmb1_ncci *np;		if (!VALID_APPLID(appl)) {			printk(KERN_ERR "b1capi: recv_handler: applid %d ? (%s)\n",			       appl, capi_message2str(skb->data));			kfree_skb(skb, FREE_READ);			continue;		}		if (APPL(appl)->signal == 0) {			printk(KERN_ERR "b1capi: recv_handler: applid %d has no signal function\n",			       appl);			kfree_skb(skb, FREE_READ);			continue;		}		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF	            && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0		    && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {			printk(KERN_ERR "b1capi: msgid %hu ncci 0x%x not on queue\n",				CAPIMSG_MSGID(skb->data), np->ncci);		}		skb_queue_tail(&APPL(appl)->recv_queue, skb);		(APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);	}}void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb){	if (card->cardstate != CARD_RUNNING) {		printk(KERN_INFO "b1capi: controller %d not active, got: %s",		       card->cnr, capi_message2str(skb->data));		goto error;		return;	}	skb_queue_tail(&recv_queue, skb);	queue_task(&tq_recv_notify, &tq_immediate);	mark_bh(IMMEDIATE_BH);	return;      error:	kfree_skb(skb, FREE_READ);}void avmb1_interrupt(int interrupt, void *devptr, struct pt_regs *regs){	avmb1_card *card;	card = (avmb1_card *) devptr;	if (!card) {		printk(KERN_WARNING "avmb1_interrupt: wrong device\n");		return;	}	if (card->interrupt) {		printk(KERN_ERR "avmb1_interrupt: reentering interrupt hander\n");		return;

⌨️ 快捷键说明

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