Commit 46796862 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-isdn.bkbits.net/linux-2.5.isdn

into home.transmeta.com:/home/torvalds/v2.5/linux
parents c06fd892 767bf8a2
...@@ -264,8 +264,6 @@ isdn_timer_funct(ulong dummy) ...@@ -264,8 +264,6 @@ isdn_timer_funct(ulong dummy)
if (tf & ISDN_TIMER_SLOW) { if (tf & ISDN_TIMER_SLOW) {
if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) { if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
isdn_timer_cnt2 = 0; isdn_timer_cnt2 = 0;
if (tf & ISDN_TIMER_NETHANGUP)
isdn_net_autohup();
if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) { if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
isdn_timer_cnt3 = 0; isdn_timer_cnt3 = 0;
if (tf & ISDN_TIMER_MODEMRING) if (tf & ISDN_TIMER_MODEMRING)
...@@ -451,8 +449,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -451,8 +449,6 @@ isdn_status_callback(isdn_ctrl * c)
case ISDN_STAT_BSENT: case ISDN_STAT_BSENT:
if (i < 0) if (i < 0)
return -1; return -1;
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
return 0; return 0;
if (isdn_v110_stat_callback(&slot[i].iv110, c)) if (isdn_v110_stat_callback(&slot[i].iv110, c))
...@@ -482,15 +478,11 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -482,15 +478,11 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0) if (i < 0)
return -1; return -1;
dbg_statcallb("ICALL: %d (%d,%ld) %s\n", i, di, c->arg, c->parm.num); dbg_statcallb("ICALL: %d (%d,%ld) %s\n", i, di, c->arg, c->parm.num);
if (dev->global_flags & ISDN_GLOBAL_STOPPED) { if (dev->global_flags & ISDN_GLOBAL_STOPPED)
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_HANGUP;
isdn_command(&cmd);
return 0; return 0;
}
/* Try to find a network-interface which will accept incoming call */ /* Try to find a network-interface which will accept incoming call */
r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup)); r = isdn_net_find_icall(di, c->arg, i, &c->parm.setup);
switch (r) { switch (r) {
case 0: case 0:
/* No network-device replies. /* No network-device replies.
...@@ -550,8 +542,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -550,8 +542,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0) if (i < 0)
return -1; return -1;
dbg_statcallb("CINF: %d %s\n", i, c->parm.num); dbg_statcallb("CINF: %d %s\n", i, c->parm.num);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
if (strcmp(c->parm.num, "0")) if (strcmp(c->parm.num, "0"))
isdn_net_stat_callback(i, c); isdn_net_stat_callback(i, c);
isdn_tty_stat_callback(i, c); isdn_tty_stat_callback(i, c);
...@@ -574,8 +564,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -574,8 +564,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0) if (i < 0)
return -1; return -1;
dbg_statcallb("DCONN: %d\n", i); dbg_statcallb("DCONN: %d\n", i);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
/* Find any net-device, waiting for D-channel setup */ /* Find any net-device, waiting for D-channel setup */
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
break; break;
...@@ -593,8 +581,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -593,8 +581,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0) if (i < 0)
return -1; return -1;
dbg_statcallb("DHUP: %d\n", i); dbg_statcallb("DHUP: %d\n", i);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
dev->drv[di]->online &= ~(1 << (c->arg)); dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update(); isdn_info_update();
/* Signal hangup to network-devices */ /* Signal hangup to network-devices */
...@@ -611,8 +597,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -611,8 +597,6 @@ isdn_status_callback(isdn_ctrl * c)
return -1; return -1;
dbg_statcallb("BCONN: %ld\n", c->arg); dbg_statcallb("BCONN: %ld\n", c->arg);
/* Signal B-channel-connect to network-devices */ /* Signal B-channel-connect to network-devices */
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
dev->drv[di]->online |= (1 << (c->arg)); dev->drv[di]->online |= (1 << (c->arg));
isdn_info_update(); isdn_info_update();
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
...@@ -625,8 +609,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -625,8 +609,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0) if (i < 0)
return -1; return -1;
dbg_statcallb("BHUP: %d\n", i); dbg_statcallb("BHUP: %d\n", i);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
dev->drv[di]->online &= ~(1 << (c->arg)); dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update(); isdn_info_update();
#ifdef CONFIG_ISDN_X25 #ifdef CONFIG_ISDN_X25
...@@ -642,8 +624,6 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -642,8 +624,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0) if (i < 0)
return -1; return -1;
dbg_statcallb("NODCH: %ld\n", c->arg); dbg_statcallb("NODCH: %ld\n", c->arg);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
break; break;
if (isdn_tty_stat_callback(i, c)) if (isdn_tty_stat_callback(i, c))
...@@ -1397,12 +1377,12 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1397,12 +1377,12 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
return 0; return 0;
case IIOCSETGST: case IIOCSETGST:
if (arg) if (arg) {
dev->global_flags |= ISDN_GLOBAL_STOPPED; dev->global_flags |= ISDN_GLOBAL_STOPPED;
else isdn_net_hangup_all();
} else {
dev->global_flags &= ~ISDN_GLOBAL_STOPPED; dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
printk(KERN_INFO "isdn: Global Mode %s\n", }
(dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
return 0; return 0;
case IIOCSETBRJ: case IIOCSETBRJ:
drvidx = -1; drvidx = -1;
...@@ -1619,8 +1599,9 @@ static struct file_operations isdn_ctrl_fops = ...@@ -1619,8 +1599,9 @@ static struct file_operations isdn_ctrl_fops =
.release = isdn_ctrl_release, .release = isdn_ctrl_release,
}; };
/* /*
* file_operations for major 43, /dev/isdn* * file_operations for major 45, /dev/isdn*
* stolen from drivers/char/misc.c * stolen from drivers/char/misc.c
*/ */
...@@ -2119,14 +2100,20 @@ isdn_slot_map_eaz2msn(int sl, char *msn) ...@@ -2119,14 +2100,20 @@ isdn_slot_map_eaz2msn(int sl, char *msn)
int int
isdn_slot_command(int sl, int cmd, isdn_ctrl *ctrl) isdn_slot_command(int sl, int cmd, isdn_ctrl *ctrl)
{ {
ctrl->command = cmd; ctrl->command = cmd;
ctrl->driver = isdn_slot_driver(sl); ctrl->driver = isdn_slot_driver(sl);
switch (cmd) { switch (cmd) {
case ISDN_CMD_SETL2: case ISDN_CMD_SETL2:
case ISDN_CMD_SETL3: case ISDN_CMD_SETL3:
case ISDN_CMD_PROT_IO: case ISDN_CMD_PROT_IO:
ctrl->arg &= ~0xff; ctrl->arg |= isdn_slot_channel(sl); ctrl->arg &= ~0xff; ctrl->arg |= isdn_slot_channel(sl);
break; break;
case ISDN_CMD_DIAL:
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return -EBUSY;
/* fall through */
default: default:
ctrl->arg = isdn_slot_channel(sl); ctrl->arg = isdn_slot_channel(sl);
break; break;
......
...@@ -206,7 +206,7 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp) ...@@ -206,7 +206,7 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
int isdn_net_force_dial_lp(isdn_net_local *); int isdn_net_force_dial_lp(isdn_net_local *);
static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
static int do_dialout(isdn_net_local *lp); static void do_dialout(isdn_net_local *lp);
static void isdn_net_ciscohdlck_connected(isdn_net_local *lp); static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp); static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
...@@ -222,22 +222,14 @@ char *isdn_net_revision = "$Revision: 1.140.6.11 $"; ...@@ -222,22 +222,14 @@ char *isdn_net_revision = "$Revision: 1.140.6.11 $";
static void static void
isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason) isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
{ {
if(skb) { u_short proto = ntohs(skb->protocol);
u_short proto = ntohs(skb->protocol); printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
dev->name,
printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n", (reason != NULL) ? reason : "unknown",
dev->name, (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
(reason != NULL) ? reason : "unknown",
(proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : ""); dst_link_failure(skb);
dst_link_failure(skb);
}
else { /* dial not triggered by rawIP packet */
printk(KERN_DEBUG "isdn_net: %s: %s\n",
dev->name,
(reason != NULL) ? reason : "reason unknown");
}
} }
static void static void
...@@ -348,7 +340,7 @@ isdn_net_unbind_channel(isdn_net_local * lp) ...@@ -348,7 +340,7 @@ isdn_net_unbind_channel(isdn_net_local * lp)
} }
/* /*
* Perform auto-hangup and cps-calculation for net-interfaces. * Perform auto-hangup for net-interfaces.
* *
* auto-hangup: * auto-hangup:
* Increment idle-counter (this counter is reset on any incoming or * Increment idle-counter (this counter is reset on any incoming or
...@@ -357,65 +349,53 @@ isdn_net_unbind_channel(isdn_net_local * lp) ...@@ -357,65 +349,53 @@ isdn_net_unbind_channel(isdn_net_local * lp)
* charge-info. * charge-info.
*/ */
void static void isdn_net_hup_timer(unsigned long data)
isdn_net_autohup()
{ {
struct list_head *l; isdn_net_local *lp = (isdn_net_local *) data;
int anymore;
anymore = 0;
list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *l = &p->local;
if (!(l->flags & ISDN_NET_CONNECTED) || l->dialstate != ST_ACTIVE)
continue;
if(dev->global_flags & ISDN_GLOBAL_STOPPED ||
ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF) {
isdn_net_hangup(&p->dev);
continue;
}
dbg_net_dial("%s: huptimer %d, onhtime %d, chargetime %ld, chargeint %d\n",
l->name, l->huptimer, l->onhtime, l->chargetime, l->chargeint);
if (!(l->onhtime)) if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate != ST_ACTIVE) {
continue; isdn_BUG();
return;
}
dbg_net_dial("%s: huptimer %d, onhtime %d, chargetime %ld, chargeint %d\n",
l->name, l->huptimer, l->onhtime, l->chargetime, l->chargeint);
if (l->huptimer++ <= l->onhtime) { if (!(lp->onhtime))
anymore = 1; return;
continue;
} if (lp->huptimer++ <= lp->onhtime)
if (l->hupflags & ISDN_MANCHARGE && l->hupflags & ISDN_CHARGEHUP) { goto mod_timer;
while (time_after(jiffies, l->chargetime + l->chargeint))
l->chargetime += l->chargeint;
if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ)) { if (lp->hupflags & ISDN_MANCHARGE && lp->hupflags & ISDN_CHARGEHUP) {
if (l->outgoing || l->hupflags & ISDN_INHUP) { while (time_after(jiffies, lp->chargetime + lp->chargeint))
isdn_net_hangup(&p->dev); lp->chargetime += lp->chargeint;
continue;
} if (time_after(jiffies, lp->chargetime + lp->chargeint - 2 * HZ)) {
if (lp->outgoing || lp->hupflags & ISDN_INHUP) {
isdn_net_hangup(lp);
return;
} }
} else if (l->outgoing) { }
if (l->hupflags & ISDN_CHARGEHUP) { } else if (lp->outgoing) {
if (l->charge_state != ST_CHARGE_HAVE_CINT) { if (lp->hupflags & ISDN_CHARGEHUP) {
dbg_net_dial("%s: did not get CINT\n", l->name); if (lp->charge_state != ST_CHARGE_HAVE_CINT) {
isdn_net_hangup(&p->dev); dbg_net_dial("%s: did not get CINT\n", lp->name);
continue; isdn_net_hangup(lp);
} else if (time_after(jiffies, l->chargetime + l->chargeint)) { return;
dbg_net_dial("%s: chtime = %lu, chint = %d\n", } else if (time_after(jiffies, lp->chargetime + lp->chargeint)) {
l->name, l->chargetime, l->chargeint); dbg_net_dial("%s: chtime = %lu, chint = %d\n",
isdn_net_hangup(&p->dev); lp->name, lp->chargetime, lp->chargeint);
continue; isdn_net_hangup(lp);
} return;
} }
} else if (l->hupflags & ISDN_INHUP) {
isdn_net_hangup(&p->dev);
continue;
} }
anymore = 1; } else if (lp->hupflags & ISDN_INHUP) {
isdn_net_hangup(lp);
return;
} }
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore); mod_timer:
mod_timer(&lp->hup_timer, lp->hup_timer.expires + HZ);
} }
static void isdn_net_lp_disconnected(isdn_net_local *lp) static void isdn_net_lp_disconnected(isdn_net_local *lp)
...@@ -430,7 +410,9 @@ static void isdn_net_connected(isdn_net_local *lp) ...@@ -430,7 +410,9 @@ static void isdn_net_connected(isdn_net_local *lp)
struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
#endif #endif
lp->dialstate = ST_ACTIVE; lp->dialstate = ST_ACTIVE;
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1); lp->hup_timer.expires = jiffies + HZ;
add_timer(&lp->hup_timer);
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
isdn_net_ciscohdlck_connected(lp); isdn_net_ciscohdlck_connected(lp);
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) { if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
...@@ -495,33 +477,17 @@ isdn_net_dial_timer(unsigned long data) ...@@ -495,33 +477,17 @@ isdn_net_dial_timer(unsigned long data)
{ {
isdn_net_local *lp = (isdn_net_local *) data; isdn_net_local *lp = (isdn_net_local *) data;
if (!lp) {
isdn_BUG();
return;
}
printk("%s: %s %#x\n", __FUNCTION__ , lp->name, lp->dial_event);
isdn_net_handle_event(lp, lp->dial_event, NULL); isdn_net_handle_event(lp, lp->dial_event, NULL);
} }
/* Initiate dialout. Set phone-number-pointer to first number /* Initiate dialout. Set phone-number-pointer to first number
* of interface. * of interface.
*/ */
static int static void
init_dialout(isdn_net_local *lp) init_dialout(isdn_net_local *lp)
{ {
unsigned long flags; lp->dial = 0;
save_flags(flags);
cli();
lp->dial = lp->phone[1];
restore_flags(flags);
if (!lp->dial) {
printk(KERN_WARNING "%s: phone number deleted?\n",
lp->name);
isdn_net_hangup(&lp->netdev->dev);
return 0;
}
if (lp->dialtimeout > 0 && if (lp->dialtimeout > 0 &&
(lp->dialstarted == 0 || (lp->dialstarted == 0 ||
time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))) { time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))) {
...@@ -529,83 +495,70 @@ init_dialout(isdn_net_local *lp) ...@@ -529,83 +495,70 @@ init_dialout(isdn_net_local *lp)
lp->dialwait_timer = 0; lp->dialwait_timer = 0;
} }
lp->dialretry = 0; lp->dialretry = 0;
return do_dialout(lp); do_dialout(lp);
} }
/* Setup interface, dial current phone-number, switch to next number. /* 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 static void
do_dialout(isdn_net_local *lp) do_dialout(isdn_net_local *lp)
{ {
int i;
unsigned long flags; unsigned long flags;
struct isdn_net_phone *phone;
if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) { struct dial_info dial = {
char *s; .l2_proto = lp->l2_proto,
if (dev->global_flags & ISDN_GLOBAL_STOPPED) .l3_proto = lp->l3_proto,
s = "dial suppressed: isdn system stopped"; .si1 = 7,
else .si2 = 0,
s = "dial suppressed: dialmode `off'"; .msn = lp->msn,
isdn_net_unreachable(&lp->netdev->dev, 0, s); };
isdn_net_hangup(&lp->netdev->dev);
return 0; if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)
return;
spin_lock_irqsave(&lp->lock, flags);
if (list_empty(&lp->phone[1])) {
spin_unlock_irqrestore(&lp->lock, flags);
return;
} }
i = 0;
save_flags(flags); list_for_each_entry(phone, &lp->phone[1], list) {
cli(); if (i++ == lp->dial)
if (!lp->dial) { goto found;
restore_flags(flags);
printk(KERN_WARNING "%s: phone number deleted?\n",
lp->name);
isdn_net_hangup(&lp->netdev->dev);
return 0;
} }
if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) { /* otherwise start in front */
restore_flags(flags); phone = list_entry(lp->phone[1].next, struct isdn_net_phone, list);
lp->dialstate = ST_OUT_WAIT_DCONN; lp->dial = 0;
printk(KERN_INFO "%s: Open leased line ...\n", lp->name); lp->dialretry++;
return 1;
} else { found:
struct dial_info dial = { lp->dial++;
.l2_proto = lp->l2_proto, dial.phone = phone->num;
.l3_proto = lp->l3_proto, spin_unlock_irqrestore(&lp->lock, flags);
.si1 = 7,
.si2 = 0, if (lp->dialretry > lp->dialmax) {
.msn = lp->msn, if (lp->dialtimeout == 0) {
.phone = lp->dial->num, lp->dialwait_timer = jiffies + lp->dialwait;
}; lp->dialstarted = 0;
if(lp->dialtimeout > 0) {
if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
restore_flags(flags);
lp->dialwait_timer = jiffies + lp->dialwait;
lp->dialstarted = 0;
isdn_net_unreachable(&lp->netdev->dev, 0, "dial: timed out");
isdn_net_hangup(&lp->netdev->dev);
return 0;
}
}
/*
* Switch to next number or back to start if at end of list.
*/
if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
lp->dial = lp->phone[1];
lp->dialretry++;
if (lp->dialretry > lp->dialmax) {
restore_flags(flags);
if (lp->dialtimeout == 0) {
lp->dialwait_timer = jiffies + lp->dialwait;
lp->dialstarted = 0;
isdn_net_unreachable(&lp->netdev->dev, 0, "dial: tried all numbers dialmax times");
}
isdn_net_hangup(&lp->netdev->dev);
return 0;
}
} }
restore_flags(flags); isdn_net_hangup(lp);
isdn_slot_dial(lp->isdn_slot, &dial); return;
} }
if(lp->dialtimeout > 0 &&
time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
lp->dialwait_timer = jiffies + lp->dialwait;
lp->dialstarted = 0;
isdn_net_hangup(lp);
return;
}
/*
* Switch to next number or back to start if at end of list.
*/
isdn_slot_dial(lp->isdn_slot, &dial);
lp->huptimer = 0; lp->huptimer = 0;
lp->outgoing = 1; lp->outgoing = 1;
if (lp->chargeint) if (lp->chargeint)
...@@ -622,7 +575,6 @@ do_dialout(isdn_net_local *lp) ...@@ -622,7 +575,6 @@ do_dialout(isdn_net_local *lp)
} }
lp->dialstate = ST_OUT_WAIT_DCONN; lp->dialstate = ST_OUT_WAIT_DCONN;
add_timer(&lp->dial_timer); add_timer(&lp->dial_timer);
return 1;
} }
/* For EV_NET_DIAL, returns 1 if timer callback is needed /* For EV_NET_DIAL, returns 1 if timer callback is needed
...@@ -725,7 +677,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -725,7 +677,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
/* Remote does callback. Hangup after cbdelay, /* Remote does callback. Hangup after cbdelay,
* then wait for incoming call */ * then wait for incoming call */
printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
isdn_net_hangup(&lp->netdev->dev); isdn_net_hangup(lp);
return 1; return 1;
case ISDN_STAT_DCONN: case ISDN_STAT_DCONN:
/* Got D-Channel-Connect, send B-Channel-request */ /* Got D-Channel-Connect, send B-Channel-request */
...@@ -766,7 +718,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -766,7 +718,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ST_IN_WAIT_DCONN: case ST_IN_WAIT_DCONN:
switch (pr) { switch (pr) {
case EV_NET_TIMER_IN_DCONN: case EV_NET_TIMER_IN_DCONN:
isdn_net_hangup(&p->dev); isdn_net_hangup(lp);
return 1; return 1;
case ISDN_STAT_DCONN: case ISDN_STAT_DCONN:
del_timer(&lp->dial_timer); del_timer(&lp->dial_timer);
...@@ -787,7 +739,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -787,7 +739,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ST_IN_WAIT_BCONN: case ST_IN_WAIT_BCONN:
switch (pr) { switch (pr) {
case EV_NET_TIMER_IN_BCONN: case EV_NET_TIMER_IN_BCONN:
isdn_net_hangup(&p->dev); isdn_net_hangup(lp);
break; break;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
del_timer(&lp->dial_timer); del_timer(&lp->dial_timer);
...@@ -822,15 +774,15 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -822,15 +774,15 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
* Perform hangup for a net-interface. * Perform hangup for a net-interface.
*/ */
void void
isdn_net_hangup(struct net_device *d) isdn_net_hangup(isdn_net_local *lp)
{ {
isdn_net_local *lp = (isdn_net_local *) d->priv;
isdn_ctrl cmd; isdn_ctrl cmd;
#ifdef CONFIG_ISDN_X25 #ifdef CONFIG_ISDN_X25
struct concap_proto *cprot = lp -> netdev -> cprot; struct concap_proto *cprot = lp -> netdev -> cprot;
struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
#endif #endif
del_timer_sync(&lp->hup_timer);
if (lp->flags & ISDN_NET_CONNECTED) { if (lp->flags & ISDN_NET_CONNECTED) {
if (lp->slave != NULL) { if (lp->slave != NULL) {
isdn_net_local *slp = (isdn_net_local *)lp->slave->priv; isdn_net_local *slp = (isdn_net_local *)lp->slave->priv;
...@@ -838,7 +790,7 @@ isdn_net_hangup(struct net_device *d) ...@@ -838,7 +790,7 @@ isdn_net_hangup(struct net_device *d)
printk(KERN_INFO printk(KERN_INFO
"isdn_net: hang up slave %s before %s\n", "isdn_net: hang up slave %s before %s\n",
slp->name, lp->name); slp->name, lp->name);
isdn_net_hangup(lp->slave); isdn_net_hangup(slp);
} }
} }
printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name); printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
...@@ -862,6 +814,17 @@ isdn_net_hangup(struct net_device *d) ...@@ -862,6 +814,17 @@ isdn_net_hangup(struct net_device *d)
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(lp);
} }
void
isdn_net_hangup_all()
{
struct list_head *l;
list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_hangup(&p->local);
}
}
typedef struct { typedef struct {
unsigned short source; unsigned short source;
unsigned short dest; unsigned short dest;
...@@ -1173,6 +1136,7 @@ void isdn_net_tx_timeout(struct net_device * ndev) ...@@ -1173,6 +1136,7 @@ void isdn_net_tx_timeout(struct net_device * ndev)
static int static int
isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
unsigned long flags;
isdn_net_local *lp = (isdn_net_local *) ndev->priv; isdn_net_local *lp = (isdn_net_local *) ndev->priv;
#ifdef CONFIG_ISDN_X25 #ifdef CONFIG_ISDN_X25
struct concap_proto * cprot = lp -> netdev -> cprot; struct concap_proto * cprot = lp -> netdev -> cprot;
...@@ -1208,80 +1172,73 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1208,80 +1172,73 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} }
if (lp->phone[1]) {
ulong flags; save_flags(flags);
save_flags(flags); cli();
cli();
if(lp->dialwait_timer <= 0)
if(lp->dialwait_timer <= 0) if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
if(lp->dialwait_timer > 0) {
if(lp->dialwait_timer > 0) { if(time_before(jiffies, lp->dialwait_timer)) {
if(time_before(jiffies, lp->dialwait_timer)) { isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
dev_kfree_skb(skb);
restore_flags(flags);
return 0;
} else
lp->dialwait_timer = 0;
}
/* Grab a free ISDN-Channel */
if (((chi =
isdn_get_free_slot(
ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
lp->pre_channel,
lp->msn)
) < 0) &&
((chi =
isdn_get_free_slot(
ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
lp->pre_channel^1,
lp->msn)
) < 0)) {
restore_flags(flags);
isdn_net_unreachable(ndev, skb,
"No channel");
dev_kfree_skb(skb); dev_kfree_skb(skb);
restore_flags(flags);
return 0; return 0;
} } else
/* Log packet, which triggered dialing */ lp->dialwait_timer = 0;
if (dev->net_verbose) }
isdn_net_log_skb(skb, lp); /* Grab a free ISDN-Channel */
/* Connect interface with channel */ if (((chi =
isdn_net_bind_channel(lp, chi); isdn_get_free_slot(
ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
lp->pre_channel,
lp->msn)
) < 0) &&
((chi =
isdn_get_free_slot(
ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
lp->pre_channel^1,
lp->msn)
) < 0)) {
restore_flags(flags);
isdn_net_unreachable(ndev, skb,
"No channel");
dev_kfree_skb(skb);
return 0;
}
/* Log packet, which triggered dialing */
if (dev->net_verbose)
isdn_net_log_skb(skb, lp);
/* Connect interface with channel */
isdn_net_bind_channel(lp, chi);
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
/* no 'first_skb' handling for syncPPP */ /* no 'first_skb' handling for syncPPP */
if (isdn_ppp_bind(lp) < 0) { if (isdn_ppp_bind(lp) < 0) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(lp);
restore_flags(flags);
return 0; /* STN (skb to nirvana) ;) */
}
restore_flags(flags); restore_flags(flags);
init_dialout(lp); return 0; /* STN (skb to nirvana) ;) */
netif_stop_queue(ndev);
return 1; /* let upper layer requeue skb packet */
} }
#endif
/* Initiate dialing */
restore_flags(flags); restore_flags(flags);
init_dialout(lp); init_dialout(lp);
isdn_net_device_stop_queue(lp); netif_stop_queue(ndev);
return 1; return 1; /* let upper layer requeue skb packet */
} else {
isdn_net_unreachable(ndev, skb,
"No phone number");
dev_kfree_skb(skb);
return 0;
} }
#endif
/* Initiate dialing */
restore_flags(flags);
init_dialout(lp);
isdn_net_device_stop_queue(lp);
return 1;
} else { } else {
/* Device is connected to an ISDN channel */ /* Device is connected to an ISDN channel */
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
...@@ -1324,11 +1281,11 @@ isdn_net_close(struct net_device *dev) ...@@ -1324,11 +1281,11 @@ isdn_net_close(struct net_device *dev)
if( cprot && cprot -> pops ) if( cprot && cprot -> pops )
cprot -> pops -> close( cprot ); cprot -> pops -> close( cprot );
#endif #endif
isdn_net_hangup(p); isdn_net_hangup(p->priv);
p = (((isdn_net_local *) p->priv)->slave); p = (((isdn_net_local *) p->priv)->slave);
} }
} }
isdn_net_hangup(dev); isdn_net_hangup(dev->priv);
isdn_MOD_DEC_USE_COUNT(); isdn_MOD_DEC_USE_COUNT();
return 0; return 0;
} }
...@@ -2118,7 +2075,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -2118,7 +2075,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
int swapped; int swapped;
int sidx = 0; int sidx = 0;
struct list_head *l; struct list_head *l;
isdn_net_phone *n; struct isdn_net_phone *n;
ulong flags; ulong flags;
char nr[32]; char nr[32];
char *my_eaz; char *my_eaz;
...@@ -2152,7 +2109,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -2152,7 +2109,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
return 0; return 0;
} }
n = (isdn_net_phone *) 0; n = NULL;
ematch = wret = swapped = 0; ematch = wret = swapped = 0;
dbg_net_icall("n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx, dbg_net_icall("n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
isdn_slot_usage(idx)); isdn_slot_usage(idx));
...@@ -2258,166 +2215,163 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -2258,166 +2215,163 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
} }
} }
dbg_net_icall("n_fi: match2\n"); dbg_net_icall("n_fi: match2\n");
n = lp->phone[0];
if (lp->flags & ISDN_NET_SECURE) { if (lp->flags & ISDN_NET_SECURE) {
while (n) { spin_lock_irqsave(&lp->lock, flags);
if (!isdn_msncmp(nr, n->num)) list_for_each_entry(n, &lp->phone[0], list) {
if (!isdn_msncmp(nr, n->num)) {
spin_unlock_irqrestore(&lp->lock, flags);
break; break;
n = (isdn_net_phone *) n->next; }
} }
spin_unlock_irqrestore(&lp->lock, flags);
continue;
} }
if (n || (!(lp->flags & ISDN_NET_SECURE))) { dbg_net_icall("n_fi: match3\n");
dbg_net_icall("n_fi: match3\n"); /* matching interface found */
/* matching interface found */
/*
* Is the state STOPPED?
* If so, no dialin is allowed,
* so reject actively.
* */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
restore_flags(flags);
printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
lp->name);
return 3;
}
/*
* Is the interface up?
* If not, reject the call actively.
*/
if (!isdn_net_device_started(p)) {
restore_flags(flags);
printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
lp->name);
return 3;
}
/* Interface is up, now see if it's a slave. If so, see if
* it's master and parent slave is online. If not, reject the call.
*/
if (lp->master) {
isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
printk(KERN_DEBUG "ICALLslv: %s\n", lp->name);
printk(KERN_DEBUG "master=%s\n", mlp->name);
if (mlp->flags & ISDN_NET_CONNECTED) {
printk(KERN_DEBUG "master online\n");
/* Master is online, find parent-slave (master if first slave) */
while (mlp->slave) {
if ((isdn_net_local *) mlp->slave->priv == lp)
break;
mlp = (isdn_net_local *) mlp->slave->priv;
}
} else
printk(KERN_DEBUG "master offline\n");
/* Found parent, if it's offline iterate next device */
printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
if (!(mlp->flags & ISDN_NET_CONNECTED)) {
continue;
}
}
if (lp->flags & ISDN_NET_CALLBACK) {
int chi;
/* /*
* Is the state STOPPED? * Is the state MANUAL?
* If so, no dialin is allowed, * If so, no callback can be made,
* so reject actively. * so reject actively.
* */ * */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
restore_flags(flags); restore_flags(flags);
printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
lp->name); lp->name);
return 3; return 3;
} }
/* printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
* Is the interface up? lp->name, nr, eaz);
* If not, reject the call actively.
*/ /* Grab a free ISDN-Channel */
if (!isdn_net_device_started(p)) { if ((chi =
isdn_get_free_slot(
ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
lp->pre_channel,
lp->msn)
) < 0) {
printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
restore_flags(flags); restore_flags(flags);
printk(KERN_INFO "%s: incoming call, interface down -> rejected\n", return 0;
lp->name);
return 3;
} }
/* Interface is up, now see if it's a slave. If so, see if /* Setup dialstate. */
* it's master and parent slave is online. If not, reject the call. lp->dial_timer.expires = jiffies + lp->cbdelay;
*/ lp->dial_event = EV_NET_TIMER_CB;
if (lp->master) { add_timer(&lp->dial_timer);
isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
printk(KERN_DEBUG "ICALLslv: %s\n", lp->name); lp->dialstate = ST_WAIT_BEFORE_CB;
printk(KERN_DEBUG "master=%s\n", mlp->name); /* Connect interface with channel */
if (mlp->flags & ISDN_NET_CONNECTED) { isdn_net_bind_channel(lp, chi);
printk(KERN_DEBUG "master online\n");
/* Master is online, find parent-slave (master if first slave) */
while (mlp->slave) {
if ((isdn_net_local *) mlp->slave->priv == lp)
break;
mlp = (isdn_net_local *) mlp->slave->priv;
}
} else
printk(KERN_DEBUG "master offline\n");
/* Found parent, if it's offline iterate next device */
printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
if (!(mlp->flags & ISDN_NET_CONNECTED)) {
continue;
}
}
if (lp->flags & ISDN_NET_CALLBACK) {
int chi;
/*
* Is the state MANUAL?
* If so, no callback can be made,
* so reject actively.
* */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
restore_flags(flags);
printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
lp->name);
return 3;
}
printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
lp->name, nr, eaz);
if (lp->phone[1]) {
/* Grab a free ISDN-Channel */
if ((chi =
isdn_get_free_slot(
ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
lp->pre_channel,
lp->msn)
) < 0) {
printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
restore_flags(flags);
return 0;
}
/* Setup dialstate. */
lp->dial_timer.expires = jiffies + lp->cbdelay;
lp->dial_event = EV_NET_TIMER_CB;
add_timer(&lp->dial_timer);
lp->dialstate = ST_WAIT_BEFORE_CB;
/* Connect interface with channel */
isdn_net_bind_channel(lp, chi);
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
if (isdn_ppp_bind(lp) < 0) { if (isdn_ppp_bind(lp) < 0) {
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(lp);
restore_flags(flags);
return 0;
}
#endif
/* Initiate dialing by returning 2 or 4 */
restore_flags(flags); restore_flags(flags);
return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4; return 0;
} else
printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);
restore_flags(flags);
return 0;
} else {
printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
eaz);
/* if this interface is dialing, it does it probably on a different
device, so free this device */
if (lp->dialstate == ST_OUT_WAIT_DCONN) {
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_free(lp);
#endif
isdn_net_lp_disconnected(lp);
isdn_slot_free(lp->isdn_slot,
ISDN_USAGE_NET);
} }
strcpy(isdn_slot_num(idx), nr); #endif
isdn_slot_set_usage(idx, (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) | ISDN_USAGE_NET); /* Initiate dialing by returning 2 or 4 */
isdn_slot_set_st_netdev(idx, lp->netdev); restore_flags(flags);
lp->isdn_slot = slot; return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
lp->ppp_slot = -1; } else {
lp->flags |= ISDN_NET_CONNECTED; printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
eaz);
lp->outgoing = 0; /* if this interface is dialing, it does it probably on a different
lp->huptimer = 0; device, so free this device */
lp->charge_state = ST_CHARGE_NULL; if (lp->dialstate == ST_OUT_WAIT_DCONN) {
/* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect
*/
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);
lp->dial_timer.expires = jiffies + 15 * HZ;
lp->dial_event = EV_NET_TIMER_IN_DCONN;
add_timer(&lp->dial_timer);
lp->dialstate = ST_IN_WAIT_DCONN;
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
if (isdn_ppp_bind(lp) < 0) { isdn_ppp_free(lp);
isdn_net_unbind_channel(lp);
restore_flags(flags);
return 0;
}
#endif #endif
restore_flags(flags); isdn_net_lp_disconnected(lp);
return 1; isdn_slot_free(lp->isdn_slot,
ISDN_USAGE_NET);
} }
strcpy(isdn_slot_num(idx), nr);
isdn_slot_set_usage(idx, (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) | ISDN_USAGE_NET);
isdn_slot_set_st_netdev(idx, lp->netdev);
lp->isdn_slot = slot;
lp->ppp_slot = -1;
lp->flags |= ISDN_NET_CONNECTED;
lp->outgoing = 0;
lp->huptimer = 0;
lp->charge_state = ST_CHARGE_NULL;
/* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect
*/
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);
lp->dial_timer.expires = jiffies + 15 * HZ;
lp->dial_event = EV_NET_TIMER_IN_DCONN;
add_timer(&lp->dial_timer);
lp->dialstate = ST_IN_WAIT_DCONN;
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
if (isdn_ppp_bind(lp) < 0) {
isdn_net_unbind_channel(lp);
restore_flags(flags);
return 0;
}
#endif
restore_flags(flags);
return 1;
} }
} }
} }
/* If none of configured EAZ/MSN matched and not verbose, be silent */ /* If none of configured EAZ/MSN matched and not verbose, be silent */
if (!ematch || dev->net_verbose) if (!ematch || dev->net_verbose)
...@@ -2450,45 +2404,38 @@ isdn_net_findif(char *name) ...@@ -2450,45 +2404,38 @@ isdn_net_findif(char *name)
int int
isdn_net_force_dial_lp(isdn_net_local * lp) isdn_net_force_dial_lp(isdn_net_local * lp)
{ {
if ((!(lp->flags & ISDN_NET_CONNECTED)) && lp->dialstate == ST_NULL) { int chi;
int chi; unsigned long flags;
if (lp->phone[1]) {
ulong flags;
save_flags(flags);
cli();
/* Grab a free ISDN-Channel */ if (lp->flags & ISDN_NET_CONNECTED || lp->dialstate != ST_NULL)
if ((chi = return -EBUSY;
isdn_get_free_slot(
ISDN_USAGE_NET, save_flags(flags);
lp->l2_proto, cli();
lp->l3_proto,
lp->pre_device, /* Grab a free ISDN-Channel */
lp->pre_channel, chi = isdn_get_free_slot(ISDN_USAGE_NET, lp->l2_proto, lp->l3_proto,
lp->msn) lp->pre_device, lp->pre_channel, lp->msn);
) < 0) { if (chi < 0) {
printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name); printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
restore_flags(flags); restore_flags(flags);
return -EAGAIN; return -EAGAIN;
} }
/* Connect interface with channel */ /* Connect interface with channel */
isdn_net_bind_channel(lp, chi); isdn_net_bind_channel(lp, chi);
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
if (isdn_ppp_bind(lp) < 0) { if (isdn_ppp_bind(lp) < 0) {
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(lp);
restore_flags(flags);
return -EAGAIN;
}
#endif
/* Initiate dialing */
restore_flags(flags); restore_flags(flags);
init_dialout(lp); return -EAGAIN;
return 0; }
} else #endif
return -EINVAL; /* Initiate dialing */
} else restore_flags(flags);
return -EBUSY; init_dialout(lp);
return 0;
} }
/* /*
...@@ -2608,6 +2555,12 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -2608,6 +2555,12 @@ isdn_net_new(char *name, struct net_device *master)
init_timer(&netdev->local.dial_timer); init_timer(&netdev->local.dial_timer);
netdev->local.dial_timer.data = (unsigned long) &netdev->local; netdev->local.dial_timer.data = (unsigned long) &netdev->local;
netdev->local.dial_timer.function = isdn_net_dial_timer; netdev->local.dial_timer.function = isdn_net_dial_timer;
init_timer(&netdev->local.hup_timer);
netdev->local.hup_timer.data = (unsigned long) &netdev->local;
netdev->local.hup_timer.function = isdn_net_hup_timer;
spin_lock_init(&netdev->local.lock);
INIT_LIST_HEAD(&netdev->local.phone[0]);
INIT_LIST_HEAD(&netdev->local.phone[1]);
/* Put into to netdev-chain */ /* Put into to netdev-chain */
list_add(&netdev->global_list, &isdn_net_devs); list_add(&netdev->global_list, &isdn_net_devs);
...@@ -2837,6 +2790,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2837,6 +2790,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
else { else {
lp->flags |= cfg->dialmode; /* turn on selected bits */ lp->flags |= cfg->dialmode; /* turn on selected bits */
} }
if (lp->flags & ISDN_NET_DM_OFF)
isdn_net_hangup(lp);
if (cfg->chargehup) if (cfg->chargehup)
lp->hupflags |= ISDN_CHARGEHUP; lp->hupflags |= ISDN_CHARGEHUP;
else else
...@@ -2937,17 +2893,21 @@ int ...@@ -2937,17 +2893,21 @@ int
isdn_net_addphone(isdn_net_ioctl_phone * phone) isdn_net_addphone(isdn_net_ioctl_phone * phone)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *p = isdn_net_findif(phone->name);
isdn_net_phone *n; unsigned long flags;
struct isdn_net_phone *n;
if (p) { if (!p)
if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) return -ENODEV;
return -ENOMEM;
strcpy(n->num, phone->phone); n = kmalloc(sizeof(*n), GFP_KERNEL);
n->next = p->local.phone[phone->outgoing & 1]; if (!n)
p->local.phone[phone->outgoing & 1] = n; return -ENOMEM;
return 0;
} strcpy(n->num, phone->phone);
return -ENODEV; spin_lock_irqsave(&p->local.lock, flags);
list_add_tail(&n->list, &p->local.phone[phone->outgoing & 1]);
spin_unlock_irqrestore(&p->local.lock, flags);
return 0;
} }
/* /*
...@@ -2958,28 +2918,37 @@ int ...@@ -2958,28 +2918,37 @@ int
isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *p = isdn_net_findif(phone->name);
unsigned long flags;
int inout = phone->outgoing & 1; int inout = phone->outgoing & 1;
int more = 0;
int count = 0; int count = 0;
isdn_net_phone *n; char *buf = (char *)__get_free_page(GFP_KERNEL);
struct isdn_net_phone *n;
if (!p) if (!p)
return -ENODEV; return -ENODEV;
if (!buf)
return -ENOMEM;
inout &= 1; inout &= 1;
for (n = p->local.phone[inout]; n; n = n->next) { spin_lock_irqsave(&p->local.lock, flags);
if (more) { list_for_each_entry(n, &p->local.phone[inout], list) {
put_user(' ', phones++); strcpy(&buf[count], n->num);
count++;
}
if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
return -EFAULT;
}
phones += strlen(n->num);
count += strlen(n->num); count += strlen(n->num);
more = 1; buf[count++] = ' ';
if (count > PAGE_SIZE - ISDN_MSNLEN - 1)
break;
} }
put_user(0, phones); spin_unlock_irqrestore(&p->local.lock, flags);
count++; if (!count)
count++;
buf[count-1] = 0;
if (copy_to_user(phones, buf, count))
count = -EFAULT;
free_page((unsigned long)buf);
return count; return count;
} }
...@@ -3017,34 +2986,25 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone) ...@@ -3017,34 +2986,25 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *p = isdn_net_findif(phone->name);
int inout = phone->outgoing & 1; int inout = phone->outgoing & 1;
isdn_net_phone *n; struct isdn_net_phone *n;
isdn_net_phone *m;
unsigned long flags; unsigned long flags;
int retval;
if (p) { if (!p)
save_flags(flags); return -ENODEV;
cli();
n = p->local.phone[inout]; retval = -EINVAL;
m = NULL; spin_lock_irqsave(&p->local.lock, flags);
while (n) { list_for_each_entry(n, &p->local.phone[inout], list) {
if (!strcmp(n->num, phone->phone)) { if (!strcmp(n->num, phone->phone)) {
if (p->local.dial == n) list_del(&n->list);
p->local.dial = n->next; kfree(n);
if (m) retval = 0;
m->next = n->next; break;
else
p->local.phone[inout] = n->next;
kfree(n);
restore_flags(flags);
return 0;
}
m = n;
n = (isdn_net_phone *) n->next;
} }
restore_flags(flags);
return -EINVAL;
} }
return -ENODEV; spin_unlock_irqrestore(&p->local.lock, flags);
return retval;
} }
/* /*
...@@ -3053,24 +3013,19 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone) ...@@ -3053,24 +3013,19 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
static int static int
isdn_net_rmallphone(isdn_net_dev * p) isdn_net_rmallphone(isdn_net_dev * p)
{ {
isdn_net_phone *n; struct isdn_net_phone *n;
isdn_net_phone *m;
unsigned long flags; unsigned long flags;
int i; int i;
save_flags(flags); spin_lock_irqsave(&p->local.lock, flags);
cli();
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
n = p->local.phone[i]; while (!list_empty(&p->local.phone[i])) {
while (n) { n = list_entry(p->local.phone[i].next, struct isdn_net_phone, list);
m = n->next; list_del(&n->list);
kfree(n); kfree(n);
n = m;
} }
p->local.phone[i] = NULL;
} }
p->local.dial = NULL; spin_lock_irqsave(&p->local.lock, flags);
restore_flags(flags);
return 0; return 0;
} }
...@@ -3089,10 +3044,10 @@ isdn_net_force_hangup(char *name) ...@@ -3089,10 +3044,10 @@ isdn_net_force_hangup(char *name)
q = p->local.slave; q = p->local.slave;
/* If this interface has slaves, do a hangup for them also. */ /* If this interface has slaves, do a hangup for them also. */
while (q) { while (q) {
isdn_net_hangup(q); isdn_net_hangup(&p->local);
q = (((isdn_net_local *) q->priv)->slave); q = (((isdn_net_local *) q->priv)->slave);
} }
isdn_net_hangup(&p->dev); isdn_net_hangup(&p->local);
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
...@@ -3146,9 +3101,6 @@ isdn_net_realrm(isdn_net_dev *p) ...@@ -3146,9 +3101,6 @@ isdn_net_realrm(isdn_net_dev *p)
} }
} }
} }
/* If no more net-devices remain, disable auto-hangup timer */
if (list_empty(&isdn_net_devs))
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
restore_flags(flags); restore_flags(flags);
kfree(p); kfree(p);
......
...@@ -41,8 +41,8 @@ extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *); ...@@ -41,8 +41,8 @@ extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *);
extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
extern int isdn_net_delphone(isdn_net_ioctl_phone *); extern int isdn_net_delphone(isdn_net_ioctl_phone *);
extern int isdn_net_find_icall(int, int, int, setup_parm *); extern int isdn_net_find_icall(int, int, int, setup_parm *);
extern void isdn_net_hangup(struct net_device *); extern void isdn_net_hangup(isdn_net_local *);
extern void isdn_net_autohup(void); extern void isdn_net_hangup_all(void);
extern int isdn_net_force_hangup(char *); extern int isdn_net_force_hangup(char *);
extern int isdn_net_force_dial(char *); extern int isdn_net_force_dial(char *);
extern isdn_net_dev *isdn_net_findif(char *); extern isdn_net_dev *isdn_net_findif(char *);
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
#include "isdn_ppp.h" #include "isdn_ppp.h"
#include "isdn_net.h" #include "isdn_net.h"
#ifndef PPP_IPX
#define PPP_IPX 0x002b
#endif
/* Prototypes */ /* Prototypes */
static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot); static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
static int isdn_ppp_closewait(int slot); static int isdn_ppp_closewait(int slot);
...@@ -348,20 +344,13 @@ isdn_ppp_release(struct inode *ino, struct file *file) ...@@ -348,20 +344,13 @@ isdn_ppp_release(struct inode *ino, struct file *file)
printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) is->lp); printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) is->lp);
if (is->lp) { /* a lp address says: this link is still up */ if (is->lp) { /* a lp address says: this link is still up */
isdn_net_dev *p = is->lp->netdev;
if (!p) {
printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__ );
unlock_kernel();
return 0;
}
is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
/* /*
* isdn_net_hangup() calls isdn_ppp_free() * isdn_net_hangup() calls isdn_ppp_free()
* isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
* removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon() * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
*/ */
isdn_net_hangup(&p->dev); is->state &= ~IPPP_CONNECT;
isdn_net_hangup(is->lp);
} }
for (i = 0; i < NUM_RCV_BUFFS; i++) { for (i = 0; i < NUM_RCV_BUFFS; i++) {
if (is->rq[i].buf) { if (is->rq[i].buf) {
...@@ -424,8 +413,6 @@ get_arg(void *b, void *val, int len) ...@@ -424,8 +413,6 @@ get_arg(void *b, void *val, int len)
static int static int
set_arg(void *b, void *val,int len) set_arg(void *b, void *val,int len)
{ {
if(len <= 0)
len = sizeof(void *);
if (copy_to_user(b, (void *) val, len)) if (copy_to_user(b, (void *) val, len))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -571,13 +558,18 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned ...@@ -571,13 +558,18 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned
return isdn_ppp_set_compressor(is, &data); return isdn_ppp_set_compressor(is, &data);
case PPPIOCGCALLINFO: case PPPIOCGCALLINFO:
{ {
struct isdn_net_phone *phone;
struct pppcallinfo pci; struct pppcallinfo pci;
int i;
memset((char *) &pci,0,sizeof(struct pppcallinfo)); memset((char *) &pci,0,sizeof(struct pppcallinfo));
if(lp) if(lp) {
{
strncpy(pci.local_num,lp->msn,63); strncpy(pci.local_num,lp->msn,63);
if(lp->dial) { i = 0;
strncpy(pci.remote_num,lp->dial->num,63); list_for_each_entry(phone, &lp->phone[1], list) {
if (i++ == lp->dial) {
strncpy(pci.remote_num,phone->num,63);
break;
}
} }
pci.charge_units = lp->charge; pci.charge_units = lp->charge;
if(lp->outgoing) if(lp->outgoing)
...@@ -2003,7 +1995,7 @@ isdn_ppp_hangup_slave(char *name) ...@@ -2003,7 +1995,7 @@ isdn_ppp_hangup_slave(char *name)
{ {
#ifdef CONFIG_ISDN_MPP #ifdef CONFIG_ISDN_MPP
isdn_net_dev *ndev; isdn_net_dev *ndev;
isdn_net_local *lp; isdn_net_local *lp, *mlp = NULL;
struct net_device *sdev; struct net_device *sdev;
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
...@@ -2014,7 +2006,7 @@ isdn_ppp_hangup_slave(char *name) ...@@ -2014,7 +2006,7 @@ isdn_ppp_hangup_slave(char *name)
sdev = lp->slave; sdev = lp->slave;
while (sdev) { while (sdev) {
isdn_net_local *mlp = (isdn_net_local *) sdev->priv; mlp = (isdn_net_local *) sdev->priv;
if (mlp->slave) { /* find last connected link in chain */ if (mlp->slave) { /* find last connected link in chain */
isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv; isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv;
...@@ -2029,7 +2021,7 @@ isdn_ppp_hangup_slave(char *name) ...@@ -2029,7 +2021,7 @@ isdn_ppp_hangup_slave(char *name)
if (!sdev) if (!sdev)
return 2; return 2;
isdn_net_hangup(sdev); isdn_net_hangup(mlp);
return 0; return 0;
#else #else
return -1; return -1;
......
...@@ -245,12 +245,10 @@ typedef struct { ...@@ -245,12 +245,10 @@ typedef struct {
#define ISDN_TIMER_MODEMPLUS 2 #define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4 #define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8 #define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_NETHANGUP 32
#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */ #define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \ #define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
ISDN_TIMER_MODEMXMIT) ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \ #define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_CARRIER)
ISDN_TIMER_CARRIER)
/* GLOBAL_FLAGS */ /* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1 #define ISDN_GLOBAL_STOPPED 1
...@@ -267,10 +265,10 @@ typedef struct { ...@@ -267,10 +265,10 @@ typedef struct {
#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */ #define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
/* Phone-list-element */ /* Phone-list-element */
typedef struct { struct isdn_net_phone {
void *next; struct list_head list;
char num[ISDN_MSNLEN]; char num[ISDN_MSNLEN];
} isdn_net_phone; };
/* /*
Principles when extending structures for generic encapsulation protocol Principles when extending structures for generic encapsulation protocol
...@@ -283,11 +281,13 @@ typedef struct { ...@@ -283,11 +281,13 @@ typedef struct {
/* Local interface-data */ /* Local interface-data */
typedef struct isdn_net_local_s { typedef struct isdn_net_local_s {
spinlock_t lock;
ulong magic; ulong magic;
char name[10]; /* Name of device */ char name[10]; /* Name of device */
struct timer_list dial_timer; /* dial timeout */ struct timer_list dial_timer; /* dial events timer */
int dial_event; /* event in case of timer expiry */ int dial_event; /* event in case of timer expiry */
struct net_device_stats stats; /* Ethernet Statistics */ struct net_device_stats stats; /* Ethernet Statistics */
struct timer_list hup_timer; /* auto hangup timer */
int isdn_slot; /* Index to isdn device/channel */ int isdn_slot; /* Index to isdn device/channel */
int ppp_slot; /* PPPD device slot number */ int ppp_slot; /* PPPD device slot number */
int pre_device; /* Preselected isdn-device */ int pre_device; /* Preselected isdn-device */
...@@ -335,10 +335,10 @@ typedef struct isdn_net_local_s { ...@@ -335,10 +335,10 @@ typedef struct isdn_net_local_s {
ulong sqfull_stamp; /* Start-Time of overload */ ulong sqfull_stamp; /* Start-Time of overload */
ulong slavedelay; /* Dynamic bundling delaytime */ ulong slavedelay; /* Dynamic bundling delaytime */
int triggercps; /* BogoCPS needed for trigger slave */ int triggercps; /* BogoCPS needed for trigger slave */
isdn_net_phone *phone[2]; /* List of remote-phonenumbers */ struct list_head phone[2]; /* List of remote-phonenumbers */
/* phone[0] = Incoming Numbers */ /* phone[0] = Incoming Numbers */
/* phone[1] = Outgoing Numbers */ /* phone[1] = Outgoing Numbers */
isdn_net_phone *dial; /* Pointer to dialed number */ int dial; /* # of phone number just dialed */
struct net_device *master; /* Ptr to Master device for slaves */ struct net_device *master; /* Ptr to Master device for slaves */
struct net_device *slave; /* Ptr to Slave device for masters */ struct net_device *slave; /* Ptr to Slave device for masters */
struct isdn_net_local_s *next; /* Ptr to next link in bundle */ struct isdn_net_local_s *next; /* Ptr to next link in bundle */
......
...@@ -275,7 +275,6 @@ typedef struct setup_parm { ...@@ -275,7 +275,6 @@ typedef struct setup_parm {
} setup_parm; } setup_parm;
#ifdef CONFIG_ISDN_TTY_FAX
/* T.30 Fax G3 */ /* T.30 Fax G3 */
#define FAXIDLEN 21 #define FAXIDLEN 21
...@@ -350,8 +349,6 @@ typedef struct T30_s { ...@@ -350,8 +349,6 @@ typedef struct T30_s {
#define ISDN_FAX_PHASE_D 4 #define ISDN_FAX_PHASE_D 4
#define ISDN_FAX_PHASE_E 5 #define ISDN_FAX_PHASE_E 5
#endif /* TTY_FAX */
#define ISDN_FAX_CLASS1_FAE 0 #define ISDN_FAX_CLASS1_FAE 0
#define ISDN_FAX_CLASS1_FTS 1 #define ISDN_FAX_CLASS1_FTS 1
#define ISDN_FAX_CLASS1_FRS 2 #define ISDN_FAX_CLASS1_FRS 2
......
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