📄 isdnl1.c
字号:
/* $Id: isdnl1.c,v 1.1.1.1 1999/11/15 13:42:18 vadim 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 * * * $Log: isdnl1.c,v $ * Revision 1.1.1.1 1999/11/15 13:42:18 vadim * Initial import * * Revision 1.15.2.19 1998/11/03 00:06:48 keil * certification related changes * fixed logging for smaller stack use * * Revision 1.15.2.18 1998/09/30 22:26:35 keil * Add init of l1.Flags * * Revision 1.15.2.17 1998/09/27 23:54:17 keil * cosmetics * * Revision 1.15.2.16 1998/09/27 13:06:22 keil * Apply most changes from 2.1.X (HiSax 3.1) * * Revision 1.15.2.15 1998/09/12 18:44:00 niemann * Added new card: Sedlbauer ISDN-Controller PC/104 * * Revision 1.15.2.14 1998/08/25 14:01:35 calle * Ported driver for AVM Fritz!Card PCI from the 2.1 tree. * I could not test it. * * Revision 1.15.2.13 1998/07/15 14:43:37 calle * Support for AVM passive PCMCIA cards: * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 * * Revision 1.15.2.12 1998/05/27 18:05:43 keil * HiSax 3.0 * * Revision 1.15.2.11 1998/05/26 10:36:51 keil * fixes from certification * * Revision 1.15.2.10 1998/04/11 18:47:45 keil * Fixed bug which was overwriting nrcards * New card support * * Revision 1.15.2.9 1998/04/08 21:52:00 keil * new debug * * Revision 1.15.2.8 1998/03/07 23:15:26 tsbogend * made HiSax working on Linux/Alpha * * Revision 1.15.2.7 1998/02/11 14:23:14 keil * support for Dr Neuhaus Niccy PnP and PCI * * Revision 1.15.2.6 1998/02/09 11:24:11 keil * New leased line support (Read README.HiSax!) * * Revision 1.15.2.5 1998/01/27 22:33:55 keil * dynalink ----> asuscom * * Revision 1.15.2.4 1998/01/11 22:55:20 keil * 16.3c support * * Revision 1.15.2.3 1997/11/15 18:50:34 keil * new common init function * * Revision 1.15.2.2 1997/10/17 22:13:54 keil * update to last hisax version * * Revision 2.6 1997/09/12 10:05:16 keil * ISDN_CTRL_DEBUG define * * Revision 2.5 1997/09/11 17:24:45 keil * Add new cards * * Revision 2.4 1997/08/15 17:47:09 keil * avoid oops because a uninitialised timer * * Revision 2.3 1997/08/01 11:16:40 keil * cosmetics * * Revision 2.2 1997/07/30 17:11:08 keil * L1deactivated exported * * Revision 2.1 1997/07/27 21:35:38 keil * new layer1 interface * * Revision 2.0 1997/06/26 11:02:53 keil * New Layer and card interface * * Revision 1.15 1997/05/27 15:17:55 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. * * old changes removed KKe * */const char *l1_revision = "$Revision: 1.1.1.1 $";#define __NO_VERSION__#include <linux/config.h>#include "hisax.h"#include "isdnl1.h"#define TIMER3_VALUE 7000staticstruct Fsm l1fsm_b ={NULL, 0, 0, NULL, NULL};staticstruct Fsm l1fsm_d ={NULL, 0, 0, NULL, NULL};enum { ST_L1_F2, ST_L1_F3, ST_L1_F4, ST_L1_F5, ST_L1_F6, ST_L1_F7, ST_L1_F8,};#define L1D_STATE_COUNT (ST_L1_F8+1)static char *strL1DState[] ={ "ST_L1_F2", "ST_L1_F3", "ST_L1_F4", "ST_L1_F5", "ST_L1_F6", "ST_L1_F7", "ST_L1_F8",};enum { 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; 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, FREE_READ); } 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, FREE_READ); } }}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); }}static 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.next = 0; 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";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -