2001-02-11 22:46:19 +00:00
|
|
|
/* $Id$
|
|
|
|
*
|
2006-03-06 12:52:08 +00:00
|
|
|
* mISDN_l1.c common low level stuff for I.430 layer1 TE mode
|
2001-02-11 22:46:19 +00:00
|
|
|
*
|
|
|
|
* Author Karsten Keil (keil@isdn4linux.de)
|
|
|
|
*
|
2006-03-06 12:52:08 +00:00
|
|
|
* This file is released under the GPLv2
|
2001-02-11 22:46:19 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2003-07-21 11:13:02 +00:00
|
|
|
static char *l1_revision = "$Revision$";
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
#include <linux/config.h>
|
|
|
|
#include <linux/module.h>
|
2003-07-21 12:44:46 +00:00
|
|
|
#include "layer1.h"
|
2001-08-02 14:51:56 +00:00
|
|
|
#include "helper.h"
|
2001-02-11 22:46:19 +00:00
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
typedef struct _layer1 {
|
2004-06-17 12:31:14 +00:00
|
|
|
struct list_head list;
|
|
|
|
u_long Flags;
|
|
|
|
struct FsmInst l1m;
|
|
|
|
struct FsmTimer timer;
|
|
|
|
int debug;
|
|
|
|
int delay;
|
|
|
|
mISDNinstance_t inst;
|
2001-02-11 22:46:19 +00:00
|
|
|
} layer1_t;
|
|
|
|
|
2001-04-11 16:38:57 +00:00
|
|
|
/* l1 status_info */
|
|
|
|
typedef struct _status_info_l1 {
|
|
|
|
int len;
|
|
|
|
int typ;
|
|
|
|
int protocol;
|
|
|
|
int status;
|
|
|
|
int state;
|
2003-07-27 11:14:19 +00:00
|
|
|
u_long Flags;
|
2001-04-11 16:38:57 +00:00
|
|
|
int T3;
|
|
|
|
int delay;
|
|
|
|
int debug;
|
|
|
|
} status_info_l1_t;
|
|
|
|
|
2001-02-11 22:46:19 +00:00
|
|
|
static int debug = 0;
|
2003-07-21 12:00:05 +00:00
|
|
|
static mISDNobject_t isdnl1;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
#define TIMER3_VALUE 7000
|
|
|
|
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2001-02-11 22:46:19 +00:00
|
|
|
static
|
|
|
|
struct Fsm l1fsm_b =
|
|
|
|
{NULL, 0, 0, NULL, NULL};
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
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",
|
|
|
|
};
|
|
|
|
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2001-02-11 22:46:19 +00:00
|
|
|
static
|
|
|
|
struct Fsm l1fsm_u =
|
|
|
|
{NULL, 0, 0, NULL, NULL};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ST_L1_RESET,
|
|
|
|
ST_L1_DEACT,
|
|
|
|
ST_L1_SYNC2,
|
|
|
|
ST_L1_TRANS,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define L1U_STATE_COUNT (ST_L1_TRANS+1)
|
|
|
|
|
|
|
|
static char *strL1UState[] =
|
|
|
|
{
|
|
|
|
"ST_L1_RESET",
|
|
|
|
"ST_L1_DEACT",
|
|
|
|
"ST_L1_SYNC2",
|
|
|
|
"ST_L1_TRANS",
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2001-02-11 22:46:19 +00:00
|
|
|
enum {
|
|
|
|
ST_L1_NULL,
|
|
|
|
ST_L1_WAIT_ACT,
|
|
|
|
ST_L1_WAIT_DEACT,
|
|
|
|
ST_L1_ACTIV,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
|
|
|
|
|
|
|
|
static char *strL1BState[] =
|
|
|
|
{
|
|
|
|
"ST_L1_NULL",
|
|
|
|
"ST_L1_WAIT_ACT",
|
|
|
|
"ST_L1_WAIT_DEACT",
|
|
|
|
"ST_L1_ACTIV",
|
|
|
|
};
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
enum {
|
|
|
|
EV_PH_ACTIVATE,
|
|
|
|
EV_PH_DEACTIVATE,
|
|
|
|
EV_RESET_IND,
|
|
|
|
EV_DEACT_CNF,
|
|
|
|
EV_DEACT_IND,
|
|
|
|
EV_POWER_UP,
|
2006-03-06 12:52:08 +00:00
|
|
|
EV_ANYSIG_IND,
|
2001-02-11 22:46:19 +00:00
|
|
|
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",
|
2006-03-06 12:52:08 +00:00
|
|
|
"EV_ANYSIG_IND",
|
2001-02-11 22:46:19 +00:00
|
|
|
"EV_INFO2_IND",
|
|
|
|
"EV_INFO4_IND",
|
|
|
|
"EV_TIMER_DEACT",
|
|
|
|
"EV_TIMER_ACT",
|
|
|
|
"EV_TIMER3",
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1m_debug(struct FsmInst *fi, char *fmt, ...)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
logdata_t log;
|
|
|
|
|
|
|
|
va_start(log.args, fmt);
|
|
|
|
log.fmt = fmt;
|
2001-03-11 21:23:39 +00:00
|
|
|
log.head = l1->inst.name;
|
2006-03-23 10:05:16 +00:00
|
|
|
mISDN_ctrl(&l1->inst, MGR_DEBUGDATA | REQUEST, &log);
|
2001-02-11 22:46:19 +00:00
|
|
|
va_end(log.args);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-08-02 14:51:56 +00:00
|
|
|
l1up(layer1_t *l1, u_int prim, int dinfo, int len, void *arg)
|
|
|
|
{
|
2006-03-06 12:52:08 +00:00
|
|
|
return(mISDN_queue_data(&l1->inst, FLG_MSG_UP, prim, dinfo, len, arg, 0));
|
2001-03-26 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(layer1_t *l1, u_int prim, int dinfo, int len, void *arg)
|
|
|
|
{
|
2006-03-06 12:52:08 +00:00
|
|
|
return(mISDN_queue_data(&l1->inst, FLG_MSG_DOWN, prim, dinfo, len, arg, 0));
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_reset(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F3);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F3);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F3);
|
|
|
|
mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
|
2001-02-11 22:46:19 +00:00
|
|
|
test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_power_up_s(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
|
|
|
if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F4);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
} else
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F3);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_go_F5(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F5);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_go_F8(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F8);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_info2_ind(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2001-02-11 22:46:19 +00:00
|
|
|
if (test_bit(FLG_L1_UINT, &l1->Flags))
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_SYNC2);
|
2001-02-11 22:46:19 +00:00
|
|
|
else
|
|
|
|
#endif
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F6);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_info4_ind(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2001-02-11 22:46:19 +00:00
|
|
|
if (test_bit(FLG_L1_UINT, &l1->Flags))
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_TRANS);
|
2001-02-11 22:46:19 +00:00
|
|
|
else
|
|
|
|
#endif
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F7);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmDelTimer(&l1->timer, 4);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
|
|
|
|
if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmDelTimer(&l1->timer, 3);
|
|
|
|
mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
|
2001-02-11 22:46:19 +00:00
|
|
|
test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_timer3(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
2001-02-13 10:42:55 +00:00
|
|
|
u_int db = HW_D_NOBLOCKED;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2006-03-06 12:52:08 +00:00
|
|
|
test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
|
2001-02-13 10:42:55 +00:00
|
|
|
if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
|
|
|
|
l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
|
2006-03-06 12:52:08 +00:00
|
|
|
mISDN_queue_data(&l1->inst, l1->inst.id | MSG_BROADCAST,
|
|
|
|
MGR_SHORTSTATUS | INDICATION, SSTATUS_L1_DEACTIVATED,
|
|
|
|
0, NULL, 0);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2001-02-11 22:46:19 +00:00
|
|
|
if (!test_bit(FLG_L1_UINT, &l1->Flags))
|
|
|
|
#endif
|
|
|
|
if (l1->l1m.state != ST_L1_F6) {
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_F3);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_timer_act(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
|
|
|
test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);
|
|
|
|
test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);
|
|
|
|
if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags))
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
else
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_ACTIVATE | INDICATION, 0, 0, NULL);
|
2006-03-06 12:52:08 +00:00
|
|
|
mISDN_queue_data(&l1->inst, l1->inst.id | MSG_BROADCAST,
|
|
|
|
MGR_SHORTSTATUS | INDICATION, SSTATUS_L1_ACTIVATED,
|
|
|
|
0, NULL, 0);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_timer_deact(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
2001-02-13 10:42:55 +00:00
|
|
|
u_int db = HW_D_NOBLOCKED;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);
|
|
|
|
test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);
|
2001-02-13 10:42:55 +00:00
|
|
|
if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
|
|
|
|
l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_CONTROL | REQUEST, HW_DEACTIVATE, 0, NULL);
|
2006-03-06 12:52:08 +00:00
|
|
|
mISDN_queue_data(&l1->inst, l1->inst.id | MSG_BROADCAST,
|
|
|
|
MGR_SHORTSTATUS | INDICATION, SSTATUS_L1_DEACTIVATED,
|
|
|
|
0, NULL, 0);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_activate_s(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2006-03-06 12:52:08 +00:00
|
|
|
mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
|
|
|
|
test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_CONTROL | REQUEST, HW_RESET, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_activate_no(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
2001-02-13 10:42:55 +00:00
|
|
|
u_int db = HW_D_NOBLOCKED;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) && (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {
|
|
|
|
test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);
|
2001-02-13 10:42:55 +00:00
|
|
|
if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
|
|
|
|
l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-02-13 10:42:55 +00:00
|
|
|
static struct FsmNode L1SFnList[] =
|
2001-02-11 22:46:19 +00:00
|
|
|
{
|
|
|
|
{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},
|
|
|
|
};
|
|
|
|
|
|
|
|
#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
|
|
|
|
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2001-02-11 22:46:19 +00:00
|
|
|
static void
|
|
|
|
l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_RESET);
|
|
|
|
mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
|
2001-02-11 22:46:19 +00:00
|
|
|
test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_power_up_u(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
|
2001-02-11 22:46:19 +00:00
|
|
|
test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_info0_ind(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_DEACT);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1_activate_u(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2001-08-02 14:51:56 +00:00
|
|
|
l1down(l1, PH_SIGNAL | REQUEST, INFO1, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
2001-02-13 10:42:55 +00:00
|
|
|
static struct FsmNode L1UFnList[] =
|
2001-02-11 22:46:19 +00:00
|
|
|
{
|
|
|
|
{ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u},
|
|
|
|
{ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u},
|
|
|
|
{ST_L1_SYNC2, EV_DEACT_IND, l1_deact_req_u},
|
|
|
|
{ST_L1_TRANS, EV_DEACT_IND, l1_deact_req_u},
|
|
|
|
{ST_L1_DEACT, EV_PH_ACTIVATE, l1_activate_u},
|
|
|
|
{ST_L1_DEACT, EV_POWER_UP, l1_power_up_u},
|
|
|
|
{ST_L1_DEACT, EV_INFO2_IND, l1_info2_ind},
|
|
|
|
{ST_L1_TRANS, EV_INFO2_IND, l1_info2_ind},
|
|
|
|
{ST_L1_RESET, EV_DEACT_CNF, l1_info0_ind},
|
|
|
|
{ST_L1_DEACT, EV_INFO4_IND, l1_info4_ind},
|
|
|
|
{ST_L1_SYNC2, EV_INFO4_IND, l1_info4_ind},
|
|
|
|
{ST_L1_RESET, EV_INFO4_IND, l1_info4_ind},
|
|
|
|
{ST_L1_DEACT, EV_TIMER3, l1_timer3},
|
|
|
|
{ST_L1_SYNC2, EV_TIMER3, l1_timer3},
|
|
|
|
{ST_L1_TRANS, EV_TIMER_ACT, l1_timer_act},
|
|
|
|
{ST_L1_DEACT, EV_TIMER_DEACT, l1_timer_deact},
|
|
|
|
{ST_L1_SYNC2, EV_TIMER_DEACT, l1_timer_deact},
|
|
|
|
{ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
|
|
|
|
};
|
|
|
|
|
|
|
|
#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
|
|
|
|
|
|
|
|
#endif
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2001-02-11 22:46:19 +00:00
|
|
|
static void
|
|
|
|
l1b_activate(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_WAIT_ACT);
|
|
|
|
mISDN_FsmRestartTimer(&l1->timer, l1->delay, EV_TIMER_ACT, NULL, 2);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1b_deactivate(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_WAIT_DEACT);
|
|
|
|
mISDN_FsmRestartTimer(&l1->timer, 10, EV_TIMER_DEACT, NULL, 2);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1b_timer_act(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_ACTIV);
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = fi->userdata;
|
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmChangeState(fi, ST_L1_NULL);
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_DEACTIVATE | CONFIRM, 0, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
2001-02-13 10:42:55 +00:00
|
|
|
static struct FsmNode L1BFnList[] =
|
2001-02-11 22:46:19 +00:00
|
|
|
{
|
|
|
|
{ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
|
|
|
|
{ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
|
|
|
|
{ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
|
|
|
|
{ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
|
|
|
|
};
|
|
|
|
|
|
|
|
#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
static int
|
2006-03-06 12:52:08 +00:00
|
|
|
l1from_up(layer1_t *l1, struct sk_buff *skb, mISDN_head_t *hh)
|
2001-08-02 14:51:56 +00:00
|
|
|
{
|
|
|
|
int err = 0;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2001-08-02 14:51:56 +00:00
|
|
|
switch(hh->prim) {
|
2001-02-11 22:46:19 +00:00
|
|
|
case (PH_DATA | REQUEST):
|
2001-02-13 10:42:55 +00:00
|
|
|
case (PH_CONTROL | REQUEST):
|
2006-03-06 12:52:08 +00:00
|
|
|
return(mISDN_queue_down(&l1->inst, 0, skb));
|
2001-02-11 22:46:19 +00:00
|
|
|
break;
|
|
|
|
case (PH_ACTIVATE | REQUEST):
|
|
|
|
if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
|
2001-03-03 18:17:16 +00:00
|
|
|
l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
else {
|
|
|
|
test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
break;
|
2001-03-04 00:48:49 +00:00
|
|
|
case (MDL_FINDTEI | REQUEST):
|
2006-03-06 12:52:08 +00:00
|
|
|
return(mISDN_queue_up(&l1->inst, 0, skb));
|
2001-08-02 14:51:56 +00:00
|
|
|
break;
|
2001-02-11 22:46:19 +00:00
|
|
|
default:
|
|
|
|
if (l1->debug)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_debug(l1->inst.st->id, NULL,
|
2001-08-02 14:51:56 +00:00
|
|
|
"l1from_up msg %x unhandled", hh->prim);
|
|
|
|
err = -EINVAL;
|
2001-02-11 22:46:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-08-02 14:51:56 +00:00
|
|
|
if (!err)
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
return(err);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-06 12:52:08 +00:00
|
|
|
l1from_down(layer1_t *l1, struct sk_buff *skb, mISDN_head_t *hh)
|
2001-08-02 14:51:56 +00:00
|
|
|
{
|
|
|
|
int err = 0;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2001-08-02 14:51:56 +00:00
|
|
|
if (hh->prim == PH_DATA_IND) {
|
2001-02-11 22:46:19 +00:00
|
|
|
if (test_bit(FLG_L1_ACTTIMER, &l1->Flags))
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_TIMER_ACT, NULL);
|
2006-03-06 12:52:08 +00:00
|
|
|
return(mISDN_queue_up(&l1->inst, 0, skb));
|
2001-08-02 14:51:56 +00:00
|
|
|
} else if (hh->prim == PH_DATA_CNF) {
|
2006-03-06 12:52:08 +00:00
|
|
|
return(mISDN_queue_up(&l1->inst, 0, skb));
|
2001-08-02 14:51:56 +00:00
|
|
|
} else if (hh->prim == (PH_CONTROL | INDICATION)) {
|
|
|
|
if (hh->dinfo == HW_RESET)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (hh->dinfo == HW_DEACTIVATE)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (hh->dinfo == HW_POWERUP)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (l1->debug)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_debug(l1->inst.st->id, NULL,
|
2001-08-02 14:51:56 +00:00
|
|
|
"l1from_down ctrl ind %x unhandled", hh->dinfo);
|
|
|
|
} else if (hh->prim == (PH_CONTROL | CONFIRM)) {
|
2006-03-06 12:52:08 +00:00
|
|
|
if (hh->dinfo == HW_DEACTIVATE)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (l1->debug)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_debug(l1->inst.st->id, NULL,
|
2001-08-02 14:51:56 +00:00
|
|
|
"l1from_down ctrl cnf %x unhandled", hh->dinfo);
|
|
|
|
} else if (hh->prim == (PH_SIGNAL | INDICATION)) {
|
|
|
|
if (hh->dinfo == ANYSIGNAL)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (hh->dinfo == LOSTFRAMING)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (hh->dinfo == INFO2)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (hh->dinfo == INFO4_P8)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (hh->dinfo == INFO4_P10)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
|
2001-08-02 14:51:56 +00:00
|
|
|
else if (l1->debug)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_debug(l1->inst.st->id, NULL,
|
2001-08-02 14:51:56 +00:00
|
|
|
"l1from_down sig %x unhandled", hh->dinfo);
|
2001-02-11 22:46:19 +00:00
|
|
|
} else {
|
|
|
|
if (l1->debug)
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_debug(l1->inst.st->id, NULL,
|
2001-08-02 14:51:56 +00:00
|
|
|
"l1from_down msg %x unhandled", hh->prim);
|
|
|
|
err = -EINVAL;
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2001-08-02 14:51:56 +00:00
|
|
|
if (!err)
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
return(err);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
2006-03-06 12:52:08 +00:00
|
|
|
static int
|
|
|
|
l1_shortstatus(layer1_t *l1, struct sk_buff *skb, mISDN_head_t *hh)
|
|
|
|
{
|
|
|
|
u_int temp;
|
|
|
|
|
|
|
|
if (hh->prim == (MGR_SHORTSTATUS | REQUEST)) {
|
|
|
|
temp = hh->dinfo & SSTATUS_ALL;
|
|
|
|
if (temp == SSTATUS_ALL || temp == SSTATUS_L1) {
|
|
|
|
skb_trim(skb, 0);
|
|
|
|
if (hh->dinfo & SSTATUS_BROADCAST_BIT)
|
|
|
|
temp = l1->inst.id | MSG_BROADCAST;
|
|
|
|
else
|
|
|
|
temp = hh->addr | FLG_MSG_TARGET;
|
|
|
|
hh->dinfo = (l1->l1m.state == ST_L1_F7) ?
|
|
|
|
SSTATUS_L1_ACTIVATED : SSTATUS_L1_DEACTIVATED;
|
|
|
|
hh->prim = MGR_SHORTSTATUS | CONFIRM;
|
|
|
|
return(mISDN_queue_message(&l1->inst, temp, skb));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(-EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
l1_function(mISDNinstance_t *inst, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
layer1_t *l1 = inst->privat;
|
|
|
|
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
|
|
if (debug)
|
|
|
|
printk(KERN_DEBUG "%s: addr(%08x) prim(%x)\n", __FUNCTION__, hh->addr, hh->prim);
|
|
|
|
|
|
|
|
if (unlikely((hh->prim & MISDN_CMD_MASK) == MGR_SHORTSTATUS))
|
|
|
|
return(l1_shortstatus(l1, skb, hh));
|
|
|
|
|
|
|
|
switch(hh->addr & MSG_DIR_MASK) {
|
|
|
|
case FLG_MSG_DOWN:
|
|
|
|
ret = l1from_up(l1, skb, hh);
|
|
|
|
break;
|
|
|
|
case FLG_MSG_UP:
|
|
|
|
ret = l1from_down(l1, skb, hh);
|
|
|
|
break;
|
|
|
|
case MSG_TO_OWNER:
|
|
|
|
/* FIXME: must be handled depending on type */
|
|
|
|
int_errtxt("not implemented yet");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* FIXME: must be handled depending on type */
|
|
|
|
int_errtxt("not implemented yet");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
2001-02-11 22:46:19 +00:00
|
|
|
static void
|
|
|
|
release_l1(layer1_t *l1) {
|
2003-07-21 12:00:05 +00:00
|
|
|
mISDNinstance_t *inst = &l1->inst;
|
2006-03-06 12:52:08 +00:00
|
|
|
u_long flags;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmDelTimer(&l1->timer, 0);
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2001-03-26 11:40:02 +00:00
|
|
|
if (inst->up.peer) {
|
|
|
|
inst->up.peer->obj->ctrl(inst->up.peer,
|
|
|
|
MGR_DISCONNECT | REQUEST, &inst->up);
|
|
|
|
}
|
|
|
|
if (inst->down.peer) {
|
|
|
|
inst->down.peer->obj->ctrl(inst->down.peer,
|
|
|
|
MGR_DISCONNECT | REQUEST, &inst->down);
|
|
|
|
}
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
|
|
|
spin_lock_irqsave(&isdnl1.lock, flags);
|
2004-06-17 12:31:14 +00:00
|
|
|
list_del(&l1->list);
|
2006-03-06 12:52:08 +00:00
|
|
|
spin_unlock_irqrestore(&isdnl1.lock, flags);
|
2006-03-23 10:05:16 +00:00
|
|
|
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
2001-02-11 22:46:19 +00:00
|
|
|
kfree(l1);
|
|
|
|
}
|
|
|
|
|
2001-03-26 11:40:02 +00:00
|
|
|
static int
|
2003-07-21 12:00:05 +00:00
|
|
|
new_l1(mISDNstack_t *st, mISDN_pid_t *pid) {
|
2006-03-06 12:52:08 +00:00
|
|
|
layer1_t *nl1;
|
|
|
|
int err;
|
|
|
|
u_long flags;
|
2001-03-26 11:40:02 +00:00
|
|
|
|
|
|
|
if (!st || !pid)
|
|
|
|
return(-EINVAL);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (!(nl1 = kmalloc(sizeof(layer1_t), GFP_ATOMIC))) {
|
|
|
|
printk(KERN_ERR "kmalloc layer1_t failed\n");
|
2001-03-26 11:40:02 +00:00
|
|
|
return(-ENOMEM);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
memset(nl1, 0, sizeof(layer1_t));
|
2003-07-21 12:00:05 +00:00
|
|
|
memcpy(&nl1->inst.pid, pid, sizeof(mISDN_pid_t));
|
2006-03-06 12:52:08 +00:00
|
|
|
mISDN_init_instance(&nl1->inst, &isdnl1, nl1, l1_function);
|
2004-01-26 22:21:32 +00:00
|
|
|
if (!mISDN_SetHandledPID(&isdnl1, &nl1->inst.pid)) {
|
2001-03-26 11:40:02 +00:00
|
|
|
int_error();
|
|
|
|
return(-ENOPROTOOPT);
|
|
|
|
}
|
|
|
|
switch(pid->protocol[1]) {
|
2001-02-11 22:46:19 +00:00
|
|
|
case ISDN_PID_L1_TE_S0:
|
2006-03-06 12:52:08 +00:00
|
|
|
sprintf(nl1->inst.name, "l1TES0 %x", st->id >> 8);
|
2001-02-11 22:46:19 +00:00
|
|
|
nl1->l1m.fsm = &l1fsm_s;
|
|
|
|
nl1->l1m.state = ST_L1_F3;
|
|
|
|
nl1->Flags = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2001-03-26 11:40:02 +00:00
|
|
|
printk(KERN_ERR "layer1 create failed prt %x\n",
|
|
|
|
pid->protocol[1]);
|
2001-02-11 22:46:19 +00:00
|
|
|
kfree(nl1);
|
2001-03-26 11:40:02 +00:00
|
|
|
return(-ENOPROTOOPT);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
nl1->debug = debug;
|
|
|
|
nl1->l1m.debug = debug;
|
|
|
|
nl1->l1m.userdata = nl1;
|
|
|
|
nl1->l1m.userint = 0;
|
|
|
|
nl1->l1m.printdebug = l1m_debug;
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
|
2006-03-06 12:52:08 +00:00
|
|
|
spin_lock_irqsave(&isdnl1.lock, flags);
|
2004-06-17 12:31:14 +00:00
|
|
|
list_add_tail(&nl1->list, &isdnl1.ilist);
|
2006-03-06 12:52:08 +00:00
|
|
|
spin_unlock_irqrestore(&isdnl1.lock, flags);
|
2006-03-23 10:05:16 +00:00
|
|
|
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (err) {
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmDelTimer(&nl1->timer, 0);
|
2004-06-17 12:31:14 +00:00
|
|
|
list_del(&nl1->list);
|
2001-03-26 11:40:02 +00:00
|
|
|
kfree(nl1);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
return(err);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
2001-04-11 16:38:57 +00:00
|
|
|
static int
|
|
|
|
l1_status(layer1_t *l1, status_info_l1_t *si)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!si)
|
|
|
|
return(-EINVAL);
|
|
|
|
memset(si, 0, sizeof(status_info_l1_t));
|
|
|
|
si->len = sizeof(status_info_l1_t) - 2*sizeof(int);
|
|
|
|
si->typ = STATUS_INFO_L1;
|
|
|
|
si->protocol = l1->inst.pid.protocol[1];
|
|
|
|
if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
|
|
|
|
si->status = 1;
|
|
|
|
si->state = l1->l1m.state;
|
|
|
|
si->Flags = l1->Flags;
|
|
|
|
si->T3 = TIMER3_VALUE;
|
|
|
|
si->debug = l1->delay;
|
|
|
|
si->debug = l1->debug;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2001-02-11 22:46:19 +00:00
|
|
|
static char MName[] = "ISDNL1";
|
|
|
|
|
|
|
|
#ifdef MODULE
|
|
|
|
MODULE_AUTHOR("Karsten Keil");
|
2006-06-28 18:03:53 +00:00
|
|
|
#ifdef OLD_MODULE_PARAM
|
|
|
|
MODULE_PARM(debug, "1i");
|
|
|
|
#else
|
2006-03-22 18:33:04 +00:00
|
|
|
module_param(debug, uint, S_IRUGO | S_IWUSR);
|
2006-06-28 18:03:53 +00:00
|
|
|
#endif
|
2003-06-24 21:58:53 +00:00
|
|
|
#ifdef MODULE_LICENSE
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
#define Isdnl1Init init_module
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
|
|
|
l1_manager(void *data, u_int prim, void *arg) {
|
2004-06-17 12:31:14 +00:00
|
|
|
mISDNinstance_t *inst = data;
|
|
|
|
layer1_t *l1l;
|
|
|
|
int err = -EINVAL;
|
2006-03-06 12:52:08 +00:00
|
|
|
u_long flags;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2003-09-06 17:13:02 +00:00
|
|
|
if (debug & 0x10000)
|
|
|
|
printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
|
|
|
|
__FUNCTION__, data, prim, arg);
|
2001-02-11 22:46:19 +00:00
|
|
|
if (!data)
|
2004-06-17 12:31:14 +00:00
|
|
|
return(err);
|
2006-03-06 12:52:08 +00:00
|
|
|
spin_lock_irqsave(&isdnl1.lock, flags);
|
2004-06-17 12:31:14 +00:00
|
|
|
list_for_each_entry(l1l, &isdnl1.ilist, list) {
|
|
|
|
if (&l1l->inst == inst) {
|
|
|
|
err = 0;
|
2001-02-11 22:46:19 +00:00
|
|
|
break;
|
2004-06-17 12:31:14 +00:00
|
|
|
}
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2006-03-06 12:52:08 +00:00
|
|
|
spin_unlock_irqrestore(&isdnl1.lock, flags);
|
2004-06-17 12:31:14 +00:00
|
|
|
if (err && (prim != (MGR_NEWLAYER | REQUEST))) {
|
2006-10-09 12:51:33 +00:00
|
|
|
if (debug)
|
|
|
|
printk(KERN_WARNING "l1_manager connect no instance\n");
|
2004-06-17 12:31:14 +00:00
|
|
|
return(err);
|
|
|
|
}
|
2006-03-06 12:52:08 +00:00
|
|
|
|
2001-02-11 22:46:19 +00:00
|
|
|
switch(prim) {
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_NEWLAYER | REQUEST:
|
2004-06-17 12:31:14 +00:00
|
|
|
err = new_l1(data, arg);
|
|
|
|
break;
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_CONNECT | REQUEST:
|
2004-06-17 12:31:14 +00:00
|
|
|
err = mISDN_ConnectIF(inst, arg);
|
2001-03-26 11:40:02 +00:00
|
|
|
break;
|
|
|
|
case MGR_SETIF | REQUEST:
|
|
|
|
case MGR_SETIF | INDICATION:
|
2004-06-17 12:31:14 +00:00
|
|
|
err = mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l);
|
2001-02-11 22:46:19 +00:00
|
|
|
break;
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_DISCONNECT | REQUEST:
|
|
|
|
case MGR_DISCONNECT | INDICATION:
|
2004-06-17 12:31:14 +00:00
|
|
|
err = mISDN_DisConnectIF(inst, arg);
|
2001-02-11 22:46:19 +00:00
|
|
|
break;
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_UNREGLAYER | REQUEST:
|
2001-02-11 22:46:19 +00:00
|
|
|
case MGR_RELEASE | INDICATION:
|
2004-06-17 12:31:14 +00:00
|
|
|
printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
|
|
|
|
release_l1(l1l);
|
|
|
|
break;
|
2001-04-11 16:38:57 +00:00
|
|
|
case MGR_STATUS | REQUEST:
|
2004-06-17 12:31:14 +00:00
|
|
|
err = l1_status(l1l, arg);
|
|
|
|
break;
|
2003-09-06 17:13:02 +00:00
|
|
|
PRIM_NOT_HANDLED(MGR_CTRLREADY|INDICATION);
|
|
|
|
PRIM_NOT_HANDLED(MGR_ADDSTPARA|INDICATION);
|
2006-10-09 12:51:33 +00:00
|
|
|
PRIM_NOT_HANDLED(MGR_SETSTACK|INDICATION);
|
2001-02-11 22:46:19 +00:00
|
|
|
default:
|
2001-02-27 17:45:44 +00:00
|
|
|
printk(KERN_WARNING "l1_manager prim %x not handled\n", prim);
|
2004-06-17 12:31:14 +00:00
|
|
|
err = -EINVAL;
|
|
|
|
break;
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2004-06-17 12:31:14 +00:00
|
|
|
return(err);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Isdnl1Init(void)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
2003-07-21 12:00:05 +00:00
|
|
|
printk(KERN_INFO "ISDN L1 driver version %s\n", mISDN_getrev(l1_revision));
|
2004-01-11 13:58:50 +00:00
|
|
|
#ifdef MODULE
|
|
|
|
isdnl1.owner = THIS_MODULE;
|
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
isdnl1.name = MName;
|
2001-03-04 17:08:33 +00:00
|
|
|
isdnl1.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
|
2001-02-11 22:46:19 +00:00
|
|
|
isdnl1.own_ctrl = l1_manager;
|
2006-03-06 12:52:08 +00:00
|
|
|
spin_lock_init(&isdnl1.lock);
|
2004-06-17 12:31:14 +00:00
|
|
|
INIT_LIST_HEAD(&isdnl1.ilist);
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2001-03-04 17:08:33 +00:00
|
|
|
isdnl1.DPROTO.protocol[1] |= ISDN_PID_L1_TE_U;
|
2001-02-11 22:46:19 +00:00
|
|
|
l1fsm_u.state_count = L1U_STATE_COUNT;
|
|
|
|
l1fsm_u.event_count = L1_EVENT_COUNT;
|
|
|
|
l1fsm_u.strEvent = strL1Event;
|
|
|
|
l1fsm_u.strState = strL1UState;
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
|
2001-02-11 22:46:19 +00:00
|
|
|
#endif
|
|
|
|
l1fsm_s.state_count = L1S_STATE_COUNT;
|
|
|
|
l1fsm_s.event_count = L1_EVENT_COUNT;
|
|
|
|
l1fsm_s.strEvent = strL1Event;
|
|
|
|
l1fsm_s.strState = strL1SState;
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2001-02-11 22:46:19 +00:00
|
|
|
l1fsm_b.state_count = L1B_STATE_COUNT;
|
|
|
|
l1fsm_b.event_count = L1_EVENT_COUNT;
|
|
|
|
l1fsm_b.strEvent = strL1Event;
|
|
|
|
l1fsm_b.strState = strL1BState;
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2003-07-21 12:00:05 +00:00
|
|
|
if ((err = mISDN_register(&isdnl1))) {
|
2001-02-11 22:46:19 +00:00
|
|
|
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmFree(&l1fsm_u);
|
2001-02-11 22:46:19 +00:00
|
|
|
#endif
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmFree(&l1fsm_s);
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmFree(&l1fsm_b);
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
return(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MODULE
|
|
|
|
void cleanup_module(void)
|
|
|
|
{
|
2004-06-17 12:31:14 +00:00
|
|
|
int err;
|
|
|
|
layer1_t *l1, *nl1;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2003-07-21 12:00:05 +00:00
|
|
|
if ((err = mISDN_unregister(&isdnl1))) {
|
2001-02-11 22:46:19 +00:00
|
|
|
printk(KERN_ERR "Can't unregister ISDN layer 1 error(%d)\n", err);
|
|
|
|
}
|
2004-06-17 12:31:14 +00:00
|
|
|
if(!list_empty(&isdnl1.ilist)) {
|
2003-07-21 12:00:05 +00:00
|
|
|
printk(KERN_WARNING "mISDNl1 inst list not empty\n");
|
2004-06-17 12:31:14 +00:00
|
|
|
list_for_each_entry_safe(l1, nl1, &isdnl1.ilist, list)
|
|
|
|
release_l1(l1);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2003-07-21 12:00:05 +00:00
|
|
|
#ifdef mISDN_UINTERFACE
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmFree(&l1fsm_u);
|
2001-02-11 22:46:19 +00:00
|
|
|
#endif
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmFree(&l1fsm_s);
|
2006-03-06 12:52:08 +00:00
|
|
|
#ifdef OBSOLETE
|
2004-01-26 22:21:32 +00:00
|
|
|
mISDN_FsmFree(&l1fsm_b);
|
2006-03-06 12:52:08 +00:00
|
|
|
#endif
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
#endif
|