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