18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Author Karsten Keil <kkeil@novell.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright 2008 by Karsten Keil <kkeil@novell.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/mISDNif.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci#include "core.h" 128c2ecf20Sopenharmony_ci#include "fsm.h" 138c2ecf20Sopenharmony_ci#include "layer2.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic u_int *debug; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic 188c2ecf20Sopenharmony_cistruct Fsm l2fsm = {NULL, 0, 0, NULL, NULL}; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic char *strL2State[] = 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci "ST_L2_1", 238c2ecf20Sopenharmony_ci "ST_L2_2", 248c2ecf20Sopenharmony_ci "ST_L2_3", 258c2ecf20Sopenharmony_ci "ST_L2_4", 268c2ecf20Sopenharmony_ci "ST_L2_5", 278c2ecf20Sopenharmony_ci "ST_L2_6", 288c2ecf20Sopenharmony_ci "ST_L2_7", 298c2ecf20Sopenharmony_ci "ST_L2_8", 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cienum { 338c2ecf20Sopenharmony_ci EV_L2_UI, 348c2ecf20Sopenharmony_ci EV_L2_SABME, 358c2ecf20Sopenharmony_ci EV_L2_DISC, 368c2ecf20Sopenharmony_ci EV_L2_DM, 378c2ecf20Sopenharmony_ci EV_L2_UA, 388c2ecf20Sopenharmony_ci EV_L2_FRMR, 398c2ecf20Sopenharmony_ci EV_L2_SUPER, 408c2ecf20Sopenharmony_ci EV_L2_I, 418c2ecf20Sopenharmony_ci EV_L2_DL_DATA, 428c2ecf20Sopenharmony_ci EV_L2_ACK_PULL, 438c2ecf20Sopenharmony_ci EV_L2_DL_UNITDATA, 448c2ecf20Sopenharmony_ci EV_L2_DL_ESTABLISH_REQ, 458c2ecf20Sopenharmony_ci EV_L2_DL_RELEASE_REQ, 468c2ecf20Sopenharmony_ci EV_L2_MDL_ASSIGN, 478c2ecf20Sopenharmony_ci EV_L2_MDL_REMOVE, 488c2ecf20Sopenharmony_ci EV_L2_MDL_ERROR, 498c2ecf20Sopenharmony_ci EV_L1_DEACTIVATE, 508c2ecf20Sopenharmony_ci EV_L2_T200, 518c2ecf20Sopenharmony_ci EV_L2_T203, 528c2ecf20Sopenharmony_ci EV_L2_T200I, 538c2ecf20Sopenharmony_ci EV_L2_T203I, 548c2ecf20Sopenharmony_ci EV_L2_SET_OWN_BUSY, 558c2ecf20Sopenharmony_ci EV_L2_CLEAR_OWN_BUSY, 568c2ecf20Sopenharmony_ci EV_L2_FRAME_ERROR, 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR + 1) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic char *strL2Event[] = 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci "EV_L2_UI", 648c2ecf20Sopenharmony_ci "EV_L2_SABME", 658c2ecf20Sopenharmony_ci "EV_L2_DISC", 668c2ecf20Sopenharmony_ci "EV_L2_DM", 678c2ecf20Sopenharmony_ci "EV_L2_UA", 688c2ecf20Sopenharmony_ci "EV_L2_FRMR", 698c2ecf20Sopenharmony_ci "EV_L2_SUPER", 708c2ecf20Sopenharmony_ci "EV_L2_I", 718c2ecf20Sopenharmony_ci "EV_L2_DL_DATA", 728c2ecf20Sopenharmony_ci "EV_L2_ACK_PULL", 738c2ecf20Sopenharmony_ci "EV_L2_DL_UNITDATA", 748c2ecf20Sopenharmony_ci "EV_L2_DL_ESTABLISH_REQ", 758c2ecf20Sopenharmony_ci "EV_L2_DL_RELEASE_REQ", 768c2ecf20Sopenharmony_ci "EV_L2_MDL_ASSIGN", 778c2ecf20Sopenharmony_ci "EV_L2_MDL_REMOVE", 788c2ecf20Sopenharmony_ci "EV_L2_MDL_ERROR", 798c2ecf20Sopenharmony_ci "EV_L1_DEACTIVATE", 808c2ecf20Sopenharmony_ci "EV_L2_T200", 818c2ecf20Sopenharmony_ci "EV_L2_T203", 828c2ecf20Sopenharmony_ci "EV_L2_T200I", 838c2ecf20Sopenharmony_ci "EV_L2_T203I", 848c2ecf20Sopenharmony_ci "EV_L2_SET_OWN_BUSY", 858c2ecf20Sopenharmony_ci "EV_L2_CLEAR_OWN_BUSY", 868c2ecf20Sopenharmony_ci "EV_L2_FRAME_ERROR", 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic void 908c2ecf20Sopenharmony_cil2m_debug(struct FsmInst *fi, char *fmt, ...) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 938c2ecf20Sopenharmony_ci struct va_format vaf; 948c2ecf20Sopenharmony_ci va_list va; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (!(*debug & DEBUG_L2_FSM)) 978c2ecf20Sopenharmony_ci return; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci va_start(va, fmt); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci vaf.fmt = fmt; 1028c2ecf20Sopenharmony_ci vaf.va = &va; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s l2 (sapi %d tei %d): %pV\n", 1058c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei, &vaf); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci va_end(va); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ciinline u_int 1118c2ecf20Sopenharmony_cil2headersize(struct layer2 *l2, int ui) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci return ((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) + 1148c2ecf20Sopenharmony_ci (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ciinline u_int 1188c2ecf20Sopenharmony_cil2addrsize(struct layer2 *l2) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return test_bit(FLG_LAPD, &l2->flag) ? 2 : 1; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic u_int 1248c2ecf20Sopenharmony_cil2_newid(struct layer2 *l2) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci u_int id; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci id = l2->next_id++; 1298c2ecf20Sopenharmony_ci if (id == 0x7fff) 1308c2ecf20Sopenharmony_ci l2->next_id = 1; 1318c2ecf20Sopenharmony_ci id <<= 16; 1328c2ecf20Sopenharmony_ci id |= l2->tei << 8; 1338c2ecf20Sopenharmony_ci id |= l2->sapi; 1348c2ecf20Sopenharmony_ci return id; 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic void 1388c2ecf20Sopenharmony_cil2up(struct layer2 *l2, u_int prim, struct sk_buff *skb) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci int err; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (!l2->up) 1438c2ecf20Sopenharmony_ci return; 1448c2ecf20Sopenharmony_ci mISDN_HEAD_PRIM(skb) = prim; 1458c2ecf20Sopenharmony_ci mISDN_HEAD_ID(skb) = (l2->ch.nr << 16) | l2->ch.addr; 1468c2ecf20Sopenharmony_ci err = l2->up->send(l2->up, skb); 1478c2ecf20Sopenharmony_ci if (err) { 1488c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: dev %s err=%d\n", __func__, 1498c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), err); 1508c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic void 1558c2ecf20Sopenharmony_cil2up_create(struct layer2 *l2, u_int prim, int len, void *arg) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci struct sk_buff *skb; 1588c2ecf20Sopenharmony_ci struct mISDNhead *hh; 1598c2ecf20Sopenharmony_ci int err; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (!l2->up) 1628c2ecf20Sopenharmony_ci return; 1638c2ecf20Sopenharmony_ci skb = mI_alloc_skb(len, GFP_ATOMIC); 1648c2ecf20Sopenharmony_ci if (!skb) 1658c2ecf20Sopenharmony_ci return; 1668c2ecf20Sopenharmony_ci hh = mISDN_HEAD_P(skb); 1678c2ecf20Sopenharmony_ci hh->prim = prim; 1688c2ecf20Sopenharmony_ci hh->id = (l2->ch.nr << 16) | l2->ch.addr; 1698c2ecf20Sopenharmony_ci if (len) 1708c2ecf20Sopenharmony_ci skb_put_data(skb, arg, len); 1718c2ecf20Sopenharmony_ci err = l2->up->send(l2->up, skb); 1728c2ecf20Sopenharmony_ci if (err) { 1738c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: dev %s err=%d\n", __func__, 1748c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), err); 1758c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic int 1808c2ecf20Sopenharmony_cil2down_skb(struct layer2 *l2, struct sk_buff *skb) { 1818c2ecf20Sopenharmony_ci int ret; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci ret = l2->ch.recv(l2->ch.peer, skb); 1848c2ecf20Sopenharmony_ci if (ret && (*debug & DEBUG_L2_RECV)) 1858c2ecf20Sopenharmony_ci printk(KERN_DEBUG "l2down_skb: dev %s ret(%d)\n", 1868c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), ret); 1878c2ecf20Sopenharmony_ci return ret; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic int 1918c2ecf20Sopenharmony_cil2down_raw(struct layer2 *l2, struct sk_buff *skb) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci struct mISDNhead *hh = mISDN_HEAD_P(skb); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (hh->prim == PH_DATA_REQ) { 1968c2ecf20Sopenharmony_ci if (test_and_set_bit(FLG_L1_NOTREADY, &l2->flag)) { 1978c2ecf20Sopenharmony_ci skb_queue_tail(&l2->down_queue, skb); 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci l2->down_id = mISDN_HEAD_ID(skb); 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci return l2down_skb(l2, skb); 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic int 2068c2ecf20Sopenharmony_cil2down(struct layer2 *l2, u_int prim, u_int id, struct sk_buff *skb) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct mISDNhead *hh = mISDN_HEAD_P(skb); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci hh->prim = prim; 2118c2ecf20Sopenharmony_ci hh->id = id; 2128c2ecf20Sopenharmony_ci return l2down_raw(l2, skb); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int 2168c2ecf20Sopenharmony_cil2down_create(struct layer2 *l2, u_int prim, u_int id, int len, void *arg) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct sk_buff *skb; 2198c2ecf20Sopenharmony_ci int err; 2208c2ecf20Sopenharmony_ci struct mISDNhead *hh; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci skb = mI_alloc_skb(len, GFP_ATOMIC); 2238c2ecf20Sopenharmony_ci if (!skb) 2248c2ecf20Sopenharmony_ci return -ENOMEM; 2258c2ecf20Sopenharmony_ci hh = mISDN_HEAD_P(skb); 2268c2ecf20Sopenharmony_ci hh->prim = prim; 2278c2ecf20Sopenharmony_ci hh->id = id; 2288c2ecf20Sopenharmony_ci if (len) 2298c2ecf20Sopenharmony_ci skb_put_data(skb, arg, len); 2308c2ecf20Sopenharmony_ci err = l2down_raw(l2, skb); 2318c2ecf20Sopenharmony_ci if (err) 2328c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 2338c2ecf20Sopenharmony_ci return err; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic int 2378c2ecf20Sopenharmony_ciph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) { 2388c2ecf20Sopenharmony_ci struct sk_buff *nskb = skb; 2398c2ecf20Sopenharmony_ci int ret = -EAGAIN; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (test_bit(FLG_L1_NOTREADY, &l2->flag)) { 2428c2ecf20Sopenharmony_ci if (hh->id == l2->down_id) { 2438c2ecf20Sopenharmony_ci nskb = skb_dequeue(&l2->down_queue); 2448c2ecf20Sopenharmony_ci if (nskb) { 2458c2ecf20Sopenharmony_ci l2->down_id = mISDN_HEAD_ID(nskb); 2468c2ecf20Sopenharmony_ci if (l2down_skb(l2, nskb)) { 2478c2ecf20Sopenharmony_ci dev_kfree_skb(nskb); 2488c2ecf20Sopenharmony_ci l2->down_id = MISDN_ID_NONE; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci } else 2518c2ecf20Sopenharmony_ci l2->down_id = MISDN_ID_NONE; 2528c2ecf20Sopenharmony_ci if (ret) { 2538c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 2548c2ecf20Sopenharmony_ci ret = 0; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci if (l2->down_id == MISDN_ID_NONE) { 2578c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L1_NOTREADY, &l2->flag); 2588c2ecf20Sopenharmony_ci mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL); 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci if (!test_and_set_bit(FLG_L1_NOTREADY, &l2->flag)) { 2638c2ecf20Sopenharmony_ci nskb = skb_dequeue(&l2->down_queue); 2648c2ecf20Sopenharmony_ci if (nskb) { 2658c2ecf20Sopenharmony_ci l2->down_id = mISDN_HEAD_ID(nskb); 2668c2ecf20Sopenharmony_ci if (l2down_skb(l2, nskb)) { 2678c2ecf20Sopenharmony_ci dev_kfree_skb(nskb); 2688c2ecf20Sopenharmony_ci l2->down_id = MISDN_ID_NONE; 2698c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L1_NOTREADY, &l2->flag); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci } else 2728c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L1_NOTREADY, &l2->flag); 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci return ret; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic void 2788c2ecf20Sopenharmony_cil2_timeout(struct FsmInst *fi, int event, void *arg) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 2818c2ecf20Sopenharmony_ci struct sk_buff *skb; 2828c2ecf20Sopenharmony_ci struct mISDNhead *hh; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci skb = mI_alloc_skb(0, GFP_ATOMIC); 2858c2ecf20Sopenharmony_ci if (!skb) { 2868c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: L2(%d,%d) nr:%x timer %s no skb\n", 2878c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei, 2888c2ecf20Sopenharmony_ci l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203"); 2898c2ecf20Sopenharmony_ci return; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci hh = mISDN_HEAD_P(skb); 2928c2ecf20Sopenharmony_ci hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND; 2938c2ecf20Sopenharmony_ci hh->id = l2->ch.nr; 2948c2ecf20Sopenharmony_ci if (*debug & DEBUG_TIMER) 2958c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: L2(%d,%d) nr:%x timer %s expired\n", 2968c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei, 2978c2ecf20Sopenharmony_ci l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203"); 2988c2ecf20Sopenharmony_ci if (l2->ch.st) 2998c2ecf20Sopenharmony_ci l2->ch.st->own.recv(&l2->ch.st->own, skb); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int 3038c2ecf20Sopenharmony_cil2mgr(struct layer2 *l2, u_int prim, void *arg) { 3048c2ecf20Sopenharmony_ci long c = (long)arg; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci printk(KERN_WARNING "l2mgr: dev %s addr:%x prim %x %c\n", 3078c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), l2->id, prim, (char)c); 3088c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) && 3098c2ecf20Sopenharmony_ci !test_bit(FLG_FIXED_TEI, &l2->flag)) { 3108c2ecf20Sopenharmony_ci switch (c) { 3118c2ecf20Sopenharmony_ci case 'C': 3128c2ecf20Sopenharmony_ci case 'D': 3138c2ecf20Sopenharmony_ci case 'G': 3148c2ecf20Sopenharmony_ci case 'H': 3158c2ecf20Sopenharmony_ci l2_tei(l2, prim, (u_long)arg); 3168c2ecf20Sopenharmony_ci break; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci return 0; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic void 3238c2ecf20Sopenharmony_ciset_peer_busy(struct layer2 *l2) { 3248c2ecf20Sopenharmony_ci test_and_set_bit(FLG_PEER_BUSY, &l2->flag); 3258c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue)) 3268c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L2BLOCK, &l2->flag); 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic void 3308c2ecf20Sopenharmony_ciclear_peer_busy(struct layer2 *l2) { 3318c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag)) 3328c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L2BLOCK, &l2->flag); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic void 3368c2ecf20Sopenharmony_ciInitWin(struct layer2 *l2) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci int i; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci for (i = 0; i < MAX_WINDOW; i++) 3418c2ecf20Sopenharmony_ci l2->windowar[i] = NULL; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int 3458c2ecf20Sopenharmony_cifreewin(struct layer2 *l2) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci int i, cnt = 0; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci for (i = 0; i < MAX_WINDOW; i++) { 3508c2ecf20Sopenharmony_ci if (l2->windowar[i]) { 3518c2ecf20Sopenharmony_ci cnt++; 3528c2ecf20Sopenharmony_ci dev_kfree_skb(l2->windowar[i]); 3538c2ecf20Sopenharmony_ci l2->windowar[i] = NULL; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci return cnt; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic void 3608c2ecf20Sopenharmony_ciReleaseWin(struct layer2 *l2) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci int cnt = freewin(l2); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (cnt) 3658c2ecf20Sopenharmony_ci printk(KERN_WARNING 3668c2ecf20Sopenharmony_ci "isdnl2 freed %d skbuffs in release\n", cnt); 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ciinline unsigned int 3708c2ecf20Sopenharmony_cicansend(struct layer2 *l2) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci unsigned int p1; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) 3758c2ecf20Sopenharmony_ci p1 = (l2->vs - l2->va) % 128; 3768c2ecf20Sopenharmony_ci else 3778c2ecf20Sopenharmony_ci p1 = (l2->vs - l2->va) % 8; 3788c2ecf20Sopenharmony_ci return (p1 < l2->window) && !test_bit(FLG_PEER_BUSY, &l2->flag); 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ciinline void 3828c2ecf20Sopenharmony_ciclear_exception(struct layer2 *l2) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 3858c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_REJEXC, &l2->flag); 3868c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_OWN_BUSY, &l2->flag); 3878c2ecf20Sopenharmony_ci clear_peer_busy(l2); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int 3918c2ecf20Sopenharmony_cisethdraddr(struct layer2 *l2, u_char *header, int rsp) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci u_char *ptr = header; 3948c2ecf20Sopenharmony_ci int crbit = rsp; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag)) { 3978c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD_NET, &l2->flag)) 3988c2ecf20Sopenharmony_ci crbit = !crbit; 3998c2ecf20Sopenharmony_ci *ptr++ = (l2->sapi << 2) | (crbit ? 2 : 0); 4008c2ecf20Sopenharmony_ci *ptr++ = (l2->tei << 1) | 1; 4018c2ecf20Sopenharmony_ci return 2; 4028c2ecf20Sopenharmony_ci } else { 4038c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 4048c2ecf20Sopenharmony_ci crbit = !crbit; 4058c2ecf20Sopenharmony_ci if (crbit) 4068c2ecf20Sopenharmony_ci *ptr++ = l2->addr.B; 4078c2ecf20Sopenharmony_ci else 4088c2ecf20Sopenharmony_ci *ptr++ = l2->addr.A; 4098c2ecf20Sopenharmony_ci return 1; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic inline void 4148c2ecf20Sopenharmony_cienqueue_super(struct layer2 *l2, struct sk_buff *skb) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci if (l2down(l2, PH_DATA_REQ, l2_newid(l2), skb)) 4178c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic inline void 4218c2ecf20Sopenharmony_cienqueue_ui(struct layer2 *l2, struct sk_buff *skb) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci if (l2->tm) 4248c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_UI_IND, 0); 4258c2ecf20Sopenharmony_ci if (l2down(l2, PH_DATA_REQ, l2_newid(l2), skb)) 4268c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ciinline int 4308c2ecf20Sopenharmony_ciIsUI(u_char *data) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci return (data[0] & 0xef) == UI; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ciinline int 4368c2ecf20Sopenharmony_ciIsUA(u_char *data) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci return (data[0] & 0xef) == UA; 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ciinline int 4428c2ecf20Sopenharmony_ciIsDM(u_char *data) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci return (data[0] & 0xef) == DM; 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ciinline int 4488c2ecf20Sopenharmony_ciIsDISC(u_char *data) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci return (data[0] & 0xef) == DISC; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ciinline int 4548c2ecf20Sopenharmony_ciIsRR(u_char *data, struct layer2 *l2) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) 4578c2ecf20Sopenharmony_ci return data[0] == RR; 4588c2ecf20Sopenharmony_ci else 4598c2ecf20Sopenharmony_ci return (data[0] & 0xf) == 1; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ciinline int 4638c2ecf20Sopenharmony_ciIsSFrame(u_char *data, struct layer2 *l2) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci register u_char d = *data; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (!test_bit(FLG_MOD128, &l2->flag)) 4688c2ecf20Sopenharmony_ci d &= 0xf; 4698c2ecf20Sopenharmony_ci return ((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c); 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ciinline int 4738c2ecf20Sopenharmony_ciIsSABME(u_char *data, struct layer2 *l2) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci u_char d = data[0] & ~0x10; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci return test_bit(FLG_MOD128, &l2->flag) ? d == SABME : d == SABM; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ciinline int 4818c2ecf20Sopenharmony_ciIsREJ(u_char *data, struct layer2 *l2) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci return test_bit(FLG_MOD128, &l2->flag) ? 4848c2ecf20Sopenharmony_ci data[0] == REJ : (data[0] & 0xf) == REJ; 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ciinline int 4888c2ecf20Sopenharmony_ciIsFRMR(u_char *data) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci return (data[0] & 0xef) == FRMR; 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ciinline int 4948c2ecf20Sopenharmony_ciIsRNR(u_char *data, struct layer2 *l2) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci return test_bit(FLG_MOD128, &l2->flag) ? 4978c2ecf20Sopenharmony_ci data[0] == RNR : (data[0] & 0xf) == RNR; 4988c2ecf20Sopenharmony_ci} 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cistatic int 5018c2ecf20Sopenharmony_ciiframe_error(struct layer2 *l2, struct sk_buff *skb) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci u_int i; 5048c2ecf20Sopenharmony_ci int rsp = *skb->data & 0x2; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci i = l2addrsize(l2) + (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1); 5078c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 5088c2ecf20Sopenharmony_ci rsp = !rsp; 5098c2ecf20Sopenharmony_ci if (rsp) 5108c2ecf20Sopenharmony_ci return 'L'; 5118c2ecf20Sopenharmony_ci if (skb->len < i) 5128c2ecf20Sopenharmony_ci return 'N'; 5138c2ecf20Sopenharmony_ci if ((skb->len - i) > l2->maxlen) 5148c2ecf20Sopenharmony_ci return 'O'; 5158c2ecf20Sopenharmony_ci return 0; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic int 5198c2ecf20Sopenharmony_cisuper_error(struct layer2 *l2, struct sk_buff *skb) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci if (skb->len != l2addrsize(l2) + 5228c2ecf20Sopenharmony_ci (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1)) 5238c2ecf20Sopenharmony_ci return 'N'; 5248c2ecf20Sopenharmony_ci return 0; 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_cistatic int 5288c2ecf20Sopenharmony_ciunnum_error(struct layer2 *l2, struct sk_buff *skb, int wantrsp) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci int rsp = (*skb->data & 0x2) >> 1; 5318c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 5328c2ecf20Sopenharmony_ci rsp = !rsp; 5338c2ecf20Sopenharmony_ci if (rsp != wantrsp) 5348c2ecf20Sopenharmony_ci return 'L'; 5358c2ecf20Sopenharmony_ci if (skb->len != l2addrsize(l2) + 1) 5368c2ecf20Sopenharmony_ci return 'N'; 5378c2ecf20Sopenharmony_ci return 0; 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_cistatic int 5418c2ecf20Sopenharmony_ciUI_error(struct layer2 *l2, struct sk_buff *skb) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci int rsp = *skb->data & 0x2; 5448c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 5458c2ecf20Sopenharmony_ci rsp = !rsp; 5468c2ecf20Sopenharmony_ci if (rsp) 5478c2ecf20Sopenharmony_ci return 'L'; 5488c2ecf20Sopenharmony_ci if (skb->len > l2->maxlen + l2addrsize(l2) + 1) 5498c2ecf20Sopenharmony_ci return 'O'; 5508c2ecf20Sopenharmony_ci return 0; 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic int 5548c2ecf20Sopenharmony_ciFRMR_error(struct layer2 *l2, struct sk_buff *skb) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci u_int headers = l2addrsize(l2) + 1; 5578c2ecf20Sopenharmony_ci u_char *datap = skb->data + headers; 5588c2ecf20Sopenharmony_ci int rsp = *skb->data & 0x2; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 5618c2ecf20Sopenharmony_ci rsp = !rsp; 5628c2ecf20Sopenharmony_ci if (!rsp) 5638c2ecf20Sopenharmony_ci return 'L'; 5648c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 5658c2ecf20Sopenharmony_ci if (skb->len < headers + 5) 5668c2ecf20Sopenharmony_ci return 'N'; 5678c2ecf20Sopenharmony_ci else if (*debug & DEBUG_L2) 5688c2ecf20Sopenharmony_ci l2m_debug(&l2->l2m, 5698c2ecf20Sopenharmony_ci "FRMR information %2x %2x %2x %2x %2x", 5708c2ecf20Sopenharmony_ci datap[0], datap[1], datap[2], datap[3], datap[4]); 5718c2ecf20Sopenharmony_ci } else { 5728c2ecf20Sopenharmony_ci if (skb->len < headers + 3) 5738c2ecf20Sopenharmony_ci return 'N'; 5748c2ecf20Sopenharmony_ci else if (*debug & DEBUG_L2) 5758c2ecf20Sopenharmony_ci l2m_debug(&l2->l2m, 5768c2ecf20Sopenharmony_ci "FRMR information %2x %2x %2x", 5778c2ecf20Sopenharmony_ci datap[0], datap[1], datap[2]); 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci return 0; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic unsigned int 5838c2ecf20Sopenharmony_cilegalnr(struct layer2 *l2, unsigned int nr) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) 5868c2ecf20Sopenharmony_ci return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128); 5878c2ecf20Sopenharmony_ci else 5888c2ecf20Sopenharmony_ci return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8); 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_cistatic void 5928c2ecf20Sopenharmony_cisetva(struct layer2 *l2, unsigned int nr) 5938c2ecf20Sopenharmony_ci{ 5948c2ecf20Sopenharmony_ci struct sk_buff *skb; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci while (l2->va != nr) { 5978c2ecf20Sopenharmony_ci l2->va++; 5988c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) 5998c2ecf20Sopenharmony_ci l2->va %= 128; 6008c2ecf20Sopenharmony_ci else 6018c2ecf20Sopenharmony_ci l2->va %= 8; 6028c2ecf20Sopenharmony_ci if (l2->windowar[l2->sow]) { 6038c2ecf20Sopenharmony_ci skb_trim(l2->windowar[l2->sow], 0); 6048c2ecf20Sopenharmony_ci skb_queue_tail(&l2->tmp_queue, l2->windowar[l2->sow]); 6058c2ecf20Sopenharmony_ci l2->windowar[l2->sow] = NULL; 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci l2->sow = (l2->sow + 1) % l2->window; 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci skb = skb_dequeue(&l2->tmp_queue); 6108c2ecf20Sopenharmony_ci while (skb) { 6118c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 6128c2ecf20Sopenharmony_ci skb = skb_dequeue(&l2->tmp_queue); 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cistatic void 6178c2ecf20Sopenharmony_cisend_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci u_char tmp[MAX_L2HEADER_LEN]; 6208c2ecf20Sopenharmony_ci int i; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci i = sethdraddr(l2, tmp, cr); 6238c2ecf20Sopenharmony_ci tmp[i++] = cmd; 6248c2ecf20Sopenharmony_ci if (skb) 6258c2ecf20Sopenharmony_ci skb_trim(skb, 0); 6268c2ecf20Sopenharmony_ci else { 6278c2ecf20Sopenharmony_ci skb = mI_alloc_skb(i, GFP_ATOMIC); 6288c2ecf20Sopenharmony_ci if (!skb) { 6298c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: can't alloc skbuff in %s\n", 6308c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), __func__); 6318c2ecf20Sopenharmony_ci return; 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci skb_put_data(skb, tmp, i); 6358c2ecf20Sopenharmony_ci enqueue_super(l2, skb); 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ciinline u_char 6408c2ecf20Sopenharmony_ciget_PollFlag(struct layer2 *l2, struct sk_buff *skb) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci return skb->data[l2addrsize(l2)] & 0x10; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ciinline u_char 6468c2ecf20Sopenharmony_ciget_PollFlagFree(struct layer2 *l2, struct sk_buff *skb) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci u_char PF; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci PF = get_PollFlag(l2, skb); 6518c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 6528c2ecf20Sopenharmony_ci return PF; 6538c2ecf20Sopenharmony_ci} 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ciinline void 6568c2ecf20Sopenharmony_cistart_t200(struct layer2 *l2, int i) 6578c2ecf20Sopenharmony_ci{ 6588c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i); 6598c2ecf20Sopenharmony_ci test_and_set_bit(FLG_T200_RUN, &l2->flag); 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ciinline void 6638c2ecf20Sopenharmony_cirestart_t200(struct layer2 *l2, int i) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci mISDN_FsmRestartTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i); 6668c2ecf20Sopenharmony_ci test_and_set_bit(FLG_T200_RUN, &l2->flag); 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ciinline void 6708c2ecf20Sopenharmony_cistop_t200(struct layer2 *l2, int i) 6718c2ecf20Sopenharmony_ci{ 6728c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_T200_RUN, &l2->flag)) 6738c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t200, i); 6748c2ecf20Sopenharmony_ci} 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ciinline void 6778c2ecf20Sopenharmony_cist5_dl_release_l2l3(struct layer2 *l2) 6788c2ecf20Sopenharmony_ci{ 6798c2ecf20Sopenharmony_ci int pr; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_PEND_REL, &l2->flag)) 6828c2ecf20Sopenharmony_ci pr = DL_RELEASE_CNF; 6838c2ecf20Sopenharmony_ci else 6848c2ecf20Sopenharmony_ci pr = DL_RELEASE_IND; 6858c2ecf20Sopenharmony_ci l2up_create(l2, pr, 0, NULL); 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ciinline void 6898c2ecf20Sopenharmony_cilapb_dl_release_l2l3(struct layer2 *l2, int f) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPB, &l2->flag)) 6928c2ecf20Sopenharmony_ci l2down_create(l2, PH_DEACTIVATE_REQ, l2_newid(l2), 0, NULL); 6938c2ecf20Sopenharmony_ci l2up_create(l2, f, 0, NULL); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_cistatic void 6978c2ecf20Sopenharmony_ciestablishlink(struct FsmInst *fi) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7008c2ecf20Sopenharmony_ci u_char cmd; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci clear_exception(l2); 7038c2ecf20Sopenharmony_ci l2->rc = 0; 7048c2ecf20Sopenharmony_ci cmd = (test_bit(FLG_MOD128, &l2->flag) ? SABME : SABM) | 0x10; 7058c2ecf20Sopenharmony_ci send_uframe(l2, NULL, cmd, CMD); 7068c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 1); 7078c2ecf20Sopenharmony_ci restart_t200(l2, 1); 7088c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_PEND_REL, &l2->flag); 7098c2ecf20Sopenharmony_ci freewin(l2); 7108c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_5); 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic void 7148c2ecf20Sopenharmony_cil2_mdl_error_ua(struct FsmInst *fi, int event, void *arg) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 7178c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci if (get_PollFlagFree(l2, skb)) 7208c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'C'); 7218c2ecf20Sopenharmony_ci else 7228c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'D'); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic void 7278c2ecf20Sopenharmony_cil2_mdl_error_dm(struct FsmInst *fi, int event, void *arg) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 7308c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci if (get_PollFlagFree(l2, skb)) 7338c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'B'); 7348c2ecf20Sopenharmony_ci else { 7358c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'E'); 7368c2ecf20Sopenharmony_ci establishlink(fi); 7378c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L3_INIT, &l2->flag); 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistatic void 7428c2ecf20Sopenharmony_cil2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 7458c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (get_PollFlagFree(l2, skb)) 7488c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'B'); 7498c2ecf20Sopenharmony_ci else 7508c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'E'); 7518c2ecf20Sopenharmony_ci establishlink(fi); 7528c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L3_INIT, &l2->flag); 7538c2ecf20Sopenharmony_ci} 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic void 7568c2ecf20Sopenharmony_cil2_go_st3(struct FsmInst *fi, int event, void *arg) 7578c2ecf20Sopenharmony_ci{ 7588c2ecf20Sopenharmony_ci dev_kfree_skb((struct sk_buff *)arg); 7598c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_3); 7608c2ecf20Sopenharmony_ci} 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_cistatic void 7638c2ecf20Sopenharmony_cil2_mdl_assign(struct FsmInst *fi, int event, void *arg) 7648c2ecf20Sopenharmony_ci{ 7658c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_3); 7688c2ecf20Sopenharmony_ci dev_kfree_skb((struct sk_buff *)arg); 7698c2ecf20Sopenharmony_ci l2_tei(l2, MDL_ASSIGN_IND, 0); 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cistatic void 7738c2ecf20Sopenharmony_cil2_queue_ui_assign(struct FsmInst *fi, int event, void *arg) 7748c2ecf20Sopenharmony_ci{ 7758c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7768c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci skb_queue_tail(&l2->ui_queue, skb); 7798c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_2); 7808c2ecf20Sopenharmony_ci l2_tei(l2, MDL_ASSIGN_IND, 0); 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_cistatic void 7848c2ecf20Sopenharmony_cil2_queue_ui(struct FsmInst *fi, int event, void *arg) 7858c2ecf20Sopenharmony_ci{ 7868c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 7878c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci skb_queue_tail(&l2->ui_queue, skb); 7908c2ecf20Sopenharmony_ci} 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_cistatic void 7938c2ecf20Sopenharmony_citx_ui(struct layer2 *l2) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci struct sk_buff *skb; 7968c2ecf20Sopenharmony_ci u_char header[MAX_L2HEADER_LEN]; 7978c2ecf20Sopenharmony_ci int i; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci i = sethdraddr(l2, header, CMD); 8008c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD_NET, &l2->flag)) 8018c2ecf20Sopenharmony_ci header[1] = 0xff; /* tei 127 */ 8028c2ecf20Sopenharmony_ci header[i++] = UI; 8038c2ecf20Sopenharmony_ci while ((skb = skb_dequeue(&l2->ui_queue))) { 8048c2ecf20Sopenharmony_ci memcpy(skb_push(skb, i), header, i); 8058c2ecf20Sopenharmony_ci enqueue_ui(l2, skb); 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci} 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic void 8108c2ecf20Sopenharmony_cil2_send_ui(struct FsmInst *fi, int event, void *arg) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8138c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci skb_queue_tail(&l2->ui_queue, skb); 8168c2ecf20Sopenharmony_ci tx_ui(l2); 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistatic void 8208c2ecf20Sopenharmony_cil2_got_ui(struct FsmInst *fi, int event, void *arg) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8238c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci skb_pull(skb, l2headersize(l2, 1)); 8268c2ecf20Sopenharmony_ci/* 8278c2ecf20Sopenharmony_ci * in states 1-3 for broadcast 8288c2ecf20Sopenharmony_ci */ 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci if (l2->tm) 8318c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_UI_IND, 0); 8328c2ecf20Sopenharmony_ci l2up(l2, DL_UNITDATA_IND, skb); 8338c2ecf20Sopenharmony_ci} 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_cistatic void 8368c2ecf20Sopenharmony_cil2_establish(struct FsmInst *fi, int event, void *arg) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8398c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci establishlink(fi); 8428c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L3_INIT, &l2->flag); 8438c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 8448c2ecf20Sopenharmony_ci} 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_cistatic void 8478c2ecf20Sopenharmony_cil2_discard_i_setl3(struct FsmInst *fi, int event, void *arg) 8488c2ecf20Sopenharmony_ci{ 8498c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8508c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 8538c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L3_INIT, &l2->flag); 8548c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_PEND_REL, &l2->flag); 8558c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_cistatic void 8598c2ecf20Sopenharmony_cil2_l3_reestablish(struct FsmInst *fi, int event, void *arg) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8628c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 8658c2ecf20Sopenharmony_ci establishlink(fi); 8668c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L3_INIT, &l2->flag); 8678c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 8688c2ecf20Sopenharmony_ci} 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_cistatic void 8718c2ecf20Sopenharmony_cil2_release(struct FsmInst *fi, int event, void *arg) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8748c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci skb_trim(skb, 0); 8778c2ecf20Sopenharmony_ci l2up(l2, DL_RELEASE_CNF, skb); 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic void 8818c2ecf20Sopenharmony_cil2_pend_rel(struct FsmInst *fi, int event, void *arg) 8828c2ecf20Sopenharmony_ci{ 8838c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8848c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci test_and_set_bit(FLG_PEND_REL, &l2->flag); 8878c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 8888c2ecf20Sopenharmony_ci} 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic void 8918c2ecf20Sopenharmony_cil2_disconnect(struct FsmInst *fi, int event, void *arg) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 8948c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 8978c2ecf20Sopenharmony_ci freewin(l2); 8988c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_6); 8998c2ecf20Sopenharmony_ci l2->rc = 0; 9008c2ecf20Sopenharmony_ci send_uframe(l2, NULL, DISC | 0x10, CMD); 9018c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 1); 9028c2ecf20Sopenharmony_ci restart_t200(l2, 2); 9038c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic void 9078c2ecf20Sopenharmony_cil2_start_multi(struct FsmInst *fi, int event, void *arg) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 9108c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci l2->vs = 0; 9138c2ecf20Sopenharmony_ci l2->va = 0; 9148c2ecf20Sopenharmony_ci l2->vr = 0; 9158c2ecf20Sopenharmony_ci l2->sow = 0; 9168c2ecf20Sopenharmony_ci clear_exception(l2); 9178c2ecf20Sopenharmony_ci send_uframe(l2, NULL, UA | get_PollFlag(l2, skb), RSP); 9188c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_7); 9198c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3); 9208c2ecf20Sopenharmony_ci skb_trim(skb, 0); 9218c2ecf20Sopenharmony_ci l2up(l2, DL_ESTABLISH_IND, skb); 9228c2ecf20Sopenharmony_ci if (l2->tm) 9238c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_UP_IND, 0); 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cistatic void 9278c2ecf20Sopenharmony_cil2_send_UA(struct FsmInst *fi, int event, void *arg) 9288c2ecf20Sopenharmony_ci{ 9298c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 9308c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP); 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic void 9368c2ecf20Sopenharmony_cil2_send_DM(struct FsmInst *fi, int event, void *arg) 9378c2ecf20Sopenharmony_ci{ 9388c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 9398c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci send_uframe(l2, skb, DM | get_PollFlag(l2, skb), RSP); 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cistatic void 9458c2ecf20Sopenharmony_cil2_restart_multi(struct FsmInst *fi, int event, void *arg) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 9488c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 9498c2ecf20Sopenharmony_ci int est = 0; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'F'); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (l2->vs != l2->va) { 9568c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 9578c2ecf20Sopenharmony_ci est = 1; 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci clear_exception(l2); 9618c2ecf20Sopenharmony_ci l2->vs = 0; 9628c2ecf20Sopenharmony_ci l2->va = 0; 9638c2ecf20Sopenharmony_ci l2->vr = 0; 9648c2ecf20Sopenharmony_ci l2->sow = 0; 9658c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_7); 9668c2ecf20Sopenharmony_ci stop_t200(l2, 3); 9678c2ecf20Sopenharmony_ci mISDN_FsmRestartTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (est) 9708c2ecf20Sopenharmony_ci l2up_create(l2, DL_ESTABLISH_IND, 0, NULL); 9718c2ecf20Sopenharmony_ci/* mISDN_queue_data(&l2->inst, l2->inst.id | MSG_BROADCAST, 9728c2ecf20Sopenharmony_ci * MGR_SHORTSTATUS | INDICATION, SSTATUS_L2_ESTABLISHED, 9738c2ecf20Sopenharmony_ci * 0, NULL, 0); 9748c2ecf20Sopenharmony_ci */ 9758c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->i_queue) && cansend(l2)) 9768c2ecf20Sopenharmony_ci mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL); 9778c2ecf20Sopenharmony_ci} 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cistatic void 9808c2ecf20Sopenharmony_cil2_stop_multi(struct FsmInst *fi, int event, void *arg) 9818c2ecf20Sopenharmony_ci{ 9828c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 9838c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 9868c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 3); 9878c2ecf20Sopenharmony_ci stop_t200(l2, 4); 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP); 9908c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 9918c2ecf20Sopenharmony_ci freewin(l2); 9928c2ecf20Sopenharmony_ci lapb_dl_release_l2l3(l2, DL_RELEASE_IND); 9938c2ecf20Sopenharmony_ci if (l2->tm) 9948c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 9958c2ecf20Sopenharmony_ci} 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_cistatic void 9988c2ecf20Sopenharmony_cil2_connected(struct FsmInst *fi, int event, void *arg) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 10018c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 10028c2ecf20Sopenharmony_ci int pr = -1; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci if (!get_PollFlag(l2, skb)) { 10058c2ecf20Sopenharmony_ci l2_mdl_error_ua(fi, event, arg); 10068c2ecf20Sopenharmony_ci return; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 10098c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_PEND_REL, &l2->flag)) 10108c2ecf20Sopenharmony_ci l2_disconnect(fi, event, NULL); 10118c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_L3_INIT, &l2->flag)) { 10128c2ecf20Sopenharmony_ci pr = DL_ESTABLISH_CNF; 10138c2ecf20Sopenharmony_ci } else if (l2->vs != l2->va) { 10148c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 10158c2ecf20Sopenharmony_ci pr = DL_ESTABLISH_IND; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci stop_t200(l2, 5); 10188c2ecf20Sopenharmony_ci l2->vr = 0; 10198c2ecf20Sopenharmony_ci l2->vs = 0; 10208c2ecf20Sopenharmony_ci l2->va = 0; 10218c2ecf20Sopenharmony_ci l2->sow = 0; 10228c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_7); 10238c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 4); 10248c2ecf20Sopenharmony_ci if (pr != -1) 10258c2ecf20Sopenharmony_ci l2up_create(l2, pr, 0, NULL); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->i_queue) && cansend(l2)) 10288c2ecf20Sopenharmony_ci mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci if (l2->tm) 10318c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_UP_IND, 0); 10328c2ecf20Sopenharmony_ci} 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_cistatic void 10358c2ecf20Sopenharmony_cil2_released(struct FsmInst *fi, int event, void *arg) 10368c2ecf20Sopenharmony_ci{ 10378c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 10388c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci if (!get_PollFlag(l2, skb)) { 10418c2ecf20Sopenharmony_ci l2_mdl_error_ua(fi, event, arg); 10428c2ecf20Sopenharmony_ci return; 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 10458c2ecf20Sopenharmony_ci stop_t200(l2, 6); 10468c2ecf20Sopenharmony_ci lapb_dl_release_l2l3(l2, DL_RELEASE_CNF); 10478c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 10488c2ecf20Sopenharmony_ci if (l2->tm) 10498c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 10508c2ecf20Sopenharmony_ci} 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_cistatic void 10538c2ecf20Sopenharmony_cil2_reestablish(struct FsmInst *fi, int event, void *arg) 10548c2ecf20Sopenharmony_ci{ 10558c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 10568c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci if (!get_PollFlagFree(l2, skb)) { 10598c2ecf20Sopenharmony_ci establishlink(fi); 10608c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L3_INIT, &l2->flag); 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic void 10658c2ecf20Sopenharmony_cil2_st5_dm_release(struct FsmInst *fi, int event, void *arg) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 10688c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (get_PollFlagFree(l2, skb)) { 10718c2ecf20Sopenharmony_ci stop_t200(l2, 7); 10728c2ecf20Sopenharmony_ci if (!test_bit(FLG_L3_INIT, &l2->flag)) 10738c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 10748c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPB, &l2->flag)) 10758c2ecf20Sopenharmony_ci l2down_create(l2, PH_DEACTIVATE_REQ, 10768c2ecf20Sopenharmony_ci l2_newid(l2), 0, NULL); 10778c2ecf20Sopenharmony_ci st5_dl_release_l2l3(l2); 10788c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 10798c2ecf20Sopenharmony_ci if (l2->tm) 10808c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 10818c2ecf20Sopenharmony_ci } 10828c2ecf20Sopenharmony_ci} 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_cistatic void 10858c2ecf20Sopenharmony_cil2_st6_dm_release(struct FsmInst *fi, int event, void *arg) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 10888c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci if (get_PollFlagFree(l2, skb)) { 10918c2ecf20Sopenharmony_ci stop_t200(l2, 8); 10928c2ecf20Sopenharmony_ci lapb_dl_release_l2l3(l2, DL_RELEASE_CNF); 10938c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 10948c2ecf20Sopenharmony_ci if (l2->tm) 10958c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci} 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_cistatic void 11008c2ecf20Sopenharmony_cienquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf) 11018c2ecf20Sopenharmony_ci{ 11028c2ecf20Sopenharmony_ci struct sk_buff *skb; 11038c2ecf20Sopenharmony_ci u_char tmp[MAX_L2HEADER_LEN]; 11048c2ecf20Sopenharmony_ci int i; 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci i = sethdraddr(l2, tmp, cr); 11078c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 11088c2ecf20Sopenharmony_ci tmp[i++] = typ; 11098c2ecf20Sopenharmony_ci tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0); 11108c2ecf20Sopenharmony_ci } else 11118c2ecf20Sopenharmony_ci tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0); 11128c2ecf20Sopenharmony_ci skb = mI_alloc_skb(i, GFP_ATOMIC); 11138c2ecf20Sopenharmony_ci if (!skb) { 11148c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: isdnl2 can't alloc sbbuff in %s\n", 11158c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), __func__); 11168c2ecf20Sopenharmony_ci return; 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci skb_put_data(skb, tmp, i); 11198c2ecf20Sopenharmony_ci enqueue_super(l2, skb); 11208c2ecf20Sopenharmony_ci} 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ciinline void 11238c2ecf20Sopenharmony_cienquiry_response(struct layer2 *l2) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci if (test_bit(FLG_OWN_BUSY, &l2->flag)) 11268c2ecf20Sopenharmony_ci enquiry_cr(l2, RNR, RSP, 1); 11278c2ecf20Sopenharmony_ci else 11288c2ecf20Sopenharmony_ci enquiry_cr(l2, RR, RSP, 1); 11298c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ciinline void 11338c2ecf20Sopenharmony_citransmit_enquiry(struct layer2 *l2) 11348c2ecf20Sopenharmony_ci{ 11358c2ecf20Sopenharmony_ci if (test_bit(FLG_OWN_BUSY, &l2->flag)) 11368c2ecf20Sopenharmony_ci enquiry_cr(l2, RNR, CMD, 1); 11378c2ecf20Sopenharmony_ci else 11388c2ecf20Sopenharmony_ci enquiry_cr(l2, RR, CMD, 1); 11398c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 11408c2ecf20Sopenharmony_ci start_t200(l2, 9); 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_cistatic void 11458c2ecf20Sopenharmony_cinrerrorrecovery(struct FsmInst *fi) 11468c2ecf20Sopenharmony_ci{ 11478c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'J'); 11508c2ecf20Sopenharmony_ci establishlink(fi); 11518c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L3_INIT, &l2->flag); 11528c2ecf20Sopenharmony_ci} 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_cistatic void 11558c2ecf20Sopenharmony_ciinvoke_retransmission(struct layer2 *l2, unsigned int nr) 11568c2ecf20Sopenharmony_ci{ 11578c2ecf20Sopenharmony_ci u_int p1; 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci if (l2->vs != nr) { 11608c2ecf20Sopenharmony_ci while (l2->vs != nr) { 11618c2ecf20Sopenharmony_ci (l2->vs)--; 11628c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 11638c2ecf20Sopenharmony_ci l2->vs %= 128; 11648c2ecf20Sopenharmony_ci p1 = (l2->vs - l2->va) % 128; 11658c2ecf20Sopenharmony_ci } else { 11668c2ecf20Sopenharmony_ci l2->vs %= 8; 11678c2ecf20Sopenharmony_ci p1 = (l2->vs - l2->va) % 8; 11688c2ecf20Sopenharmony_ci } 11698c2ecf20Sopenharmony_ci p1 = (p1 + l2->sow) % l2->window; 11708c2ecf20Sopenharmony_ci if (l2->windowar[p1]) 11718c2ecf20Sopenharmony_ci skb_queue_head(&l2->i_queue, l2->windowar[p1]); 11728c2ecf20Sopenharmony_ci else 11738c2ecf20Sopenharmony_ci printk(KERN_WARNING 11748c2ecf20Sopenharmony_ci "%s: windowar[%d] is NULL\n", 11758c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), p1); 11768c2ecf20Sopenharmony_ci l2->windowar[p1] = NULL; 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL); 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci} 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_cistatic void 11838c2ecf20Sopenharmony_cil2_st7_got_super(struct FsmInst *fi, int event, void *arg) 11848c2ecf20Sopenharmony_ci{ 11858c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 11868c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 11878c2ecf20Sopenharmony_ci int PollFlag, rsp, typ = RR; 11888c2ecf20Sopenharmony_ci unsigned int nr; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci rsp = *skb->data & 0x2; 11918c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 11928c2ecf20Sopenharmony_ci rsp = !rsp; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci skb_pull(skb, l2addrsize(l2)); 11958c2ecf20Sopenharmony_ci if (IsRNR(skb->data, l2)) { 11968c2ecf20Sopenharmony_ci set_peer_busy(l2); 11978c2ecf20Sopenharmony_ci typ = RNR; 11988c2ecf20Sopenharmony_ci } else 11998c2ecf20Sopenharmony_ci clear_peer_busy(l2); 12008c2ecf20Sopenharmony_ci if (IsREJ(skb->data, l2)) 12018c2ecf20Sopenharmony_ci typ = REJ; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 12048c2ecf20Sopenharmony_ci PollFlag = (skb->data[1] & 0x1) == 0x1; 12058c2ecf20Sopenharmony_ci nr = skb->data[1] >> 1; 12068c2ecf20Sopenharmony_ci } else { 12078c2ecf20Sopenharmony_ci PollFlag = (skb->data[0] & 0x10); 12088c2ecf20Sopenharmony_ci nr = (skb->data[0] >> 5) & 0x7; 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci if (PollFlag) { 12138c2ecf20Sopenharmony_ci if (rsp) 12148c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'A'); 12158c2ecf20Sopenharmony_ci else 12168c2ecf20Sopenharmony_ci enquiry_response(l2); 12178c2ecf20Sopenharmony_ci } 12188c2ecf20Sopenharmony_ci if (legalnr(l2, nr)) { 12198c2ecf20Sopenharmony_ci if (typ == REJ) { 12208c2ecf20Sopenharmony_ci setva(l2, nr); 12218c2ecf20Sopenharmony_ci invoke_retransmission(l2, nr); 12228c2ecf20Sopenharmony_ci stop_t200(l2, 10); 12238c2ecf20Sopenharmony_ci if (mISDN_FsmAddTimer(&l2->t203, l2->T203, 12248c2ecf20Sopenharmony_ci EV_L2_T203, NULL, 6)) 12258c2ecf20Sopenharmony_ci l2m_debug(&l2->l2m, "Restart T203 ST7 REJ"); 12268c2ecf20Sopenharmony_ci } else if ((nr == l2->vs) && (typ == RR)) { 12278c2ecf20Sopenharmony_ci setva(l2, nr); 12288c2ecf20Sopenharmony_ci stop_t200(l2, 11); 12298c2ecf20Sopenharmony_ci mISDN_FsmRestartTimer(&l2->t203, l2->T203, 12308c2ecf20Sopenharmony_ci EV_L2_T203, NULL, 7); 12318c2ecf20Sopenharmony_ci } else if ((l2->va != nr) || (typ == RNR)) { 12328c2ecf20Sopenharmony_ci setva(l2, nr); 12338c2ecf20Sopenharmony_ci if (typ != RR) 12348c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 9); 12358c2ecf20Sopenharmony_ci restart_t200(l2, 12); 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->i_queue) && (typ == RR)) 12388c2ecf20Sopenharmony_ci mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL); 12398c2ecf20Sopenharmony_ci } else 12408c2ecf20Sopenharmony_ci nrerrorrecovery(fi); 12418c2ecf20Sopenharmony_ci} 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_cistatic void 12448c2ecf20Sopenharmony_cil2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg) 12458c2ecf20Sopenharmony_ci{ 12468c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 12478c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci if (!test_bit(FLG_L3_INIT, &l2->flag)) 12508c2ecf20Sopenharmony_ci skb_queue_tail(&l2->i_queue, skb); 12518c2ecf20Sopenharmony_ci else 12528c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic void 12568c2ecf20Sopenharmony_cil2_feed_i_pull(struct FsmInst *fi, int event, void *arg) 12578c2ecf20Sopenharmony_ci{ 12588c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 12598c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci skb_queue_tail(&l2->i_queue, skb); 12628c2ecf20Sopenharmony_ci mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL); 12638c2ecf20Sopenharmony_ci} 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_cistatic void 12668c2ecf20Sopenharmony_cil2_feed_iqueue(struct FsmInst *fi, int event, void *arg) 12678c2ecf20Sopenharmony_ci{ 12688c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 12698c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci skb_queue_tail(&l2->i_queue, skb); 12728c2ecf20Sopenharmony_ci} 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_cistatic void 12758c2ecf20Sopenharmony_cil2_got_iframe(struct FsmInst *fi, int event, void *arg) 12768c2ecf20Sopenharmony_ci{ 12778c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 12788c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 12798c2ecf20Sopenharmony_ci int PollFlag, i; 12808c2ecf20Sopenharmony_ci u_int ns, nr; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci i = l2addrsize(l2); 12838c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 12848c2ecf20Sopenharmony_ci PollFlag = ((skb->data[i + 1] & 0x1) == 0x1); 12858c2ecf20Sopenharmony_ci ns = skb->data[i] >> 1; 12868c2ecf20Sopenharmony_ci nr = (skb->data[i + 1] >> 1) & 0x7f; 12878c2ecf20Sopenharmony_ci } else { 12888c2ecf20Sopenharmony_ci PollFlag = (skb->data[i] & 0x10); 12898c2ecf20Sopenharmony_ci ns = (skb->data[i] >> 1) & 0x7; 12908c2ecf20Sopenharmony_ci nr = (skb->data[i] >> 5) & 0x7; 12918c2ecf20Sopenharmony_ci } 12928c2ecf20Sopenharmony_ci if (test_bit(FLG_OWN_BUSY, &l2->flag)) { 12938c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 12948c2ecf20Sopenharmony_ci if (PollFlag) 12958c2ecf20Sopenharmony_ci enquiry_response(l2); 12968c2ecf20Sopenharmony_ci } else { 12978c2ecf20Sopenharmony_ci if (l2->vr == ns) { 12988c2ecf20Sopenharmony_ci l2->vr++; 12998c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) 13008c2ecf20Sopenharmony_ci l2->vr %= 128; 13018c2ecf20Sopenharmony_ci else 13028c2ecf20Sopenharmony_ci l2->vr %= 8; 13038c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_REJEXC, &l2->flag); 13048c2ecf20Sopenharmony_ci if (PollFlag) 13058c2ecf20Sopenharmony_ci enquiry_response(l2); 13068c2ecf20Sopenharmony_ci else 13078c2ecf20Sopenharmony_ci test_and_set_bit(FLG_ACK_PEND, &l2->flag); 13088c2ecf20Sopenharmony_ci skb_pull(skb, l2headersize(l2, 0)); 13098c2ecf20Sopenharmony_ci l2up(l2, DL_DATA_IND, skb); 13108c2ecf20Sopenharmony_ci } else { 13118c2ecf20Sopenharmony_ci /* n(s)!=v(r) */ 13128c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 13138c2ecf20Sopenharmony_ci if (test_and_set_bit(FLG_REJEXC, &l2->flag)) { 13148c2ecf20Sopenharmony_ci if (PollFlag) 13158c2ecf20Sopenharmony_ci enquiry_response(l2); 13168c2ecf20Sopenharmony_ci } else { 13178c2ecf20Sopenharmony_ci enquiry_cr(l2, REJ, RSP, PollFlag); 13188c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci } 13228c2ecf20Sopenharmony_ci if (legalnr(l2, nr)) { 13238c2ecf20Sopenharmony_ci if (!test_bit(FLG_PEER_BUSY, &l2->flag) && 13248c2ecf20Sopenharmony_ci (fi->state == ST_L2_7)) { 13258c2ecf20Sopenharmony_ci if (nr == l2->vs) { 13268c2ecf20Sopenharmony_ci stop_t200(l2, 13); 13278c2ecf20Sopenharmony_ci mISDN_FsmRestartTimer(&l2->t203, l2->T203, 13288c2ecf20Sopenharmony_ci EV_L2_T203, NULL, 7); 13298c2ecf20Sopenharmony_ci } else if (nr != l2->va) 13308c2ecf20Sopenharmony_ci restart_t200(l2, 14); 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci setva(l2, nr); 13338c2ecf20Sopenharmony_ci } else { 13348c2ecf20Sopenharmony_ci nrerrorrecovery(fi); 13358c2ecf20Sopenharmony_ci return; 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->i_queue) && (fi->state == ST_L2_7)) 13388c2ecf20Sopenharmony_ci mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL); 13398c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_ACK_PEND, &l2->flag)) 13408c2ecf20Sopenharmony_ci enquiry_cr(l2, RR, RSP, 0); 13418c2ecf20Sopenharmony_ci} 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_cistatic void 13448c2ecf20Sopenharmony_cil2_got_tei(struct FsmInst *fi, int event, void *arg) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 13478c2ecf20Sopenharmony_ci u_int info; 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci l2->tei = (signed char)(long)arg; 13508c2ecf20Sopenharmony_ci set_channel_address(&l2->ch, l2->sapi, l2->tei); 13518c2ecf20Sopenharmony_ci info = DL_INFO_L2_CONNECT; 13528c2ecf20Sopenharmony_ci l2up_create(l2, DL_INFORMATION_IND, sizeof(info), &info); 13538c2ecf20Sopenharmony_ci if (fi->state == ST_L2_3) { 13548c2ecf20Sopenharmony_ci establishlink(fi); 13558c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L3_INIT, &l2->flag); 13568c2ecf20Sopenharmony_ci } else 13578c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 13588c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->ui_queue)) 13598c2ecf20Sopenharmony_ci tx_ui(l2); 13608c2ecf20Sopenharmony_ci} 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_cistatic void 13638c2ecf20Sopenharmony_cil2_st5_tout_200(struct FsmInst *fi, int event, void *arg) 13648c2ecf20Sopenharmony_ci{ 13658c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) && 13688c2ecf20Sopenharmony_ci test_bit(FLG_DCHAN_BUSY, &l2->flag)) { 13698c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9); 13708c2ecf20Sopenharmony_ci } else if (l2->rc == l2->N200) { 13718c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 13728c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_T200_RUN, &l2->flag); 13738c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 13748c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'G'); 13758c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPB, &l2->flag)) 13768c2ecf20Sopenharmony_ci l2down_create(l2, PH_DEACTIVATE_REQ, 13778c2ecf20Sopenharmony_ci l2_newid(l2), 0, NULL); 13788c2ecf20Sopenharmony_ci st5_dl_release_l2l3(l2); 13798c2ecf20Sopenharmony_ci if (l2->tm) 13808c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 13818c2ecf20Sopenharmony_ci } else { 13828c2ecf20Sopenharmony_ci l2->rc++; 13838c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9); 13848c2ecf20Sopenharmony_ci send_uframe(l2, NULL, (test_bit(FLG_MOD128, &l2->flag) ? 13858c2ecf20Sopenharmony_ci SABME : SABM) | 0x10, CMD); 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic void 13908c2ecf20Sopenharmony_cil2_st6_tout_200(struct FsmInst *fi, int event, void *arg) 13918c2ecf20Sopenharmony_ci{ 13928c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) && 13958c2ecf20Sopenharmony_ci test_bit(FLG_DCHAN_BUSY, &l2->flag)) { 13968c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9); 13978c2ecf20Sopenharmony_ci } else if (l2->rc == l2->N200) { 13988c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 13998c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_T200_RUN, &l2->flag); 14008c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'H'); 14018c2ecf20Sopenharmony_ci lapb_dl_release_l2l3(l2, DL_RELEASE_CNF); 14028c2ecf20Sopenharmony_ci if (l2->tm) 14038c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 14048c2ecf20Sopenharmony_ci } else { 14058c2ecf20Sopenharmony_ci l2->rc++; 14068c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, 14078c2ecf20Sopenharmony_ci NULL, 9); 14088c2ecf20Sopenharmony_ci send_uframe(l2, NULL, DISC | 0x10, CMD); 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic void 14138c2ecf20Sopenharmony_cil2_st7_tout_200(struct FsmInst *fi, int event, void *arg) 14148c2ecf20Sopenharmony_ci{ 14158c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) && 14188c2ecf20Sopenharmony_ci test_bit(FLG_DCHAN_BUSY, &l2->flag)) { 14198c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9); 14208c2ecf20Sopenharmony_ci return; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_T200_RUN, &l2->flag); 14238c2ecf20Sopenharmony_ci l2->rc = 0; 14248c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_8); 14258c2ecf20Sopenharmony_ci transmit_enquiry(l2); 14268c2ecf20Sopenharmony_ci l2->rc++; 14278c2ecf20Sopenharmony_ci} 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_cistatic void 14308c2ecf20Sopenharmony_cil2_st8_tout_200(struct FsmInst *fi, int event, void *arg) 14318c2ecf20Sopenharmony_ci{ 14328c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) && 14358c2ecf20Sopenharmony_ci test_bit(FLG_DCHAN_BUSY, &l2->flag)) { 14368c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9); 14378c2ecf20Sopenharmony_ci return; 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_T200_RUN, &l2->flag); 14408c2ecf20Sopenharmony_ci if (l2->rc == l2->N200) { 14418c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'I'); 14428c2ecf20Sopenharmony_ci establishlink(fi); 14438c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L3_INIT, &l2->flag); 14448c2ecf20Sopenharmony_ci } else { 14458c2ecf20Sopenharmony_ci transmit_enquiry(l2); 14468c2ecf20Sopenharmony_ci l2->rc++; 14478c2ecf20Sopenharmony_ci } 14488c2ecf20Sopenharmony_ci} 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic void 14518c2ecf20Sopenharmony_cil2_st7_tout_203(struct FsmInst *fi, int event, void *arg) 14528c2ecf20Sopenharmony_ci{ 14538c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) && 14568c2ecf20Sopenharmony_ci test_bit(FLG_DCHAN_BUSY, &l2->flag)) { 14578c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 9); 14588c2ecf20Sopenharmony_ci return; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_8); 14618c2ecf20Sopenharmony_ci transmit_enquiry(l2); 14628c2ecf20Sopenharmony_ci l2->rc = 0; 14638c2ecf20Sopenharmony_ci} 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic void 14668c2ecf20Sopenharmony_cil2_pull_iqueue(struct FsmInst *fi, int event, void *arg) 14678c2ecf20Sopenharmony_ci{ 14688c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 14698c2ecf20Sopenharmony_ci struct sk_buff *skb, *nskb; 14708c2ecf20Sopenharmony_ci u_char header[MAX_L2HEADER_LEN]; 14718c2ecf20Sopenharmony_ci u_int i, p1; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if (!cansend(l2)) 14748c2ecf20Sopenharmony_ci return; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci skb = skb_dequeue(&l2->i_queue); 14778c2ecf20Sopenharmony_ci if (!skb) 14788c2ecf20Sopenharmony_ci return; 14798c2ecf20Sopenharmony_ci i = sethdraddr(l2, header, CMD); 14808c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 14818c2ecf20Sopenharmony_ci header[i++] = l2->vs << 1; 14828c2ecf20Sopenharmony_ci header[i++] = l2->vr << 1; 14838c2ecf20Sopenharmony_ci } else 14848c2ecf20Sopenharmony_ci header[i++] = (l2->vr << 5) | (l2->vs << 1); 14858c2ecf20Sopenharmony_ci nskb = skb_realloc_headroom(skb, i); 14868c2ecf20Sopenharmony_ci if (!nskb) { 14878c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: no headroom(%d) copy for IFrame\n", 14888c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), i); 14898c2ecf20Sopenharmony_ci skb_queue_head(&l2->i_queue, skb); 14908c2ecf20Sopenharmony_ci return; 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 14938c2ecf20Sopenharmony_ci p1 = (l2->vs - l2->va) % 128; 14948c2ecf20Sopenharmony_ci l2->vs = (l2->vs + 1) % 128; 14958c2ecf20Sopenharmony_ci } else { 14968c2ecf20Sopenharmony_ci p1 = (l2->vs - l2->va) % 8; 14978c2ecf20Sopenharmony_ci l2->vs = (l2->vs + 1) % 8; 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci p1 = (p1 + l2->sow) % l2->window; 15008c2ecf20Sopenharmony_ci if (l2->windowar[p1]) { 15018c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n", 15028c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), p1); 15038c2ecf20Sopenharmony_ci dev_kfree_skb(l2->windowar[p1]); 15048c2ecf20Sopenharmony_ci } 15058c2ecf20Sopenharmony_ci l2->windowar[p1] = skb; 15068c2ecf20Sopenharmony_ci memcpy(skb_push(nskb, i), header, i); 15078c2ecf20Sopenharmony_ci l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb); 15088c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 15098c2ecf20Sopenharmony_ci if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) { 15108c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 13); 15118c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 11); 15128c2ecf20Sopenharmony_ci } 15138c2ecf20Sopenharmony_ci} 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_cistatic void 15168c2ecf20Sopenharmony_cil2_st8_got_super(struct FsmInst *fi, int event, void *arg) 15178c2ecf20Sopenharmony_ci{ 15188c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 15198c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 15208c2ecf20Sopenharmony_ci int PollFlag, rsp, rnr = 0; 15218c2ecf20Sopenharmony_ci unsigned int nr; 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci rsp = *skb->data & 0x2; 15248c2ecf20Sopenharmony_ci if (test_bit(FLG_ORIG, &l2->flag)) 15258c2ecf20Sopenharmony_ci rsp = !rsp; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci skb_pull(skb, l2addrsize(l2)); 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci if (IsRNR(skb->data, l2)) { 15308c2ecf20Sopenharmony_ci set_peer_busy(l2); 15318c2ecf20Sopenharmony_ci rnr = 1; 15328c2ecf20Sopenharmony_ci } else 15338c2ecf20Sopenharmony_ci clear_peer_busy(l2); 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci if (test_bit(FLG_MOD128, &l2->flag)) { 15368c2ecf20Sopenharmony_ci PollFlag = (skb->data[1] & 0x1) == 0x1; 15378c2ecf20Sopenharmony_ci nr = skb->data[1] >> 1; 15388c2ecf20Sopenharmony_ci } else { 15398c2ecf20Sopenharmony_ci PollFlag = (skb->data[0] & 0x10); 15408c2ecf20Sopenharmony_ci nr = (skb->data[0] >> 5) & 0x7; 15418c2ecf20Sopenharmony_ci } 15428c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 15438c2ecf20Sopenharmony_ci if (rsp && PollFlag) { 15448c2ecf20Sopenharmony_ci if (legalnr(l2, nr)) { 15458c2ecf20Sopenharmony_ci if (rnr) { 15468c2ecf20Sopenharmony_ci restart_t200(l2, 15); 15478c2ecf20Sopenharmony_ci } else { 15488c2ecf20Sopenharmony_ci stop_t200(l2, 16); 15498c2ecf20Sopenharmony_ci mISDN_FsmAddTimer(&l2->t203, l2->T203, 15508c2ecf20Sopenharmony_ci EV_L2_T203, NULL, 5); 15518c2ecf20Sopenharmony_ci setva(l2, nr); 15528c2ecf20Sopenharmony_ci } 15538c2ecf20Sopenharmony_ci invoke_retransmission(l2, nr); 15548c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_7); 15558c2ecf20Sopenharmony_ci if (skb_queue_len(&l2->i_queue) && cansend(l2)) 15568c2ecf20Sopenharmony_ci mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL); 15578c2ecf20Sopenharmony_ci } else 15588c2ecf20Sopenharmony_ci nrerrorrecovery(fi); 15598c2ecf20Sopenharmony_ci } else { 15608c2ecf20Sopenharmony_ci if (!rsp && PollFlag) 15618c2ecf20Sopenharmony_ci enquiry_response(l2); 15628c2ecf20Sopenharmony_ci if (legalnr(l2, nr)) 15638c2ecf20Sopenharmony_ci setva(l2, nr); 15648c2ecf20Sopenharmony_ci else 15658c2ecf20Sopenharmony_ci nrerrorrecovery(fi); 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_cistatic void 15708c2ecf20Sopenharmony_cil2_got_FRMR(struct FsmInst *fi, int event, void *arg) 15718c2ecf20Sopenharmony_ci{ 15728c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 15738c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci skb_pull(skb, l2addrsize(l2) + 1); 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */ 15788c2ecf20Sopenharmony_ci (IsUA(skb->data) && (fi->state == ST_L2_7))) { 15798c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, (void *) 'K'); 15808c2ecf20Sopenharmony_ci establishlink(fi); 15818c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L3_INIT, &l2->flag); 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 15848c2ecf20Sopenharmony_ci} 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_cistatic void 15878c2ecf20Sopenharmony_cil2_st24_tei_remove(struct FsmInst *fi, int event, void *arg) 15888c2ecf20Sopenharmony_ci{ 15898c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 15928c2ecf20Sopenharmony_ci l2->tei = GROUP_TEI; 15938c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_1); 15948c2ecf20Sopenharmony_ci} 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_cistatic void 15978c2ecf20Sopenharmony_cil2_st3_tei_remove(struct FsmInst *fi, int event, void *arg) 15988c2ecf20Sopenharmony_ci{ 15998c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16028c2ecf20Sopenharmony_ci l2->tei = GROUP_TEI; 16038c2ecf20Sopenharmony_ci l2up_create(l2, DL_RELEASE_IND, 0, NULL); 16048c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_1); 16058c2ecf20Sopenharmony_ci} 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_cistatic void 16088c2ecf20Sopenharmony_cil2_st5_tei_remove(struct FsmInst *fi, int event, void *arg) 16098c2ecf20Sopenharmony_ci{ 16108c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 16138c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16148c2ecf20Sopenharmony_ci freewin(l2); 16158c2ecf20Sopenharmony_ci l2->tei = GROUP_TEI; 16168c2ecf20Sopenharmony_ci stop_t200(l2, 17); 16178c2ecf20Sopenharmony_ci st5_dl_release_l2l3(l2); 16188c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_1); 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_cistatic void 16228c2ecf20Sopenharmony_cil2_st6_tei_remove(struct FsmInst *fi, int event, void *arg) 16238c2ecf20Sopenharmony_ci{ 16248c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16278c2ecf20Sopenharmony_ci l2->tei = GROUP_TEI; 16288c2ecf20Sopenharmony_ci stop_t200(l2, 18); 16298c2ecf20Sopenharmony_ci l2up_create(l2, DL_RELEASE_IND, 0, NULL); 16308c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_1); 16318c2ecf20Sopenharmony_ci} 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_cistatic void 16348c2ecf20Sopenharmony_cil2_tei_remove(struct FsmInst *fi, int event, void *arg) 16358c2ecf20Sopenharmony_ci{ 16368c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 16398c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16408c2ecf20Sopenharmony_ci freewin(l2); 16418c2ecf20Sopenharmony_ci l2->tei = GROUP_TEI; 16428c2ecf20Sopenharmony_ci stop_t200(l2, 17); 16438c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 19); 16448c2ecf20Sopenharmony_ci l2up_create(l2, DL_RELEASE_IND, 0, NULL); 16458c2ecf20Sopenharmony_ci/* mISDN_queue_data(&l2->inst, l2->inst.id | MSG_BROADCAST, 16468c2ecf20Sopenharmony_ci * MGR_SHORTSTATUS_IND, SSTATUS_L2_RELEASED, 16478c2ecf20Sopenharmony_ci * 0, NULL, 0); 16488c2ecf20Sopenharmony_ci */ 16498c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_1); 16508c2ecf20Sopenharmony_ci} 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_cistatic void 16538c2ecf20Sopenharmony_cil2_st14_persistent_da(struct FsmInst *fi, int event, void *arg) 16548c2ecf20Sopenharmony_ci{ 16558c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16568c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 16598c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16608c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag)) 16618c2ecf20Sopenharmony_ci l2up(l2, DL_RELEASE_IND, skb); 16628c2ecf20Sopenharmony_ci else 16638c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 16648c2ecf20Sopenharmony_ci} 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_cistatic void 16678c2ecf20Sopenharmony_cil2_st5_persistent_da(struct FsmInst *fi, int event, void *arg) 16688c2ecf20Sopenharmony_ci{ 16698c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16708c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 16738c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16748c2ecf20Sopenharmony_ci freewin(l2); 16758c2ecf20Sopenharmony_ci stop_t200(l2, 19); 16768c2ecf20Sopenharmony_ci st5_dl_release_l2l3(l2); 16778c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 16788c2ecf20Sopenharmony_ci if (l2->tm) 16798c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 16808c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 16818c2ecf20Sopenharmony_ci} 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_cistatic void 16848c2ecf20Sopenharmony_cil2_st6_persistent_da(struct FsmInst *fi, int event, void *arg) 16858c2ecf20Sopenharmony_ci{ 16868c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 16878c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 16908c2ecf20Sopenharmony_ci stop_t200(l2, 20); 16918c2ecf20Sopenharmony_ci l2up(l2, DL_RELEASE_CNF, skb); 16928c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 16938c2ecf20Sopenharmony_ci if (l2->tm) 16948c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 16958c2ecf20Sopenharmony_ci} 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_cistatic void 16988c2ecf20Sopenharmony_cil2_persistent_da(struct FsmInst *fi, int event, void *arg) 16998c2ecf20Sopenharmony_ci{ 17008c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 17018c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 17048c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 17058c2ecf20Sopenharmony_ci freewin(l2); 17068c2ecf20Sopenharmony_ci stop_t200(l2, 19); 17078c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 19); 17088c2ecf20Sopenharmony_ci l2up(l2, DL_RELEASE_IND, skb); 17098c2ecf20Sopenharmony_ci mISDN_FsmChangeState(fi, ST_L2_4); 17108c2ecf20Sopenharmony_ci if (l2->tm) 17118c2ecf20Sopenharmony_ci l2_tei(l2, MDL_STATUS_DOWN_IND, 0); 17128c2ecf20Sopenharmony_ci} 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_cistatic void 17158c2ecf20Sopenharmony_cil2_set_own_busy(struct FsmInst *fi, int event, void *arg) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 17188c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci if (!test_and_set_bit(FLG_OWN_BUSY, &l2->flag)) { 17218c2ecf20Sopenharmony_ci enquiry_cr(l2, RNR, RSP, 0); 17228c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 17258c2ecf20Sopenharmony_ci} 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_cistatic void 17288c2ecf20Sopenharmony_cil2_clear_own_busy(struct FsmInst *fi, int event, void *arg) 17298c2ecf20Sopenharmony_ci{ 17308c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 17318c2ecf20Sopenharmony_ci struct sk_buff *skb = arg; 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci if (!test_and_clear_bit(FLG_OWN_BUSY, &l2->flag)) { 17348c2ecf20Sopenharmony_ci enquiry_cr(l2, RR, RSP, 0); 17358c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_ACK_PEND, &l2->flag); 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 17388c2ecf20Sopenharmony_ci} 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_cistatic void 17418c2ecf20Sopenharmony_cil2_frame_error(struct FsmInst *fi, int event, void *arg) 17428c2ecf20Sopenharmony_ci{ 17438c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, arg); 17468c2ecf20Sopenharmony_ci} 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_cistatic void 17498c2ecf20Sopenharmony_cil2_frame_error_reest(struct FsmInst *fi, int event, void *arg) 17508c2ecf20Sopenharmony_ci{ 17518c2ecf20Sopenharmony_ci struct layer2 *l2 = fi->userdata; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci l2mgr(l2, MDL_ERROR_IND, arg); 17548c2ecf20Sopenharmony_ci establishlink(fi); 17558c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L3_INIT, &l2->flag); 17568c2ecf20Sopenharmony_ci} 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_cistatic struct FsmNode L2FnList[] = 17598c2ecf20Sopenharmony_ci{ 17608c2ecf20Sopenharmony_ci {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign}, 17618c2ecf20Sopenharmony_ci {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3}, 17628c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish}, 17638c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3}, 17648c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, 17658c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, 17668c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release}, 17678c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel}, 17688c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect}, 17698c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect}, 17708c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest}, 17718c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull}, 17728c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue}, 17738c2ecf20Sopenharmony_ci {ST_L2_1, EV_L2_DL_UNITDATA, l2_queue_ui_assign}, 17748c2ecf20Sopenharmony_ci {ST_L2_2, EV_L2_DL_UNITDATA, l2_queue_ui}, 17758c2ecf20Sopenharmony_ci {ST_L2_3, EV_L2_DL_UNITDATA, l2_queue_ui}, 17768c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_DL_UNITDATA, l2_send_ui}, 17778c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_DL_UNITDATA, l2_send_ui}, 17788c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_DL_UNITDATA, l2_send_ui}, 17798c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_DL_UNITDATA, l2_send_ui}, 17808c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_DL_UNITDATA, l2_send_ui}, 17818c2ecf20Sopenharmony_ci {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei}, 17828c2ecf20Sopenharmony_ci {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei}, 17838c2ecf20Sopenharmony_ci {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei}, 17848c2ecf20Sopenharmony_ci {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove}, 17858c2ecf20Sopenharmony_ci {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove}, 17868c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove}, 17878c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove}, 17888c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove}, 17898c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove}, 17908c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove}, 17918c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_SABME, l2_start_multi}, 17928c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_SABME, l2_send_UA}, 17938c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_SABME, l2_send_DM}, 17948c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_SABME, l2_restart_multi}, 17958c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_SABME, l2_restart_multi}, 17968c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_DISC, l2_send_DM}, 17978c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_DISC, l2_send_DM}, 17988c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_DISC, l2_send_UA}, 17998c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_DISC, l2_stop_multi}, 18008c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_DISC, l2_stop_multi}, 18018c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_UA, l2_mdl_error_ua}, 18028c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_UA, l2_connected}, 18038c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_UA, l2_released}, 18048c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_UA, l2_mdl_error_ua}, 18058c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_UA, l2_mdl_error_ua}, 18068c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_DM, l2_reestablish}, 18078c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_DM, l2_st5_dm_release}, 18088c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_DM, l2_st6_dm_release}, 18098c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_DM, l2_mdl_error_dm}, 18108c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm}, 18118c2ecf20Sopenharmony_ci {ST_L2_1, EV_L2_UI, l2_got_ui}, 18128c2ecf20Sopenharmony_ci {ST_L2_2, EV_L2_UI, l2_got_ui}, 18138c2ecf20Sopenharmony_ci {ST_L2_3, EV_L2_UI, l2_got_ui}, 18148c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_UI, l2_got_ui}, 18158c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_UI, l2_got_ui}, 18168c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_UI, l2_got_ui}, 18178c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_UI, l2_got_ui}, 18188c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_UI, l2_got_ui}, 18198c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_FRMR, l2_got_FRMR}, 18208c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_FRMR, l2_got_FRMR}, 18218c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_SUPER, l2_st7_got_super}, 18228c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_SUPER, l2_st8_got_super}, 18238c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_I, l2_got_iframe}, 18248c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_I, l2_got_iframe}, 18258c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_T200, l2_timeout}, 18268c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_T200, l2_timeout}, 18278c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_T200, l2_timeout}, 18288c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_T200, l2_timeout}, 18298c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_T203, l2_timeout}, 18308c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_T200I, l2_st5_tout_200}, 18318c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_T200I, l2_st6_tout_200}, 18328c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_T200I, l2_st7_tout_200}, 18338c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_T200I, l2_st8_tout_200}, 18348c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_T203I, l2_st7_tout_203}, 18358c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue}, 18368c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, 18378c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, 18388c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, 18398c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, 18408c2ecf20Sopenharmony_ci {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error}, 18418c2ecf20Sopenharmony_ci {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error}, 18428c2ecf20Sopenharmony_ci {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, 18438c2ecf20Sopenharmony_ci {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, 18448c2ecf20Sopenharmony_ci {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, 18458c2ecf20Sopenharmony_ci {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da}, 18468c2ecf20Sopenharmony_ci {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, 18478c2ecf20Sopenharmony_ci {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, 18488c2ecf20Sopenharmony_ci {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da}, 18498c2ecf20Sopenharmony_ci {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da}, 18508c2ecf20Sopenharmony_ci {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da}, 18518c2ecf20Sopenharmony_ci {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da}, 18528c2ecf20Sopenharmony_ci {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, 18538c2ecf20Sopenharmony_ci}; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int 18568c2ecf20Sopenharmony_ciph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) 18578c2ecf20Sopenharmony_ci{ 18588c2ecf20Sopenharmony_ci u_char *datap = skb->data; 18598c2ecf20Sopenharmony_ci int ret = -EINVAL; 18608c2ecf20Sopenharmony_ci int psapi, ptei; 18618c2ecf20Sopenharmony_ci u_int l; 18628c2ecf20Sopenharmony_ci int c = 0; 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_ci l = l2addrsize(l2); 18658c2ecf20Sopenharmony_ci if (skb->len <= l) { 18668c2ecf20Sopenharmony_ci mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *) 'N'); 18678c2ecf20Sopenharmony_ci return ret; 18688c2ecf20Sopenharmony_ci } 18698c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag)) { /* Maybe not needed */ 18708c2ecf20Sopenharmony_ci psapi = *datap++; 18718c2ecf20Sopenharmony_ci ptei = *datap++; 18728c2ecf20Sopenharmony_ci if ((psapi & 1) || !(ptei & 1)) { 18738c2ecf20Sopenharmony_ci printk(KERN_WARNING 18748c2ecf20Sopenharmony_ci "%s l2 D-channel frame wrong EA0/EA1\n", 18758c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch)); 18768c2ecf20Sopenharmony_ci return ret; 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci psapi >>= 2; 18798c2ecf20Sopenharmony_ci ptei >>= 1; 18808c2ecf20Sopenharmony_ci if (psapi != l2->sapi) { 18818c2ecf20Sopenharmony_ci /* not our business */ 18828c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2) 18838c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n", 18848c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), psapi, 18858c2ecf20Sopenharmony_ci l2->sapi); 18868c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 18878c2ecf20Sopenharmony_ci return 0; 18888c2ecf20Sopenharmony_ci } 18898c2ecf20Sopenharmony_ci if ((ptei != l2->tei) && (ptei != GROUP_TEI)) { 18908c2ecf20Sopenharmony_ci /* not our business */ 18918c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2) 18928c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: tei %d/%d mismatch\n", 18938c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), ptei, l2->tei); 18948c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 18958c2ecf20Sopenharmony_ci return 0; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci } else 18988c2ecf20Sopenharmony_ci datap += l; 18998c2ecf20Sopenharmony_ci if (!(*datap & 1)) { /* I-Frame */ 19008c2ecf20Sopenharmony_ci c = iframe_error(l2, skb); 19018c2ecf20Sopenharmony_ci if (!c) 19028c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_I, skb); 19038c2ecf20Sopenharmony_ci } else if (IsSFrame(datap, l2)) { /* S-Frame */ 19048c2ecf20Sopenharmony_ci c = super_error(l2, skb); 19058c2ecf20Sopenharmony_ci if (!c) 19068c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SUPER, skb); 19078c2ecf20Sopenharmony_ci } else if (IsUI(datap)) { 19088c2ecf20Sopenharmony_ci c = UI_error(l2, skb); 19098c2ecf20Sopenharmony_ci if (!c) 19108c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UI, skb); 19118c2ecf20Sopenharmony_ci } else if (IsSABME(datap, l2)) { 19128c2ecf20Sopenharmony_ci c = unnum_error(l2, skb, CMD); 19138c2ecf20Sopenharmony_ci if (!c) 19148c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SABME, skb); 19158c2ecf20Sopenharmony_ci } else if (IsUA(datap)) { 19168c2ecf20Sopenharmony_ci c = unnum_error(l2, skb, RSP); 19178c2ecf20Sopenharmony_ci if (!c) 19188c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UA, skb); 19198c2ecf20Sopenharmony_ci } else if (IsDISC(datap)) { 19208c2ecf20Sopenharmony_ci c = unnum_error(l2, skb, CMD); 19218c2ecf20Sopenharmony_ci if (!c) 19228c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DISC, skb); 19238c2ecf20Sopenharmony_ci } else if (IsDM(datap)) { 19248c2ecf20Sopenharmony_ci c = unnum_error(l2, skb, RSP); 19258c2ecf20Sopenharmony_ci if (!c) 19268c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DM, skb); 19278c2ecf20Sopenharmony_ci } else if (IsFRMR(datap)) { 19288c2ecf20Sopenharmony_ci c = FRMR_error(l2, skb); 19298c2ecf20Sopenharmony_ci if (!c) 19308c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_FRMR, skb); 19318c2ecf20Sopenharmony_ci } else 19328c2ecf20Sopenharmony_ci c = 'L'; 19338c2ecf20Sopenharmony_ci if (c) { 19348c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s:l2 D-channel frame error %c\n", 19358c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), c); 19368c2ecf20Sopenharmony_ci mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c); 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci return ret; 19398c2ecf20Sopenharmony_ci} 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_cistatic int 19428c2ecf20Sopenharmony_cil2_send(struct mISDNchannel *ch, struct sk_buff *skb) 19438c2ecf20Sopenharmony_ci{ 19448c2ecf20Sopenharmony_ci struct layer2 *l2 = container_of(ch, struct layer2, ch); 19458c2ecf20Sopenharmony_ci struct mISDNhead *hh = mISDN_HEAD_P(skb); 19468c2ecf20Sopenharmony_ci int ret = -EINVAL; 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2_RECV) 19498c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: %s prim(%x) id(%x) sapi(%d) tei(%d)\n", 19508c2ecf20Sopenharmony_ci __func__, mISDNDevName4ch(&l2->ch), hh->prim, hh->id, 19518c2ecf20Sopenharmony_ci l2->sapi, l2->tei); 19528c2ecf20Sopenharmony_ci if (hh->prim == DL_INTERN_MSG) { 19538c2ecf20Sopenharmony_ci struct mISDNhead *chh = hh + 1; /* saved copy */ 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci *hh = *chh; 19568c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2_RECV) 19578c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n", 19588c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), hh->prim, hh->id); 19598c2ecf20Sopenharmony_ci } 19608c2ecf20Sopenharmony_ci switch (hh->prim) { 19618c2ecf20Sopenharmony_ci case PH_DATA_IND: 19628c2ecf20Sopenharmony_ci ret = ph_data_indication(l2, hh, skb); 19638c2ecf20Sopenharmony_ci break; 19648c2ecf20Sopenharmony_ci case PH_DATA_CNF: 19658c2ecf20Sopenharmony_ci ret = ph_data_confirm(l2, hh, skb); 19668c2ecf20Sopenharmony_ci break; 19678c2ecf20Sopenharmony_ci case PH_ACTIVATE_IND: 19688c2ecf20Sopenharmony_ci test_and_set_bit(FLG_L1_ACTIV, &l2->flag); 19698c2ecf20Sopenharmony_ci l2up_create(l2, MPH_ACTIVATE_IND, 0, NULL); 19708c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag)) 19718c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, 19728c2ecf20Sopenharmony_ci EV_L2_DL_ESTABLISH_REQ, skb); 19738c2ecf20Sopenharmony_ci break; 19748c2ecf20Sopenharmony_ci case PH_DEACTIVATE_IND: 19758c2ecf20Sopenharmony_ci test_and_clear_bit(FLG_L1_ACTIV, &l2->flag); 19768c2ecf20Sopenharmony_ci l2up_create(l2, MPH_DEACTIVATE_IND, 0, NULL); 19778c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L1_DEACTIVATE, skb); 19788c2ecf20Sopenharmony_ci break; 19798c2ecf20Sopenharmony_ci case MPH_INFORMATION_IND: 19808c2ecf20Sopenharmony_ci if (!l2->up) 19818c2ecf20Sopenharmony_ci break; 19828c2ecf20Sopenharmony_ci ret = l2->up->send(l2->up, skb); 19838c2ecf20Sopenharmony_ci break; 19848c2ecf20Sopenharmony_ci case DL_DATA_REQ: 19858c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_DATA, skb); 19868c2ecf20Sopenharmony_ci break; 19878c2ecf20Sopenharmony_ci case DL_UNITDATA_REQ: 19888c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_UNITDATA, skb); 19898c2ecf20Sopenharmony_ci break; 19908c2ecf20Sopenharmony_ci case DL_ESTABLISH_REQ: 19918c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPB, &l2->flag)) 19928c2ecf20Sopenharmony_ci test_and_set_bit(FLG_ORIG, &l2->flag); 19938c2ecf20Sopenharmony_ci if (test_bit(FLG_L1_ACTIV, &l2->flag)) { 19948c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) || 19958c2ecf20Sopenharmony_ci test_bit(FLG_ORIG, &l2->flag)) 19968c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, 19978c2ecf20Sopenharmony_ci EV_L2_DL_ESTABLISH_REQ, skb); 19988c2ecf20Sopenharmony_ci } else { 19998c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag) || 20008c2ecf20Sopenharmony_ci test_bit(FLG_ORIG, &l2->flag)) { 20018c2ecf20Sopenharmony_ci test_and_set_bit(FLG_ESTAB_PEND, 20028c2ecf20Sopenharmony_ci &l2->flag); 20038c2ecf20Sopenharmony_ci } 20048c2ecf20Sopenharmony_ci ret = l2down(l2, PH_ACTIVATE_REQ, l2_newid(l2), 20058c2ecf20Sopenharmony_ci skb); 20068c2ecf20Sopenharmony_ci } 20078c2ecf20Sopenharmony_ci break; 20088c2ecf20Sopenharmony_ci case DL_RELEASE_REQ: 20098c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPB, &l2->flag)) 20108c2ecf20Sopenharmony_ci l2down_create(l2, PH_DEACTIVATE_REQ, 20118c2ecf20Sopenharmony_ci l2_newid(l2), 0, NULL); 20128c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ, 20138c2ecf20Sopenharmony_ci skb); 20148c2ecf20Sopenharmony_ci break; 20158c2ecf20Sopenharmony_ci case DL_TIMER200_IND: 20168c2ecf20Sopenharmony_ci mISDN_FsmEvent(&l2->l2m, EV_L2_T200I, NULL); 20178c2ecf20Sopenharmony_ci break; 20188c2ecf20Sopenharmony_ci case DL_TIMER203_IND: 20198c2ecf20Sopenharmony_ci mISDN_FsmEvent(&l2->l2m, EV_L2_T203I, NULL); 20208c2ecf20Sopenharmony_ci break; 20218c2ecf20Sopenharmony_ci default: 20228c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2) 20238c2ecf20Sopenharmony_ci l2m_debug(&l2->l2m, "l2 unknown pr %04x", 20248c2ecf20Sopenharmony_ci hh->prim); 20258c2ecf20Sopenharmony_ci } 20268c2ecf20Sopenharmony_ci if (ret) { 20278c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 20288c2ecf20Sopenharmony_ci ret = 0; 20298c2ecf20Sopenharmony_ci } 20308c2ecf20Sopenharmony_ci return ret; 20318c2ecf20Sopenharmony_ci} 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ciint 20348c2ecf20Sopenharmony_citei_l2(struct layer2 *l2, u_int cmd, u_long arg) 20358c2ecf20Sopenharmony_ci{ 20368c2ecf20Sopenharmony_ci int ret = -EINVAL; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2_TEI) 20398c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: cmd(%x) in %s\n", 20408c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch), cmd, __func__); 20418c2ecf20Sopenharmony_ci switch (cmd) { 20428c2ecf20Sopenharmony_ci case (MDL_ASSIGN_REQ): 20438c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, (void *)arg); 20448c2ecf20Sopenharmony_ci break; 20458c2ecf20Sopenharmony_ci case (MDL_REMOVE_REQ): 20468c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_REMOVE, NULL); 20478c2ecf20Sopenharmony_ci break; 20488c2ecf20Sopenharmony_ci case (MDL_ERROR_IND): 20498c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL); 20508c2ecf20Sopenharmony_ci break; 20518c2ecf20Sopenharmony_ci case (MDL_ERROR_RSP): 20528c2ecf20Sopenharmony_ci /* ETS 300-125 5.3.2.1 Test: TC13010 */ 20538c2ecf20Sopenharmony_ci printk(KERN_NOTICE "%s: MDL_ERROR|REQ (tei_l2)\n", 20548c2ecf20Sopenharmony_ci mISDNDevName4ch(&l2->ch)); 20558c2ecf20Sopenharmony_ci ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL); 20568c2ecf20Sopenharmony_ci break; 20578c2ecf20Sopenharmony_ci } 20588c2ecf20Sopenharmony_ci return ret; 20598c2ecf20Sopenharmony_ci} 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_cistatic void 20628c2ecf20Sopenharmony_cirelease_l2(struct layer2 *l2) 20638c2ecf20Sopenharmony_ci{ 20648c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t200, 21); 20658c2ecf20Sopenharmony_ci mISDN_FsmDelTimer(&l2->t203, 16); 20668c2ecf20Sopenharmony_ci skb_queue_purge(&l2->i_queue); 20678c2ecf20Sopenharmony_ci skb_queue_purge(&l2->ui_queue); 20688c2ecf20Sopenharmony_ci skb_queue_purge(&l2->down_queue); 20698c2ecf20Sopenharmony_ci ReleaseWin(l2); 20708c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag)) { 20718c2ecf20Sopenharmony_ci TEIrelease(l2); 20728c2ecf20Sopenharmony_ci if (l2->ch.st) 20738c2ecf20Sopenharmony_ci l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D, 20748c2ecf20Sopenharmony_ci CLOSE_CHANNEL, NULL); 20758c2ecf20Sopenharmony_ci } 20768c2ecf20Sopenharmony_ci kfree(l2); 20778c2ecf20Sopenharmony_ci} 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_cistatic int 20808c2ecf20Sopenharmony_cil2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) 20818c2ecf20Sopenharmony_ci{ 20828c2ecf20Sopenharmony_ci struct layer2 *l2 = container_of(ch, struct layer2, ch); 20838c2ecf20Sopenharmony_ci u_int info; 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci if (*debug & DEBUG_L2_CTRL) 20868c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: %s cmd(%x)\n", 20878c2ecf20Sopenharmony_ci mISDNDevName4ch(ch), __func__, cmd); 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci switch (cmd) { 20908c2ecf20Sopenharmony_ci case OPEN_CHANNEL: 20918c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPD, &l2->flag)) { 20928c2ecf20Sopenharmony_ci set_channel_address(&l2->ch, l2->sapi, l2->tei); 20938c2ecf20Sopenharmony_ci info = DL_INFO_L2_CONNECT; 20948c2ecf20Sopenharmony_ci l2up_create(l2, DL_INFORMATION_IND, 20958c2ecf20Sopenharmony_ci sizeof(info), &info); 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci break; 20988c2ecf20Sopenharmony_ci case CLOSE_CHANNEL: 20998c2ecf20Sopenharmony_ci if (l2->ch.peer) 21008c2ecf20Sopenharmony_ci l2->ch.peer->ctrl(l2->ch.peer, CLOSE_CHANNEL, NULL); 21018c2ecf20Sopenharmony_ci release_l2(l2); 21028c2ecf20Sopenharmony_ci break; 21038c2ecf20Sopenharmony_ci } 21048c2ecf20Sopenharmony_ci return 0; 21058c2ecf20Sopenharmony_ci} 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_cistruct layer2 * 21088c2ecf20Sopenharmony_cicreate_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei, 21098c2ecf20Sopenharmony_ci int sapi) 21108c2ecf20Sopenharmony_ci{ 21118c2ecf20Sopenharmony_ci struct layer2 *l2; 21128c2ecf20Sopenharmony_ci struct channel_req rq; 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci l2 = kzalloc(sizeof(struct layer2), GFP_KERNEL); 21158c2ecf20Sopenharmony_ci if (!l2) { 21168c2ecf20Sopenharmony_ci printk(KERN_ERR "kzalloc layer2 failed\n"); 21178c2ecf20Sopenharmony_ci return NULL; 21188c2ecf20Sopenharmony_ci } 21198c2ecf20Sopenharmony_ci l2->next_id = 1; 21208c2ecf20Sopenharmony_ci l2->down_id = MISDN_ID_NONE; 21218c2ecf20Sopenharmony_ci l2->up = ch; 21228c2ecf20Sopenharmony_ci l2->ch.st = ch->st; 21238c2ecf20Sopenharmony_ci l2->ch.send = l2_send; 21248c2ecf20Sopenharmony_ci l2->ch.ctrl = l2_ctrl; 21258c2ecf20Sopenharmony_ci switch (protocol) { 21268c2ecf20Sopenharmony_ci case ISDN_P_LAPD_NT: 21278c2ecf20Sopenharmony_ci test_and_set_bit(FLG_LAPD, &l2->flag); 21288c2ecf20Sopenharmony_ci test_and_set_bit(FLG_LAPD_NET, &l2->flag); 21298c2ecf20Sopenharmony_ci test_and_set_bit(FLG_MOD128, &l2->flag); 21308c2ecf20Sopenharmony_ci l2->sapi = sapi; 21318c2ecf20Sopenharmony_ci l2->maxlen = MAX_DFRAME_LEN; 21328c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_PMX, &options)) 21338c2ecf20Sopenharmony_ci l2->window = 7; 21348c2ecf20Sopenharmony_ci else 21358c2ecf20Sopenharmony_ci l2->window = 1; 21368c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_PTP, &options)) 21378c2ecf20Sopenharmony_ci test_and_set_bit(FLG_PTP, &l2->flag); 21388c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_FIXEDTEI, &options)) 21398c2ecf20Sopenharmony_ci test_and_set_bit(FLG_FIXED_TEI, &l2->flag); 21408c2ecf20Sopenharmony_ci l2->tei = tei; 21418c2ecf20Sopenharmony_ci l2->T200 = 1000; 21428c2ecf20Sopenharmony_ci l2->N200 = 3; 21438c2ecf20Sopenharmony_ci l2->T203 = 10000; 21448c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_PMX, &options)) 21458c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_NT_E1; 21468c2ecf20Sopenharmony_ci else 21478c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_NT_S0; 21488c2ecf20Sopenharmony_ci rq.adr.channel = 0; 21498c2ecf20Sopenharmony_ci l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D, OPEN_CHANNEL, &rq); 21508c2ecf20Sopenharmony_ci break; 21518c2ecf20Sopenharmony_ci case ISDN_P_LAPD_TE: 21528c2ecf20Sopenharmony_ci test_and_set_bit(FLG_LAPD, &l2->flag); 21538c2ecf20Sopenharmony_ci test_and_set_bit(FLG_MOD128, &l2->flag); 21548c2ecf20Sopenharmony_ci test_and_set_bit(FLG_ORIG, &l2->flag); 21558c2ecf20Sopenharmony_ci l2->sapi = sapi; 21568c2ecf20Sopenharmony_ci l2->maxlen = MAX_DFRAME_LEN; 21578c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_PMX, &options)) 21588c2ecf20Sopenharmony_ci l2->window = 7; 21598c2ecf20Sopenharmony_ci else 21608c2ecf20Sopenharmony_ci l2->window = 1; 21618c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_PTP, &options)) 21628c2ecf20Sopenharmony_ci test_and_set_bit(FLG_PTP, &l2->flag); 21638c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_FIXEDTEI, &options)) 21648c2ecf20Sopenharmony_ci test_and_set_bit(FLG_FIXED_TEI, &l2->flag); 21658c2ecf20Sopenharmony_ci l2->tei = tei; 21668c2ecf20Sopenharmony_ci l2->T200 = 1000; 21678c2ecf20Sopenharmony_ci l2->N200 = 3; 21688c2ecf20Sopenharmony_ci l2->T203 = 10000; 21698c2ecf20Sopenharmony_ci if (test_bit(OPTION_L2_PMX, &options)) 21708c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_TE_E1; 21718c2ecf20Sopenharmony_ci else 21728c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_TE_S0; 21738c2ecf20Sopenharmony_ci rq.adr.channel = 0; 21748c2ecf20Sopenharmony_ci l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D, OPEN_CHANNEL, &rq); 21758c2ecf20Sopenharmony_ci break; 21768c2ecf20Sopenharmony_ci case ISDN_P_B_X75SLP: 21778c2ecf20Sopenharmony_ci test_and_set_bit(FLG_LAPB, &l2->flag); 21788c2ecf20Sopenharmony_ci l2->window = 7; 21798c2ecf20Sopenharmony_ci l2->maxlen = MAX_DATA_SIZE; 21808c2ecf20Sopenharmony_ci l2->T200 = 1000; 21818c2ecf20Sopenharmony_ci l2->N200 = 4; 21828c2ecf20Sopenharmony_ci l2->T203 = 5000; 21838c2ecf20Sopenharmony_ci l2->addr.A = 3; 21848c2ecf20Sopenharmony_ci l2->addr.B = 1; 21858c2ecf20Sopenharmony_ci break; 21868c2ecf20Sopenharmony_ci default: 21878c2ecf20Sopenharmony_ci printk(KERN_ERR "layer2 create failed prt %x\n", 21888c2ecf20Sopenharmony_ci protocol); 21898c2ecf20Sopenharmony_ci kfree(l2); 21908c2ecf20Sopenharmony_ci return NULL; 21918c2ecf20Sopenharmony_ci } 21928c2ecf20Sopenharmony_ci skb_queue_head_init(&l2->i_queue); 21938c2ecf20Sopenharmony_ci skb_queue_head_init(&l2->ui_queue); 21948c2ecf20Sopenharmony_ci skb_queue_head_init(&l2->down_queue); 21958c2ecf20Sopenharmony_ci skb_queue_head_init(&l2->tmp_queue); 21968c2ecf20Sopenharmony_ci InitWin(l2); 21978c2ecf20Sopenharmony_ci l2->l2m.fsm = &l2fsm; 21988c2ecf20Sopenharmony_ci if (test_bit(FLG_LAPB, &l2->flag) || 21998c2ecf20Sopenharmony_ci test_bit(FLG_FIXED_TEI, &l2->flag) || 22008c2ecf20Sopenharmony_ci test_bit(FLG_LAPD_NET, &l2->flag)) 22018c2ecf20Sopenharmony_ci l2->l2m.state = ST_L2_4; 22028c2ecf20Sopenharmony_ci else 22038c2ecf20Sopenharmony_ci l2->l2m.state = ST_L2_1; 22048c2ecf20Sopenharmony_ci l2->l2m.debug = *debug; 22058c2ecf20Sopenharmony_ci l2->l2m.userdata = l2; 22068c2ecf20Sopenharmony_ci l2->l2m.userint = 0; 22078c2ecf20Sopenharmony_ci l2->l2m.printdebug = l2m_debug; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci mISDN_FsmInitTimer(&l2->l2m, &l2->t200); 22108c2ecf20Sopenharmony_ci mISDN_FsmInitTimer(&l2->l2m, &l2->t203); 22118c2ecf20Sopenharmony_ci return l2; 22128c2ecf20Sopenharmony_ci} 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_cistatic int 22158c2ecf20Sopenharmony_cix75create(struct channel_req *crq) 22168c2ecf20Sopenharmony_ci{ 22178c2ecf20Sopenharmony_ci struct layer2 *l2; 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci if (crq->protocol != ISDN_P_B_X75SLP) 22208c2ecf20Sopenharmony_ci return -EPROTONOSUPPORT; 22218c2ecf20Sopenharmony_ci l2 = create_l2(crq->ch, crq->protocol, 0, 0, 0); 22228c2ecf20Sopenharmony_ci if (!l2) 22238c2ecf20Sopenharmony_ci return -ENOMEM; 22248c2ecf20Sopenharmony_ci crq->ch = &l2->ch; 22258c2ecf20Sopenharmony_ci crq->protocol = ISDN_P_B_HDLC; 22268c2ecf20Sopenharmony_ci return 0; 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_cistatic struct Bprotocol X75SLP = { 22308c2ecf20Sopenharmony_ci .Bprotocols = (1 << (ISDN_P_B_X75SLP & ISDN_P_B_MASK)), 22318c2ecf20Sopenharmony_ci .name = "X75SLP", 22328c2ecf20Sopenharmony_ci .create = x75create 22338c2ecf20Sopenharmony_ci}; 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ciint 22368c2ecf20Sopenharmony_ciIsdnl2_Init(u_int *deb) 22378c2ecf20Sopenharmony_ci{ 22388c2ecf20Sopenharmony_ci int res; 22398c2ecf20Sopenharmony_ci debug = deb; 22408c2ecf20Sopenharmony_ci mISDN_register_Bprotocol(&X75SLP); 22418c2ecf20Sopenharmony_ci l2fsm.state_count = L2_STATE_COUNT; 22428c2ecf20Sopenharmony_ci l2fsm.event_count = L2_EVENT_COUNT; 22438c2ecf20Sopenharmony_ci l2fsm.strEvent = strL2Event; 22448c2ecf20Sopenharmony_ci l2fsm.strState = strL2State; 22458c2ecf20Sopenharmony_ci res = mISDN_FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList)); 22468c2ecf20Sopenharmony_ci if (res) 22478c2ecf20Sopenharmony_ci goto error; 22488c2ecf20Sopenharmony_ci res = TEIInit(deb); 22498c2ecf20Sopenharmony_ci if (res) 22508c2ecf20Sopenharmony_ci goto error_fsm; 22518c2ecf20Sopenharmony_ci return 0; 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_cierror_fsm: 22548c2ecf20Sopenharmony_ci mISDN_FsmFree(&l2fsm); 22558c2ecf20Sopenharmony_cierror: 22568c2ecf20Sopenharmony_ci mISDN_unregister_Bprotocol(&X75SLP); 22578c2ecf20Sopenharmony_ci return res; 22588c2ecf20Sopenharmony_ci} 22598c2ecf20Sopenharmony_ci 22608c2ecf20Sopenharmony_civoid 22618c2ecf20Sopenharmony_ciIsdnl2_cleanup(void) 22628c2ecf20Sopenharmony_ci{ 22638c2ecf20Sopenharmony_ci mISDN_unregister_Bprotocol(&X75SLP); 22648c2ecf20Sopenharmony_ci TEIFree(); 22658c2ecf20Sopenharmony_ci mISDN_FsmFree(&l2fsm); 22668c2ecf20Sopenharmony_ci} 2267