diff options
author | David S. Miller <davem@davemloft.net> | 2019-06-02 17:48:58 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-02 17:48:58 -0700 |
commit | 8a7e8ff8ce8ae7d34ed979f41b572bfe7cab421c (patch) | |
tree | 7084e209ef4e21a9b92075cf445a617ecf190ee7 /drivers/isdn/hisax/isdnl2.c | |
parent | 57f0410279096095e013b08b5e8e44d0ea2098d6 (diff) | |
parent | 6d97985072dc270032dc7a08631080bfd6253e82 (diff) | |
download | linux-8a7e8ff8ce8ae7d34ed979f41b572bfe7cab421c.tar.gz |
Merge tag 'isdn-removal' of https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground
Arnd Bergmann says:
====================
isdn: deprecate non-mISDN drivers
When isdn4linux came up in the context of another patch series, I
remembered that we had discussed removing it a while ago.
It turns out that the suggestion from Karsten Keil wa to remove I4L
in 2018 after the last public ISDN networks are shut down. This has
happened now (with a very small number of exceptions), so I guess it's
time to try again.
We currently have three ISDN stacks in the kernel: the original
isdn4linux (with the hisax driver), the newer CAPI (with four drivers),
and finally the mISDN stack (supporting roughly the same hardware as
hisax).
As far as I can tell, anyone using ISDN with mainline kernel drivers in
the past few years uses mISDN, and this is typically used for voice-only
PBX installations that don't require a public network.
The older stacks support additional features for data networks, but those
typically make no sense any more if there is no network to connect to.
My proposal for this time is to kill off isdn4linux entirely, as it seems
to have been unusable for quite a while. This code has been abandoned
for many years and it does cause problems for treewide maintenance as
it tends to do everything that we try to stop doing.
Birger Harzenetter mentioned that is is still using i4l in order to
make use of the 'divert' feature that is not part of mISDN, but has
otherwise moved on to mISDN for normal operation, like apparently
everyone else.
CAPI in turn is not quite as obsolete, but two of the drivers (avm
and hysdn) don't seem to be used at all, while another one (gigaset)
will stop being maintained as Paul Bolle is no longer able to
test it after the network gets shut down in September.
All three are now moved into drivers/staging to let others speak
up in case there are remaining users.
This leaves Bluetooth CMTP as the only remaining user of CAPI, but
Marcel Holtmann wishes to keep maintaining it.
For the discussion on version 1, see [2]
Unfortunately, Karsten Keil as the maintainer has not participated in
the discussion.
Arnd
[1] https://patchwork.kernel.org/patch/8484861/#17900371
[2] https://listserv.isdn4linux.de/pipermail/isdn4linux/2019-April/thread.html
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/hisax/isdnl2.c')
-rw-r--r-- | drivers/isdn/hisax/isdnl2.c | 1839 |
1 files changed, 0 insertions, 1839 deletions
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c deleted file mode 100644 index 1a40ed04cb52..000000000000 --- a/drivers/isdn/hisax/isdnl2.c +++ /dev/null @@ -1,1839 +0,0 @@ -/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 keil Exp $ - * - * Author Karsten Keil - * based on the teles driver from Jan den Ouden - * Copyright by Karsten Keil <keil@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * For changes and modifications please read - * Documentation/isdn/HiSax.cert - * - * Thanks to Jan den Ouden - * Fritz Elfert - * - */ - -#include <linux/init.h> -#include <linux/gfp.h> -#include "hisax.h" -#include "isdnl2.h" - -const char *l2_revision = "$Revision: 2.30.2.4 $"; - -static void l2m_debug(struct FsmInst *fi, char *fmt, ...); - -static struct Fsm l2fsm; - -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_SABME, - 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_REQ, - EV_L2_DL_RELEASE_REQ, - EV_L2_MDL_ASSIGN, - EV_L2_MDL_REMOVE, - EV_L2_MDL_ERROR, - EV_L1_DEACTIVATE, - EV_L2_T200, - EV_L2_T203, - EV_L2_SET_OWN_BUSY, - EV_L2_CLEAR_OWN_BUSY, - EV_L2_FRAME_ERROR, -}; - -#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR + 1) - -static char *strL2Event[] = -{ - "EV_L2_UI", - "EV_L2_SABME", - "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_REQ", - "EV_L2_DL_RELEASE_REQ", - "EV_L2_MDL_ASSIGN", - "EV_L2_MDL_REMOVE", - "EV_L2_MDL_ERROR", - "EV_L1_DEACTIVATE", - "EV_L2_T200", - "EV_L2_T203", - "EV_L2_SET_OWN_BUSY", - "EV_L2_CLEAR_OWN_BUSY", - "EV_L2_FRAME_ERROR", -}; - -static int l2addrsize(struct Layer2 *l2); - -static void -set_peer_busy(struct Layer2 *l2) { - test_and_set_bit(FLG_PEER_BUSY, &l2->flag); - if (!skb_queue_empty(&l2->i_queue) || - !skb_queue_empty(&l2->ui_queue)) - test_and_set_bit(FLG_L2BLOCK, &l2->flag); -} - -static void -clear_peer_busy(struct Layer2 *l2) { - if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag)) - test_and_clear_bit(FLG_L2BLOCK, &l2->flag); -} - -static void -InitWin(struct Layer2 *l2) -{ - int i; - - for (i = 0; i < MAX_WINDOW; i++) - l2->windowar[i] = NULL; -} - -static int -freewin1(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]); - l2->windowar[i] = NULL; - } - } - return cnt; -} - -static inline void -freewin(struct PStack *st) -{ - freewin1(&st->l2); -} - -static void -ReleaseWin(struct Layer2 *l2) -{ - int cnt; - - if ((cnt = freewin1(l2))) - printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt); -} - -static inline unsigned int -cansend(struct PStack *st) -{ - unsigned int p1; - - if (test_bit(FLG_MOD128, &st->l2.flag)) - p1 = (st->l2.vs - st->l2.va) % 128; - else - p1 = (st->l2.vs - st->l2.va) % 8; - return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag)); -} - -static inline void -clear_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); - clear_peer_busy(l2); -} - -static inline int -l2headersize(struct Layer2 *l2, int ui) -{ - return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) + - (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1)); -} - -inline int -l2addrsize(struct Layer2 *l2) -{ - return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1); -} - -static int -sethdraddr(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); - } -} - -static inline void -enqueue_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) - -static inline int -IsUI(u_char *data) -{ - return ((data[0] & 0xef) == UI); -} - -static inline int -IsUA(u_char *data) -{ - return ((data[0] & 0xef) == UA); -} - -static inline int -IsDM(u_char *data) -{ - return ((data[0] & 0xef) == DM); -} - -static inline int -IsDISC(u_char *data) -{ - return ((data[0] & 0xef) == DISC); -} - -static inline int -IsSFrame(u_char *data, struct PStack *st) -{ - register u_char d = *data; - - if (!test_bit(FLG_MOD128, &st->l2.flag)) - d &= 0xf; - return (((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c)); -} - -static inline int -IsSABME(u_char *data, struct PStack *st) -{ - u_char d = data[0] & ~0x10; - - return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM); -} - -static inline int -IsREJ(u_char *data, struct PStack *st) -{ - return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ); -} - -static inline int -IsFRMR(u_char *data) -{ - return ((data[0] & 0xef) == FRMR); -} - -static inline int -IsRNR(u_char *data, struct PStack *st) -{ - return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR); -} - -static int -iframe_error(struct PStack *st, struct sk_buff *skb) -{ - int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); - int rsp = *skb->data & 0x2; - - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - - if (rsp) - return 'L'; - - - if (skb->len < i) - return 'N'; - - if ((skb->len - i) > st->l2.maxlen) - return 'O'; - - - return 0; -} - -static int -super_error(struct PStack *st, struct sk_buff *skb) -{ - if (skb->len != l2addrsize(&st->l2) + - (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1)) - return 'N'; - - return 0; -} - -static int -unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp) -{ - int rsp = (*skb->data & 0x2) >> 1; - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - - if (rsp != wantrsp) - return 'L'; - - if (skb->len != l2addrsize(&st->l2) + 1) - return 'N'; - - return 0; -} - -static int -UI_error(struct PStack *st, struct sk_buff *skb) -{ - int rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - - if (rsp) - return 'L'; - - if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1) - return 'O'; - - return 0; -} - -static int -FRMR_error(struct PStack *st, struct sk_buff *skb) -{ - int headers = l2addrsize(&st->l2) + 1; - u_char *datap = skb->data + headers; - int rsp = *skb->data & 0x2; - - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - - if (!rsp) - return 'L'; - - if (test_bit(FLG_MOD128, &st->l2.flag)) { - if (skb->len < headers + 5) - return 'N'; - else - l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x", - datap[0], datap[1], datap[2], - datap[3], datap[4]); - } else { - if (skb->len < headers + 3) - return 'N'; - else - l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x", - datap[0], datap[1], datap[2]); - } - - return 0; -} - -static unsigned int -legalnr(struct PStack *st, unsigned int nr) -{ - struct Layer2 *l2 = &st->l2; - - if (test_bit(FLG_MOD128, &l2->flag)) - return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128); - else - return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8); -} - -static void -setva(struct PStack *st, unsigned int nr) -{ - struct Layer2 *l2 = &st->l2; - int len; - u_long flags; - - spin_lock_irqsave(&l2->lock, flags); - while (l2->va != nr) { - (l2->va)++; - if (test_bit(FLG_MOD128, &l2->flag)) - l2->va %= 128; - else - l2->va %= 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]); - l2->windowar[l2->sow] = NULL; - l2->sow = (l2->sow + 1) % l2->window; - spin_unlock_irqrestore(&l2->lock, flags); - if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >= 0)) - lli_writewakeup(st, len); - spin_lock_irqsave(&l2->lock, flags); - } - spin_unlock_irqrestore(&l2->lock, flags); -} - -static void -send_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; - } - skb_put_data(skb, tmp, i); - enqueue_super(st, skb); -} - -static inline u_char -get_PollFlag(struct PStack *st, struct sk_buff *skb) -{ - return (skb->data[l2addrsize(&(st->l2))] & 0x10); -} - -static inline u_char -get_PollFlagFree(struct PStack *st, struct sk_buff *skb) -{ - u_char PF; - - PF = get_PollFlag(st, skb); - dev_kfree_skb(skb); - return (PF); -} - -static inline void -start_t200(struct PStack *st, int i) -{ - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); -} - -static inline void -restart_t200(struct PStack *st, int i) -{ - FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); -} - -static inline void -stop_t200(struct PStack *st, int i) -{ - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, i); -} - -static inline void -st5_dl_release_l2l3(struct PStack *st) -{ - int pr; - - if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) - pr = DL_RELEASE | CONFIRM; - else - pr = DL_RELEASE | INDICATION; - - st->l2.l2l3(st, pr, NULL); -} - -static inline void -lapb_dl_release_l2l3(struct PStack *st, int f) -{ - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); - st->l2.l2l3(st, DL_RELEASE | f, NULL); -} - -static void -establishlink(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); - restart_t200(st, 1); - test_and_clear_bit(FLG_PEND_REL, &st->l2.flag); - freewin(st); - FsmChangeState(fi, ST_L2_5); -} - -static void -l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg) -{ - struct sk_buff *skb = arg; - struct PStack *st = fi->userdata; - - if (get_PollFlagFree(st, skb)) - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C'); - else - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D'); -} - -static void -l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg) -{ - struct sk_buff *skb = arg; - struct PStack *st = fi->userdata; - - 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); - } -} - -static void -l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg) -{ - struct sk_buff *skb = arg; - struct PStack *st = fi->userdata; - - 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); -} - -static void -l2_go_st3(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L2_3); -} - -static void -l2_mdl_assign(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - FsmChangeState(fi, ST_L2_3); - st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL); -} - -static void -l2_queue_ui_assign(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); - FsmChangeState(fi, ST_L2_2); - st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL); -} - -static void -l2_queue_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); -} - -static void -tx_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 void -l2_send_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); - tx_ui(st); -} - -static void -l2_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)); - st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb); -/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * in states 1-3 for broadcast - */ - - -} - -static void -l2_establish(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - establishlink(fi); - test_and_set_bit(FLG_L3_INIT, &st->l2.flag); -} - -static void -l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - test_and_set_bit(FLG_L3_INIT, &st->l2.flag); - test_and_clear_bit(FLG_PEND_REL, &st->l2.flag); -} - -static void -l2_l3_reestablish(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - establishlink(fi); - test_and_set_bit(FLG_L3_INIT, &st->l2.flag); -} - -static void -l2_release(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); -} - -static void -l2_pend_rel(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - test_and_set_bit(FLG_PEND_REL, &st->l2.flag); -} - -static void -l2_disconnect(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - freewin(st); - FsmChangeState(fi, ST_L2_6); - st->l2.rc = 0; - send_uframe(st, DISC | 0x10, CMD); - FsmDelTimer(&st->l2.t203, 1); - restart_t200(st, 2); -} - -static void -l2_start_multi(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); - - clear_exception(&st->l2); - st->l2.vs = 0; - st->l2.va = 0; - st->l2.vr = 0; - st->l2.sow = 0; - FsmChangeState(fi, ST_L2_7); - FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); - - st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); -} - -static void -l2_send_UA(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); -} - -static void -l2_send_DM(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - send_uframe(st, DM | get_PollFlagFree(st, skb), RSP); -} - -static void -l2_restart_multi(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - int est = 0, state; - - state = fi->state; - - send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); - - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F'); - - if (st->l2.vs != st->l2.va) { - skb_queue_purge(&st->l2.i_queue); - est = 1; - } - - clear_exception(&st->l2); - st->l2.vs = 0; - st->l2.va = 0; - st->l2.vr = 0; - st->l2.sow = 0; - FsmChangeState(fi, ST_L2_7); - stop_t200(st, 3); - FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); - - if (est) - st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); - - if ((ST_L2_7 == state) || (ST_L2_8 == state)) - if (!skb_queue_empty(&st->l2.i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); -} - -static void -l2_stop_multi(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - FsmChangeState(fi, ST_L2_4); - FsmDelTimer(&st->l2.t203, 3); - stop_t200(st, 4); - - send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); - - skb_queue_purge(&st->l2.i_queue); - freewin(st); - lapb_dl_release_l2l3(st, INDICATION); -} - -static void -l2_connected(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - int pr = -1; - - if (!get_PollFlag(st, skb)) { - l2_mdl_error_ua(fi, event, arg); - return; - } - dev_kfree_skb(skb); - - if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) - l2_disconnect(fi, event, arg); - - if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) { - pr = DL_ESTABLISH | CONFIRM; - } else if (st->l2.vs != st->l2.va) { - skb_queue_purge(&st->l2.i_queue); - pr = DL_ESTABLISH | INDICATION; - } - - stop_t200(st, 5); - - st->l2.vr = 0; - st->l2.vs = 0; - st->l2.va = 0; - st->l2.sow = 0; - FsmChangeState(fi, ST_L2_7); - FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4); - - if (pr != -1) - st->l2.l2l3(st, pr, NULL); - - if (!skb_queue_empty(&st->l2.i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); -} - -static void -l2_released(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (!get_PollFlag(st, skb)) { - l2_mdl_error_ua(fi, event, arg); - return; - } - dev_kfree_skb(skb); - - stop_t200(st, 6); - lapb_dl_release_l2l3(st, CONFIRM); - FsmChangeState(fi, ST_L2_4); -} - -static void -l2_reestablish(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (!get_PollFlagFree(st, skb)) { - establishlink(fi); - test_and_set_bit(FLG_L3_INIT, &st->l2.flag); - } -} - -static void -l2_st5_dm_release(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (get_PollFlagFree(st, skb)) { - stop_t200(st, 7); - if (!test_bit(FLG_L3_INIT, &st->l2.flag)) - skb_queue_purge(&st->l2.i_queue); - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); - st5_dl_release_l2l3(st); - FsmChangeState(fi, ST_L2_4); - } -} - -static void -l2_st6_dm_release(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (get_PollFlagFree(st, skb)) { - stop_t200(st, 8); - lapb_dl_release_l2l3(st, CONFIRM); - FsmChangeState(fi, ST_L2_4); - } -} - -static inline void -enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf) -{ - struct sk_buff *skb; - struct Layer2 *l2; - u_char tmp[MAX_HEADER_LEN]; - int i; - - l2 = &st->l2; - i = sethdraddr(l2, tmp, cr); - if (test_bit(FLG_MOD128, &l2->flag)) { - tmp[i++] = typ; - tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0); - } else - tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0); - if (!(skb = alloc_skb(i, GFP_ATOMIC))) { - printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n"); - return; - } - skb_put_data(skb, tmp, i); - enqueue_super(st, skb); -} - -static inline void -enquiry_response(struct PStack *st) -{ - if (test_bit(FLG_OWN_BUSY, &st->l2.flag)) - enquiry_cr(st, RNR, RSP, 1); - else - enquiry_cr(st, RR, RSP, 1); - test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); -} - -static inline void -transmit_enquiry(struct PStack *st) -{ - if (test_bit(FLG_OWN_BUSY, &st->l2.flag)) - enquiry_cr(st, RNR, CMD, 1); - else - enquiry_cr(st, RR, CMD, 1); - test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); - start_t200(st, 9); -} - - -static void -nrerrorrecovery(struct FsmInst *fi) -{ - struct PStack *st = fi->userdata; - - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J'); - establishlink(fi); - test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); -} - -static void -invoke_retransmission(struct PStack *st, unsigned int nr) -{ - struct Layer2 *l2 = &st->l2; - u_int p1; - u_long flags; - - spin_lock_irqsave(&l2->lock, flags); - if (l2->vs != nr) { - while (l2->vs != nr) { - (l2->vs)--; - if (test_bit(FLG_MOD128, &l2->flag)) { - l2->vs %= 128; - p1 = (l2->vs - l2->va) % 128; - } else { - l2->vs %= 8; - p1 = (l2->vs - l2->va) % 8; - } - p1 = (p1 + l2->sow) % l2->window; - if (test_bit(FLG_LAPB, &l2->flag)) - st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0); - skb_queue_head(&l2->i_queue, l2->windowar[p1]); - l2->windowar[p1] = NULL; - } - spin_unlock_irqrestore(&l2->lock, flags); - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); - return; - } - spin_unlock_irqrestore(&l2->lock, flags); -} - -static void -l2_st7_got_super(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - int PollFlag, rsp, typ = RR; - unsigned int nr; - struct Layer2 *l2 = &st->l2; - - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &l2->flag)) - rsp = !rsp; - - skb_pull(skb, l2addrsize(l2)); - if (IsRNR(skb->data, st)) { - set_peer_busy(l2); - typ = RNR; - } else - clear_peer_busy(l2); - if (IsREJ(skb->data, st)) - typ = REJ; - - if (test_bit(FLG_MOD128, &l2->flag)) { - PollFlag = (skb->data[1] & 0x1) == 0x1; - nr = skb->data[1] >> 1; - } else { - PollFlag = (skb->data[0] & 0x10); - nr = (skb->data[0] >> 5) & 0x7; - } - dev_kfree_skb(skb); - - if (PollFlag) { - if (rsp) - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A'); - else - enquiry_response(st); - } - if (legalnr(st, nr)) { - if (typ == REJ) { - setva(st, nr); - invoke_retransmission(st, nr); - stop_t200(st, 10); - if (FsmAddTimer(&st->l2.t203, st->l2.T203, - EV_L2_T203, NULL, 6)) - l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ"); - } else if ((nr == l2->vs) && (typ == RR)) { - setva(st, nr); - stop_t200(st, 11); - FsmRestartTimer(&st->l2.t203, st->l2.T203, - EV_L2_T203, NULL, 7); - } else if ((l2->va != nr) || (typ == RNR)) { - setva(st, nr); - if (typ != RR) FsmDelTimer(&st->l2.t203, 9); - restart_t200(st, 12); - } - if (!skb_queue_empty(&st->l2.i_queue) && (typ == RR)) - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); - } else - nrerrorrecovery(fi); -} - -static void -l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); - if (!test_bit(FLG_L3_INIT, &st->l2.flag)) - skb_queue_tail(&st->l2.i_queue, skb); - else - dev_kfree_skb(skb); -} - -static void -l2_feed_i_pull(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); - skb_queue_tail(&st->l2.i_queue, skb); - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); -} - -static void -l2_feed_iqueue(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); - skb_queue_tail(&st->l2.i_queue, skb); -} - -static void -l2_got_iframe(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - struct Layer2 *l2 = &(st->l2); - int PollFlag, ns, i; - unsigned int nr; - - i = l2addrsize(l2); - if (test_bit(FLG_MOD128, &l2->flag)) { - PollFlag = ((skb->data[i + 1] & 0x1) == 0x1); - ns = skb->data[i] >> 1; - nr = (skb->data[i + 1] >> 1) & 0x7f; - } else { - PollFlag = (skb->data[i] & 0x10); - ns = (skb->data[i] >> 1) & 0x7; - nr = (skb->data[i] >> 5) & 0x7; - } - if (test_bit(FLG_OWN_BUSY, &l2->flag)) { - dev_kfree_skb(skb); - if (PollFlag) enquiry_response(st); - } else if (l2->vr == ns) { - (l2->vr)++; - if (test_bit(FLG_MOD128, &l2->flag)) - l2->vr %= 128; - else - l2->vr %= 8; - test_and_clear_bit(FLG_REJEXC, &l2->flag); - - if (PollFlag) - enquiry_response(st); - else - test_and_set_bit(FLG_ACK_PEND, &l2->flag); - skb_pull(skb, l2headersize(l2, 0)); - st->l2.l2l3(st, DL_DATA | INDICATION, skb); - } else { - /* n(s)!=v(r) */ - dev_kfree_skb(skb); - if (test_and_set_bit(FLG_REJEXC, &l2->flag)) { - if (PollFlag) - enquiry_response(st); - } else { - enquiry_cr(st, REJ, RSP, PollFlag); - test_and_clear_bit(FLG_ACK_PEND, &l2->flag); - } - } - - if (legalnr(st, nr)) { - if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) { - if (nr == st->l2.vs) { - stop_t200(st, 13); - FsmRestartTimer(&st->l2.t203, st->l2.T203, - EV_L2_T203, NULL, 7); - } else if (nr != st->l2.va) - restart_t200(st, 14); - } - setva(st, nr); - } else { - nrerrorrecovery(fi); - return; - } - - if (!skb_queue_empty(&st->l2.i_queue) && (fi->state == ST_L2_7)) - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); - if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag)) - enquiry_cr(st, RR, RSP, 0); -} - -static void -l2_got_tei(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - st->l2.tei = (long) arg; - - if (fi->state == ST_L2_3) { - establishlink(fi); - test_and_set_bit(FLG_L3_INIT, &st->l2.flag); - } else - FsmChangeState(fi, ST_L2_4); - if (!skb_queue_empty(&st->l2.ui_queue)) - tx_ui(st); -} - -static void -l2_st5_tout_200(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (test_bit(FLG_LAPD, &st->l2.flag) && - test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); - } else if (st->l2.rc == st->l2.N200) { - FsmChangeState(fi, ST_L2_4); - test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - skb_queue_purge(&st->l2.i_queue); - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G'); - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); - st5_dl_release_l2l3(st); - } else { - st->l2.rc++; - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); - send_uframe(st, (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) - | 0x10, CMD); - } -} - -static void -l2_st6_tout_200(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (test_bit(FLG_LAPD, &st->l2.flag) && - test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); - } else if (st->l2.rc == st->l2.N200) { - FsmChangeState(fi, ST_L2_4); - test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H'); - lapb_dl_release_l2l3(st, CONFIRM); - } else { - st->l2.rc++; - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, - NULL, 9); - send_uframe(st, DISC | 0x10, CMD); - } -} - -static void -l2_st7_tout_200(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (test_bit(FLG_LAPD, &st->l2.flag) && - test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); - return; - } - test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - st->l2.rc = 0; - FsmChangeState(fi, ST_L2_8); - - transmit_enquiry(st); - st->l2.rc++; -} - -static void -l2_st8_tout_200(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (test_bit(FLG_LAPD, &st->l2.flag) && - test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); - return; - } - test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - if (st->l2.rc == st->l2.N200) { - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I'); - establishlink(fi); - test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); - } else { - transmit_enquiry(st); - st->l2.rc++; - } -} - -static void -l2_st7_tout_203(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (test_bit(FLG_LAPD, &st->l2.flag) && - test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { - FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 9); - return; - } - FsmChangeState(fi, ST_L2_8); - transmit_enquiry(st); - st->l2.rc = 0; -} - -static void -l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb, *nskb; - struct Layer2 *l2 = &st->l2; - u_char header[MAX_HEADER_LEN]; - int i, hdr_space_needed; - int unsigned p1; - u_long flags; - - if (!cansend(st)) - return; - - skb = skb_dequeue(&l2->i_queue); - if (!skb) - return; - - hdr_space_needed = l2headersize(l2, 0); - nskb = skb_realloc_headroom(skb, hdr_space_needed); - if (!nskb) { - skb_queue_head(&l2->i_queue, skb); - return; - } - spin_lock_irqsave(&l2->lock, flags); - if (test_bit(FLG_MOD128, &l2->flag)) - p1 = (l2->vs - l2->va) % 128; - else - p1 = (l2->vs - l2->va) % 8; - p1 = (p1 + l2->sow) % l2->window; - if (l2->windowar[p1]) { - printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n", - p1); - dev_kfree_skb(l2->windowar[p1]); - } - l2->windowar[p1] = skb; - - i = sethdraddr(&st->l2, header, CMD); - - if (test_bit(FLG_MOD128, &l2->flag)) { - header[i++] = l2->vs << 1; - header[i++] = l2->vr << 1; - l2->vs = (l2->vs + 1) % 128; - } else { - header[i++] = (l2->vr << 5) | (l2->vs << 1); - l2->vs = (l2->vs + 1) % 8; - } - spin_unlock_irqrestore(&l2->lock, flags); - memcpy(skb_push(nskb, i), header, i); - st->l2.l2l1(st, PH_PULL | INDICATION, nskb); - test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); - if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { - FsmDelTimer(&st->l2.t203, 13); - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11); - } - if (!skb_queue_empty(&l2->i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); -} - -static void -l2_st8_got_super(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - int PollFlag, rsp, rnr = 0; - unsigned int nr; - struct Layer2 *l2 = &st->l2; - - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &l2->flag)) - rsp = !rsp; - - skb_pull(skb, l2addrsize(l2)); - - if (IsRNR(skb->data, st)) { - set_peer_busy(l2); - rnr = 1; - } else - clear_peer_busy(l2); - - if (test_bit(FLG_MOD128, &l2->flag)) { - PollFlag = (skb->data[1] & 0x1) == 0x1; - nr = skb->data[1] >> 1; - } else { - PollFlag = (skb->data[0] & 0x10); - nr = (skb->data[0] >> 5) & 0x7; - } - dev_kfree_skb(skb); - - if (rsp && PollFlag) { - if (legalnr(st, nr)) { - if (rnr) { - restart_t200(st, 15); - } else { - stop_t200(st, 16); - FsmAddTimer(&l2->t203, l2->T203, - EV_L2_T203, NULL, 5); - setva(st, nr); - } - invoke_retransmission(st, nr); - FsmChangeState(fi, ST_L2_7); - if (!skb_queue_empty(&l2->i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL | REQUEST, NULL); - } else - nrerrorrecovery(fi); - } else { - if (!rsp && PollFlag) - enquiry_response(st); - if (legalnr(st, nr)) { - setva(st, nr); - } else - nrerrorrecovery(fi); - } -} - -static void -l2_got_FRMR(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - struct sk_buff *skb = arg; - - skb_pull(skb, l2addrsize(&st->l2) + 1); - - if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */ - (IsUA(skb->data) && (fi->state == ST_L2_7))) { - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K'); - establishlink(fi); - test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); - } - dev_kfree_skb(skb); -} - -static void -l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.ui_queue); - st->l2.tei = -1; - FsmChangeState(fi, ST_L2_1); -} - -static void -l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.ui_queue); - st->l2.tei = -1; - st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); - FsmChangeState(fi, ST_L2_1); -} - -static void -l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - skb_queue_purge(&st->l2.ui_queue); - freewin(st); - st->l2.tei = -1; - stop_t200(st, 17); - st5_dl_release_l2l3(st); - FsmChangeState(fi, ST_L2_1); -} - -static void -l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.ui_queue); - st->l2.tei = -1; - stop_t200(st, 18); - st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); - FsmChangeState(fi, ST_L2_1); -} - -static void -l2_tei_remove(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - skb_queue_purge(&st->l2.ui_queue); - freewin(st); - st->l2.tei = -1; - stop_t200(st, 17); - FsmDelTimer(&st->l2.t203, 19); - st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); - FsmChangeState(fi, ST_L2_1); -} - -static void -l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - skb_queue_purge(&st->l2.ui_queue); - if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) - st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); -} - -static void -l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - skb_queue_purge(&st->l2.ui_queue); - freewin(st); - stop_t200(st, 19); - st5_dl_release_l2l3(st); - FsmChangeState(fi, ST_L2_4); -} - -static void -l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.ui_queue); - stop_t200(st, 20); - st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); - FsmChangeState(fi, ST_L2_4); -} - -static void -l2_persistent_da(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - skb_queue_purge(&st->l2.i_queue); - skb_queue_purge(&st->l2.ui_queue); - freewin(st); - stop_t200(st, 19); - FsmDelTimer(&st->l2.t203, 19); - st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); - FsmChangeState(fi, ST_L2_4); -} - -static void -l2_set_own_busy(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) { - enquiry_cr(st, RNR, RSP, 0); - test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); - } -} - -static void -l2_clear_own_busy(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - if (!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) { - enquiry_cr(st, RR, RSP, 0); - test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); - } -} - -static void -l2_frame_error(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - st->ma.layer(st, MDL_ERROR | INDICATION, arg); -} - -static void -l2_frame_error_reest(struct FsmInst *fi, int event, void *arg) -{ - struct PStack *st = fi->userdata; - - st->ma.layer(st, MDL_ERROR | INDICATION, arg); - establishlink(fi); - test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); -} - -static struct FsmNode L2FnList[] __initdata = -{ - {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign}, - {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3}, - {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish}, - {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3}, - {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, - {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, - {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release}, - {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel}, - {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect}, - {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect}, - {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest}, - {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull}, - {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue}, - {ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign}, - {ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui}, - {ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui}, - {ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui}, - {ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui}, - {ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui}, - {ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui}, - {ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui}, - {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei}, - {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei}, - {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei}, - {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove}, - {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove}, - {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove}, - {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove}, - {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove}, - {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove}, - {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove}, - {ST_L2_4, EV_L2_SABME, l2_start_multi}, - {ST_L2_5, EV_L2_SABME, l2_send_UA}, - {ST_L2_6, EV_L2_SABME, l2_send_DM}, - {ST_L2_7, EV_L2_SABME, l2_restart_multi}, - {ST_L2_8, EV_L2_SABME, l2_restart_multi}, - {ST_L2_4, EV_L2_DISC, l2_send_DM}, - {ST_L2_5, EV_L2_DISC, l2_send_DM}, - {ST_L2_6, EV_L2_DISC, l2_send_UA}, - {ST_L2_7, EV_L2_DISC, l2_stop_multi}, - {ST_L2_8, EV_L2_DISC, l2_stop_multi}, - {ST_L2_4, EV_L2_UA, l2_mdl_error_ua}, - {ST_L2_5, EV_L2_UA, l2_connected}, - {ST_L2_6, EV_L2_UA, l2_released}, - {ST_L2_7, EV_L2_UA, l2_mdl_error_ua}, - {ST_L2_8, EV_L2_UA, l2_mdl_error_ua}, - {ST_L2_4, EV_L2_DM, l2_reestablish}, - {ST_L2_5, EV_L2_DM, l2_st5_dm_release}, - {ST_L2_6, EV_L2_DM, l2_st6_dm_release}, - {ST_L2_7, EV_L2_DM, l2_mdl_error_dm}, - {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm}, - {ST_L2_1, EV_L2_UI, l2_got_ui}, - {ST_L2_2, EV_L2_UI, l2_got_ui}, - {ST_L2_3, EV_L2_UI, l2_got_ui}, - {ST_L2_4, EV_L2_UI, l2_got_ui}, - {ST_L2_5, EV_L2_UI, l2_got_ui}, - {ST_L2_6, EV_L2_UI, l2_got_ui}, - {ST_L2_7, EV_L2_UI, l2_got_ui}, - {ST_L2_8, EV_L2_UI, l2_got_ui}, - {ST_L2_7, EV_L2_FRMR, l2_got_FRMR}, - {ST_L2_8, EV_L2_FRMR, l2_got_FRMR}, - {ST_L2_7, EV_L2_SUPER, l2_st7_got_super}, - {ST_L2_8, EV_L2_SUPER, l2_st8_got_super}, - {ST_L2_7, EV_L2_I, l2_got_iframe}, - {ST_L2_8, EV_L2_I, l2_got_iframe}, - {ST_L2_5, EV_L2_T200, l2_st5_tout_200}, - {ST_L2_6, EV_L2_T200, l2_st6_tout_200}, - {ST_L2_7, EV_L2_T200, l2_st7_tout_200}, - {ST_L2_8, EV_L2_T200, l2_st8_tout_200}, - {ST_L2_7, EV_L2_T203, l2_st7_tout_203}, - {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue}, - {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, - {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, - {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, - {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, - {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error}, - {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error}, - {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, - {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, - {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, - {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da}, - {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, - {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, - {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da}, - {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da}, - {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da}, - {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da}, - {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, -}; - -static void -isdnl2_l1l2(struct PStack *st, int pr, void *arg) -{ - struct sk_buff *skb = arg; - u_char *datap; - int ret = 1, len; - int c = 0; - - switch (pr) { - case (PH_DATA | INDICATION): - datap = skb->data; - len = l2addrsize(&st->l2); - if (skb->len > len) - datap += len; - else { - FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N'); - dev_kfree_skb(skb); - return; - } - if (!(*datap & 1)) { /* I-Frame */ - if (!(c = iframe_error(st, skb))) - ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb); - } else if (IsSFrame(datap, st)) { /* S-Frame */ - if (!(c = super_error(st, skb))) - ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb); - } else if (IsUI(datap)) { - if (!(c = UI_error(st, skb))) - ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb); - } else if (IsSABME(datap, st)) { - if (!(c = unnum_error(st, skb, CMD))) - ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb); - } else if (IsUA(datap)) { - if (!(c = unnum_error(st, skb, RSP))) - ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb); - } else if (IsDISC(datap)) { - if (!(c = unnum_error(st, skb, CMD))) - ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb); - } else if (IsDM(datap)) { - if (!(c = unnum_error(st, skb, RSP))) - ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb); - } else if (IsFRMR(datap)) { - if (!(c = FRMR_error(st, skb))) - ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb); - } else { - FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L'); - dev_kfree_skb(skb); - ret = 0; - } - if (c) { - dev_kfree_skb(skb); - FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c); - ret = 0; - } - if (ret) - dev_kfree_skb(skb); - break; - case (PH_PULL | CONFIRM): - FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg); - break; - case (PH_PAUSE | INDICATION): - test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag); - break; - case (PH_PAUSE | CONFIRM): - test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag); - break; - case (PH_ACTIVATE | CONFIRM): - case (PH_ACTIVATE | INDICATION): - test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag); - if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) - FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg); - break; - case (PH_DEACTIVATE | INDICATION): - case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag); - FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg); - break; - default: - l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr); - break; - } -} - -static void -isdnl2_l3l2(struct PStack *st, int pr, void *arg) -{ - switch (pr) { - case (DL_DATA | REQUEST): - if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) { - dev_kfree_skb((struct sk_buff *) arg); - } - break; - case (DL_UNIT_DATA | REQUEST): - if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) { - dev_kfree_skb((struct sk_buff *) arg); - } - break; - case (DL_ESTABLISH | REQUEST): - if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) { - if (test_bit(FLG_LAPD, &st->l2.flag) || - test_bit(FLG_ORIG, &st->l2.flag)) { - FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg); - } - } else { - if (test_bit(FLG_LAPD, &st->l2.flag) || - test_bit(FLG_ORIG, &st->l2.flag)) { - test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag); - } - st->l2.l2l1(st, PH_ACTIVATE, NULL); - } - break; - case (DL_RELEASE | REQUEST): - if (test_bit(FLG_LAPB, &st->l2.flag)) { - st->l2.l2l1(st, PH_DEACTIVATE, NULL); - } - FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg); - break; - case (MDL_ASSIGN | REQUEST): - FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg); - break; - case (MDL_REMOVE | REQUEST): - FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg); - break; - case (MDL_ERROR | RESPONSE): - FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg); - break; - } -} - -void -releasestack_isdnl2(struct PStack *st) -{ - FsmDelTimer(&st->l2.t200, 21); - FsmDelTimer(&st->l2.t203, 16); - skb_queue_purge(&st->l2.i_queue); - skb_queue_purge(&st->l2.ui_queue); - ReleaseWin(&st->l2); -} - -static void -l2m_debug(struct FsmInst *fi, char *fmt, ...) -{ - va_list args; - struct PStack *st = fi->userdata; - - va_start(args, fmt); - VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args); - va_end(args); -} - -void -setstack_isdnl2(struct PStack *st, char *debug_id) -{ - spin_lock_init(&st->l2.lock); - st->l1.l1l2 = isdnl2_l1l2; - st->l3.l3l2 = isdnl2_l3l2; - - skb_queue_head_init(&st->l2.i_queue); - skb_queue_head_init(&st->l2.ui_queue); - InitWin(&st->l2); - st->l2.debug = 0; - - st->l2.l2m.fsm = &l2fsm; - if (test_bit(FLG_LAPB, &st->l2.flag)) - st->l2.l2m.state = ST_L2_4; - else - st->l2.l2m.state = ST_L2_1; - st->l2.l2m.debug = 0; - st->l2.l2m.userdata = st; - st->l2.l2m.userint = 0; - st->l2.l2m.printdebug = l2m_debug; - strcpy(st->l2.debug_id, debug_id); - - FsmInitTimer(&st->l2.l2m, &st->l2.t200); - FsmInitTimer(&st->l2.l2m, &st->l2.t203); -} - -static void -transl2_l3l2(struct PStack *st, int pr, void *arg) -{ - switch (pr) { - case (DL_DATA | REQUEST): - case (DL_UNIT_DATA | REQUEST): - st->l2.l2l1(st, PH_DATA | REQUEST, arg); - break; - case (DL_ESTABLISH | REQUEST): - st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); - break; - case (DL_RELEASE | REQUEST): - st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); - break; - } -} - -void -setstack_transl2(struct PStack *st) -{ - st->l3.l3l2 = transl2_l3l2; -} - -void -releasestack_transl2(struct PStack *st) -{ -} - -int __init -Isdnl2New(void) -{ - l2fsm.state_count = L2_STATE_COUNT; - l2fsm.event_count = L2_EVENT_COUNT; - l2fsm.strEvent = strL2Event; - l2fsm.strState = strL2State; - return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList)); -} - -void -Isdnl2Free(void) -{ - FsmFree(&l2fsm); -} |