Commit 93796c1f authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: More I4L linklayer cleanup

Add a helper function to prepare for and start dialing, removing duplicated
code from isdn_tty.c/isdn_net.c.

Move some parts of the big switch statement in isdn_net.c into their own 
functions.
parent cd5869cb
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/isdn.h> #include <linux/isdn.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/ctype.h>
#include "isdn_common.h" #include "isdn_common.h"
#include "isdn_tty.h" #include "isdn_tty.h"
#include "isdn_net.h" #include "isdn_net.h"
...@@ -2166,6 +2167,53 @@ isdn_slot_command(int sl, int cmd, isdn_ctrl *ctrl) ...@@ -2166,6 +2167,53 @@ isdn_slot_command(int sl, int cmd, isdn_ctrl *ctrl)
return isdn_command(ctrl); return isdn_command(ctrl);
} }
int
isdn_slot_dial(int sl, struct dial_info *dial)
{
isdn_ctrl cmd;
int retval;
char *msn = isdn_slot_map_eaz2msn(sl, dial->msn);
/* check for DOV */
if (dial->si1 == 7 && tolower(dial->phone[0]) == 'v') { /* DOV call */
dial->si1 = 1;
dial->phone++; /* skip v/V */
}
strcpy(isdn_slot_num(sl), dial->phone);
isdn_slot_set_usage(sl, isdn_slot_usage(sl) | ISDN_USAGE_OUTGOING);
retval = isdn_slot_command(sl, ISDN_CMD_CLREAZ, &cmd);
if (retval)
return retval;
strcpy(cmd.parm.num, msn);
retval = isdn_slot_command(sl, ISDN_CMD_SETEAZ, &cmd);
cmd.arg = dial->l2_proto << 8;
cmd.parm.fax = dial->fax;
retval = isdn_slot_command(sl, ISDN_CMD_SETL2, &cmd);
if (retval)
return retval;
cmd.arg = dial->l3_proto << 8;
retval = isdn_slot_command(sl, ISDN_CMD_SETL3, &cmd);
if (retval)
return retval;
cmd.parm.setup.si1 = dial->si1;
cmd.parm.setup.si2 = dial->si2;
strcpy(cmd.parm.setup.eazmsn, msn);
strcpy(cmd.parm.setup.phone, dial->phone);
printk(KERN_INFO "ISDN: slot %d: Dialing %s -> %s (SI %d/%d) (B %d/%d)\n",
sl, cmd.parm.setup.eazmsn, cmd.parm.setup.phone,
cmd.parm.setup.si1, cmd.parm.setup.si2,
dial->l2_proto, dial->l3_proto);
return isdn_slot_command(sl, ISDN_CMD_DIAL, &cmd);
}
void void
isdn_slot_all_eaz(int sl) isdn_slot_all_eaz(int sl)
{ {
......
...@@ -42,10 +42,21 @@ extern int isdn_add_channels(driver *, int, int, int); ...@@ -42,10 +42,21 @@ extern int isdn_add_channels(driver *, int, int, int);
extern void isdn_dumppkt(char *, u_char *, int, int); extern void isdn_dumppkt(char *, u_char *, int, int);
#endif #endif
struct dial_info {
int l2_proto;
int l3_proto;
struct T30_s *fax;
unsigned char si1;
unsigned char si2;
unsigned char *msn;
unsigned char *phone;
};
extern int isdn_get_free_slot(int, int, int, int, int, char *); extern int isdn_get_free_slot(int, int, int, int, int, char *);
extern void isdn_slot_free(int slot, int usage); extern void isdn_slot_free(int slot, int usage);
extern void isdn_slot_all_eaz(int slot); extern void isdn_slot_all_eaz(int slot);
extern int isdn_slot_command(int slot, int cmd, isdn_ctrl *); extern int isdn_slot_command(int slot, int cmd, isdn_ctrl *);
extern int isdn_slot_dial(int slot, struct dial_info *dial);
extern char *isdn_slot_map_eaz2msn(int slot, char *msn); extern char *isdn_slot_map_eaz2msn(int slot, char *msn);
extern int isdn_slot_write(int slot, struct sk_buff *); extern int isdn_slot_write(int slot, struct sk_buff *);
extern int isdn_slot_readbchan(int slot, u_char *, u_char *, int); extern int isdn_slot_readbchan(int slot, u_char *, u_char *, int);
......
...@@ -556,124 +556,87 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) ...@@ -556,124 +556,87 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
return 0; return 0;
} }
/* /* Initiate dialout. Set phone-number-pointer to first number
* Perform dialout for net-interfaces and timeout-handling for * of interface.
* 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 static int
isdn_net_dial(void) init_dialout(isdn_net_local *lp)
{ {
isdn_net_dev *p = dev->netdev;
int anymore = 0;
unsigned long flags; unsigned long flags;
isdn_ctrl cmd;
u_char *phone_number;
while (p) {
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 0:
/* Nothing to do for this interface */
break;
case 1:
/* Initiate dialout. Set phone-number-pointer to first number
* of interface.
*/
save_flags(flags); save_flags(flags);
cli(); cli();
lp->dial = lp->phone[1]; lp->dial = lp->phone[1];
restore_flags(flags); restore_flags(flags);
if (!lp->dial) { if (!lp->dial) {
printk(KERN_WARNING "%s: phone number deleted?\n", printk(KERN_WARNING "%s: phone number deleted?\n",
lp->name); lp->name);
isdn_net_hangup(&p->dev); isdn_net_hangup(&lp->netdev->dev);
break; return 0;
} }
anymore = 1; if (lp->dialtimeout > 0 &&
(lp->dialstarted == 0 ||
if(lp->dialtimeout > 0) time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))) {
if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
lp->dialstarted = jiffies; lp->dialstarted = jiffies;
lp->dialwait_timer = 0; lp->dialwait_timer = 0;
} }
lp->dialstate = 2;
return 1;
}
lp->dialstate++; /* Setup interface, dial current phone-number, switch to next number.
/* Fall through */
case 2:
/* Prepare dialing. Clear EAZ, then set EAZ. */
isdn_slot_command(lp->isdn_slot, ISDN_CMD_CLREAZ, &cmd);
sprintf(cmd.parm.num, "%s", isdn_slot_map_eaz2msn(lp->isdn_slot, lp->msn));
isdn_slot_command(lp->isdn_slot, ISDN_CMD_SETEAZ, &cmd);
lp->dialretry = 0;
anymore = 1;
lp->dialstate++;
/* Fall through */
case 3:
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment * If list of phone-numbers is exhausted, increment
* retry-counter. * retry-counter.
*/ */
static int
do_dialout(isdn_net_local *lp)
{
unsigned long flags;
if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) { if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
char *s; char *s;
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
s = "dial suppressed: isdn system stopped"; s = "dial suppressed: isdn system stopped";
else else
s = "dial suppressed: dialmode `off'"; s = "dial suppressed: dialmode `off'";
isdn_net_unreachable(&p->dev, 0, s); isdn_net_unreachable(&lp->netdev->dev, 0, s);
isdn_net_hangup(&p->dev); isdn_net_hangup(&lp->netdev->dev);
break; return 0;
} }
cmd.arg = lp->l2_proto << 8;
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);
save_flags(flags); save_flags(flags);
cli(); cli();
if (!lp->dial) { if (!lp->dial) {
restore_flags(flags); restore_flags(flags);
printk(KERN_WARNING "%s: phone number deleted?\n", printk(KERN_WARNING "%s: phone number deleted?\n",
lp->name); lp->name);
isdn_net_hangup(&p->dev); isdn_net_hangup(&lp->netdev->dev);
break; return 0;
} }
if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) { if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
restore_flags(flags); restore_flags(flags);
lp->dialstate = 4; lp->dialstate = 4;
printk(KERN_INFO "%s: Open leased line ...\n", lp->name); printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
} else { } else {
if(lp->dialtimeout > 0) struct dial_info dial = {
.l2_proto = lp->l2_proto,
.l3_proto = lp->l3_proto,
.si1 = 7,
.si2 = 0,
.msn = lp->msn,
.phone = lp->dial->num,
};
if(lp->dialtimeout > 0) {
if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) { if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
restore_flags(flags); restore_flags(flags);
lp->dialwait_timer = jiffies + lp->dialwait; lp->dialwait_timer = jiffies + lp->dialwait;
lp->dialstarted = 0; lp->dialstarted = 0;
isdn_net_unreachable(&p->dev, 0, "dial: timed out"); isdn_net_unreachable(&lp->netdev->dev, 0, "dial: timed out");
isdn_net_hangup(&p->dev); isdn_net_hangup(&lp->netdev->dev);
break; return 0;
} }
cmd.parm.setup.si2 = 0;
/* check for DOV */
phone_number = lp->dial->num;
if ((*phone_number == 'v') ||
(*phone_number == 'V')) { /* DOV call */
cmd.parm.setup.si1 = 1;
} else { /* DATA call */
cmd.parm.setup.si1 = 7;
} }
strcpy(cmd.parm.setup.phone, phone_number);
/* /*
* Switch to next number or back to start if at end of list. * Switch to next number or back to start if at end of list.
*/ */
...@@ -686,28 +649,15 @@ isdn_net_dial(void) ...@@ -686,28 +649,15 @@ isdn_net_dial(void)
if (lp->dialtimeout == 0) { if (lp->dialtimeout == 0) {
lp->dialwait_timer = jiffies + lp->dialwait; lp->dialwait_timer = jiffies + lp->dialwait;
lp->dialstarted = 0; lp->dialstarted = 0;
isdn_net_unreachable(&p->dev, 0, "dial: tried all numbers dialmax times"); isdn_net_unreachable(&lp->netdev->dev, 0, "dial: tried all numbers dialmax times");
} }
isdn_net_hangup(&p->dev); isdn_net_hangup(&lp->netdev->dev);
break; return 0;
} }
} }
restore_flags(flags); restore_flags(flags);
sprintf(cmd.parm.setup.eazmsn, "%s",
isdn_slot_map_eaz2msn(lp->isdn_slot, lp->msn));
if (lp->isdn_slot >= 0) {
strcpy(isdn_slot_num(lp->isdn_slot), cmd.parm.setup.phone);
isdn_slot_set_usage(lp->isdn_slot, isdn_slot_usage(lp->isdn_slot) | ISDN_USAGE_OUTGOING);
}
printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
lp->dialretry, cmd.parm.setup.phone,
(cmd.parm.setup.si1 == 1) ? "DOV" : "");
lp->dtimer = 0; lp->dtimer = 0;
#ifdef ISDN_DEBUG_NET_DIAL isdn_slot_dial(lp->isdn_slot, &dial);
printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
lp->isdn_channel);
#endif
isdn_slot_command(lp->isdn_slot, ISDN_CMD_DIAL, &cmd);
} }
lp->huptimer = 0; lp->huptimer = 0;
lp->outgoing = 1; lp->outgoing = 1;
...@@ -718,10 +668,50 @@ isdn_net_dial(void) ...@@ -718,10 +668,50 @@ isdn_net_dial(void)
lp->hupflags |= ISDN_WAITCHARGE; lp->hupflags |= ISDN_WAITCHARGE;
lp->hupflags &= ~ISDN_HAVECHARGE; lp->hupflags &= ~ISDN_HAVECHARGE;
} }
anymore = 1;
lp->dialstate = lp->dialstate =
(lp->cbdelay && (lp->cbdelay &&
(lp->flags & ISDN_NET_CBOUT)) ? 12 : 4; (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
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)
{
isdn_net_dev *p = dev->netdev;
int anymore = 0;
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 0:
/* Nothing to do for this interface */
break;
case 1:
anymore = init_dialout(lp);
/* Fall through */
case 2:
lp->dialretry = 0;
anymore = 1;
lp->dialstate++;
/* Fall through */
case 3:
anymore = do_dialout(lp);
break; break;
case 4: case 4:
/* Wait for D-Channel-connect. /* Wait for D-Channel-connect.
...@@ -796,8 +786,7 @@ isdn_net_dial(void) ...@@ -796,8 +786,7 @@ isdn_net_dial(void)
/* 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).
*/ */
if (lp->dtimer++ > lp->cbdelay) if (lp->dtimer++ > lp->cbdelay) {
{
printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
lp->dtimer = 0; lp->dtimer = 0;
lp->dialstate = 4; lp->dialstate = 4;
...@@ -810,7 +799,6 @@ isdn_net_dial(void) ...@@ -810,7 +799,6 @@ isdn_net_dial(void)
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n", printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
lp->dialstate, lp->name); lp->dialstate, lp->name);
} }
p = (isdn_net_dev *) p->next;
} }
isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore); isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
} }
......
...@@ -626,7 +626,6 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m) ...@@ -626,7 +626,6 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
int usg = ISDN_USAGE_MODEM; int usg = ISDN_USAGE_MODEM;
int si = 7; int si = 7;
int l2 = m->mdmreg[REG_L2PROT]; int l2 = m->mdmreg[REG_L2PROT];
isdn_ctrl cmd;
ulong flags; ulong flags;
int i; int i;
int j; int j;
...@@ -656,36 +655,29 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m) ...@@ -656,36 +655,29 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
restore_flags(flags); restore_flags(flags);
isdn_tty_modem_result(RESULT_NO_DIALTONE, info); isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else { } else {
struct dial_info dial = {
.l2_proto = l2,
.l3_proto = m->mdmreg[REG_L3PROT],
.si1 = si,
.si2 = m->mdmreg[REG_SI2],
.msn = m->msn,
.phone = n,
};
info->isdn_slot = i; info->isdn_slot = i;
isdn_slot_set_m_idx(i, info->line); isdn_slot_set_m_idx(i, info->line);
info->last_dir = 1; info->last_dir = 1;
info->last_l2 = l2;
strcpy(info->last_num, n); strcpy(info->last_num, n);
isdn_slot_set_usage(i, isdn_slot_usage(i) | ISDN_USAGE_OUTGOING);
restore_flags(flags); restore_flags(flags);
isdn_slot_command(info->isdn_slot, ISDN_CMD_CLREAZ, &cmd);
strcpy(cmd.parm.num, isdn_slot_map_eaz2msn(info->isdn_slot, m->msn));
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETEAZ, &cmd);
info->last_l2 = l2;
cmd.arg = l2 << 8;
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.arg = m->mdmreg[REG_L3PROT] << 8;
#ifdef CONFIG_ISDN_TTY_FAX #ifdef CONFIG_ISDN_TTY_FAX
if (l2 == ISDN_PROTO_L2_FAX) { if (l2 == ISDN_PROTO_L2_FAX) {
cmd.parm.fax = info->fax; dial.fax = info->fax;
info->fax->direction = ISDN_TTY_FAX_CONN_OUT; info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
} }
#endif #endif
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
sprintf(cmd.parm.setup.phone, "%s", n);
sprintf(cmd.parm.setup.eazmsn, "%s",
isdn_slot_map_eaz2msn(info->isdn_slot, m->msn));
cmd.parm.setup.si1 = si;
cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
info->dialing = 1; info->dialing = 1;
info->emu.carrierwait = 0; info->emu.carrierwait = 0;
strcpy(isdn_slot_num(i), n); isdn_slot_dial(info->isdn_slot, &dial);
isdn_info_update();
isdn_slot_command(info->isdn_slot, ISDN_CMD_DIAL, &cmd);
isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
} }
} }
...@@ -852,9 +844,6 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) ...@@ -852,9 +844,6 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
info->last_dir = 1; info->last_dir = 1;
// strcpy(info->last_num, n); // strcpy(info->last_num, n);
restore_flags(flags); restore_flags(flags);
isdn_slot_command(info->isdn_slot, ISDN_CMD_CLREAZ, &cmd);
strcpy(cmd.parm.num, isdn_slot_map_eaz2msn(info->isdn_slot, m->msn));
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETEAZ, &cmd);
info->last_l2 = l2; info->last_l2 = l2;
cmd.arg = l2 << 8; cmd.arg = l2 << 8;
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
...@@ -930,9 +919,6 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg) ...@@ -930,9 +919,6 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
isdn_slot_set_usage(i, isdn_slot_usage(i) | ISDN_USAGE_OUTGOING); isdn_slot_set_usage(i, isdn_slot_usage(i) | ISDN_USAGE_OUTGOING);
info->last_dir = 1; info->last_dir = 1;
restore_flags(flags); restore_flags(flags);
isdn_slot_command(info->isdn_slot, ISDN_CMD_CLREAZ, &cmd);
strcpy(cmd.parm.num, isdn_slot_map_eaz2msn(info->isdn_slot, m->msn));
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETEAZ, &cmd);
info->last_l2 = l2; info->last_l2 = l2;
cmd.arg = l2 << 8; cmd.arg = l2 << 8;
isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
......
...@@ -391,7 +391,7 @@ typedef struct isdn_net_dev_s { ...@@ -391,7 +391,7 @@ typedef struct isdn_net_dev_s {
channels, which are currently channels, which are currently
online */ online */
spinlock_t queue_lock; /* lock to protect queue */ spinlock_t queue_lock; /* lock to protect queue */
void *next; /* Pointer to next isdn-interface */ struct isdn_net_dev_s *next; /* Pointer to next isdn-interface */
struct net_device dev; /* interface to upper levels */ struct net_device dev; /* interface to upper levels */
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
ippp_bundle * pb; /* pointer to the common bundle structure ippp_bundle * pb; /* pointer to the common bundle structure
......
...@@ -418,9 +418,7 @@ typedef struct { ...@@ -418,9 +418,7 @@ typedef struct {
char display[85];/* display message data */ char display[85];/* display message data */
isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result */ isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result */
aux_s aux; /* for modem commands/indications */ aux_s aux; /* for modem commands/indications */
#ifdef CONFIG_ISDN_TTY_FAX
T30_s *fax; /* Pointer to ttys fax struct */ T30_s *fax; /* Pointer to ttys fax struct */
#endif
ulong userdata; /* User Data */ ulong userdata; /* User Data */
} parm; } parm;
} isdn_ctrl; } isdn_ctrl;
......
...@@ -529,7 +529,6 @@ static void do_pre_smp_initcalls(void) ...@@ -529,7 +529,6 @@ static void do_pre_smp_initcalls(void)
extern int migration_init(void); extern int migration_init(void);
extern int spawn_ksoftirqd(void); extern int spawn_ksoftirqd(void);
migration_init();
spawn_ksoftirqd(); spawn_ksoftirqd();
} }
......
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