416 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *4 * Author Karsten Keil <kkeil@novell.com>5 *6 * Copyright 2008 by Karsten Keil <kkeil@novell.com>7 */8 9 10#include <linux/slab.h>11#include <linux/module.h>12#include <linux/mISDNhw.h>13#include "core.h"14#include "layer1.h"15#include "fsm.h"16 17static u_int *debug;18 19struct layer1 {20 u_long Flags;21 struct FsmInst l1m;22 struct FsmTimer timer3;23 struct FsmTimer timerX;24 int delay;25 int t3_value;26 struct dchannel *dch;27 dchannel_l1callback *dcb;28};29 30#define TIMER3_DEFAULT_VALUE 700031 32static33struct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};34 35enum {36 ST_L1_F2,37 ST_L1_F3,38 ST_L1_F4,39 ST_L1_F5,40 ST_L1_F6,41 ST_L1_F7,42 ST_L1_F8,43};44 45#define L1S_STATE_COUNT (ST_L1_F8 + 1)46 47static char *strL1SState[] =48{49 "ST_L1_F2",50 "ST_L1_F3",51 "ST_L1_F4",52 "ST_L1_F5",53 "ST_L1_F6",54 "ST_L1_F7",55 "ST_L1_F8",56};57 58enum {59 EV_PH_ACTIVATE,60 EV_PH_DEACTIVATE,61 EV_RESET_IND,62 EV_DEACT_CNF,63 EV_DEACT_IND,64 EV_POWER_UP,65 EV_ANYSIG_IND,66 EV_INFO2_IND,67 EV_INFO4_IND,68 EV_TIMER_DEACT,69 EV_TIMER_ACT,70 EV_TIMER3,71};72 73#define L1_EVENT_COUNT (EV_TIMER3 + 1)74 75static char *strL1Event[] =76{77 "EV_PH_ACTIVATE",78 "EV_PH_DEACTIVATE",79 "EV_RESET_IND",80 "EV_DEACT_CNF",81 "EV_DEACT_IND",82 "EV_POWER_UP",83 "EV_ANYSIG_IND",84 "EV_INFO2_IND",85 "EV_INFO4_IND",86 "EV_TIMER_DEACT",87 "EV_TIMER_ACT",88 "EV_TIMER3",89};90 91static void92l1m_debug(struct FsmInst *fi, char *fmt, ...)93{94 struct layer1 *l1 = fi->userdata;95 struct va_format vaf;96 va_list va;97 98 va_start(va, fmt);99 100 vaf.fmt = fmt;101 vaf.va = &va;102 103 printk(KERN_DEBUG "%s: %pV\n", dev_name(&l1->dch->dev.dev), &vaf);104 105 va_end(va);106}107 108static void109l1_reset(struct FsmInst *fi, int event, void *arg)110{111 mISDN_FsmChangeState(fi, ST_L1_F3);112}113 114static void115l1_deact_cnf(struct FsmInst *fi, int event, void *arg)116{117 struct layer1 *l1 = fi->userdata;118 119 mISDN_FsmChangeState(fi, ST_L1_F3);120 if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))121 l1->dcb(l1->dch, HW_POWERUP_REQ);122}123 124static void125l1_deact_req_s(struct FsmInst *fi, int event, void *arg)126{127 struct layer1 *l1 = fi->userdata;128 129 mISDN_FsmChangeState(fi, ST_L1_F3);130 mISDN_FsmRestartTimer(&l1->timerX, 550, EV_TIMER_DEACT, NULL, 2);131 test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);132}133 134static void135l1_power_up_s(struct FsmInst *fi, int event, void *arg)136{137 struct layer1 *l1 = fi->userdata;138 139 if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {140 mISDN_FsmChangeState(fi, ST_L1_F4);141 l1->dcb(l1->dch, INFO3_P8);142 } else143 mISDN_FsmChangeState(fi, ST_L1_F3);144}145 146static void147l1_go_F5(struct FsmInst *fi, int event, void *arg)148{149 mISDN_FsmChangeState(fi, ST_L1_F5);150}151 152static void153l1_go_F8(struct FsmInst *fi, int event, void *arg)154{155 mISDN_FsmChangeState(fi, ST_L1_F8);156}157 158static void159l1_info2_ind(struct FsmInst *fi, int event, void *arg)160{161 struct layer1 *l1 = fi->userdata;162 163 mISDN_FsmChangeState(fi, ST_L1_F6);164 l1->dcb(l1->dch, INFO3_P8);165}166 167static void168l1_info4_ind(struct FsmInst *fi, int event, void *arg)169{170 struct layer1 *l1 = fi->userdata;171 172 mISDN_FsmChangeState(fi, ST_L1_F7);173 l1->dcb(l1->dch, INFO3_P8);174 if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))175 mISDN_FsmDelTimer(&l1->timerX, 4);176 if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {177 if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))178 mISDN_FsmDelTimer(&l1->timer3, 3);179 mISDN_FsmRestartTimer(&l1->timerX, 110, EV_TIMER_ACT, NULL, 2);180 test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);181 }182}183 184static void185l1_timer3(struct FsmInst *fi, int event, void *arg)186{187 struct layer1 *l1 = fi->userdata;188 189 test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);190 if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {191 if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))192 l1->dcb(l1->dch, HW_D_NOBLOCKED);193 l1->dcb(l1->dch, PH_DEACTIVATE_IND);194 }195 if (l1->l1m.state != ST_L1_F6) {196 mISDN_FsmChangeState(fi, ST_L1_F3);197 /* do not force anything here, we need send INFO 0 */198 }199}200 201static void202l1_timer_act(struct FsmInst *fi, int event, void *arg)203{204 struct layer1 *l1 = fi->userdata;205 206 test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);207 test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);208 l1->dcb(l1->dch, PH_ACTIVATE_IND);209}210 211static void212l1_timer_deact(struct FsmInst *fi, int event, void *arg)213{214 struct layer1 *l1 = fi->userdata;215 216 test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);217 test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);218 if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))219 l1->dcb(l1->dch, HW_D_NOBLOCKED);220 l1->dcb(l1->dch, PH_DEACTIVATE_IND);221 l1->dcb(l1->dch, HW_DEACT_REQ);222}223 224static void225l1_activate_s(struct FsmInst *fi, int event, void *arg)226{227 struct layer1 *l1 = fi->userdata;228 229 mISDN_FsmRestartTimer(&l1->timer3, l1->t3_value, EV_TIMER3, NULL, 2);230 test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);231 /* Tell HW to send INFO 1 */232 l1->dcb(l1->dch, HW_RESET_REQ);233}234 235static void236l1_activate_no(struct FsmInst *fi, int event, void *arg)237{238 struct layer1 *l1 = fi->userdata;239 240 if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) &&241 (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {242 test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);243 if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))244 l1->dcb(l1->dch, HW_D_NOBLOCKED);245 l1->dcb(l1->dch, PH_DEACTIVATE_IND);246 }247}248 249static struct FsmNode L1SFnList[] =250{251 {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},252 {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},253 {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},254 {ST_L1_F3, EV_RESET_IND, l1_reset},255 {ST_L1_F4, EV_RESET_IND, l1_reset},256 {ST_L1_F5, EV_RESET_IND, l1_reset},257 {ST_L1_F6, EV_RESET_IND, l1_reset},258 {ST_L1_F7, EV_RESET_IND, l1_reset},259 {ST_L1_F8, EV_RESET_IND, l1_reset},260 {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},261 {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},262 {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},263 {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},264 {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},265 {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},266 {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},267 {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},268 {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},269 {ST_L1_F3, EV_POWER_UP, l1_power_up_s},270 {ST_L1_F4, EV_ANYSIG_IND, l1_go_F5},271 {ST_L1_F6, EV_ANYSIG_IND, l1_go_F8},272 {ST_L1_F7, EV_ANYSIG_IND, l1_go_F8},273 {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},274 {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},275 {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},276 {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},277 {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},278 {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},279 {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},280 {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},281 {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},282 {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},283 {ST_L1_F3, EV_TIMER3, l1_timer3},284 {ST_L1_F4, EV_TIMER3, l1_timer3},285 {ST_L1_F5, EV_TIMER3, l1_timer3},286 {ST_L1_F6, EV_TIMER3, l1_timer3},287 {ST_L1_F8, EV_TIMER3, l1_timer3},288 {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},289 {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},290 {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},291 {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},292 {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},293 {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},294 {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},295};296 297static void298release_l1(struct layer1 *l1) {299 mISDN_FsmDelTimer(&l1->timerX, 0);300 mISDN_FsmDelTimer(&l1->timer3, 0);301 if (l1->dch)302 l1->dch->l1 = NULL;303 module_put(THIS_MODULE);304 kfree(l1);305}306 307int308l1_event(struct layer1 *l1, u_int event)309{310 int err = 0;311 312 if (!l1)313 return -EINVAL;314 switch (event) {315 case HW_RESET_IND:316 mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);317 break;318 case HW_DEACT_IND:319 mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);320 break;321 case HW_POWERUP_IND:322 mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);323 break;324 case HW_DEACT_CNF:325 mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);326 break;327 case ANYSIGNAL:328 mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);329 break;330 case LOSTFRAMING:331 mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);332 break;333 case INFO2:334 mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);335 break;336 case INFO4_P8:337 mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);338 break;339 case INFO4_P10:340 mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);341 break;342 case PH_ACTIVATE_REQ:343 if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))344 l1->dcb(l1->dch, PH_ACTIVATE_IND);345 else {346 test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);347 mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);348 }349 break;350 case CLOSE_CHANNEL:351 release_l1(l1);352 break;353 default:354 if ((event & ~HW_TIMER3_VMASK) == HW_TIMER3_VALUE) {355 int val = event & HW_TIMER3_VMASK;356 357 if (val < 5)358 val = 5;359 if (val > 30)360 val = 30;361 l1->t3_value = val;362 break;363 }364 if (*debug & DEBUG_L1)365 printk(KERN_DEBUG "%s %x unhandled\n",366 __func__, event);367 err = -EINVAL;368 }369 return err;370}371EXPORT_SYMBOL(l1_event);372 373int374create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {375 struct layer1 *nl1;376 377 nl1 = kzalloc(sizeof(struct layer1), GFP_ATOMIC);378 if (!nl1) {379 printk(KERN_ERR "kmalloc struct layer1 failed\n");380 return -ENOMEM;381 }382 nl1->l1m.fsm = &l1fsm_s;383 nl1->l1m.state = ST_L1_F3;384 nl1->Flags = 0;385 nl1->t3_value = TIMER3_DEFAULT_VALUE;386 nl1->l1m.debug = *debug & DEBUG_L1_FSM;387 nl1->l1m.userdata = nl1;388 nl1->l1m.userint = 0;389 nl1->l1m.printdebug = l1m_debug;390 nl1->dch = dch;391 nl1->dcb = dcb;392 mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer3);393 mISDN_FsmInitTimer(&nl1->l1m, &nl1->timerX);394 __module_get(THIS_MODULE);395 dch->l1 = nl1;396 return 0;397}398EXPORT_SYMBOL(create_l1);399 400int401Isdnl1_Init(u_int *deb)402{403 debug = deb;404 l1fsm_s.state_count = L1S_STATE_COUNT;405 l1fsm_s.event_count = L1_EVENT_COUNT;406 l1fsm_s.strEvent = strL1Event;407 l1fsm_s.strState = strL1SState;408 return mISDN_FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));409}410 411void412Isdnl1_cleanup(void)413{414 mISDN_FsmFree(&l1fsm_s);415}416