18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Author	Karsten Keil <kkeil@novell.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright 2008  by Karsten Keil <kkeil@novell.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/mISDNhw.h>
138c2ecf20Sopenharmony_ci#include "core.h"
148c2ecf20Sopenharmony_ci#include "layer1.h"
158c2ecf20Sopenharmony_ci#include "fsm.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistatic u_int *debug;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistruct layer1 {
208c2ecf20Sopenharmony_ci	u_long Flags;
218c2ecf20Sopenharmony_ci	struct FsmInst l1m;
228c2ecf20Sopenharmony_ci	struct FsmTimer timer3;
238c2ecf20Sopenharmony_ci	struct FsmTimer timerX;
248c2ecf20Sopenharmony_ci	int delay;
258c2ecf20Sopenharmony_ci	int t3_value;
268c2ecf20Sopenharmony_ci	struct dchannel *dch;
278c2ecf20Sopenharmony_ci	dchannel_l1callback *dcb;
288c2ecf20Sopenharmony_ci};
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define TIMER3_DEFAULT_VALUE	7000
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic
338c2ecf20Sopenharmony_cistruct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cienum {
368c2ecf20Sopenharmony_ci	ST_L1_F2,
378c2ecf20Sopenharmony_ci	ST_L1_F3,
388c2ecf20Sopenharmony_ci	ST_L1_F4,
398c2ecf20Sopenharmony_ci	ST_L1_F5,
408c2ecf20Sopenharmony_ci	ST_L1_F6,
418c2ecf20Sopenharmony_ci	ST_L1_F7,
428c2ecf20Sopenharmony_ci	ST_L1_F8,
438c2ecf20Sopenharmony_ci};
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define L1S_STATE_COUNT (ST_L1_F8 + 1)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic char *strL1SState[] =
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	"ST_L1_F2",
508c2ecf20Sopenharmony_ci	"ST_L1_F3",
518c2ecf20Sopenharmony_ci	"ST_L1_F4",
528c2ecf20Sopenharmony_ci	"ST_L1_F5",
538c2ecf20Sopenharmony_ci	"ST_L1_F6",
548c2ecf20Sopenharmony_ci	"ST_L1_F7",
558c2ecf20Sopenharmony_ci	"ST_L1_F8",
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cienum {
598c2ecf20Sopenharmony_ci	EV_PH_ACTIVATE,
608c2ecf20Sopenharmony_ci	EV_PH_DEACTIVATE,
618c2ecf20Sopenharmony_ci	EV_RESET_IND,
628c2ecf20Sopenharmony_ci	EV_DEACT_CNF,
638c2ecf20Sopenharmony_ci	EV_DEACT_IND,
648c2ecf20Sopenharmony_ci	EV_POWER_UP,
658c2ecf20Sopenharmony_ci	EV_ANYSIG_IND,
668c2ecf20Sopenharmony_ci	EV_INFO2_IND,
678c2ecf20Sopenharmony_ci	EV_INFO4_IND,
688c2ecf20Sopenharmony_ci	EV_TIMER_DEACT,
698c2ecf20Sopenharmony_ci	EV_TIMER_ACT,
708c2ecf20Sopenharmony_ci	EV_TIMER3,
718c2ecf20Sopenharmony_ci};
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define L1_EVENT_COUNT (EV_TIMER3 + 1)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic char *strL1Event[] =
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	"EV_PH_ACTIVATE",
788c2ecf20Sopenharmony_ci	"EV_PH_DEACTIVATE",
798c2ecf20Sopenharmony_ci	"EV_RESET_IND",
808c2ecf20Sopenharmony_ci	"EV_DEACT_CNF",
818c2ecf20Sopenharmony_ci	"EV_DEACT_IND",
828c2ecf20Sopenharmony_ci	"EV_POWER_UP",
838c2ecf20Sopenharmony_ci	"EV_ANYSIG_IND",
848c2ecf20Sopenharmony_ci	"EV_INFO2_IND",
858c2ecf20Sopenharmony_ci	"EV_INFO4_IND",
868c2ecf20Sopenharmony_ci	"EV_TIMER_DEACT",
878c2ecf20Sopenharmony_ci	"EV_TIMER_ACT",
888c2ecf20Sopenharmony_ci	"EV_TIMER3",
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic void
928c2ecf20Sopenharmony_cil1m_debug(struct FsmInst *fi, char *fmt, ...)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
958c2ecf20Sopenharmony_ci	struct va_format vaf;
968c2ecf20Sopenharmony_ci	va_list va;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	va_start(va, fmt);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
1018c2ecf20Sopenharmony_ci	vaf.va = &va;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "%s: %pV\n", dev_name(&l1->dch->dev.dev), &vaf);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	va_end(va);
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic void
1098c2ecf20Sopenharmony_cil1_reset(struct FsmInst *fi, int event, void *arg)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F3);
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic void
1158c2ecf20Sopenharmony_cil1_deact_cnf(struct FsmInst *fi, int event, void *arg)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F3);
1208c2ecf20Sopenharmony_ci	if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))
1218c2ecf20Sopenharmony_ci		l1->dcb(l1->dch, HW_POWERUP_REQ);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic void
1258c2ecf20Sopenharmony_cil1_deact_req_s(struct FsmInst *fi, int event, void *arg)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F3);
1308c2ecf20Sopenharmony_ci	mISDN_FsmRestartTimer(&l1->timerX, 550, EV_TIMER_DEACT, NULL, 2);
1318c2ecf20Sopenharmony_ci	test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic void
1358c2ecf20Sopenharmony_cil1_power_up_s(struct FsmInst *fi, int event, void *arg)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
1408c2ecf20Sopenharmony_ci		mISDN_FsmChangeState(fi, ST_L1_F4);
1418c2ecf20Sopenharmony_ci		l1->dcb(l1->dch, INFO3_P8);
1428c2ecf20Sopenharmony_ci	} else
1438c2ecf20Sopenharmony_ci		mISDN_FsmChangeState(fi, ST_L1_F3);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic void
1478c2ecf20Sopenharmony_cil1_go_F5(struct FsmInst *fi, int event, void *arg)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F5);
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic void
1538c2ecf20Sopenharmony_cil1_go_F8(struct FsmInst *fi, int event, void *arg)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F8);
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic void
1598c2ecf20Sopenharmony_cil1_info2_ind(struct FsmInst *fi, int event, void *arg)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F6);
1648c2ecf20Sopenharmony_ci	l1->dcb(l1->dch, INFO3_P8);
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic void
1688c2ecf20Sopenharmony_cil1_info4_ind(struct FsmInst *fi, int event, void *arg)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	mISDN_FsmChangeState(fi, ST_L1_F7);
1738c2ecf20Sopenharmony_ci	l1->dcb(l1->dch, INFO3_P8);
1748c2ecf20Sopenharmony_ci	if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
1758c2ecf20Sopenharmony_ci		mISDN_FsmDelTimer(&l1->timerX, 4);
1768c2ecf20Sopenharmony_ci	if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
1778c2ecf20Sopenharmony_ci		if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
1788c2ecf20Sopenharmony_ci			mISDN_FsmDelTimer(&l1->timer3, 3);
1798c2ecf20Sopenharmony_ci		mISDN_FsmRestartTimer(&l1->timerX, 110, EV_TIMER_ACT, NULL, 2);
1808c2ecf20Sopenharmony_ci		test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic void
1858c2ecf20Sopenharmony_cil1_timer3(struct FsmInst *fi, int event, void *arg)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);
1908c2ecf20Sopenharmony_ci	if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
1918c2ecf20Sopenharmony_ci		if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
1928c2ecf20Sopenharmony_ci			l1->dcb(l1->dch, HW_D_NOBLOCKED);
1938c2ecf20Sopenharmony_ci		l1->dcb(l1->dch, PH_DEACTIVATE_IND);
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci	if (l1->l1m.state != ST_L1_F6) {
1968c2ecf20Sopenharmony_ci		mISDN_FsmChangeState(fi, ST_L1_F3);
1978c2ecf20Sopenharmony_ci		/* do not force anything here, we need send INFO 0 */
1988c2ecf20Sopenharmony_ci	}
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic void
2028c2ecf20Sopenharmony_cil1_timer_act(struct FsmInst *fi, int event, void *arg)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);
2078c2ecf20Sopenharmony_ci	test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);
2088c2ecf20Sopenharmony_ci	l1->dcb(l1->dch, PH_ACTIVATE_IND);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic void
2128c2ecf20Sopenharmony_cil1_timer_deact(struct FsmInst *fi, int event, void *arg)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);
2178c2ecf20Sopenharmony_ci	test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);
2188c2ecf20Sopenharmony_ci	if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
2198c2ecf20Sopenharmony_ci		l1->dcb(l1->dch, HW_D_NOBLOCKED);
2208c2ecf20Sopenharmony_ci	l1->dcb(l1->dch, PH_DEACTIVATE_IND);
2218c2ecf20Sopenharmony_ci	l1->dcb(l1->dch, HW_DEACT_REQ);
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic void
2258c2ecf20Sopenharmony_cil1_activate_s(struct FsmInst *fi, int event, void *arg)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	mISDN_FsmRestartTimer(&l1->timer3, l1->t3_value, EV_TIMER3, NULL, 2);
2308c2ecf20Sopenharmony_ci	test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
2318c2ecf20Sopenharmony_ci	/* Tell HW to send INFO 1 */
2328c2ecf20Sopenharmony_ci	l1->dcb(l1->dch, HW_RESET_REQ);
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void
2368c2ecf20Sopenharmony_cil1_activate_no(struct FsmInst *fi, int event, void *arg)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct layer1 *l1 = fi->userdata;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) &&
2418c2ecf20Sopenharmony_ci	    (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {
2428c2ecf20Sopenharmony_ci		test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);
2438c2ecf20Sopenharmony_ci		if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
2448c2ecf20Sopenharmony_ci			l1->dcb(l1->dch, HW_D_NOBLOCKED);
2458c2ecf20Sopenharmony_ci		l1->dcb(l1->dch, PH_DEACTIVATE_IND);
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic struct FsmNode L1SFnList[] =
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
2528c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
2538c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
2548c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_RESET_IND, l1_reset},
2558c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_RESET_IND, l1_reset},
2568c2ecf20Sopenharmony_ci	{ST_L1_F5, EV_RESET_IND, l1_reset},
2578c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_RESET_IND, l1_reset},
2588c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_RESET_IND, l1_reset},
2598c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_RESET_IND, l1_reset},
2608c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
2618c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
2628c2ecf20Sopenharmony_ci	{ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
2638c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
2648c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
2658c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
2668c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
2678c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
2688c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
2698c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_POWER_UP,  l1_power_up_s},
2708c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_ANYSIG_IND, l1_go_F5},
2718c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_ANYSIG_IND, l1_go_F8},
2728c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_ANYSIG_IND, l1_go_F8},
2738c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
2748c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
2758c2ecf20Sopenharmony_ci	{ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
2768c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
2778c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
2788c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
2798c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
2808c2ecf20Sopenharmony_ci	{ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
2818c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
2828c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
2838c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_TIMER3, l1_timer3},
2848c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_TIMER3, l1_timer3},
2858c2ecf20Sopenharmony_ci	{ST_L1_F5, EV_TIMER3, l1_timer3},
2868c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_TIMER3, l1_timer3},
2878c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_TIMER3, l1_timer3},
2888c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
2898c2ecf20Sopenharmony_ci	{ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
2908c2ecf20Sopenharmony_ci	{ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
2918c2ecf20Sopenharmony_ci	{ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
2928c2ecf20Sopenharmony_ci	{ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
2938c2ecf20Sopenharmony_ci	{ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
2948c2ecf20Sopenharmony_ci	{ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
2958c2ecf20Sopenharmony_ci};
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic void
2988c2ecf20Sopenharmony_cirelease_l1(struct layer1 *l1) {
2998c2ecf20Sopenharmony_ci	mISDN_FsmDelTimer(&l1->timerX, 0);
3008c2ecf20Sopenharmony_ci	mISDN_FsmDelTimer(&l1->timer3, 0);
3018c2ecf20Sopenharmony_ci	if (l1->dch)
3028c2ecf20Sopenharmony_ci		l1->dch->l1 = NULL;
3038c2ecf20Sopenharmony_ci	module_put(THIS_MODULE);
3048c2ecf20Sopenharmony_ci	kfree(l1);
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ciint
3088c2ecf20Sopenharmony_cil1_event(struct layer1 *l1, u_int event)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	int		err = 0;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (!l1)
3138c2ecf20Sopenharmony_ci		return -EINVAL;
3148c2ecf20Sopenharmony_ci	switch (event) {
3158c2ecf20Sopenharmony_ci	case HW_RESET_IND:
3168c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);
3178c2ecf20Sopenharmony_ci		break;
3188c2ecf20Sopenharmony_ci	case HW_DEACT_IND:
3198c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);
3208c2ecf20Sopenharmony_ci		break;
3218c2ecf20Sopenharmony_ci	case HW_POWERUP_IND:
3228c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);
3238c2ecf20Sopenharmony_ci		break;
3248c2ecf20Sopenharmony_ci	case HW_DEACT_CNF:
3258c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);
3268c2ecf20Sopenharmony_ci		break;
3278c2ecf20Sopenharmony_ci	case ANYSIGNAL:
3288c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
3298c2ecf20Sopenharmony_ci		break;
3308c2ecf20Sopenharmony_ci	case LOSTFRAMING:
3318c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
3328c2ecf20Sopenharmony_ci		break;
3338c2ecf20Sopenharmony_ci	case INFO2:
3348c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);
3358c2ecf20Sopenharmony_ci		break;
3368c2ecf20Sopenharmony_ci	case INFO4_P8:
3378c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
3388c2ecf20Sopenharmony_ci		break;
3398c2ecf20Sopenharmony_ci	case INFO4_P10:
3408c2ecf20Sopenharmony_ci		mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
3418c2ecf20Sopenharmony_ci		break;
3428c2ecf20Sopenharmony_ci	case PH_ACTIVATE_REQ:
3438c2ecf20Sopenharmony_ci		if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
3448c2ecf20Sopenharmony_ci			l1->dcb(l1->dch, PH_ACTIVATE_IND);
3458c2ecf20Sopenharmony_ci		else {
3468c2ecf20Sopenharmony_ci			test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);
3478c2ecf20Sopenharmony_ci			mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);
3488c2ecf20Sopenharmony_ci		}
3498c2ecf20Sopenharmony_ci		break;
3508c2ecf20Sopenharmony_ci	case CLOSE_CHANNEL:
3518c2ecf20Sopenharmony_ci		release_l1(l1);
3528c2ecf20Sopenharmony_ci		break;
3538c2ecf20Sopenharmony_ci	default:
3548c2ecf20Sopenharmony_ci		if ((event & ~HW_TIMER3_VMASK) == HW_TIMER3_VALUE) {
3558c2ecf20Sopenharmony_ci			int val = event & HW_TIMER3_VMASK;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci			if (val < 5)
3588c2ecf20Sopenharmony_ci				val = 5;
3598c2ecf20Sopenharmony_ci			if (val > 30)
3608c2ecf20Sopenharmony_ci				val = 30;
3618c2ecf20Sopenharmony_ci			l1->t3_value = val;
3628c2ecf20Sopenharmony_ci			break;
3638c2ecf20Sopenharmony_ci		}
3648c2ecf20Sopenharmony_ci		if (*debug & DEBUG_L1)
3658c2ecf20Sopenharmony_ci			printk(KERN_DEBUG "%s %x unhandled\n",
3668c2ecf20Sopenharmony_ci			       __func__, event);
3678c2ecf20Sopenharmony_ci		err = -EINVAL;
3688c2ecf20Sopenharmony_ci	}
3698c2ecf20Sopenharmony_ci	return err;
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(l1_event);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ciint
3748c2ecf20Sopenharmony_cicreate_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
3758c2ecf20Sopenharmony_ci	struct layer1	*nl1;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	nl1 = kzalloc(sizeof(struct layer1), GFP_ATOMIC);
3788c2ecf20Sopenharmony_ci	if (!nl1) {
3798c2ecf20Sopenharmony_ci		printk(KERN_ERR "kmalloc struct layer1 failed\n");
3808c2ecf20Sopenharmony_ci		return -ENOMEM;
3818c2ecf20Sopenharmony_ci	}
3828c2ecf20Sopenharmony_ci	nl1->l1m.fsm = &l1fsm_s;
3838c2ecf20Sopenharmony_ci	nl1->l1m.state = ST_L1_F3;
3848c2ecf20Sopenharmony_ci	nl1->Flags = 0;
3858c2ecf20Sopenharmony_ci	nl1->t3_value = TIMER3_DEFAULT_VALUE;
3868c2ecf20Sopenharmony_ci	nl1->l1m.debug = *debug & DEBUG_L1_FSM;
3878c2ecf20Sopenharmony_ci	nl1->l1m.userdata = nl1;
3888c2ecf20Sopenharmony_ci	nl1->l1m.userint = 0;
3898c2ecf20Sopenharmony_ci	nl1->l1m.printdebug = l1m_debug;
3908c2ecf20Sopenharmony_ci	nl1->dch = dch;
3918c2ecf20Sopenharmony_ci	nl1->dcb = dcb;
3928c2ecf20Sopenharmony_ci	mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer3);
3938c2ecf20Sopenharmony_ci	mISDN_FsmInitTimer(&nl1->l1m, &nl1->timerX);
3948c2ecf20Sopenharmony_ci	__module_get(THIS_MODULE);
3958c2ecf20Sopenharmony_ci	dch->l1 = nl1;
3968c2ecf20Sopenharmony_ci	return 0;
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(create_l1);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ciint
4018c2ecf20Sopenharmony_ciIsdnl1_Init(u_int *deb)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	debug = deb;
4048c2ecf20Sopenharmony_ci	l1fsm_s.state_count = L1S_STATE_COUNT;
4058c2ecf20Sopenharmony_ci	l1fsm_s.event_count = L1_EVENT_COUNT;
4068c2ecf20Sopenharmony_ci	l1fsm_s.strEvent = strL1Event;
4078c2ecf20Sopenharmony_ci	l1fsm_s.strState = strL1SState;
4088c2ecf20Sopenharmony_ci	return mISDN_FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_civoid
4128c2ecf20Sopenharmony_ciIsdnl1_cleanup(void)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	mISDN_FsmFree(&l1fsm_s);
4158c2ecf20Sopenharmony_ci}
416