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