linux/drivers/isdn/hisax/isdnl1.c
<<
>>
Prefs
   1/* $Id: isdnl1.c,v 2.46.2.5 2004/02/11 13:21:34 keil Exp $
   2 *
   3 * common low level stuff for Siemens Chipsetbased isdn cards
   4 *
   5 * Author       Karsten Keil
   6 *              based on the teles driver from Jan den Ouden
   7 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
   8 * 
   9 * This software may be used and distributed according to the terms
  10 * of the GNU General Public License, incorporated herein by reference.
  11 *
  12 * For changes and modifications please read
  13 * Documentation/isdn/HiSax.cert
  14 *
  15 * Thanks to    Jan den Ouden
  16 *              Fritz Elfert
  17 *              Beat Doebeli
  18 *
  19 */
  20
  21#include <linux/init.h>
  22#include <linux/gfp.h>
  23#include "hisax.h"
  24#include "isdnl1.h"
  25
  26const char *l1_revision = "$Revision: 2.46.2.5 $";
  27
  28#define TIMER3_VALUE 7000
  29
  30static struct Fsm l1fsm_b;
  31static struct Fsm l1fsm_s;
  32
  33enum {
  34        ST_L1_F2,
  35        ST_L1_F3,
  36        ST_L1_F4,
  37        ST_L1_F5,
  38        ST_L1_F6,
  39        ST_L1_F7,
  40        ST_L1_F8,
  41};
  42
  43#define L1S_STATE_COUNT (ST_L1_F8+1)
  44
  45static char *strL1SState[] =
  46{
  47        "ST_L1_F2",
  48        "ST_L1_F3",
  49        "ST_L1_F4",
  50        "ST_L1_F5",
  51        "ST_L1_F6",
  52        "ST_L1_F7",
  53        "ST_L1_F8",
  54};
  55
  56#ifdef HISAX_UINTERFACE
  57static
  58struct Fsm l1fsm_u =
  59{NULL, 0, 0, NULL, NULL};
  60
  61enum {
  62        ST_L1_RESET,
  63        ST_L1_DEACT,
  64        ST_L1_SYNC2,
  65        ST_L1_TRANS,
  66};
  67
  68#define L1U_STATE_COUNT (ST_L1_TRANS+1)
  69
  70static char *strL1UState[] =
  71{
  72        "ST_L1_RESET",
  73        "ST_L1_DEACT",
  74        "ST_L1_SYNC2",
  75        "ST_L1_TRANS",
  76};
  77#endif
  78
  79enum {
  80        ST_L1_NULL,
  81        ST_L1_WAIT_ACT,
  82        ST_L1_WAIT_DEACT,
  83        ST_L1_ACTIV,
  84};
  85
  86#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
  87
  88static char *strL1BState[] =
  89{
  90        "ST_L1_NULL",
  91        "ST_L1_WAIT_ACT",
  92        "ST_L1_WAIT_DEACT",
  93        "ST_L1_ACTIV",
  94};
  95
  96enum {
  97        EV_PH_ACTIVATE,
  98        EV_PH_DEACTIVATE,
  99        EV_RESET_IND,
 100        EV_DEACT_CNF,
 101        EV_DEACT_IND,
 102        EV_POWER_UP,
 103        EV_RSYNC_IND, 
 104        EV_INFO2_IND,
 105        EV_INFO4_IND,
 106        EV_TIMER_DEACT,
 107        EV_TIMER_ACT,
 108        EV_TIMER3,
 109};
 110
 111#define L1_EVENT_COUNT (EV_TIMER3 + 1)
 112
 113static char *strL1Event[] =
 114{
 115        "EV_PH_ACTIVATE",
 116        "EV_PH_DEACTIVATE",
 117        "EV_RESET_IND",
 118        "EV_DEACT_CNF",
 119        "EV_DEACT_IND",
 120        "EV_POWER_UP",
 121        "EV_RSYNC_IND", 
 122        "EV_INFO2_IND",
 123        "EV_INFO4_IND",
 124        "EV_TIMER_DEACT",
 125        "EV_TIMER_ACT",
 126        "EV_TIMER3",
 127};
 128
 129void
 130debugl1(struct IsdnCardState *cs, char *fmt, ...)
 131{
 132        va_list args;
 133        char tmp[8];
 134        
 135        va_start(args, fmt);
 136        sprintf(tmp, "Card%d ", cs->cardnr + 1);
 137        VHiSax_putstatus(cs, tmp, fmt, args);
 138        va_end(args);
 139}
 140
 141static void
 142l1m_debug(struct FsmInst *fi, char *fmt, ...)
 143{
 144        va_list args;
 145        struct PStack *st = fi->userdata;
 146        struct IsdnCardState *cs = st->l1.hardware;
 147        char tmp[8];
 148        
 149        va_start(args, fmt);
 150        sprintf(tmp, "Card%d ", cs->cardnr + 1);
 151        VHiSax_putstatus(cs, tmp, fmt, args);
 152        va_end(args);
 153}
 154
 155static void
 156L1activated(struct IsdnCardState *cs)
 157{
 158        struct PStack *st;
 159
 160        st = cs->stlist;
 161        while (st) {
 162                if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
 163                        st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 164                else
 165                        st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL);
 166                st = st->next;
 167        }
 168}
 169
 170static void
 171L1deactivated(struct IsdnCardState *cs)
 172{
 173        struct PStack *st;
 174
 175        st = cs->stlist;
 176        while (st) {
 177                if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
 178                        st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
 179                st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL);
 180                st = st->next;
 181        }
 182        test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 183}
 184
 185void
 186DChannel_proc_xmt(struct IsdnCardState *cs)
 187{
 188        struct PStack *stptr;
 189
 190        if (cs->tx_skb)
 191                return;
 192
 193        stptr = cs->stlist;
 194        while (stptr != NULL) {
 195                if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) {
 196                        stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL);
 197                        break;
 198                } else
 199                        stptr = stptr->next;
 200        }
 201}
 202
 203void
 204DChannel_proc_rcv(struct IsdnCardState *cs)
 205{
 206        struct sk_buff *skb, *nskb;
 207        struct PStack *stptr = cs->stlist;
 208        int found, tei, sapi;
 209
 210        if (stptr)
 211                if (test_bit(FLG_L1_ACTTIMER, &stptr->l1.Flags))
 212                        FsmEvent(&stptr->l1.l1m, EV_TIMER_ACT, NULL);   
 213        while ((skb = skb_dequeue(&cs->rq))) {
 214#ifdef L2FRAME_DEBUG            /* psa */
 215                if (cs->debug & L1_DEB_LAPD)
 216                        Logl2Frame(cs, skb, "PH_DATA", 1);
 217#endif
 218                stptr = cs->stlist;
 219                if (skb->len<3) {
 220                        debugl1(cs, "D-channel frame too short(%d)",skb->len);
 221                        dev_kfree_skb(skb);
 222                        return;
 223                }
 224                if ((skb->data[0] & 1) || !(skb->data[1] &1)) {
 225                        debugl1(cs, "D-channel frame wrong EA0/EA1");
 226                        dev_kfree_skb(skb);
 227                        return;
 228                }
 229                sapi = skb->data[0] >> 2;
 230                tei = skb->data[1] >> 1;
 231                if (cs->debug & DEB_DLOG_HEX)
 232                        LogFrame(cs, skb->data, skb->len);
 233                if (cs->debug & DEB_DLOG_VERBOSE)
 234                        dlogframe(cs, skb, 1);
 235                if (tei == GROUP_TEI) {
 236                        if (sapi == CTRL_SAPI) { /* sapi 0 */
 237                                while (stptr != NULL) {
 238                                        if ((nskb = skb_clone(skb, GFP_ATOMIC)))
 239                                                stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb);
 240                                        else
 241                                                printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n");
 242                                        stptr = stptr->next;
 243                                }
 244                        } else if (sapi == TEI_SAPI) {
 245                                while (stptr != NULL) {
 246                                        if ((nskb = skb_clone(skb, GFP_ATOMIC)))
 247                                                stptr->l1.l1tei(stptr, PH_DATA | INDICATION, nskb);
 248                                        else
 249                                                printk(KERN_WARNING "HiSax: tei broadcast buffer shortage\n");
 250                                        stptr = stptr->next;
 251                                }
 252                        }
 253                        dev_kfree_skb(skb);
 254                } else if (sapi == CTRL_SAPI) { /* sapi 0 */
 255                        found = 0;
 256                        while (stptr != NULL)
 257                                if (tei == stptr->l2.tei) {
 258                                        stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb);
 259                                        found = !0;
 260                                        break;
 261                                } else
 262                                        stptr = stptr->next;
 263                        if (!found)
 264                                dev_kfree_skb(skb);
 265                } else
 266                        dev_kfree_skb(skb);
 267        }
 268}
 269
 270static void
 271BChannel_proc_xmt(struct BCState *bcs)
 272{
 273        struct PStack *st = bcs->st;
 274
 275        if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {
 276                debugl1(bcs->cs, "BC_BUSY Error");
 277                return;
 278        }
 279
 280        if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))
 281                st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 282        if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {
 283                if (!test_bit(BC_FLG_BUSY, &bcs->Flag) &&
 284                    skb_queue_empty(&bcs->squeue)) {
 285                        st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
 286                }
 287        }
 288}
 289
 290static void
 291BChannel_proc_rcv(struct BCState *bcs)
 292{
 293        struct sk_buff *skb;
 294
 295        if (bcs->st->l1.l1m.state == ST_L1_WAIT_ACT) {
 296                FsmDelTimer(&bcs->st->l1.timer, 4);
 297                FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL);
 298        }
 299        while ((skb = skb_dequeue(&bcs->rqueue))) {
 300                bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb);
 301        }
 302}
 303
 304static void
 305BChannel_proc_ack(struct BCState *bcs)
 306{
 307        u_long  flags;
 308        int     ack;
 309
 310        spin_lock_irqsave(&bcs->aclock, flags);
 311        ack = bcs->ackcnt;
 312        bcs->ackcnt = 0;
 313        spin_unlock_irqrestore(&bcs->aclock, flags);
 314        if (ack)
 315                lli_writewakeup(bcs->st, ack);
 316}
 317
 318void
 319BChannel_bh(struct work_struct *work)
 320{
 321        struct BCState *bcs = container_of(work, struct BCState, tqueue);
 322
 323        if (!bcs)
 324                return;
 325        if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event))
 326                BChannel_proc_rcv(bcs);
 327        if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event))
 328                BChannel_proc_xmt(bcs);
 329        if (test_and_clear_bit(B_ACKPENDING, &bcs->event))
 330                BChannel_proc_ack(bcs);
 331}
 332
 333void
 334HiSax_addlist(struct IsdnCardState *cs,
 335              struct PStack *st)
 336{
 337        st->next = cs->stlist;
 338        cs->stlist = st;
 339}
 340
 341void
 342HiSax_rmlist(struct IsdnCardState *cs,
 343             struct PStack *st)
 344{
 345        struct PStack *p;
 346
 347        FsmDelTimer(&st->l1.timer, 0);
 348        if (cs->stlist == st)
 349                cs->stlist = st->next;
 350        else {
 351                p = cs->stlist;
 352                while (p)
 353                        if (p->next == st) {
 354                                p->next = st->next;
 355                                return;
 356                        } else
 357                                p = p->next;
 358        }
 359}
 360
 361void
 362init_bcstate(struct IsdnCardState *cs, int bc)
 363{
 364        struct BCState *bcs = cs->bcs + bc;
 365
 366        bcs->cs = cs;
 367        bcs->channel = bc;
 368        INIT_WORK(&bcs->tqueue, BChannel_bh);
 369        spin_lock_init(&bcs->aclock);
 370        bcs->BC_SetStack = NULL;
 371        bcs->BC_Close = NULL;
 372        bcs->Flag = 0;
 373}
 374
 375#ifdef L2FRAME_DEBUG            /* psa */
 376
 377static char *
 378l2cmd(u_char cmd)
 379{
 380        switch (cmd & ~0x10) {
 381                case 1:
 382                        return "RR";
 383                case 5:
 384                        return "RNR";
 385                case 9:
 386                        return "REJ";
 387                case 0x6f:
 388                        return "SABME";
 389                case 0x0f:
 390                        return "DM";
 391                case 3:
 392                        return "UI";
 393                case 0x43:
 394                        return "DISC";
 395                case 0x63:
 396                        return "UA";
 397                case 0x87:
 398                        return "FRMR";
 399                case 0xaf:
 400                        return "XID";
 401                default:
 402                        if (!(cmd & 1))
 403                                return "I";
 404                        else
 405                                return "invalid command";
 406        }
 407}
 408
 409static char tmpdeb[32];
 410
 411static char *
 412l2frames(u_char * ptr)
 413{
 414        switch (ptr[2] & ~0x10) {
 415                case 1:
 416                case 5:
 417                case 9:
 418                        sprintf(tmpdeb, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);
 419                        break;
 420                case 0x6f:
 421                case 0x0f:
 422                case 3:
 423                case 0x43:
 424                case 0x63:
 425                case 0x87:
 426                case 0xaf:
 427                        sprintf(tmpdeb, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);
 428                        break;
 429                default:
 430                        if (!(ptr[2] & 1)) {
 431                                sprintf(tmpdeb, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);
 432                                break;
 433                        } else
 434                                return "invalid command";
 435        }
 436
 437
 438        return tmpdeb;
 439}
 440
 441void
 442Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir)
 443{
 444        u_char *ptr;
 445
 446        ptr = skb->data;
 447
 448        if (ptr[0] & 1 || !(ptr[1] & 1))
 449                debugl1(cs, "Address not LAPD");
 450        else
 451                debugl1(cs, "%s %s: %s%c (sapi %d, tei %d)",
 452                        (dir ? "<-" : "->"), buf, l2frames(ptr),
 453                        ((ptr[0] & 2) >> 1) == dir ? 'C' : 'R', ptr[0] >> 2, ptr[1] >> 1);
 454}
 455#endif
 456
 457static void
 458l1_reset(struct FsmInst *fi, int event, void *arg)
 459{
 460        FsmChangeState(fi, ST_L1_F3);
 461}
 462
 463static void
 464l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
 465{
 466        struct PStack *st = fi->userdata;
 467
 468        FsmChangeState(fi, ST_L1_F3);
 469        if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
 470                st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
 471}
 472
 473static void
 474l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
 475{
 476        struct PStack *st = fi->userdata;
 477
 478        FsmChangeState(fi, ST_L1_F3);
 479        FsmRestartTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
 480        test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
 481}
 482
 483static void
 484l1_power_up_s(struct FsmInst *fi, int event, void *arg)
 485{
 486        struct PStack *st = fi->userdata;
 487
 488        if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) {
 489                FsmChangeState(fi, ST_L1_F4);
 490                st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
 491                FsmRestartTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
 492                test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
 493        } else
 494                FsmChangeState(fi, ST_L1_F3);
 495}
 496
 497static void
 498l1_go_F5(struct FsmInst *fi, int event, void *arg)
 499{
 500        FsmChangeState(fi, ST_L1_F5);
 501}
 502
 503static void
 504l1_go_F8(struct FsmInst *fi, int event, void *arg)
 505{
 506        FsmChangeState(fi, ST_L1_F8);
 507}
 508
 509static void
 510l1_info2_ind(struct FsmInst *fi, int event, void *arg)
 511{
 512        struct PStack *st = fi->userdata;
 513
 514#ifdef HISAX_UINTERFACE
 515        if (test_bit(FLG_L1_UINT, &st->l1.Flags))
 516                FsmChangeState(fi, ST_L1_SYNC2);
 517        else
 518#endif
 519                FsmChangeState(fi, ST_L1_F6);
 520        st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
 521}
 522
 523static void
 524l1_info4_ind(struct FsmInst *fi, int event, void *arg)
 525{
 526        struct PStack *st = fi->userdata;
 527
 528#ifdef HISAX_UINTERFACE
 529        if (test_bit(FLG_L1_UINT, &st->l1.Flags))
 530                FsmChangeState(fi, ST_L1_TRANS);
 531        else
 532#endif
 533                FsmChangeState(fi, ST_L1_F7);
 534        st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
 535        if (test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags))
 536                FsmDelTimer(&st->l1.timer, 4);
 537        if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) {
 538                if (test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags))
 539                        FsmDelTimer(&st->l1.timer, 3);
 540                FsmRestartTimer(&st->l1.timer, 110, EV_TIMER_ACT, NULL, 2);
 541                test_and_set_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
 542        }
 543}
 544
 545static void
 546l1_timer3(struct FsmInst *fi, int event, void *arg)
 547{
 548        struct PStack *st = fi->userdata;
 549
 550        test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags);        
 551        if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
 552                L1deactivated(st->l1.hardware);
 553
 554#ifdef HISAX_UINTERFACE
 555        if (!test_bit(FLG_L1_UINT, &st->l1.Flags))
 556#endif
 557        if (st->l1.l1m.state != ST_L1_F6) {
 558                FsmChangeState(fi, ST_L1_F3);
 559                st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
 560        }
 561}
 562
 563static void
 564l1_timer_act(struct FsmInst *fi, int event, void *arg)
 565{
 566        struct PStack *st = fi->userdata;
 567        
 568        test_and_clear_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
 569        test_and_set_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
 570        L1activated(st->l1.hardware);
 571}
 572
 573static void
 574l1_timer_deact(struct FsmInst *fi, int event, void *arg)
 575{
 576        struct PStack *st = fi->userdata;
 577        
 578        test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
 579        test_and_clear_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
 580        L1deactivated(st->l1.hardware);
 581        st->l1.l1hw(st, HW_DEACTIVATE | RESPONSE, NULL);
 582}
 583
 584static void
 585l1_activate_s(struct FsmInst *fi, int event, void *arg)
 586{
 587        struct PStack *st = fi->userdata;
 588                
 589        st->l1.l1hw(st, HW_RESET | REQUEST, NULL);
 590}
 591
 592static void
 593l1_activate_no(struct FsmInst *fi, int event, void *arg)
 594{
 595        struct PStack *st = fi->userdata;
 596
 597        if ((!test_bit(FLG_L1_DEACTTIMER, &st->l1.Flags)) && (!test_bit(FLG_L1_T3RUN, &st->l1.Flags))) {
 598                test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
 599                L1deactivated(st->l1.hardware);
 600        }
 601}
 602
 603static struct FsmNode L1SFnList[] __initdata =
 604{
 605        {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
 606        {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
 607        {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
 608        {ST_L1_F3, EV_RESET_IND, l1_reset},
 609        {ST_L1_F4, EV_RESET_IND, l1_reset},
 610        {ST_L1_F5, EV_RESET_IND, l1_reset},
 611        {ST_L1_F6, EV_RESET_IND, l1_reset},
 612        {ST_L1_F7, EV_RESET_IND, l1_reset},
 613        {ST_L1_F8, EV_RESET_IND, l1_reset},
 614        {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
 615        {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
 616        {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
 617        {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
 618        {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
 619        {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
 620        {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
 621        {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
 622        {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
 623        {ST_L1_F3, EV_POWER_UP, l1_power_up_s},
 624        {ST_L1_F4, EV_RSYNC_IND, l1_go_F5},
 625        {ST_L1_F6, EV_RSYNC_IND, l1_go_F8},
 626        {ST_L1_F7, EV_RSYNC_IND, l1_go_F8},
 627        {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
 628        {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
 629        {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
 630        {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
 631        {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
 632        {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
 633        {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
 634        {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
 635        {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
 636        {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
 637        {ST_L1_F3, EV_TIMER3, l1_timer3},
 638        {ST_L1_F4, EV_TIMER3, l1_timer3},
 639        {ST_L1_F5, EV_TIMER3, l1_timer3},
 640        {ST_L1_F6, EV_TIMER3, l1_timer3},
 641        {ST_L1_F8, EV_TIMER3, l1_timer3},
 642        {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
 643        {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
 644        {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
 645        {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
 646        {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
 647        {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
 648        {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
 649};
 650
 651#ifdef HISAX_UINTERFACE
 652static void
 653l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
 654{
 655        struct PStack *st = fi->userdata;
 656
 657        FsmChangeState(fi, ST_L1_RESET);
 658        FsmRestartTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
 659        test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
 660        st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
 661}
 662
 663static void
 664l1_power_up_u(struct FsmInst *fi, int event, void *arg)
 665{
 666        struct PStack *st = fi->userdata;
 667
 668        FsmRestartTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
 669        test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
 670}
 671
 672static void
 673l1_info0_ind(struct FsmInst *fi, int event, void *arg)
 674{
 675        FsmChangeState(fi, ST_L1_DEACT);
 676}
 677
 678static void
 679l1_activate_u(struct FsmInst *fi, int event, void *arg)
 680{
 681        struct PStack *st = fi->userdata;
 682                
 683        st->l1.l1hw(st, HW_INFO1 | REQUEST, NULL);
 684}
 685
 686static struct FsmNode L1UFnList[] __initdata =
 687{
 688        {ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u},
 689        {ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u},
 690        {ST_L1_SYNC2, EV_DEACT_IND, l1_deact_req_u},
 691        {ST_L1_TRANS, EV_DEACT_IND, l1_deact_req_u},
 692        {ST_L1_DEACT, EV_PH_ACTIVATE, l1_activate_u},
 693        {ST_L1_DEACT, EV_POWER_UP, l1_power_up_u},
 694        {ST_L1_DEACT, EV_INFO2_IND, l1_info2_ind},
 695        {ST_L1_TRANS, EV_INFO2_IND, l1_info2_ind},
 696        {ST_L1_RESET, EV_DEACT_CNF, l1_info0_ind},
 697        {ST_L1_DEACT, EV_INFO4_IND, l1_info4_ind},
 698        {ST_L1_SYNC2, EV_INFO4_IND, l1_info4_ind},
 699        {ST_L1_RESET, EV_INFO4_IND, l1_info4_ind},
 700        {ST_L1_DEACT, EV_TIMER3, l1_timer3},
 701        {ST_L1_SYNC2, EV_TIMER3, l1_timer3},
 702        {ST_L1_TRANS, EV_TIMER_ACT, l1_timer_act},
 703        {ST_L1_DEACT, EV_TIMER_DEACT, l1_timer_deact},
 704        {ST_L1_SYNC2, EV_TIMER_DEACT, l1_timer_deact},
 705        {ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
 706};
 707
 708#endif
 709
 710static void
 711l1b_activate(struct FsmInst *fi, int event, void *arg)
 712{
 713        struct PStack *st = fi->userdata;
 714
 715        FsmChangeState(fi, ST_L1_WAIT_ACT);
 716        FsmRestartTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
 717}
 718
 719static void
 720l1b_deactivate(struct FsmInst *fi, int event, void *arg)
 721{
 722        struct PStack *st = fi->userdata;
 723
 724        FsmChangeState(fi, ST_L1_WAIT_DEACT);
 725        FsmRestartTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
 726}
 727
 728static void
 729l1b_timer_act(struct FsmInst *fi, int event, void *arg)
 730{
 731        struct PStack *st = fi->userdata;
 732
 733        FsmChangeState(fi, ST_L1_ACTIV);
 734        st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 735}
 736
 737static void
 738l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
 739{
 740        struct PStack *st = fi->userdata;
 741
 742        FsmChangeState(fi, ST_L1_NULL);
 743        st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
 744}
 745
 746static struct FsmNode L1BFnList[] __initdata =
 747{
 748        {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
 749        {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
 750        {ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
 751        {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
 752};
 753
 754int __init 
 755Isdnl1New(void)
 756{
 757        int retval;
 758
 759        l1fsm_s.state_count = L1S_STATE_COUNT;
 760        l1fsm_s.event_count = L1_EVENT_COUNT;
 761        l1fsm_s.strEvent = strL1Event;
 762        l1fsm_s.strState = strL1SState;
 763        retval = FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
 764        if (retval)
 765                return retval;
 766
 767        l1fsm_b.state_count = L1B_STATE_COUNT;
 768        l1fsm_b.event_count = L1_EVENT_COUNT;
 769        l1fsm_b.strEvent = strL1Event;
 770        l1fsm_b.strState = strL1BState;
 771        retval = FsmNew(&l1fsm_b, L1BFnList, ARRAY_SIZE(L1BFnList));
 772        if (retval) {
 773                FsmFree(&l1fsm_s);
 774                return retval;
 775        }
 776#ifdef HISAX_UINTERFACE
 777        l1fsm_u.state_count = L1U_STATE_COUNT;
 778        l1fsm_u.event_count = L1_EVENT_COUNT;
 779        l1fsm_u.strEvent = strL1Event;
 780        l1fsm_u.strState = strL1UState;
 781        retval = FsmNew(&l1fsm_u, L1UFnList, ARRAY_SIZE(L1UFnList));
 782        if (retval) {
 783                FsmFree(&l1fsm_s);
 784                FsmFree(&l1fsm_b);
 785                return retval;
 786        }
 787#endif
 788        return 0;
 789}
 790
 791void Isdnl1Free(void)
 792{
 793#ifdef HISAX_UINTERFACE
 794        FsmFree(&l1fsm_u);
 795#endif
 796        FsmFree(&l1fsm_s);
 797        FsmFree(&l1fsm_b);
 798}
 799
 800static void
 801dch_l2l1(struct PStack *st, int pr, void *arg)
 802{
 803        struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 804
 805        switch (pr) {
 806                case (PH_DATA | REQUEST):
 807                case (PH_PULL | REQUEST):
 808                case (PH_PULL |INDICATION):
 809                        st->l1.l1hw(st, pr, arg);
 810                        break;
 811                case (PH_ACTIVATE | REQUEST):
 812                        if (cs->debug)
 813                                debugl1(cs, "PH_ACTIVATE_REQ %s",
 814                                        st->l1.l1m.fsm->strState[st->l1.l1m.state]);
 815                        if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags))
 816                                st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 817                        else {
 818                                test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
 819                                FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg);
 820                        }
 821                        break;
 822                case (PH_TESTLOOP | REQUEST):
 823                        if (1 & (long) arg)
 824                                debugl1(cs, "PH_TEST_LOOP B1");
 825                        if (2 & (long) arg)
 826                                debugl1(cs, "PH_TEST_LOOP B2");
 827                        if (!(3 & (long) arg))
 828                                debugl1(cs, "PH_TEST_LOOP DISABLED");
 829                        st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
 830                        break;
 831                default:
 832                        if (cs->debug)
 833                                debugl1(cs, "dch_l2l1 msg %04X unhandled", pr);
 834                        break;
 835        }
 836}
 837
 838void
 839l1_msg(struct IsdnCardState *cs, int pr, void *arg) {
 840        struct PStack *st;
 841
 842        st = cs->stlist;
 843        
 844        while (st) {
 845                switch(pr) {
 846                        case (HW_RESET | INDICATION):
 847                                FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
 848                                break;
 849                        case (HW_DEACTIVATE | CONFIRM):
 850                                FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
 851                                break;
 852                        case (HW_DEACTIVATE | INDICATION):
 853                                FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
 854                                break;
 855                        case (HW_POWERUP | CONFIRM):
 856                                FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
 857                                break;
 858                        case (HW_RSYNC | INDICATION):
 859                                FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
 860                                break;
 861                        case (HW_INFO2 | INDICATION):
 862                                FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
 863                                break;
 864                        case (HW_INFO4_P8 | INDICATION):
 865                        case (HW_INFO4_P10 | INDICATION):
 866                                FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
 867                                break;
 868                        default:
 869                                if (cs->debug)
 870                                        debugl1(cs, "l1msg %04X unhandled", pr);
 871                                break;
 872                }
 873                st = st->next;
 874        }
 875}
 876
 877void
 878l1_msg_b(struct PStack *st, int pr, void *arg) {
 879        switch(pr) {
 880                case (PH_ACTIVATE | REQUEST):
 881                        FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, NULL);
 882                        break;
 883                case (PH_DEACTIVATE | REQUEST):
 884                        FsmEvent(&st->l1.l1m, EV_PH_DEACTIVATE, NULL);
 885                        break;
 886        }
 887}
 888
 889void
 890setstack_HiSax(struct PStack *st, struct IsdnCardState *cs)
 891{
 892        st->l1.hardware = cs;
 893        st->protocol = cs->protocol;
 894        st->l1.l1m.fsm = &l1fsm_s;
 895        st->l1.l1m.state = ST_L1_F3;
 896        st->l1.Flags = 0;
 897#ifdef HISAX_UINTERFACE
 898        if (test_bit(FLG_HW_L1_UINT, &cs->HW_Flags)) {
 899                st->l1.l1m.fsm = &l1fsm_u;
 900                st->l1.l1m.state = ST_L1_RESET;
 901                st->l1.Flags = FLG_L1_UINT;
 902        }
 903#endif
 904        st->l1.l1m.debug = cs->debug;
 905        st->l1.l1m.userdata = st;
 906        st->l1.l1m.userint = 0;
 907        st->l1.l1m.printdebug = l1m_debug;
 908        FsmInitTimer(&st->l1.l1m, &st->l1.timer);
 909        setstack_tei(st);
 910        setstack_manager(st);
 911        st->l1.stlistp = &(cs->stlist);
 912        st->l2.l2l1  = dch_l2l1;
 913        if (cs->setstack_d)
 914                cs->setstack_d(st, cs);
 915}
 916
 917void
 918setstack_l1_B(struct PStack *st)
 919{
 920        struct IsdnCardState *cs = st->l1.hardware;
 921
 922        st->l1.l1m.fsm = &l1fsm_b;
 923        st->l1.l1m.state = ST_L1_NULL;
 924        st->l1.l1m.debug = cs->debug;
 925        st->l1.l1m.userdata = st;
 926        st->l1.l1m.userint = 0;
 927        st->l1.l1m.printdebug = l1m_debug;
 928        st->l1.Flags = 0;
 929        FsmInitTimer(&st->l1.l1m, &st->l1.timer);
 930}
 931
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.