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