Commit fb0c37b6 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Start a unified state machine in isdn_net.c

Currently, the state machine is distributed over multiple functions,
the goal is to convert these to just one function, so it's easier to
grasp what is happening for which state/event combinations.
parent 34f57d0b
......@@ -24,6 +24,10 @@
#undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d", __FILE__, __LINE__); \
} while(0)
/* Prototypes */
extern void isdn_MOD_INC_USE_COUNT(void);
extern void isdn_MOD_DEC_USE_COUNT(void);
......
......@@ -54,6 +54,11 @@ enum {
ST_12,
};
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */
enum {
EV_NET_DIAL = 0x200,
};
/*
* Outline of new tbusy handling:
*
......@@ -625,6 +630,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
}
break;
}
return 0;
}
/* Initiate dialout. Set phone-number-pointer to first number
......@@ -745,62 +751,70 @@ do_dialout(isdn_net_local *lp)
return 1;
}
/*
* Perform dialout for net-interfaces and timeout-handling for
* D-Channel-up and B-Channel-up Messages.
* This function is initially called from within isdn_net_start_xmit() or
* or isdn_net_find_icall() after initializing the dialstate for an
* interface. If further calls are needed, the function schedules itself
* for a timer-callback via isdn_timer_function().
* The dialstate is also affected by incoming status-messages from
* the ISDN-Channel which are handled in isdn_net_stat_callback() above.
*/
void
isdn_net_dial(void)
/* returns 1 if timer callback is needed */
static int
isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
{
isdn_net_dev *p = dev->netdev;
int anymore = 0;
isdn_net_dev *p = lp->netdev;
isdn_ctrl cmd;
for (p = dev->netdev; p; p = p->next) {
isdn_net_local *lp = p->local;
#ifdef ISDN_DEBUG_NET_DIAL
if (lp->dialstate)
printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
#endif
switch (lp->dialstate) {
case ST_0:
/* Nothing to do for this interface */
break;
case ST_1:
anymore = init_dialout(lp);
/* Fall through */
switch (pr) {
case EV_NET_DIAL:
if (init_dialout(lp) == 0)
return 0;
lp->dialstate = ST_2;
goto st_2_net_dial;
}
break;
case ST_2:
switch (pr) {
case EV_NET_DIAL:
st_2_net_dial:
lp->dialretry = 0;
anymore = 1;
lp->dialstate = ST_3;
/* Fall through */
goto st_3_net_dial;
}
break;
case ST_3:
anymore = do_dialout(lp);
switch (pr) {
case EV_NET_DIAL:
st_3_net_dial:
return do_dialout(lp);
}
break;
case ST_4:
switch (pr) {
case EV_NET_DIAL:
/* Wait for D-Channel-connect.
* If timeout, switch back to state 3.
* Dialmax-handling moved to state 3.
*/
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
lp->dialstate = ST_3;
anymore = 1;
return 1;
}
break;
case ST_5:
switch (pr) {
case EV_NET_DIAL:
/* Got D-Channel-Connect, send B-Channel-request */
anymore = 1;
lp->dtimer = 0;
lp->dialstate = ST_6;
isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
return 1;
}
break;
case ST_6:
switch (pr) {
case EV_NET_DIAL:
/* Wait for B- or D-Channel-connect. If timeout,
* switch back to state 3.
*/
......@@ -809,9 +823,12 @@ isdn_net_dial(void)
#endif
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
lp->dialstate = ST_3;
anymore = 1;
return 1;
}
break;
case ST_7:
switch (pr) {
case EV_NET_DIAL:
/* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect
*/
......@@ -822,22 +839,29 @@ isdn_net_dial(void)
isdn_slot_command(lp->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.arg = lp->l3_proto << 8;
isdn_slot_command(lp->isdn_slot, ISDN_CMD_SETL3, &cmd);
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15) {
isdn_net_hangup(&p->dev);
else {
anymore = 1;
} else {
lp->dialstate = ST_8;
return 1;
}
break;
}
break;
case ST_9:
switch (pr) {
case EV_NET_DIAL:
/* Got incoming D-Channel-Connect, send B-Channel-request */
isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
anymore = 1;
lp->dtimer = 0;
lp->dialstate = ST_10;
return 1;
}
break;
case ST_8:
case ST_10:
switch (pr) {
case EV_NET_DIAL:
/* Wait for B- or D-channel-connect */
#ifdef ISDN_DEBUG_NET_DIAL
printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
......@@ -845,15 +869,22 @@ isdn_net_dial(void)
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
isdn_net_hangup(&p->dev);
else
anymore = 1;
return 1;
break;
}
break;
case ST_11:
switch (pr) {
case EV_NET_DIAL:
/* Callback Delay */
if (lp->dtimer++ > lp->cbdelay)
lp->dialstate = ST_1;
anymore = 1;
return 1;
}
break;
case ST_12:
switch (pr) {
case EV_NET_DIAL:
/* Remote does callback. Hangup after cbdelay, then wait for incoming
* call (in state 4).
*/
......@@ -864,12 +895,40 @@ isdn_net_dial(void)
isdn_slot_command(lp->isdn_slot, ISDN_CMD_HANGUP, &cmd);
isdn_slot_all_eaz(lp->isdn_slot);
}
anymore = 1;
return 1;
}
break;
default:
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
lp->dialstate, lp->name);
isdn_BUG();
break;
}
return 0;
}
/*
* Perform dialout for net-interfaces and timeout-handling for
* D-Channel-up and B-Channel-up Messages.
* This function is initially called from within isdn_net_start_xmit() or
* or isdn_net_find_icall() after initializing the dialstate for an
* interface. If further calls are needed, the function schedules itself
* for a timer-callback via isdn_timer_function().
* The dialstate is also affected by incoming status-messages from
* the ISDN-Channel which are handled in isdn_net_stat_callback() above.
*/
void
isdn_net_dial(void)
{
int anymore = 0;
isdn_net_dev *p = dev->netdev;
for (p = dev->netdev; p; p = p->next) {
isdn_net_local *lp = p->local;
if (lp->dialstate == ST_0)
continue;
if (isdn_net_handle_event(lp, EV_NET_DIAL, NULL))
anymore = 1;
}
isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment