📄 isdnl2.c
字号:
/* $Id: isdnl2.c,v 1.1.1.1 1999/11/15 13:42:18 vadim Exp $ * Author Karsten Keil (keil@temic-ech.spacenet.de) * based on the teles driver from Jan den Ouden * * 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 * * $Log: isdnl2.c,v $ * Revision 1.1.1.1 1999/11/15 13:42:18 vadim * Initial import * * Revision 1.10.2.11 1998/11/03 00:06:57 keil * certification related changes * fixed logging for smaller stack use * * Revision 1.10.2.10 1998/09/27 13:06:30 keil * Apply most changes from 2.1.X (HiSax 3.1) * * Revision 1.10.2.9 1998/06/19 15:17:56 keil * fix LAPB tx_cnt for none I-frames * * Revision 1.10.2.8 1998/06/18 23:12:05 keil * LAPB bugfix * * Revision 1.10.2.7 1998/05/27 18:05:51 keil * HiSax 3.0 * * Revision 1.10.2.6 1998/05/26 10:36:57 keil * fixes from certification * * Revision 1.10.2.5 1998/03/07 23:15:31 tsbogend * made HiSax working on Linux/Alpha * * Revision 1.10.2.4 1998/01/27 22:44:38 keil * fixed window size calculation * * Revision 1.10.2.3 1997/11/15 18:54:03 keil * cosmetics * * Revision 1.10.2.2 1997/10/17 22:13:59 keil * update to last hisax version * * Revision 2.2 1997/07/31 11:49:05 keil * Eroor handling for no TEI assign * * Revision 2.1 1997/07/27 21:34:38 keil * cosmetics * * Revision 2.0 1997/06/26 11:07:29 keil * New q.921 and X.75 Layer2 * * * Old log removed KKe * */#define __NO_VERSION__#include "hisax.h"#include "isdnl2.h"const char *l2_revision = "$Revision: 1.1.1.1 $";static void l2m_debug(struct FsmInst *fi, char *fmt, ...);staticstruct Fsm l2fsm ={NULL, 0, 0, NULL, NULL};enum { ST_L2_1, ST_L2_2, ST_L2_3, ST_L2_4, ST_L2_5, ST_L2_6, ST_L2_7, ST_L2_8,};#define L2_STATE_COUNT (ST_L2_8+1)static char *strL2State[] ={ "ST_L2_1", "ST_L2_2", "ST_L2_3", "ST_L2_4", "ST_L2_5", "ST_L2_6", "ST_L2_7", "ST_L2_8",};enum { EV_L2_UI, EV_L2_SABMX, EV_L2_DISC, EV_L2_DM, EV_L2_UA, EV_L2_FRMR, EV_L2_SUPER, EV_L2_I, EV_L2_DL_DATA, EV_L2_ACK_PULL, EV_L2_DL_UNIT_DATA, EV_L2_DL_ESTABLISH, EV_L2_DL_RELEASE, EV_L2_MDL_ASSIGN, EV_L2_MDL_REMOVE, EV_L2_MDL_ERROR, EV_L1_DEACTIVATE, EV_L2_T200, EV_L2_T203,};#define L2_EVENT_COUNT (EV_L2_T203+1)static char *strL2Event[] ={ "EV_L2_UI", "EV_L2_SABMX", "EV_L2_DISC", "EV_L2_DM", "EV_L2_UA", "EV_L2_FRMR", "EV_L2_SUPER", "EV_L2_I", "EV_L2_DL_DATA", "EV_L2_ACK_PULL", "EV_L2_DL_UNIT_DATA", "EV_L2_DL_ESTABLISH", "EV_L2_DL_RELEASE", "EV_L2_MDL_ASSIGN", "EV_L2_MDL_REMOVE", "EV_L2_MDL_ERROR", "EV_L1_DEACTIVATE", "EV_L2_T200", "EV_L2_T203",};static int l2addrsize(struct Layer2 *l2);static voidInitWin(struct Layer2 *l2){ int i; for (i = 0; i < MAX_WINDOW; i++) l2->windowar[i] = NULL;}static voidReleaseWin(struct Layer2 *l2){ int i, cnt = 0; for (i = 0; i < MAX_WINDOW; i++) { if (l2->windowar[i]) { cnt++; dev_kfree_skb(l2->windowar[i], FREE_WRITE); l2->windowar[i] = NULL; } } if (cnt) printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);}inline intcansend(struct PStack *st){ int p1; p1 = st->l2.vs - st->l2.va; if (p1 < 0) p1 += (test_bit(FLG_MOD128, &st->l2.flag) ? 128 : 8); return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));}inline voidclear_exception(struct Layer2 *l2){ test_and_clear_bit(FLG_ACK_PEND, &l2->flag); test_and_clear_bit(FLG_REJEXC, &l2->flag); test_and_clear_bit(FLG_OWN_BUSY, &l2->flag); test_and_clear_bit(FLG_PEER_BUSY, &l2->flag);}inline intl2headersize(struct Layer2 *l2, int ui){ return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));}inline intl2addrsize(struct Layer2 *l2){ return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);}static intsethdraddr(struct Layer2 *l2, u_char * header, int rsp){ u_char *ptr = header; int crbit = rsp; if (test_bit(FLG_LAPD, &l2->flag)) { *ptr++ = (l2->sap << 2) | (rsp ? 2 : 0); *ptr++ = (l2->tei << 1) | 1; return (2); } else { if (test_bit(FLG_ORIG, &l2->flag)) crbit = !crbit; if (crbit) *ptr++ = 1; else *ptr++ = 3; return (1); }}inline static voidenqueue_super(struct PStack *st, struct sk_buff *skb){ if (test_bit(FLG_LAPB, &st->l2.flag)) st->l1.bcs->tx_cnt += skb->len; st->l2.l2l1(st, PH_DATA | REQUEST, skb);}#define enqueue_ui(a, b) enqueue_super(a, b)inline intIsUI(u_char * data, int ext){ return ((data[0] & 0xef) == UI);}inline intIsUA(u_char * data, int ext){ return ((data[0] & 0xef) == UA);}inline intIsDM(u_char * data, int ext){ return ((data[0] & 0xef) == DM);}inline intIsDISC(u_char * data, int ext){ return ((data[0] & 0xef) == DISC);}inline intIsRR(u_char * data, int ext){ if (ext) return (data[0] == RR); else return ((data[0] & 0xf) == 1);}inline intIsSFrame(u_char * data, int ext){ register u_char d = *data; if (!ext) d &= 0xf; return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));}inline intIsSABMX(u_char * data, int ext){ u_char d = data[0] & ~0x10; return (ext ? d == SABME : d == SABM);}inline intIsREJ(u_char * data, int ext){ return (ext ? data[0] == REJ : (data[0] & 0xf) == REJ);}inline intIsFRMR(u_char * data, int ext){ return ((data[0] & 0xef) == FRMR);}inline intIsRNR(u_char * data, int ext){ return (ext ? data[0] == RNR : (data[0] & 0xf) == RNR);}static intlegalnr(struct PStack *st, int nr){ struct Layer2 *l2 = &st->l2; int lnr, lvs; lvs = (l2->vs >= l2->va) ? l2->vs : (l2->vs + (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8)); lnr = (nr >= l2->va) ? nr : (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); return (lnr <= lvs);}static voidsetva(struct PStack *st, int nr){ struct Layer2 *l2 = &st->l2; int len; while (l2->va != nr) { l2->va = (l2->va + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); len = l2->windowar[l2->sow]->len; if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) len = -1; dev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE); l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; if (st->lli.l2writewakeup && (len >=0)) st->lli.l2writewakeup(st, len); }}static voidsend_uframe(struct PStack *st, u_char cmd, u_char cr){ struct sk_buff *skb; u_char tmp[MAX_HEADER_LEN]; int i; i = sethdraddr(&st->l2, tmp, cr); tmp[i++] = cmd; if (!(skb = alloc_skb(i, GFP_ATOMIC))) { printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n"); return; } SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb);}inline u_charget_PollFlag(struct PStack * st, struct sk_buff * skb){ return (skb->data[l2addrsize(&(st->l2))] & 0x10);}inline voidFreeSkb(struct sk_buff *skb){ dev_kfree_skb(skb, FREE_READ);}inline u_charget_PollFlagFree(struct PStack *st, struct sk_buff *skb){ u_char PF; PF = get_PollFlag(st, skb); FreeSkb(skb); return (PF);}static voidestablishlink(struct FsmInst *fi){ struct PStack *st = fi->userdata; u_char cmd; clear_exception(&st->l2); st->l2.rc = 0; cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10; send_uframe(st, cmd, CMD); FsmDelTimer(&st->l2.t203, 1); FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 1); test_and_set_bit(FLG_T200_RUN, &st->l2.flag); FsmChangeState(fi, ST_L2_5);}static voidl2_mdl_error(struct FsmInst *fi, int event, void *arg){ struct sk_buff *skb = arg; struct PStack *st = fi->userdata; switch (event) { case EV_L2_UA: if (get_PollFlagFree(st, skb)) st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C'); else st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D'); break; case EV_L2_DM: if (get_PollFlagFree(st, skb)) st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B'); else { st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E'); establishlink(fi); test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } break; }}static voidl2_dl_establish(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; int state = fi->state; if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) { FsmChangeState(fi, ST_L2_4); establishlink(fi); test_and_set_bit(FLG_L3_INIT, &st->l2.flag); } else { FsmChangeState(fi, ST_L2_3); if (state == ST_L2_1) st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL); }}static voidl2_send_ui(struct PStack *st){ struct sk_buff *skb; u_char header[MAX_HEADER_LEN]; int i; i = sethdraddr(&(st->l2), header, CMD); header[i++] = UI; while ((skb = skb_dequeue(&st->l2.ui_queue))) { memcpy(skb_push(skb, i), header, i); enqueue_ui(st, skb); }}static voidl2_put_ui(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; skb_queue_tail(&st->l2.ui_queue, skb); if (fi->state == ST_L2_1) { FsmChangeState(fi, ST_L2_2); st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL); } if (fi->state > ST_L2_3) l2_send_ui(st);}static voidl2_got_ui(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; skb_pull(skb, l2headersize(&st->l2, 1)); if (skb->len > st->l2.maxlen) { st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O'); FreeSkb(skb); } else st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);}static voidl2_establish(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; if (fi->state != ST_L2_4) discard_queue(&st->l2.i_queue); if (fi->state != ST_L2_5) establishlink(fi); test_and_set_bit(FLG_L3_INIT, &st->l2.flag);}static voidl2_dl_release(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; if (fi->state == ST_L2_4) { st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); return; } else if (fi->state == ST_L2_5) { test_and_set_bit(FLG_PEND_REL, &st->l2.flag); return; } discard_queue(&st->l2.i_queue); FsmChangeState(fi, ST_L2_6); st->l2.rc = 0; send_uframe(st, DISC | 0x10, CMD); FsmDelTimer(&st->l2.t203, 1); FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 2); test_and_set_bit(FLG_T200_RUN, &st->l2.flag);}static voidl2_got_SABMX(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; int est = 1, state, rsp; u_char PollFlag; state = fi->state; rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &st->l2.flag)) rsp = !rsp; if (rsp) { st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L'); FreeSkb(skb); if ((state == ST_L2_7) || (state == ST_L2_8)) establishlink(fi); return; } if (skb->len != (l2addrsize(&st->l2) + 1)) { st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N'); FreeSkb(skb); if ((state == ST_L2_7) || (state == ST_L2_8)) establishlink(fi); return; } PollFlag = get_PollFlagFree(st, skb); if (ST_L2_6 == state) { send_uframe(st, DM | PollFlag, RSP); return; } else send_uframe(st, UA | PollFlag, RSP); if (ST_L2_5 == state) return; if (ST_L2_4 != state) { st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F'); if (st->l2.vs != st->l2.va) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -