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

📄 isdnl1.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: isdnl1.c,v 2.41.6.1 2000/12/10 22:01:04 kai Exp $ * * isdnl1.c     common low level stuff for Siemens Chipsetbased isdn cards *              based on the teles driver from Jan den Ouden * * Author       Karsten Keil (keil@isdn4linux.de) * *		This file is (c) under GNU PUBLIC LICENSE *		For changes and modifications please read *		../../../Documentation/isdn/HiSax.cert * * Thanks to    Jan den Ouden *              Fritz Elfert *              Beat Doebeli * */const char *l1_revision = "$Revision: 2.41.6.1 $";#define __NO_VERSION__#include <linux/init.h>#include "hisax.h"#include "isdnl1.h"#define TIMER3_VALUE 7000static struct Fsm l1fsm_b;static struct Fsm l1fsm_s;enum {	ST_L1_F2,	ST_L1_F3,	ST_L1_F4,	ST_L1_F5,	ST_L1_F6,	ST_L1_F7,	ST_L1_F8,};#define L1S_STATE_COUNT (ST_L1_F8+1)static char *strL1SState[] ={	"ST_L1_F2",	"ST_L1_F3",	"ST_L1_F4",	"ST_L1_F5",	"ST_L1_F6",	"ST_L1_F7",	"ST_L1_F8",};#ifdef HISAX_UINTERFACEstaticstruct Fsm l1fsm_u ={NULL, 0, 0, NULL, NULL};enum {	ST_L1_RESET,	ST_L1_DEACT,	ST_L1_SYNC2,	ST_L1_TRANS,};#define L1U_STATE_COUNT (ST_L1_TRANS+1)static char *strL1UState[] ={	"ST_L1_RESET",	"ST_L1_DEACT",	"ST_L1_SYNC2",	"ST_L1_TRANS",};#endifenum {	ST_L1_NULL,	ST_L1_WAIT_ACT,	ST_L1_WAIT_DEACT,	ST_L1_ACTIV,};#define L1B_STATE_COUNT (ST_L1_ACTIV+1)static char *strL1BState[] ={	"ST_L1_NULL",	"ST_L1_WAIT_ACT",	"ST_L1_WAIT_DEACT",	"ST_L1_ACTIV",};enum {	EV_PH_ACTIVATE,	EV_PH_DEACTIVATE,	EV_RESET_IND,	EV_DEACT_CNF,	EV_DEACT_IND,	EV_POWER_UP,	EV_RSYNC_IND, 	EV_INFO2_IND,	EV_INFO4_IND,	EV_TIMER_DEACT,	EV_TIMER_ACT,	EV_TIMER3,};#define L1_EVENT_COUNT (EV_TIMER3 + 1)static char *strL1Event[] ={	"EV_PH_ACTIVATE",	"EV_PH_DEACTIVATE",	"EV_RESET_IND",	"EV_DEACT_CNF",	"EV_DEACT_IND",	"EV_POWER_UP",	"EV_RSYNC_IND", 	"EV_INFO2_IND",	"EV_INFO4_IND",	"EV_TIMER_DEACT",	"EV_TIMER_ACT",	"EV_TIMER3",};voiddebugl1(struct IsdnCardState *cs, char *fmt, ...){	va_list args;	char tmp[8];		va_start(args, fmt);	sprintf(tmp, "Card%d ", cs->cardnr + 1);	VHiSax_putstatus(cs, tmp, fmt, args);	va_end(args);}static voidl1m_debug(struct FsmInst *fi, char *fmt, ...){	va_list args;	struct PStack *st = fi->userdata;	struct IsdnCardState *cs = st->l1.hardware;	char tmp[8];		va_start(args, fmt);	sprintf(tmp, "Card%d ", cs->cardnr + 1);	VHiSax_putstatus(cs, tmp, fmt, args);	va_end(args);}voidL1activated(struct IsdnCardState *cs){	struct PStack *st;	st = cs->stlist;	while (st) {		if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);		else			st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL);		st = st->next;	}}voidL1deactivated(struct IsdnCardState *cs){	struct PStack *st;	st = cs->stlist;	while (st) {		if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags))			st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);		st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL);		st = st->next;	}	test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);}voidDChannel_proc_xmt(struct IsdnCardState *cs){	struct PStack *stptr;	if (cs->tx_skb)		return;	stptr = cs->stlist;	while (stptr != NULL)		if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) {			stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL);			break;		} else			stptr = stptr->next;}voidDChannel_proc_rcv(struct IsdnCardState *cs){	struct sk_buff *skb, *nskb;	struct PStack *stptr = cs->stlist;	int found, tei, sapi;	if (stptr)		if (test_bit(FLG_L1_ACTTIMER, &stptr->l1.Flags))			FsmEvent(&stptr->l1.l1m, EV_TIMER_ACT, NULL);		while ((skb = skb_dequeue(&cs->rq))) {#ifdef L2FRAME_DEBUG		/* psa */		if (cs->debug & L1_DEB_LAPD)			Logl2Frame(cs, skb, "PH_DATA", 1);#endif		stptr = cs->stlist;		if (skb->len<3) {			debugl1(cs, "D-channel frame too short(%d)",skb->len);			dev_kfree_skb(skb);			return;		}		if ((skb->data[0] & 1) || !(skb->data[1] &1)) {			debugl1(cs, "D-channel frame wrong EA0/EA1");			dev_kfree_skb(skb);			return;		}		sapi = skb->data[0] >> 2;		tei = skb->data[1] >> 1;		if (cs->debug & DEB_DLOG_HEX)			LogFrame(cs, skb->data, skb->len);		if (cs->debug & DEB_DLOG_VERBOSE)			dlogframe(cs, skb, 1);		if (tei == GROUP_TEI) {			if (sapi == CTRL_SAPI) { /* sapi 0 */				while (stptr != NULL) {					if ((nskb = skb_clone(skb, GFP_ATOMIC)))						stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb);					else						printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n");					stptr = stptr->next;				}			} else if (sapi == TEI_SAPI) {				while (stptr != NULL) {					if ((nskb = skb_clone(skb, GFP_ATOMIC)))						stptr->l1.l1tei(stptr, PH_DATA | INDICATION, nskb);					else						printk(KERN_WARNING "HiSax: tei broadcast buffer shortage\n");					stptr = stptr->next;				}			}			dev_kfree_skb(skb);		} else if (sapi == CTRL_SAPI) { /* sapi 0 */			found = 0;			while (stptr != NULL)				if (tei == stptr->l2.tei) {					stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb);					found = !0;					break;				} else					stptr = stptr->next;			if (!found)				dev_kfree_skb(skb);		} else			dev_kfree_skb(skb);	}}static voidBChannel_proc_xmt(struct BCState *bcs){	struct PStack *st = bcs->st;	if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {		debugl1(bcs->cs, "BC_BUSY Error");		return;	}	if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))		st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);	if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {		if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) {			st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);		}	}}static voidBChannel_proc_rcv(struct BCState *bcs){	struct sk_buff *skb;	if (bcs->st->l1.l1m.state == ST_L1_WAIT_ACT) {		FsmDelTimer(&bcs->st->l1.timer, 4);		FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL);	}	while ((skb = skb_dequeue(&bcs->rqueue))) {		bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb);	}}voidBChannel_bh(struct BCState *bcs){	if (!bcs)		return;	if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event))		BChannel_proc_rcv(bcs);	if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event))		BChannel_proc_xmt(bcs);}voidHiSax_addlist(struct IsdnCardState *cs,	      struct PStack *st){	st->next = cs->stlist;	cs->stlist = st;}voidHiSax_rmlist(struct IsdnCardState *cs,	     struct PStack *st){	struct PStack *p;	FsmDelTimer(&st->l1.timer, 0);	if (cs->stlist == st)		cs->stlist = st->next;	else {		p = cs->stlist;		while (p)			if (p->next == st) {				p->next = st->next;				return;			} else				p = p->next;	}}voidinit_bcstate(struct IsdnCardState *cs,	     int bc){	struct BCState *bcs = cs->bcs + bc;	bcs->cs = cs;	bcs->channel = bc;	bcs->tqueue.sync = 0;	bcs->tqueue.routine = (void *) (void *) BChannel_bh;	bcs->tqueue.data = bcs;	bcs->BC_SetStack = NULL;	bcs->BC_Close = NULL;	bcs->Flag = 0;}#ifdef L2FRAME_DEBUG		/* psa */char *l2cmd(u_char cmd){	switch (cmd & ~0x10) {		case 1:			return "RR";		case 5:			return "RNR";		case 9:			return "REJ";		case 0x6f:			return "SABME";		case 0x0f:			return "DM";		case 3:			return "UI";		case 0x43:			return "DISC";		case 0x63:			return "UA";		case 0x87:			return "FRMR";		case 0xaf:			return "XID";		default:			if (!(cmd & 1))				return "I";			else				return "invalid command";	}}static char tmpdeb[32];char *l2frames(u_char * ptr){	switch (ptr[2] & ~0x10) {		case 1:		case 5:		case 9:			sprintf(tmpdeb, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);			break;		case 0x6f:		case 0x0f:		case 3:		case 0x43:		case 0x63:		case 0x87:		case 0xaf:			sprintf(tmpdeb, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);			break;		default:			if (!(ptr[2] & 1)) {				sprintf(tmpdeb, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);				break;			} else				return "invalid command";	}	return tmpdeb;}voidLogl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir){	u_char *ptr;	ptr = skb->data;	if (ptr[0] & 1 || !(ptr[1] & 1))		debugl1(cs, "Address not LAPD");	else		debugl1(cs, "%s %s: %s%c (sapi %d, tei %d)",			(dir ? "<-" : "->"), buf, l2frames(ptr),			((ptr[0] & 2) >> 1) == dir ? 'C' : 'R', ptr[0] >> 2, ptr[1] >> 1);}#endifstatic voidl1_reset(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F3);}static voidl1_deact_cnf(struct FsmInst *fi, int event, void *arg){	struct PStack *st = fi->userdata;	FsmChangeState(fi, ST_L1_F3);	if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags))		st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);}

⌨️ 快捷键说明

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