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 @@ ...@@ -24,6 +24,10 @@
#undef ISDN_DEBUG_NET_DIAL #undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL #undef ISDN_DEBUG_NET_ICALL
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d", __FILE__, __LINE__); \
} while(0)
/* Prototypes */ /* Prototypes */
extern void isdn_MOD_INC_USE_COUNT(void); extern void isdn_MOD_INC_USE_COUNT(void);
extern void isdn_MOD_DEC_USE_COUNT(void); extern void isdn_MOD_DEC_USE_COUNT(void);
......
...@@ -54,6 +54,11 @@ enum { ...@@ -54,6 +54,11 @@ enum {
ST_12, ST_12,
}; };
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */
enum {
EV_NET_DIAL = 0x200,
};
/* /*
* Outline of new tbusy handling: * Outline of new tbusy handling:
* *
...@@ -625,6 +630,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) ...@@ -625,6 +630,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
} }
break; break;
} }
return 0;
} }
/* Initiate dialout. Set phone-number-pointer to first number /* Initiate dialout. Set phone-number-pointer to first number
...@@ -745,62 +751,70 @@ do_dialout(isdn_net_local *lp) ...@@ -745,62 +751,70 @@ do_dialout(isdn_net_local *lp)
return 1; return 1;
} }
/* /* returns 1 if timer callback is needed */
* Perform dialout for net-interfaces and timeout-handling for static int
* D-Channel-up and B-Channel-up Messages. isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
* 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)
{ {
isdn_net_dev *p = dev->netdev; isdn_net_dev *p = lp->netdev;
int anymore = 0;
isdn_ctrl cmd; isdn_ctrl cmd;
for (p = dev->netdev; p; p = p->next) {
isdn_net_local *lp = p->local;
#ifdef ISDN_DEBUG_NET_DIAL #ifdef ISDN_DEBUG_NET_DIAL
if (lp->dialstate) printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
#endif #endif
switch (lp->dialstate) {
case ST_0: switch (lp->dialstate) {
/* Nothing to do for this interface */ case ST_0:
break; break;
case ST_1: case ST_1:
anymore = init_dialout(lp); switch (pr) {
/* Fall through */ case EV_NET_DIAL:
case ST_2: 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; lp->dialretry = 0;
anymore = 1;
lp->dialstate = ST_3; lp->dialstate = ST_3;
/* Fall through */ goto st_3_net_dial;
case ST_3: }
anymore = do_dialout(lp); break;
break; case ST_3:
case ST_4: 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. /* Wait for D-Channel-connect.
* If timeout, switch back to state 3. * If timeout, switch back to state 3.
* Dialmax-handling moved to state 3. * Dialmax-handling moved to state 3.
*/ */
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
lp->dialstate = ST_3; lp->dialstate = ST_3;
anymore = 1; return 1;
break; }
case ST_5: break;
case ST_5:
switch (pr) {
case EV_NET_DIAL:
/* Got D-Channel-Connect, send B-Channel-request */ /* Got D-Channel-Connect, send B-Channel-request */
anymore = 1;
lp->dtimer = 0; lp->dtimer = 0;
lp->dialstate = ST_6; lp->dialstate = ST_6;
isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd); isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
break; return 1;
case ST_6: }
break;
case ST_6:
switch (pr) {
case EV_NET_DIAL:
/* Wait for B- or D-Channel-connect. If timeout, /* Wait for B- or D-Channel-connect. If timeout,
* switch back to state 3. * switch back to state 3.
*/ */
...@@ -809,9 +823,12 @@ isdn_net_dial(void) ...@@ -809,9 +823,12 @@ isdn_net_dial(void)
#endif #endif
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
lp->dialstate = ST_3; lp->dialstate = ST_3;
anymore = 1; return 1;
break; }
case ST_7: break;
case ST_7:
switch (pr) {
case EV_NET_DIAL:
/* Got incoming Call, setup L2 and L3 protocols, /* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect * then wait for D-Channel-connect
*/ */
...@@ -822,38 +839,52 @@ isdn_net_dial(void) ...@@ -822,38 +839,52 @@ isdn_net_dial(void)
isdn_slot_command(lp->isdn_slot, ISDN_CMD_SETL2, &cmd); isdn_slot_command(lp->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.arg = lp->l3_proto << 8; cmd.arg = lp->l3_proto << 8;
isdn_slot_command(lp->isdn_slot, ISDN_CMD_SETL3, &cmd); 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); isdn_net_hangup(&p->dev);
else { } else {
anymore = 1;
lp->dialstate = ST_8; lp->dialstate = ST_8;
return 1;
} }
break; break;
case ST_9: }
break;
case ST_9:
switch (pr) {
case EV_NET_DIAL:
/* Got incoming D-Channel-Connect, send B-Channel-request */ /* Got incoming D-Channel-Connect, send B-Channel-request */
isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd); isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
anymore = 1;
lp->dtimer = 0; lp->dtimer = 0;
lp->dialstate = ST_10; lp->dialstate = ST_10;
break; return 1;
case ST_8: }
case ST_10: break;
/* Wait for B- or D-channel-connect */ case ST_8:
case ST_10:
switch (pr) {
case EV_NET_DIAL:
/* Wait for B- or D-channel-connect */
#ifdef ISDN_DEBUG_NET_DIAL #ifdef ISDN_DEBUG_NET_DIAL
printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
#endif #endif
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
isdn_net_hangup(&p->dev); isdn_net_hangup(&p->dev);
else else
anymore = 1; return 1;
break; break;
case ST_11: }
break;
case ST_11:
switch (pr) {
case EV_NET_DIAL:
/* Callback Delay */ /* Callback Delay */
if (lp->dtimer++ > lp->cbdelay) if (lp->dtimer++ > lp->cbdelay)
lp->dialstate = ST_1; lp->dialstate = ST_1;
anymore = 1; return 1;
break; }
case ST_12: break;
case ST_12:
switch (pr) {
case EV_NET_DIAL:
/* Remote does callback. Hangup after cbdelay, then wait for incoming /* Remote does callback. Hangup after cbdelay, then wait for incoming
* call (in state 4). * call (in state 4).
*/ */
...@@ -864,12 +895,40 @@ isdn_net_dial(void) ...@@ -864,12 +895,40 @@ isdn_net_dial(void)
isdn_slot_command(lp->isdn_slot, ISDN_CMD_HANGUP, &cmd); isdn_slot_command(lp->isdn_slot, ISDN_CMD_HANGUP, &cmd);
isdn_slot_all_eaz(lp->isdn_slot); 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);
} }
break;
default:
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); 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