Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  layer1.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 *
 * Author Karsten Keil <kkeil@novell.com>
 *
 * Copyright 2008  by Karsten Keil <kkeil@novell.com>
 */



#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mISDNhw.h>
#include "core.h"
#include "layer1.h"
#include "fsm.h"

static u_int *debug;

struct layer1 {
 u_long Flags;
 struct FsmInst l1m;
 struct FsmTimer timer3;
 struct FsmTimer timerX;
 int delay;
 int t3_value;
 struct dchannel *dch;
 dchannel_l1callback *dcb;
};

#define TIMER3_DEFAULT_VALUE 7000

static
struct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};

enum {
 ST_L1_F2,
 ST_L1_F3,
 ST_L1_F4,
 ST_L1_F5,
 ST_L1_F6,
 ST_L1_F7,
 ST_L1_F8,
};

#define L1S_STATE_COUNT (ST_L1_F8 + 1)

static char *strL1SState[] =
{
 "ST_L1_F2",
 "ST_L1_F3",
 "ST_L1_F4",
 "ST_L1_F5",
 "ST_L1_F6",
 "ST_L1_F7",
 "ST_L1_F8",
};

enum {
 EV_PH_ACTIVATE,
 EV_PH_DEACTIVATE,
 EV_RESET_IND,
 EV_DEACT_CNF,
 EV_DEACT_IND,
 EV_POWER_UP,
 EV_ANYSIG_IND,
 EV_INFO2_IND,
 EV_INFO4_IND,
 EV_TIMER_DEACT,
 EV_TIMER_ACT,
 EV_TIMER3,
};

#define L1_EVENT_COUNT (EV_TIMER3 + 1)

static char *strL1Event[] =
{
 "EV_PH_ACTIVATE",
 "EV_PH_DEACTIVATE",
 "EV_RESET_IND",
 "EV_DEACT_CNF",
 "EV_DEACT_IND",
 "EV_POWER_UP",
 "EV_ANYSIG_IND",
 "EV_INFO2_IND",
 "EV_INFO4_IND",
 "EV_TIMER_DEACT",
 "EV_TIMER_ACT",
 "EV_TIMER3",
};

static void
l1m_debug(struct FsmInst *fi, char *fmt, ...)
{
 struct layer1 *l1 = fi->userdata;
 struct va_format vaf;
 va_list va;

 va_start(va, fmt);

 vaf.fmt = fmt;
 vaf.va = &va;

 printk(KERN_DEBUG "%s: %pV\n", dev_name(&l1->dch->dev.dev), &vaf);

 va_end(va);
}

static void
l1_reset(struct FsmInst *fi, int event, void *arg)
{
 mISDN_FsmChangeState(fi, ST_L1_F3);
}

static void
l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 mISDN_FsmChangeState(fi, ST_L1_F3);
 if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))
  l1->dcb(l1->dch, HW_POWERUP_REQ);
}

static void
l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 mISDN_FsmChangeState(fi, ST_L1_F3);
 mISDN_FsmRestartTimer(&l1->timerX, 550, EV_TIMER_DEACT, NULL, 2);
 test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
}

static void
l1_power_up_s(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
  mISDN_FsmChangeState(fi, ST_L1_F4);
  l1->dcb(l1->dch, INFO3_P8);
 } else
  mISDN_FsmChangeState(fi, ST_L1_F3);
}

static void
l1_go_F5(struct FsmInst *fi, int event, void *arg)
{
 mISDN_FsmChangeState(fi, ST_L1_F5);
}

static void
l1_go_F8(struct FsmInst *fi, int event, void *arg)
{
 mISDN_FsmChangeState(fi, ST_L1_F8);
}

static void
l1_info2_ind(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 mISDN_FsmChangeState(fi, ST_L1_F6);
 l1->dcb(l1->dch, INFO3_P8);
}

static void
l1_info4_ind(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 mISDN_FsmChangeState(fi, ST_L1_F7);
 l1->dcb(l1->dch, INFO3_P8);
 if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
  mISDN_FsmDelTimer(&l1->timerX, 4);
 if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
  if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
   mISDN_FsmDelTimer(&l1->timer3, 3);
  mISDN_FsmRestartTimer(&l1->timerX, 110, EV_TIMER_ACT, NULL, 2);
  test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
 }
}

static void
l1_timer3(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);
 if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
  if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
   l1->dcb(l1->dch, HW_D_NOBLOCKED);
  l1->dcb(l1->dch, PH_DEACTIVATE_IND);
 }
 if (l1->l1m.state != ST_L1_F6) {
  mISDN_FsmChangeState(fi, ST_L1_F3);
  /* do not force anything here, we need send INFO 0 */
 }
}

static void
l1_timer_act(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);
 test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);
 l1->dcb(l1->dch, PH_ACTIVATE_IND);
}

static void
l1_timer_deact(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);
 test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);
 if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
  l1->dcb(l1->dch, HW_D_NOBLOCKED);
 l1->dcb(l1->dch, PH_DEACTIVATE_IND);
 l1->dcb(l1->dch, HW_DEACT_REQ);
}

static void
l1_activate_s(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 mISDN_FsmRestartTimer(&l1->timer3, l1->t3_value, EV_TIMER3, NULL, 2);
 test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
 /* Tell HW to send INFO 1 */
 l1->dcb(l1->dch, HW_RESET_REQ);
}

static void
l1_activate_no(struct FsmInst *fi, int event, void *arg)
{
 struct layer1 *l1 = fi->userdata;

 if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) &&
     (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {
  test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);
  if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
   l1->dcb(l1->dch, HW_D_NOBLOCKED);
  l1->dcb(l1->dch, PH_DEACTIVATE_IND);
 }
}

static struct FsmNode L1SFnList[] =
{
 {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
 {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
 {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
 {ST_L1_F3, EV_RESET_IND, l1_reset},
 {ST_L1_F4, EV_RESET_IND, l1_reset},
 {ST_L1_F5, EV_RESET_IND, l1_reset},
 {ST_L1_F6, EV_RESET_IND, l1_reset},
 {ST_L1_F7, EV_RESET_IND, l1_reset},
 {ST_L1_F8, EV_RESET_IND, l1_reset},
 {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
 {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
 {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
 {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
 {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
 {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
 {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
 {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
 {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
 {ST_L1_F3, EV_POWER_UP,  l1_power_up_s},
 {ST_L1_F4, EV_ANYSIG_IND, l1_go_F5},
 {ST_L1_F6, EV_ANYSIG_IND, l1_go_F8},
 {ST_L1_F7, EV_ANYSIG_IND, l1_go_F8},
 {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
 {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
 {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
 {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
 {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
 {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
 {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
 {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
 {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
 {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
 {ST_L1_F3, EV_TIMER3, l1_timer3},
 {ST_L1_F4, EV_TIMER3, l1_timer3},
 {ST_L1_F5, EV_TIMER3, l1_timer3},
 {ST_L1_F6, EV_TIMER3, l1_timer3},
 {ST_L1_F8, EV_TIMER3, l1_timer3},
 {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
 {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
 {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
 {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
 {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
 {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
 {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
};

static void
release_l1(struct layer1 *l1) {
 mISDN_FsmDelTimer(&l1->timerX, 0);
 mISDN_FsmDelTimer(&l1->timer3, 0);
 if (l1->dch)
  l1->dch->l1 = NULL;
 module_put(THIS_MODULE);
 kfree(l1);
}

int
l1_event(struct layer1 *l1, u_int event)
{
 int  err = 0;

 if (!l1)
  return -EINVAL;
 switch (event) {
 case HW_RESET_IND:
  mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);
  break;
 case HW_DEACT_IND:
  mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);
  break;
 case HW_POWERUP_IND:
  mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);
  break;
 case HW_DEACT_CNF:
  mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);
  break;
 case ANYSIGNAL:
  mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
  break;
 case LOSTFRAMING:
  mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
  break;
 case INFO2:
  mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);
  break;
 case INFO4_P8:
  mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
  break;
 case INFO4_P10:
  mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
  break;
 case PH_ACTIVATE_REQ:
  if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
   l1->dcb(l1->dch, PH_ACTIVATE_IND);
  else {
   test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);
   mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);
  }
  break;
 case CLOSE_CHANNEL:
  release_l1(l1);
  break;
 default:
  if ((event & ~HW_TIMER3_VMASK) == HW_TIMER3_VALUE) {
   int val = event & HW_TIMER3_VMASK;

   if (val < 5)
    val = 5;
   if (val > 30)
    val = 30;
   l1->t3_value = val;
   break;
  }
  if (*debug & DEBUG_L1)
   printk(KERN_DEBUG "%s %x unhandled\n",
          __func__, event);
  err = -EINVAL;
 }
 return err;
}
EXPORT_SYMBOL(l1_event);

int
create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
 struct layer1 *nl1;

 nl1 = kzalloc(sizeof(struct layer1), GFP_ATOMIC);
 if (!nl1) {
  printk(KERN_ERR "kmalloc struct layer1 failed\n");
  return -ENOMEM;
 }
 nl1->l1m.fsm = &l1fsm_s;
 nl1->l1m.state = ST_L1_F3;
 nl1->Flags = 0;
 nl1->t3_value = TIMER3_DEFAULT_VALUE;
 nl1->l1m.debug = *debug & DEBUG_L1_FSM;
 nl1->l1m.userdata = nl1;
 nl1->l1m.userint = 0;
 nl1->l1m.printdebug = l1m_debug;
 nl1->dch = dch;
 nl1->dcb = dcb;
 mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer3);
 mISDN_FsmInitTimer(&nl1->l1m, &nl1->timerX);
 __module_get(THIS_MODULE);
 dch->l1 = nl1;
 return 0;
}
EXPORT_SYMBOL(create_l1);

int
Isdnl1_Init(u_int *deb)
{
 debug = deb;
 l1fsm_s.state_count = L1S_STATE_COUNT;
 l1fsm_s.event_count = L1_EVENT_COUNT;
 l1fsm_s.strEvent = strL1Event;
 l1fsm_s.strState = strL1SState;
 return mISDN_FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
}

void
Isdnl1_cleanup(void)
{
 mISDN_FsmFree(&l1fsm_s);
}

Messung V0.5
C=97 H=98 G=97

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge