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)
if (tf & ISDN_TIMER_SLOW) {
if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
isdn_timer_cnt2 = 0;
if (tf & ISDN_TIMER_NETHANGUP)
isdn_net_autohup();
if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
isdn_timer_cnt3 = 0;
if (tf & ISDN_TIMER_MODEMRING)
......@@ -451,8 +449,6 @@ isdn_status_callback(isdn_ctrl * c)
case ISDN_STAT_BSENT:
if (i < 0)
return -1;
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
if (isdn_net_stat_callback(i, c))
return 0;
if (isdn_v110_stat_callback(&slot[i].iv110, c))
......@@ -482,15 +478,11 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0)
return -1;
dbg_statcallb("ICALL: %d (%d,%ld) %s\n", i, di, c->arg, c->parm.num);
if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_HANGUP;
isdn_command(&cmd);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
}
/* 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) {
case 0:
/* No network-device replies.
......@@ -550,8 +542,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0)
return -1;
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"))
isdn_net_stat_callback(i, c);
isdn_tty_stat_callback(i, c);
......@@ -574,8 +564,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0)
return -1;
dbg_statcallb("DCONN: %d\n", i);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
/* Find any net-device, waiting for D-channel setup */
if (isdn_net_stat_callback(i, c))
break;
......@@ -593,8 +581,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0)
return -1;
dbg_statcallb("DHUP: %d\n", i);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update();
/* Signal hangup to network-devices */
......@@ -611,8 +597,6 @@ isdn_status_callback(isdn_ctrl * c)
return -1;
dbg_statcallb("BCONN: %ld\n", c->arg);
/* Signal B-channel-connect to network-devices */
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
dev->drv[di]->online |= (1 << (c->arg));
isdn_info_update();
if (isdn_net_stat_callback(i, c))
......@@ -625,8 +609,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0)
return -1;
dbg_statcallb("BHUP: %d\n", i);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update();
#ifdef CONFIG_ISDN_X25
......@@ -642,8 +624,6 @@ isdn_status_callback(isdn_ctrl * c)
if (i < 0)
return -1;
dbg_statcallb("NODCH: %ld\n", c->arg);
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
if (isdn_net_stat_callback(i, c))
break;
if (isdn_tty_stat_callback(i, c))
......@@ -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);
return 0;
case IIOCSETGST:
if (arg)
if (arg) {
dev->global_flags |= ISDN_GLOBAL_STOPPED;
else
isdn_net_hangup_all();
} else {
dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
printk(KERN_INFO "isdn: Global Mode %s\n",
(dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
}
return 0;
case IIOCSETBRJ:
drvidx = -1;
......@@ -1619,8 +1599,9 @@ static struct file_operations isdn_ctrl_fops =
.release = isdn_ctrl_release,
};
/*
* file_operations for major 43, /dev/isdn*
* file_operations for major 45, /dev/isdn*
* stolen from drivers/char/misc.c
*/
......@@ -2119,14 +2100,20 @@ isdn_slot_map_eaz2msn(int sl, char *msn)
int
isdn_slot_command(int sl, int cmd, isdn_ctrl *ctrl)
{
ctrl->command = cmd;
ctrl->driver = isdn_slot_driver(sl);
switch (cmd) {
case ISDN_CMD_SETL2:
case ISDN_CMD_SETL3:
case ISDN_CMD_PROT_IO:
ctrl->arg &= ~0xff; ctrl->arg |= isdn_slot_channel(sl);
break;
case ISDN_CMD_DIAL:
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return -EBUSY;
/* fall through */
default:
ctrl->arg = isdn_slot_channel(sl);
break;
......
......@@ -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 *);
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_disconnected(isdn_net_local *lp);
......@@ -222,8 +222,6 @@ char *isdn_net_revision = "$Revision: 1.140.6.11 $";
static void
isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
{
if(skb) {
u_short proto = ntohs(skb->protocol);
printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
......@@ -232,12 +230,6 @@ isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
(proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
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
......@@ -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:
* Increment idle-counter (this counter is reset on any incoming or
......@@ -357,65 +349,53 @@ isdn_net_unbind_channel(isdn_net_local * lp)
* charge-info.
*/
void
isdn_net_autohup()
static void isdn_net_hup_timer(unsigned long data)
{
struct list_head *l;
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;
isdn_net_local *lp = (isdn_net_local *) data;
if(dev->global_flags & ISDN_GLOBAL_STOPPED ||
ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF) {
isdn_net_hangup(&p->dev);
continue;
if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate != ST_ACTIVE) {
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->onhtime))
continue;
if (!(lp->onhtime))
return;
if (l->huptimer++ <= l->onhtime) {
anymore = 1;
continue;
}
if (l->hupflags & ISDN_MANCHARGE && l->hupflags & ISDN_CHARGEHUP) {
while (time_after(jiffies, l->chargetime + l->chargeint))
l->chargetime += l->chargeint;
if (lp->huptimer++ <= lp->onhtime)
goto mod_timer;
if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ)) {
if (l->outgoing || l->hupflags & ISDN_INHUP) {
isdn_net_hangup(&p->dev);
continue;
if (lp->hupflags & ISDN_MANCHARGE && lp->hupflags & ISDN_CHARGEHUP) {
while (time_after(jiffies, lp->chargetime + lp->chargeint))
lp->chargetime += lp->chargeint;
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) {
if (l->charge_state != ST_CHARGE_HAVE_CINT) {
dbg_net_dial("%s: did not get CINT\n", l->name);
isdn_net_hangup(&p->dev);
continue;
} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
} else if (lp->outgoing) {
if (lp->hupflags & ISDN_CHARGEHUP) {
if (lp->charge_state != ST_CHARGE_HAVE_CINT) {
dbg_net_dial("%s: did not get CINT\n", lp->name);
isdn_net_hangup(lp);
return;
} else if (time_after(jiffies, lp->chargetime + lp->chargeint)) {
dbg_net_dial("%s: chtime = %lu, chint = %d\n",
l->name, l->chargetime, l->chargeint);
isdn_net_hangup(&p->dev);
continue;
}
lp->name, lp->chargetime, lp->chargeint);
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)
......@@ -430,7 +410,9 @@ static void isdn_net_connected(isdn_net_local *lp)
struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
#endif
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)
isdn_net_ciscohdlck_connected(lp);
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
......@@ -495,33 +477,17 @@ isdn_net_dial_timer(unsigned long 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);
}
/* Initiate dialout. Set phone-number-pointer to first number
* of interface.
*/
static int
static void
init_dialout(isdn_net_local *lp)
{
unsigned long flags;
save_flags(flags);
cli();
lp->dial = lp->phone[1];
restore_flags(flags);
lp->dial = 0;
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 &&
(lp->dialstarted == 0 ||
time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))) {
......@@ -529,83 +495,70 @@ init_dialout(isdn_net_local *lp)
lp->dialwait_timer = 0;
}
lp->dialretry = 0;
return do_dialout(lp);
do_dialout(lp);
}
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment
* retry-counter.
*/
static int
static void
do_dialout(isdn_net_local *lp)
{
int i;
unsigned long flags;
if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
char *s;
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
s = "dial suppressed: isdn system stopped";
else
s = "dial suppressed: dialmode `off'";
isdn_net_unreachable(&lp->netdev->dev, 0, s);
isdn_net_hangup(&lp->netdev->dev);
return 0;
}
save_flags(flags);
cli();
if (!lp->dial) {
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"))) {
restore_flags(flags);
lp->dialstate = ST_OUT_WAIT_DCONN;
printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
return 1;
} else {
struct isdn_net_phone *phone;
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)) {
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;
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;
list_for_each_entry(phone, &lp->phone[1], list) {
if (i++ == lp->dial)
goto found;
}
/*
* 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];
/* otherwise start in front */
phone = list_entry(lp->phone[1].next, struct isdn_net_phone, list);
lp->dial = 0;
lp->dialretry++;
found:
lp->dial++;
dial.phone = phone->num;
spin_unlock_irqrestore(&lp->lock, flags);
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;
isdn_net_hangup(lp);
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;
}
restore_flags(flags);
/*
* Switch to next number or back to start if at end of list.
*/
isdn_slot_dial(lp->isdn_slot, &dial);
}
lp->huptimer = 0;
lp->outgoing = 1;
if (lp->chargeint)
......@@ -622,7 +575,6 @@ do_dialout(isdn_net_local *lp)
}
lp->dialstate = ST_OUT_WAIT_DCONN;
add_timer(&lp->dial_timer);
return 1;
}
/* 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)
/* Remote does callback. Hangup after cbdelay,
* then wait for incoming call */
printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
isdn_net_hangup(&lp->netdev->dev);
isdn_net_hangup(lp);
return 1;
case ISDN_STAT_DCONN:
/* Got D-Channel-Connect, send B-Channel-request */
......@@ -766,7 +718,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ST_IN_WAIT_DCONN:
switch (pr) {
case EV_NET_TIMER_IN_DCONN:
isdn_net_hangup(&p->dev);
isdn_net_hangup(lp);
return 1;
case ISDN_STAT_DCONN:
del_timer(&lp->dial_timer);
......@@ -787,7 +739,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ST_IN_WAIT_BCONN:
switch (pr) {
case EV_NET_TIMER_IN_BCONN:
isdn_net_hangup(&p->dev);
isdn_net_hangup(lp);
break;
case ISDN_STAT_BCONN:
del_timer(&lp->dial_timer);
......@@ -822,15 +774,15 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
* Perform hangup for a net-interface.
*/
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;
#ifdef CONFIG_ISDN_X25
struct concap_proto *cprot = lp -> netdev -> cprot;
struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
#endif
del_timer_sync(&lp->hup_timer);
if (lp->flags & ISDN_NET_CONNECTED) {
if (lp->slave != NULL) {
isdn_net_local *slp = (isdn_net_local *)lp->slave->priv;
......@@ -838,7 +790,7 @@ isdn_net_hangup(struct net_device *d)
printk(KERN_INFO
"isdn_net: hang up slave %s before %s\n",
slp->name, lp->name);
isdn_net_hangup(lp->slave);
isdn_net_hangup(slp);
}
}
printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
......@@ -862,6 +814,17 @@ isdn_net_hangup(struct net_device *d)
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 {
unsigned short source;
unsigned short dest;
......@@ -1173,6 +1136,7 @@ void isdn_net_tx_timeout(struct net_device * ndev)
static int
isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
unsigned long flags;
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
#ifdef CONFIG_ISDN_X25
struct concap_proto * cprot = lp -> netdev -> cprot;
......@@ -1208,8 +1172,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
dev_kfree_skb(skb);
return 0;
}
if (lp->phone[1]) {
ulong flags;
save_flags(flags);
cli();
......@@ -1276,12 +1239,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
init_dialout(lp);
isdn_net_device_stop_queue(lp);
return 1;
} else {
isdn_net_unreachable(ndev, skb,
"No phone number");
dev_kfree_skb(skb);
return 0;
}
} else {
/* Device is connected to an ISDN channel */
ndev->trans_start = jiffies;
......@@ -1324,11 +1281,11 @@ isdn_net_close(struct net_device *dev)
if( cprot && cprot -> pops )
cprot -> pops -> close( cprot );
#endif
isdn_net_hangup(p);
isdn_net_hangup(p->priv);
p = (((isdn_net_local *) p->priv)->slave);
}
}
isdn_net_hangup(dev);
isdn_net_hangup(dev->priv);
isdn_MOD_DEC_USE_COUNT();
return 0;
}
......@@ -2118,7 +2075,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
int swapped;
int sidx = 0;
struct list_head *l;
isdn_net_phone *n;
struct isdn_net_phone *n;
ulong flags;
char nr[32];
char *my_eaz;
......@@ -2152,7 +2109,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
return 0;
}
n = (isdn_net_phone *) 0;
n = NULL;
ematch = wret = swapped = 0;
dbg_net_icall("n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
isdn_slot_usage(idx));
......@@ -2258,15 +2215,17 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
}
}
dbg_net_icall("n_fi: match2\n");
n = lp->phone[0];
if (lp->flags & ISDN_NET_SECURE) {
while (n) {
if (!isdn_msncmp(nr, n->num))
spin_lock_irqsave(&lp->lock, flags);
list_for_each_entry(n, &lp->phone[0], list) {
if (!isdn_msncmp(nr, n->num)) {
spin_unlock_irqrestore(&lp->lock, flags);
break;
n = (isdn_net_phone *) n->next;
}
}
if (n || (!(lp->flags & ISDN_NET_SECURE))) {
spin_unlock_irqrestore(&lp->lock, flags);
continue;
}
dbg_net_icall("n_fi: match3\n");
/* matching interface found */
......@@ -2329,7 +2288,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
}
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(
......@@ -2364,10 +2323,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
/* Initiate dialing by returning 2 or 4 */
restore_flags(flags);
return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
} 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);
......@@ -2418,7 +2373,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
}
}
}
}
/* If none of configured EAZ/MSN matched and not verbose, be silent */
if (!ematch || dev->net_verbose)
printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, slot, eaz);
......@@ -2450,23 +2404,19 @@ isdn_net_findif(char *name)
int
isdn_net_force_dial_lp(isdn_net_local * lp)
{
if ((!(lp->flags & ISDN_NET_CONNECTED)) && lp->dialstate == ST_NULL) {
int chi;
if (lp->phone[1]) {
ulong flags;
unsigned long flags;
if (lp->flags & ISDN_NET_CONNECTED || lp->dialstate != ST_NULL)
return -EBUSY;
save_flags(flags);
cli();
/* 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, lp->msn);
if (chi < 0) {
printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
restore_flags(flags);
return -EAGAIN;
......@@ -2484,11 +2434,8 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
/* Initiate dialing */
restore_flags(flags);
init_dialout(lp);
return 0;
} else
return -EINVAL;
} else
return -EBUSY;
}
/*
......@@ -2608,6 +2555,12 @@ isdn_net_new(char *name, struct net_device *master)
init_timer(&netdev->local.dial_timer);
netdev->local.dial_timer.data = (unsigned long) &netdev->local;
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 */
list_add(&netdev->global_list, &isdn_net_devs);
......@@ -2837,6 +2790,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
else {
lp->flags |= cfg->dialmode; /* turn on selected bits */
}
if (lp->flags & ISDN_NET_DM_OFF)
isdn_net_hangup(lp);
if (cfg->chargehup)
lp->hupflags |= ISDN_CHARGEHUP;
else
......@@ -2937,17 +2893,21 @@ int
isdn_net_addphone(isdn_net_ioctl_phone * phone)
{
isdn_net_dev *p = isdn_net_findif(phone->name);
isdn_net_phone *n;
unsigned long flags;
struct isdn_net_phone *n;
if (p) {
if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
if (!p)
return -ENODEV;
n = kmalloc(sizeof(*n), GFP_KERNEL);
if (!n)
return -ENOMEM;
strcpy(n->num, phone->phone);
n->next = p->local.phone[phone->outgoing & 1];
p->local.phone[phone->outgoing & 1] = n;
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;
}
return -ENODEV;
}
/*
......@@ -2958,28 +2918,37 @@ int
isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
{
isdn_net_dev *p = isdn_net_findif(phone->name);
unsigned long flags;
int inout = phone->outgoing & 1;
int more = 0;
int count = 0;
isdn_net_phone *n;
char *buf = (char *)__get_free_page(GFP_KERNEL);
struct isdn_net_phone *n;
if (!p)
return -ENODEV;
if (!buf)
return -ENOMEM;
inout &= 1;
for (n = p->local.phone[inout]; n; n = n->next) {
if (more) {
put_user(' ', phones++);
count++;
}
if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
return -EFAULT;
}
phones += strlen(n->num);
spin_lock_irqsave(&p->local.lock, flags);
list_for_each_entry(n, &p->local.phone[inout], list) {
strcpy(&buf[count], 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);
if (!count)
count++;
buf[count-1] = 0;
if (copy_to_user(phones, buf, count))
count = -EFAULT;
free_page((unsigned long)buf);
return count;
}
......@@ -3017,34 +2986,25 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
{
isdn_net_dev *p = isdn_net_findif(phone->name);
int inout = phone->outgoing & 1;
isdn_net_phone *n;
isdn_net_phone *m;
struct isdn_net_phone *n;
unsigned long flags;
int retval;
if (p) {
save_flags(flags);
cli();
n = p->local.phone[inout];
m = NULL;
while (n) {
if (!p)
return -ENODEV;
retval = -EINVAL;
spin_lock_irqsave(&p->local.lock, flags);
list_for_each_entry(n, &p->local.phone[inout], list) {
if (!strcmp(n->num, phone->phone)) {
if (p->local.dial == n)
p->local.dial = n->next;
if (m)
m->next = n->next;
else
p->local.phone[inout] = n->next;
list_del(&n->list);
kfree(n);
restore_flags(flags);
return 0;
}
m = n;
n = (isdn_net_phone *) n->next;
retval = 0;
break;
}
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)
static int
isdn_net_rmallphone(isdn_net_dev * p)
{
isdn_net_phone *n;
isdn_net_phone *m;
struct isdn_net_phone *n;
unsigned long flags;
int i;
save_flags(flags);
cli();
spin_lock_irqsave(&p->local.lock, flags);
for (i = 0; i < 2; i++) {
n = p->local.phone[i];
while (n) {
m = n->next;
while (!list_empty(&p->local.phone[i])) {
n = list_entry(p->local.phone[i].next, struct isdn_net_phone, list);
list_del(&n->list);
kfree(n);
n = m;
}
p->local.phone[i] = NULL;
}
p->local.dial = NULL;
restore_flags(flags);
spin_lock_irqsave(&p->local.lock, flags);
return 0;
}
......@@ -3089,10 +3044,10 @@ isdn_net_force_hangup(char *name)
q = p->local.slave;
/* If this interface has slaves, do a hangup for them also. */
while (q) {
isdn_net_hangup(q);
isdn_net_hangup(&p->local);
q = (((isdn_net_local *) q->priv)->slave);
}
isdn_net_hangup(&p->dev);
isdn_net_hangup(&p->local);
return 0;
}
return -ENODEV;
......@@ -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);
kfree(p);
......
......@@ -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_delphone(isdn_net_ioctl_phone *);
extern int isdn_net_find_icall(int, int, int, setup_parm *);
extern void isdn_net_hangup(struct net_device *);
extern void isdn_net_autohup(void);
extern void isdn_net_hangup(isdn_net_local *);
extern void isdn_net_hangup_all(void);
extern int isdn_net_force_hangup(char *);
extern int isdn_net_force_dial(char *);
extern isdn_net_dev *isdn_net_findif(char *);
......
......@@ -19,10 +19,6 @@
#include "isdn_ppp.h"
#include "isdn_net.h"
#ifndef PPP_IPX
#define PPP_IPX 0x002b
#endif
/* Prototypes */
static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
static int isdn_ppp_closewait(int slot);
......@@ -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);
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_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()
*/
isdn_net_hangup(&p->dev);
is->state &= ~IPPP_CONNECT;
isdn_net_hangup(is->lp);
}
for (i = 0; i < NUM_RCV_BUFFS; i++) {
if (is->rq[i].buf) {
......@@ -424,8 +413,6 @@ get_arg(void *b, void *val, int len)
static int
set_arg(void *b, void *val,int len)
{
if(len <= 0)
len = sizeof(void *);
if (copy_to_user(b, (void *) val, len))
return -EFAULT;
return 0;
......@@ -571,13 +558,18 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned
return isdn_ppp_set_compressor(is, &data);
case PPPIOCGCALLINFO:
{
struct isdn_net_phone *phone;
struct pppcallinfo pci;
int i;
memset((char *) &pci,0,sizeof(struct pppcallinfo));
if(lp)
{
if(lp) {
strncpy(pci.local_num,lp->msn,63);
if(lp->dial) {
strncpy(pci.remote_num,lp->dial->num,63);
i = 0;
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;
if(lp->outgoing)
......@@ -2003,7 +1995,7 @@ isdn_ppp_hangup_slave(char *name)
{
#ifdef CONFIG_ISDN_MPP
isdn_net_dev *ndev;
isdn_net_local *lp;
isdn_net_local *lp, *mlp = NULL;
struct net_device *sdev;
if (!(ndev = isdn_net_findif(name)))
......@@ -2014,7 +2006,7 @@ isdn_ppp_hangup_slave(char *name)
sdev = lp->slave;
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 */
isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv;
......@@ -2029,7 +2021,7 @@ isdn_ppp_hangup_slave(char *name)
if (!sdev)
return 2;
isdn_net_hangup(sdev);
isdn_net_hangup(mlp);
return 0;
#else
return -1;
......
......@@ -245,12 +245,10 @@ typedef struct {
#define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_NETHANGUP 32
#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
ISDN_TIMER_CARRIER)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_CARRIER)
/* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1
......@@ -267,10 +265,10 @@ typedef struct {
#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
/* Phone-list-element */
typedef struct {
void *next;
struct isdn_net_phone {
struct list_head list;
char num[ISDN_MSNLEN];
} isdn_net_phone;
};
/*
Principles when extending structures for generic encapsulation protocol
......@@ -283,11 +281,13 @@ typedef struct {
/* Local interface-data */
typedef struct isdn_net_local_s {
spinlock_t lock;
ulong magic;
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 */
struct net_device_stats stats; /* Ethernet Statistics */
struct timer_list hup_timer; /* auto hangup timer */
int isdn_slot; /* Index to isdn device/channel */
int ppp_slot; /* PPPD device slot number */
int pre_device; /* Preselected isdn-device */
......@@ -335,10 +335,10 @@ typedef struct isdn_net_local_s {
ulong sqfull_stamp; /* Start-Time of overload */
ulong slavedelay; /* Dynamic bundling delaytime */
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[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 *slave; /* Ptr to Slave device for masters */
struct isdn_net_local_s *next; /* Ptr to next link in bundle */
......
......@@ -275,7 +275,6 @@ typedef struct setup_parm {
} setup_parm;
#ifdef CONFIG_ISDN_TTY_FAX
/* T.30 Fax G3 */
#define FAXIDLEN 21
......@@ -350,8 +349,6 @@ typedef struct T30_s {
#define ISDN_FAX_PHASE_D 4
#define ISDN_FAX_PHASE_E 5
#endif /* TTY_FAX */
#define ISDN_FAX_CLASS1_FAE 0
#define ISDN_FAX_CLASS1_FTS 1
#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