Commit 4a38941a authored by Ralf Bächle's avatar Ralf Bächle

Merge dea.linux-mips.net:/usr/src/bk/linux-2.5

into dea.linux-mips.net:/home/ralf/src/ax25/linux-2.5
parents f8104ad8 6865a163
...@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd { ...@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd {
typedef struct actcapi_msg { typedef struct actcapi_msg {
actcapi_msghdr hdr; actcapi_msghdr hdr;
union msg { union {
__u16 manuf_msg; __u16 manuf_msg;
struct manufacturer_req_net { struct manufacturer_req_net {
__u16 manuf_msg; __u16 manuf_msg;
......
...@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info) ...@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags); save_flags(flags);
cli(); cli();
di = info->isdn_driver; di = isdn_slot_driver(info->isdn_slot);
ch = info->isdn_channel; ch = isdn_slot_channel(info->isdn_slot);
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2; dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags); restore_flags(flags);
...@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) ...@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags); save_flags(flags);
cli(); cli();
di = info->isdn_driver; di = isdn_slot_driver(info->isdn_slot);
ch = info->isdn_channel; ch = isdn_slot_channel(info->isdn_slot);
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2; dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags); restore_flags(flags);
......
...@@ -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"
...@@ -26,24 +27,31 @@ ...@@ -26,24 +27,31 @@
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
#include "isdn_audio.h" #include "isdn_audio.h"
#endif #endif
#ifdef CONFIG_ISDN_DIVERSION_MODULE
#define CONFIG_ISDN_DIVERSION
#endif
#ifdef CONFIG_ISDN_DIVERSION
#include <linux/isdn_divertif.h> #include <linux/isdn_divertif.h>
#endif /* CONFIG_ISDN_DIVERSION */
#include "isdn_v110.h" #include "isdn_v110.h"
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
/* Debugflags */
#undef ISDN_DEBUG_STATCALLB
MODULE_DESCRIPTION("ISDN4Linux: link layer"); MODULE_DESCRIPTION("ISDN4Linux: link layer");
MODULE_AUTHOR("Fritz Elfert"); MODULE_AUTHOR("Fritz Elfert");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
isdn_dev *dev; isdn_dev *dev;
struct isdn_slot {
int di; /* driver index */
int ch; /* channel index (per driver) */
int usage; /* how is it used */
char num[ISDN_MSNLEN]; /* the current phone number */
unsigned long ibytes; /* Statistics incoming bytes */
unsigned long obytes; /* Statistics outgoing bytes */
struct isdn_v110 iv110; /* For V.110 */
int m_idx; /* Index for mdm.... */
isdn_net_dev *rx_netdev; /* rx netdev-pointers */
isdn_net_dev *st_netdev; /* stat netdev-pointers */
};
static struct isdn_slot slot[ISDN_MAX_CHANNELS];
static char *isdn_revision = "$Revision: 1.114.6.16 $"; static char *isdn_revision = "$Revision: 1.114.6.16 $";
extern char *isdn_net_revision; extern char *isdn_net_revision;
...@@ -60,15 +68,18 @@ static char *isdn_audio_revision = ": none $"; ...@@ -60,15 +68,18 @@ static char *isdn_audio_revision = ": none $";
#endif #endif
extern char *isdn_v110_revision; extern char *isdn_v110_revision;
#ifdef CONFIG_ISDN_DIVERSION #if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
static isdn_divert_if *divert_if; /* = NULL */ static isdn_divert_if *divert_if; /* = NULL */
#endif /* CONFIG_ISDN_DIVERSION */ #else
#define divert_if ((isdn_divert_if *) NULL)
#endif
static void set_global_features(void); static void set_global_features(void);
static void isdn_register_devfs(int); static void isdn_register_devfs(int);
static void isdn_unregister_devfs(int); static void isdn_unregister_devfs(int);
static int isdn_wildmat(char *s, char *p); static int isdn_wildmat(char *s, char *p);
static int isdn_command(isdn_ctrl *cmd);
void void
isdn_lock_drivers(void) isdn_lock_drivers(void)
...@@ -230,12 +241,11 @@ isdn_dc2minor(int di, int ch) ...@@ -230,12 +241,11 @@ isdn_dc2minor(int di, int ch)
{ {
int i; int i;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (dev->chanmap[i] == ch && dev->drvmap[i] == di) if (slot[i].ch == ch && slot[i].di == di)
return i; return i;
return -1; return -1;
} }
static int isdn_timer_cnt1 = 0;
static int isdn_timer_cnt2 = 0; static int isdn_timer_cnt2 = 0;
static int isdn_timer_cnt3 = 0; static int isdn_timer_cnt3 = 0;
...@@ -252,11 +262,6 @@ isdn_timer_funct(ulong dummy) ...@@ -252,11 +262,6 @@ isdn_timer_funct(ulong dummy)
isdn_tty_modem_xmit(); isdn_tty_modem_xmit();
} }
if (tf & ISDN_TIMER_SLOW) { if (tf & ISDN_TIMER_SLOW) {
if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) {
isdn_timer_cnt1 = 0;
if (tf & ISDN_TIMER_NETDIAL)
isdn_net_dial();
}
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) if (tf & ISDN_TIMER_NETHANGUP)
...@@ -291,7 +296,6 @@ isdn_timer_ctrl(int tf, int onoff) ...@@ -291,7 +296,6 @@ isdn_timer_ctrl(int tf, int onoff)
cli(); cli();
if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) { if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
/* If the slow-timer wasn't activated until now */ /* If the slow-timer wasn't activated until now */
isdn_timer_cnt1 = 0;
isdn_timer_cnt2 = 0; isdn_timer_cnt2 = 0;
} }
old_tflags = dev->tflags; old_tflags = dev->tflags;
...@@ -317,7 +321,7 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb) ...@@ -317,7 +321,7 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
return; return;
} }
/* Update statistics */ /* Update statistics */
dev->ibytes[i] += skb->len; slot[i].ibytes += skb->len;
/* First, try to deliver data to network-device */ /* First, try to deliver data to network-device */
if (isdn_net_rcv_skb(i, skb)) if (isdn_net_rcv_skb(i, skb))
...@@ -327,10 +331,10 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb) ...@@ -327,10 +331,10 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
* makes sense for async streams only, so it is * makes sense for async streams only, so it is
* called after possible net-device delivery. * called after possible net-device delivery.
*/ */
if (dev->v110[i]) { if (slot[i].iv110.v110) {
atomic_inc(&dev->v110use[i]); atomic_inc(&slot[i].iv110.v110use);
skb = isdn_v110_decode(dev->v110[i], skb); skb = isdn_v110_decode(slot[i].iv110.v110, skb);
atomic_dec(&dev->v110use[i]); atomic_dec(&slot[i].iv110.v110use);
if (!skb) if (!skb)
return; return;
} }
...@@ -350,15 +354,16 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb) ...@@ -350,15 +354,16 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
* lowlevel-driver, use driver's transparent mode and handle V.110 in * lowlevel-driver, use driver's transparent mode and handle V.110 in
* linklevel instead. * linklevel instead.
*/ */
int static int
isdn_command(isdn_ctrl *cmd) isdn_command(isdn_ctrl *cmd)
{ {
int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
if (cmd->driver == -1) { if (cmd->driver == -1) {
printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command); printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
return(1); return(1);
} }
if (cmd->command == ISDN_CMD_SETL2) { if (cmd->command == ISDN_CMD_SETL2) {
int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
unsigned long l2prot = (cmd->arg >> 8) & 255; unsigned long l2prot = (cmd->arg >> 8) & 255;
unsigned long features = (dev->drv[cmd->driver]->interface->features unsigned long features = (dev->drv[cmd->driver]->interface->features
>> ISDN_FEATURE_L2_SHIFT) & >> ISDN_FEATURE_L2_SHIFT) &
...@@ -374,30 +379,38 @@ isdn_command(isdn_ctrl *cmd) ...@@ -374,30 +379,38 @@ isdn_command(isdn_ctrl *cmd)
* Layer-2 to transparent * Layer-2 to transparent
*/ */
if (!(features & l2_feature)) { if (!(features & l2_feature)) {
dev->v110emu[idx] = l2prot; slot[idx].iv110.v110emu = l2prot;
cmd->arg = (cmd->arg & 255) | cmd->arg = (cmd->arg & 255) |
(ISDN_PROTO_L2_TRANS << 8); (ISDN_PROTO_L2_TRANS << 8);
} else } else
dev->v110emu[idx] = 0; slot[idx].iv110.v110emu = 0;
} }
} }
#ifdef ISDN_DEBUG_COMMAND
switch (cmd->command) {
case ISDN_CMD_SETL2:
printk(KERN_DEBUG "ISDN_CMD_SETL2 %d\n", idx); break;
case ISDN_CMD_SETL3:
printk(KERN_DEBUG "ISDN_CMD_SETL3 %d\n", idx); break;
case ISDN_CMD_DIAL:
printk(KERN_DEBUG "ISDN_CMD_DIAL %d\n", idx); break;
case ISDN_CMD_ACCEPTD:
printk(KERN_DEBUG "ISDN_CMD_ACCEPTD %d\n", idx); break;
case ISDN_CMD_ACCEPTB:
printk(KERN_DEBUG "ISDN_CMD_ACCEPTB %d\n", idx); break;
case ISDN_CMD_HANGUP:
printk(KERN_DEBUG "ISDN_CMD_HANGUP %d\n", idx); break;
case ISDN_CMD_CLREAZ:
printk(KERN_DEBUG "ISDN_CMD_CLREAZ %d\n", idx); break;
case ISDN_CMD_SETEAZ:
printk(KERN_DEBUG "ISDN_CMD_SETEAZ %d\n", idx); break;
default:
printk(KERN_DEBUG "%s: cmd = %d\n", __FUNCTION__, cmd->command);
}
#endif
return dev->drv[cmd->driver]->interface->command(cmd); return dev->drv[cmd->driver]->interface->command(cmd);
} }
void
isdn_all_eaz(int di, int ch)
{
isdn_ctrl cmd;
if (di < 0)
return;
cmd.driver = di;
cmd.arg = ch;
cmd.command = ISDN_CMD_SETEAZ;
cmd.parm.num[0] = '\0';
isdn_command(&cmd);
}
/* /*
* Begin of a CAPI like LL<->HL interface, currently used only for * Begin of a CAPI like LL<->HL interface, currently used only for
* supplementary service (CAPI 2.0 part III) * supplementary service (CAPI 2.0 part III)
...@@ -430,7 +443,7 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -430,7 +443,7 @@ isdn_status_callback(isdn_ctrl * c)
int r; int r;
int retval = 0; int retval = 0;
isdn_ctrl cmd; isdn_ctrl cmd;
isdn_net_dev *p; struct list_head *l;
di = c->driver; di = c->driver;
i = isdn_dc2minor(di, c->arg); i = isdn_dc2minor(di, c->arg);
...@@ -442,7 +455,7 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -442,7 +455,7 @@ isdn_status_callback(isdn_ctrl * c)
return 0; 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(i, c)) if (isdn_v110_stat_callback(&slot[i].iv110, c))
return 0; return 0;
if (isdn_tty_stat_callback(i, c)) if (isdn_tty_stat_callback(i, c))
return 0; return 0;
...@@ -458,8 +471,8 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -458,8 +471,8 @@ isdn_status_callback(isdn_ctrl * c)
case ISDN_STAT_RUN: case ISDN_STAT_RUN:
dev->drv[di]->flags |= DRV_FLAG_RUNNING; dev->drv[di]->flags |= DRV_FLAG_RUNNING;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (dev->drvmap[i] == di) if (slot[i].di == di)
isdn_all_eaz(di, dev->chanmap[i]); isdn_slot_all_eaz(i);
set_global_features(); set_global_features();
break; break;
case ISDN_STAT_STOP: case ISDN_STAT_STOP:
...@@ -468,9 +481,7 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -468,9 +481,7 @@ isdn_status_callback(isdn_ctrl * c)
case ISDN_STAT_ICALL: case ISDN_STAT_ICALL:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("ICALL: %d (%d,%ld) %s\n", i, di, c->arg, c->parm.num);
printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED) { if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
cmd.driver = di; cmd.driver = di;
cmd.arg = c->arg; cmd.arg = c->arg;
...@@ -488,12 +499,10 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -488,12 +499,10 @@ isdn_status_callback(isdn_ctrl * c)
* 3 on eventually match, if CID is longer. * 3 on eventually match, if CID is longer.
*/ */
if (c->command == ISDN_STAT_ICALL) if (c->command == ISDN_STAT_ICALL)
if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval); if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval);
#ifdef CONFIG_ISDN_DIVERSION
if (divert_if) if (divert_if)
if ((retval = divert_if->stat_callback(c))) if ((retval = divert_if->stat_callback(c)))
return(retval); /* processed */ return(retval); /* processed */
#endif /* CONFIG_ISDN_DIVERSION */
if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) { if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
/* No tty responding */ /* No tty responding */
cmd.driver = di; cmd.driver = di;
...@@ -504,19 +513,15 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -504,19 +513,15 @@ isdn_status_callback(isdn_ctrl * c)
} }
break; break;
case 1: case 1:
/* Schedule connection-setup */ list_for_each(l, &isdn_net_devs) {
isdn_net_dial(); isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
cmd.driver = di; if (p->local.isdn_slot == i) {
cmd.arg = c->arg; strcpy(cmd.parm.setup.eazmsn, p->local.msn);
cmd.command = ISDN_CMD_ACCEPTD; isdn_slot_command(i, ISDN_CMD_ACCEPTD, &cmd);
for ( p = dev->netdev; p; p = p->next )
if ( p->local->isdn_channel == cmd.arg )
{
strcpy( cmd.parm.setup.eazmsn, p->local->msn );
isdn_command(&cmd);
retval = 1; retval = 1;
break; break;
} }
}
break; break;
case 2: /* For calling back, first reject incoming call ... */ case 2: /* For calling back, first reject incoming call ... */
...@@ -532,24 +537,19 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -532,24 +537,19 @@ isdn_status_callback(isdn_ctrl * c)
/* Fall through */ /* Fall through */
case 4: case 4:
/* ... then start callback. */ /* ... then start callback. */
isdn_net_dial();
break; break;
case 5: case 5:
/* Number would eventually match, if longer */ /* Number would eventually match, if longer */
retval = 3; retval = 3;
break; break;
} }
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("ICALL: ret=%d\n", retval);
printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
#endif
return retval; return retval;
break; break;
case ISDN_STAT_CINF: case ISDN_STAT_CINF:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("CINF: %d %s\n", i, c->parm.num);
printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; return 0;
if (strcmp(c->parm.num, "0")) if (strcmp(c->parm.num, "0"))
...@@ -557,39 +557,29 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -557,39 +557,29 @@ isdn_status_callback(isdn_ctrl * c)
isdn_tty_stat_callback(i, c); isdn_tty_stat_callback(i, c);
break; break;
case ISDN_STAT_CAUSE: case ISDN_STAT_CAUSE:
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("CAUSE: %d %s\n", i, c->parm.num);
printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
#endif
printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n", printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
dev->drvid[di], c->arg, c->parm.num); dev->drvid[di], c->arg, c->parm.num);
isdn_tty_stat_callback(i, c); isdn_tty_stat_callback(i, c);
#ifdef CONFIG_ISDN_DIVERSION
if (divert_if) if (divert_if)
divert_if->stat_callback(c); divert_if->stat_callback(c);
#endif /* CONFIG_ISDN_DIVERSION */
break; break;
case ISDN_STAT_DISPLAY: case ISDN_STAT_DISPLAY:
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("DISPLAY: %d %s\n", i, c->parm.display);
printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
#endif
isdn_tty_stat_callback(i, c); isdn_tty_stat_callback(i, c);
#ifdef CONFIG_ISDN_DIVERSION
if (divert_if) if (divert_if)
divert_if->stat_callback(c); divert_if->stat_callback(c);
#endif /* CONFIG_ISDN_DIVERSION */
break; break;
case ISDN_STAT_DCONN: case ISDN_STAT_DCONN:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("DCONN: %d\n", i);
printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; 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;
isdn_v110_stat_callback(i, c); isdn_v110_stat_callback(&slot[i].iv110, c);
/* Find any ttyI, waiting for D-channel setup */ /* Find any ttyI, waiting for D-channel setup */
if (isdn_tty_stat_callback(i, c)) { if (isdn_tty_stat_callback(i, c)) {
cmd.driver = di; cmd.driver = di;
...@@ -602,9 +592,7 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -602,9 +592,7 @@ isdn_status_callback(isdn_ctrl * c)
case ISDN_STAT_DHUP: case ISDN_STAT_DHUP:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("DHUP: %d\n", i);
printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; return 0;
dev->drv[di]->online &= ~(1 << (c->arg)); dev->drv[di]->online &= ~(1 << (c->arg));
...@@ -612,21 +600,16 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -612,21 +600,16 @@ isdn_status_callback(isdn_ctrl * c)
/* Signal hangup to network-devices */ /* Signal hangup to network-devices */
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
break; break;
isdn_v110_stat_callback(i, c); isdn_v110_stat_callback(&slot[i].iv110, c);
if (isdn_tty_stat_callback(i, c)) if (isdn_tty_stat_callback(i, c))
break; break;
#ifdef CONFIG_ISDN_DIVERSION
if (divert_if) if (divert_if)
divert_if->stat_callback(c); divert_if->stat_callback(c);
#endif /* CONFIG_ISDN_DIVERSION */
break;
break; break;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("BCONN: %ld\n", c->arg);
printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
#endif
/* Signal B-channel-connect to network-devices */ /* Signal B-channel-connect to network-devices */
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; return 0;
...@@ -634,16 +617,14 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -634,16 +617,14 @@ isdn_status_callback(isdn_ctrl * c)
isdn_info_update(); isdn_info_update();
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
break; break;
isdn_v110_stat_callback(i, c); isdn_v110_stat_callback(&slot[i].iv110, c);
if (isdn_tty_stat_callback(i, c)) if (isdn_tty_stat_callback(i, c))
break; break;
break; break;
case ISDN_STAT_BHUP: case ISDN_STAT_BHUP:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("BHUP: %d\n", i);
printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; return 0;
dev->drv[di]->online &= ~(1 << (c->arg)); dev->drv[di]->online &= ~(1 << (c->arg));
...@@ -653,16 +634,14 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -653,16 +634,14 @@ isdn_status_callback(isdn_ctrl * c)
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
break; break;
#endif #endif
isdn_v110_stat_callback(i, c); isdn_v110_stat_callback(&slot[i].iv110, c);
if (isdn_tty_stat_callback(i, c)) if (isdn_tty_stat_callback(i, c))
break; break;
break; break;
case ISDN_STAT_NODCH: case ISDN_STAT_NODCH:
if (i < 0) if (i < 0)
return -1; return -1;
#ifdef ISDN_DEBUG_STATCALLB dbg_statcallb("NODCH: %ld\n", c->arg);
printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; return 0;
if (isdn_net_stat_callback(i, c)) if (isdn_net_stat_callback(i, c))
...@@ -679,20 +658,17 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -679,20 +658,17 @@ isdn_status_callback(isdn_ctrl * c)
save_flags(flags); save_flags(flags);
cli(); cli();
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if ((dev->drvmap[i] == di) && if ((slot[i].di == di) &&
(dev->chanmap[i] == c->arg)) { (slot[i].ch == c->arg)) {
if (c->parm.num[0]) if (c->parm.num[0])
dev->usage[i] &= ~ISDN_USAGE_DISABLED; isdn_slot_set_usage(i, isdn_slot_usage(i) & ~ISDN_USAGE_DISABLED);
else else if (USG_NONE(isdn_slot_usage(i)))
if (USG_NONE(dev->usage[i])) { isdn_slot_set_usage(i, isdn_slot_usage(i) | ISDN_USAGE_DISABLED);
dev->usage[i] |= ISDN_USAGE_DISABLED; else
} retval = -1;
else break;
retval = -1;
break;
} }
restore_flags(flags); restore_flags(flags);
isdn_info_update();
break; break;
case ISDN_STAT_UNLOAD: case ISDN_STAT_UNLOAD:
while (dev->drv[di]->locks > 0) { while (dev->drv[di]->locks > 0) {
...@@ -707,10 +683,10 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -707,10 +683,10 @@ isdn_status_callback(isdn_ctrl * c)
cli(); cli();
isdn_tty_stat_callback(i, c); isdn_tty_stat_callback(i, c);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (dev->drvmap[i] == di) { if (slot[i].di == di) {
dev->drvmap[i] = -1; slot[i].di = -1;
dev->chanmap[i] = -1; slot[i].ch = -1;
dev->usage[i] &= ~ISDN_USAGE_DISABLED; slot[i].usage &= ~ISDN_USAGE_DISABLED;
isdn_unregister_devfs(i); isdn_unregister_devfs(i);
} }
dev->drivers--; dev->drivers--;
...@@ -742,12 +718,10 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -742,12 +718,10 @@ isdn_status_callback(isdn_ctrl * c)
isdn_tty_stat_callback(i, c); isdn_tty_stat_callback(i, c);
break; break;
#endif #endif
#ifdef CONFIG_ISDN_DIVERSION
case ISDN_STAT_PROT: case ISDN_STAT_PROT:
case ISDN_STAT_REDIR: case ISDN_STAT_REDIR:
if (divert_if) if (divert_if)
return(divert_if->stat_callback(c)); return(divert_if->stat_callback(c));
#endif /* CONFIG_ISDN_DIVERSION */
default: default:
return -1; return -1;
} }
...@@ -770,50 +744,40 @@ isdn_getnum(char **p) ...@@ -770,50 +744,40 @@ isdn_getnum(char **p)
#define DLE 0x10 #define DLE 0x10
/* /*
* isdn_readbchan() tries to get data from the read-queue. * isdn_slot_readbchan() tries to get data from the read-queue.
* It MUST be called with interrupts off. * It MUST be called with interrupts off.
*
* Be aware that this is not an atomic operation when sleep != 0, even though
* interrupts are turned off! Well, like that we are currently only called
* on behalf of a read system call on raw device files (which are documented
* to be dangerous and for for debugging purpose only). The inode semaphore
* takes care that this is not called for the same minor device number while
* we are sleeping, but access is not serialized against simultaneous read()
* from the corresponding ttyI device. Can other ugly events, like changes
* of the mapping (di,ch)<->minor, happen during the sleep? --he
*/ */
int int
isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) isdn_slot_readbchan(int sl, u_char * buf, u_char * fp, int len)
{ {
int count; int count;
int count_pull; int count_pull;
int count_put; int count_put;
int dflag; int dflag;
int di = isdn_slot_driver(sl);
int ch = isdn_slot_channel(sl);
struct sk_buff *skb; struct sk_buff *skb;
u_char *cp; u_char *cp;
if (!dev->drv[di]) if (!dev->drv[di])
return 0; return 0;
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) { if (skb_queue_empty(&dev->drv[di]->rpqueue[ch]))
if (sleep) return 0;
interruptible_sleep_on(sleep);
else if (len > dev->drv[di]->rcvcount[ch])
return 0; len = dev->drv[di]->rcvcount[ch];
}
if (len > dev->drv[di]->rcvcount[channel])
len = dev->drv[di]->rcvcount[channel];
cp = buf; cp = buf;
count = 0; count = 0;
while (len) { while (len) {
if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel]))) if (!(skb = skb_peek(&dev->drv[di]->rpqueue[ch])))
break; break;
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
if (ISDN_AUDIO_SKB_LOCK(skb)) if (ISDN_AUDIO_SKB_LOCK(skb))
break; break;
ISDN_AUDIO_SKB_LOCK(skb) = 1; ISDN_AUDIO_SKB_LOCK(skb) = 1;
if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) { if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << ch))) {
char *p = skb->data; char *p = skb->data;
unsigned long DLEmask = (1 << channel); unsigned long DLEmask = (1 << ch);
dflag = 0; dflag = 0;
count_pull = count_put = 0; count_pull = count_put = 0;
...@@ -864,7 +828,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que ...@@ -864,7 +828,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
#endif #endif
skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]); skb = skb_dequeue(&dev->drv[di]->rpqueue[ch]);
dev_kfree_skb(skb); dev_kfree_skb(skb);
} else { } else {
/* Not yet emptied this buff, so it /* Not yet emptied this buff, so it
...@@ -876,7 +840,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que ...@@ -876,7 +840,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
#endif #endif
} }
dev->drv[di]->rcvcount[channel] -= count_put; dev->drv[di]->rcvcount[ch] -= count_put;
} }
return count; return count;
} }
...@@ -884,13 +848,13 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que ...@@ -884,13 +848,13 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
static __inline int static __inline int
isdn_minor2drv(int minor) isdn_minor2drv(int minor)
{ {
return (dev->drvmap[minor]); return slot[minor].di;
} }
static __inline int static __inline int
isdn_minor2chan(int minor) isdn_minor2chan(int minor)
{ {
return (dev->chanmap[minor]); return slot[minor].ch;
} }
static char * static char *
...@@ -903,25 +867,25 @@ isdn_statstr(void) ...@@ -903,25 +867,25 @@ isdn_statstr(void)
sprintf(istatbuf, "idmap:\t"); sprintf(istatbuf, "idmap:\t");
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]); sprintf(p, "%s ", (slot[i].di < 0) ? "-" : dev->drvid[slot[i].di]);
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
} }
sprintf(p, "\nchmap:\t"); sprintf(p, "\nchmap:\t");
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
sprintf(p, "%d ", dev->chanmap[i]); sprintf(p, "%d ", slot[i].ch);
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
} }
sprintf(p, "\ndrmap:\t"); sprintf(p, "\ndrmap:\t");
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
sprintf(p, "%d ", dev->drvmap[i]); sprintf(p, "%d ", slot[i].di);
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
} }
sprintf(p, "\nusage:\t"); sprintf(p, "\nusage:\t");
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
sprintf(p, "%d ", dev->usage[i]); sprintf(p, "%d ", slot[i].usage);
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
} }
sprintf(p, "\nflags:\t"); sprintf(p, "\nflags:\t");
...@@ -938,7 +902,7 @@ isdn_statstr(void) ...@@ -938,7 +902,7 @@ isdn_statstr(void)
sprintf(p, "\nphone:\t"); sprintf(p, "\nphone:\t");
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
sprintf(p, "%s ", dev->num[i]); sprintf(p, "%s ", isdn_slot_num(i));
p = istatbuf + strlen(istatbuf); p = istatbuf + strlen(istatbuf);
} }
sprintf(p, "\n"); sprintf(p, "\n");
...@@ -1095,8 +1059,8 @@ isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1095,8 +1059,8 @@ isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
sizeof(ulong) * ISDN_MAX_CHANNELS * 2))) sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
return ret; return ret;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
put_user(dev->ibytes[i], p++); put_user(slot[i].ibytes, p++);
put_user(dev->obytes[i], p++); put_user(slot[i].obytes, p++);
} }
return 0; return 0;
} else } else
...@@ -1279,10 +1243,9 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1279,10 +1243,9 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int ret; int ret;
int i; int i;
char *p; char *p;
char *s;
union iocpar { union iocpar {
char name[10]; char name[10];
char bname[22]; char bname[20];
isdn_ioctl_struct iocts; isdn_ioctl_struct iocts;
isdn_net_ioctl_phone phone; isdn_net_ioctl_phone phone;
isdn_net_ioctl_cfg cfg; isdn_net_ioctl_cfg cfg;
...@@ -1310,42 +1273,24 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1310,42 +1273,24 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
#ifdef CONFIG_NETDEVICES #ifdef CONFIG_NETDEVICES
case IIOCNETAIF: case IIOCNETAIF:
/* Add a network-interface */ /* Add a network-interface */
if (arg) { if (copy_from_user(name, (char *) arg, sizeof(name) - 1))
if (copy_from_user(name, (char *) arg, sizeof(name))) return -EFAULT;
return -EFAULT; name[sizeof(name)-1] = 0;
s = name;
} else {
s = NULL;
}
ret = down_interruptible(&dev->sem); ret = down_interruptible(&dev->sem);
if( ret ) return ret; if (ret)
if ((s = isdn_net_new(s, NULL))) { return ret;
if (copy_to_user((char *) arg, s, strlen(s) + 1)){ ret = isdn_net_new(name, NULL);
ret = -EFAULT;
} else {
ret = 0;
}
} else
ret = -ENODEV;
up(&dev->sem); up(&dev->sem);
return ret; return ret;
case IIOCNETASL: case IIOCNETASL:
/* Add a slave to a network-interface */ /* Add a slave to a network-interface */
if (arg) { if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1)) return -EFAULT;
return -EFAULT; bname[sizeof(bname)-1] = 0;
} else
return -EINVAL;
ret = down_interruptible(&dev->sem); ret = down_interruptible(&dev->sem);
if( ret ) return ret; if (ret)
if ((s = isdn_net_newslave(bname))) { return ret;
if (copy_to_user((char *) arg, s, strlen(s) + 1)){ ret = isdn_net_newslave(bname);
ret = -EFAULT;
} else {
ret = 0;
}
} else
ret = -ENODEV;
up(&dev->sem); up(&dev->sem);
return ret; return ret;
case IIOCNETDIF: case IIOCNETDIF:
...@@ -1742,8 +1687,8 @@ isdn_map_eaz2msn(char *msn, int di) ...@@ -1742,8 +1687,8 @@ isdn_map_eaz2msn(char *msn, int di)
#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038)) #define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
int int
isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
,int pre_chan, char *msn) int pre_dev, int pre_chan, char *msn)
{ {
int i; int i;
ulong flags; ulong flags;
...@@ -1760,34 +1705,28 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev ...@@ -1760,34 +1705,28 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
* because we can emulate this in linklevel. * because we can emulate this in linklevel.
*/ */
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (USG_NONE(dev->usage[i]) && if (USG_NONE(slot[i].usage) &&
(dev->drvmap[i] != -1)) { (slot[i].di != -1)) {
int d = dev->drvmap[i]; int d = slot[i].di;
if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) && if ((slot[i].usage & ISDN_USAGE_EXCLUSIVE) &&
((pre_dev != d) || (pre_chan != dev->chanmap[i]))) ((pre_dev != d) || (pre_chan != slot[i].ch)))
continue; continue;
if (!strcmp(isdn_map_eaz2msn(msn, d), "-")) if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
continue; continue;
if (dev->usage[i] & ISDN_USAGE_DISABLED) if (slot[i].usage & ISDN_USAGE_DISABLED)
continue; /* usage not allowed */ continue; /* usage not allowed */
if (dev->drv[d]->flags & DRV_FLAG_RUNNING) { if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
if (((dev->drv[d]->interface->features & features) == features) || if (((dev->drv[d]->interface->features & features) == features) ||
(((dev->drv[d]->interface->features & vfeatures) == vfeatures) && (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
(dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) { (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
if ((pre_dev < 0) || (pre_chan < 0)) { if ((pre_dev < 0) || (pre_chan < 0)) {
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE; isdn_slot_set_usage(i, (isdn_slot_usage(i) & ISDN_USAGE_EXCLUSIVE) | usage);
dev->usage[i] |= usage; restore_flags(flags);
isdn_info_update(); return i;
} else if ((pre_dev == d) && (pre_chan == slot[i].ch)) {
isdn_slot_set_usage(i, (isdn_slot_usage(i) & ISDN_USAGE_EXCLUSIVE) | usage);
restore_flags(flags); restore_flags(flags);
return i; return i;
} else {
if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
restore_flags(flags);
return i;
}
} }
} }
} }
...@@ -1802,28 +1741,32 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev ...@@ -1802,28 +1741,32 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
void void
isdn_free_channel(int di, int ch, int usage) isdn_free_channel(int di, int ch, int usage)
{ {
int i; int sl;
ulong flags;
sl = isdn_dc2minor(di, ch);
isdn_slot_free(sl, usage);
}
void
isdn_slot_free(int sl, int usage)
{
unsigned long flags;
save_flags(flags); save_flags(flags);
cli(); cli();
for (i = 0; i < ISDN_MAX_CHANNELS; i++) if (!usage || (slot[sl].usage & ISDN_USAGE_MASK) == usage) {
if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) && strcpy(isdn_slot_num(sl), "???");
(dev->drvmap[i] == di) && slot[sl].ibytes = 0;
(dev->chanmap[i] == ch)) { slot[sl].obytes = 0;
dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
strcpy(dev->num[i], "???");
dev->ibytes[i] = 0;
dev->obytes[i] = 0;
// 20.10.99 JIM, try to reinitialize v110 ! // 20.10.99 JIM, try to reinitialize v110 !
dev->v110emu[i] = 0; slot[sl].iv110.v110emu = 0;
atomic_set(&(dev->v110use[i]), 0); atomic_set(&slot[sl].iv110.v110use, 0);
isdn_v110_close(dev->v110[i]); isdn_v110_close(slot[sl].iv110.v110);
dev->v110[i] = NULL; slot[sl].iv110.v110 = NULL;
// 20.10.99 JIM, try to reinitialize v110 ! // 20.10.99 JIM, try to reinitialize v110 !
isdn_info_update(); isdn_slot_set_usage(sl, isdn_slot_usage(sl) & (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE));
skb_queue_purge(&dev->drv[di]->rpqueue[ch]); skb_queue_purge(&dev->drv[isdn_slot_driver(sl)]->rpqueue[isdn_slot_channel(sl)]);
} }
restore_flags(flags); restore_flags(flags);
} }
...@@ -1839,10 +1782,9 @@ isdn_unexclusive_channel(int di, int ch) ...@@ -1839,10 +1782,9 @@ isdn_unexclusive_channel(int di, int ch)
save_flags(flags); save_flags(flags);
cli(); cli();
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if ((dev->drvmap[i] == di) && if ((slot[i].di == di) &&
(dev->chanmap[i] == ch)) { (slot[i].ch == ch)) {
dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE; isdn_slot_set_usage(i, isdn_slot_usage(i) & ~ISDN_USAGE_EXCLUSIVE);
isdn_info_update();
restore_flags(flags); restore_flags(flags);
return; return;
} }
...@@ -1853,17 +1795,20 @@ isdn_unexclusive_channel(int di, int ch) ...@@ -1853,17 +1795,20 @@ isdn_unexclusive_channel(int di, int ch)
* Return: length of data on success, -ERRcode on failure. * Return: length of data on success, -ERRcode on failure.
*/ */
int int
isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) isdn_slot_write(int sl, struct sk_buff *skb)
{ {
int ret; int ret;
struct sk_buff *nskb = NULL; struct sk_buff *nskb = NULL;
int v110_ret = skb->len; int v110_ret = skb->len;
int idx = isdn_dc2minor(drvidx, chan); int di = isdn_slot_driver(sl);
int ch = isdn_slot_channel(sl);
BUG_ON(sl < 0);
if (dev->v110[idx]) { if (slot[sl].iv110.v110) {
atomic_inc(&dev->v110use[idx]); atomic_inc(&slot[sl].iv110.v110use);
nskb = isdn_v110_encode(dev->v110[idx], skb); nskb = isdn_v110_encode(slot[sl].iv110.v110, skb);
atomic_dec(&dev->v110use[idx]); atomic_dec(&slot[sl].iv110.v110use);
if (!nskb) if (!nskb)
return 0; return 0;
v110_ret = *((int *)nskb->data); v110_ret = *((int *)nskb->data);
...@@ -1873,10 +1818,9 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) ...@@ -1873,10 +1818,9 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
return v110_ret; return v110_ret;
} }
/* V.110 must always be acknowledged */ /* V.110 must always be acknowledged */
ack = 1; ret = dev->drv[di]->interface->writebuf_skb(di, ch, 1, nskb);
ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
} else { } else {
int hl = dev->drv[drvidx]->interface->hl_hdrlen; int hl = isdn_slot_hdrlen(sl);
if( skb_headroom(skb) < hl ){ if( skb_headroom(skb) < hl ){
/* /*
...@@ -1892,22 +1836,22 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) ...@@ -1892,22 +1836,22 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
skb_tmp = skb_realloc_headroom(skb, hl); skb_tmp = skb_realloc_headroom(skb, hl);
printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed"); printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
if (!skb_tmp) return -ENOMEM; /* 0 better? */ if (!skb_tmp) return -ENOMEM; /* 0 better? */
ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp); ret = dev->drv[di]->interface->writebuf_skb(di, ch, 1, skb_tmp);
if( ret > 0 ){ if( ret > 0 ){
dev_kfree_skb(skb); dev_kfree_skb(skb);
} else { } else {
dev_kfree_skb(skb_tmp); dev_kfree_skb(skb_tmp);
} }
} else { } else {
ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); ret = dev->drv[di]->interface->writebuf_skb(di, ch, 1, skb);
} }
} }
if (ret > 0) { if (ret > 0) {
dev->obytes[idx] += ret; slot[sl].obytes += ret;
if (dev->v110[idx]) { if (slot[sl].iv110.v110) {
atomic_inc(&dev->v110use[idx]); atomic_inc(&slot[sl].iv110.v110use);
dev->v110[idx]->skbuser++; slot[sl].iv110.v110->skbuser++;
atomic_dec(&dev->v110use[idx]); atomic_dec(&slot[sl].iv110.v110use);
/* For V.110 return unencoded data length */ /* For V.110 return unencoded data length */
ret = v110_ret; ret = v110_ret;
/* if the complete frame was send we free the skb; /* if the complete frame was send we free the skb;
...@@ -1916,7 +1860,7 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) ...@@ -1916,7 +1860,7 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
} else } else
if (dev->v110[idx]) if (slot[sl].iv110.v110)
dev_kfree_skb(nskb); dev_kfree_skb(nskb);
return ret; return ret;
} }
...@@ -1997,9 +1941,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) ...@@ -1997,9 +1941,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
cli(); cli();
for (j = d->channels; j < m; j++) for (j = d->channels; j < m; j++)
for (k = 0; k < ISDN_MAX_CHANNELS; k++) for (k = 0; k < ISDN_MAX_CHANNELS; k++)
if (dev->chanmap[k] < 0) { if (slot[k].ch < 0) {
dev->chanmap[k] = j; slot[k].ch = j;
dev->drvmap[k] = drvidx; slot[k].di = drvidx;
isdn_register_devfs(k); isdn_register_devfs(k);
break; break;
} }
...@@ -2026,7 +1970,7 @@ set_global_features(void) ...@@ -2026,7 +1970,7 @@ set_global_features(void)
} }
} }
#ifdef CONFIG_ISDN_DIVERSION #if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
static char *map_drvname(int di) static char *map_drvname(int di)
{ {
...@@ -2075,7 +2019,7 @@ int DIVERT_REG_NAME(isdn_divert_if *i_div) ...@@ -2075,7 +2019,7 @@ int DIVERT_REG_NAME(isdn_divert_if *i_div)
EXPORT_SYMBOL(DIVERT_REG_NAME); EXPORT_SYMBOL(DIVERT_REG_NAME);
#endif /* CONFIG_ISDN_DIVERSION */ #endif
EXPORT_SYMBOL(register_isdn); EXPORT_SYMBOL(register_isdn);
...@@ -2140,6 +2084,186 @@ register_isdn(isdn_if * i) ...@@ -2140,6 +2084,186 @@ register_isdn(isdn_if * i)
return 1; return 1;
} }
int
isdn_slot_driver(int sl)
{
BUG_ON(sl < 0);
return slot[sl].di;
}
int
isdn_slot_channel(int sl)
{
BUG_ON(sl < 0);
return slot[sl].ch;
}
int
isdn_slot_hdrlen(int sl)
{
int di = isdn_slot_driver(sl);
return dev->drv[di]->interface->hl_hdrlen;
}
char *
isdn_slot_map_eaz2msn(int sl, char *msn)
{
int di = isdn_slot_driver(sl);
return isdn_map_eaz2msn(msn, di);
}
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;
default:
ctrl->arg = isdn_slot_channel(sl);
break;
}
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
isdn_slot_all_eaz(int sl)
{
isdn_ctrl cmd;
cmd.parm.num[0] = '\0';
isdn_slot_command(sl, ISDN_CMD_SETEAZ, &cmd);
}
int
isdn_slot_usage(int sl)
{
BUG_ON(sl < 0);
return slot[sl].usage;
}
void
isdn_slot_set_usage(int sl, int usage)
{
BUG_ON(sl < 0);
slot[sl].usage = usage;
isdn_info_update();
}
int
isdn_slot_m_idx(int sl)
{
BUG_ON(sl < 0);
return slot[sl].m_idx;
}
void
isdn_slot_set_m_idx(int sl, int midx)
{
BUG_ON(sl < 0);
slot[sl].m_idx = midx;
}
char *
isdn_slot_num(int sl)
{
BUG_ON(sl < 0);
return slot[sl].num;
}
void
isdn_slot_set_rx_netdev(int sl, isdn_net_dev *nd)
{
BUG_ON(sl < 0);
slot[sl].rx_netdev = nd;
}
isdn_net_dev *
isdn_slot_rx_netdev(int sl)
{
BUG_ON(sl < 0);
return slot[sl].rx_netdev;
}
void
isdn_slot_set_st_netdev(int sl, isdn_net_dev *nd)
{
BUG_ON(sl < 0);
slot[sl].st_netdev = nd;
}
isdn_net_dev *
isdn_slot_st_netdev(int sl)
{
BUG_ON(sl < 0);
return slot[sl].st_netdev;
}
/* /*
***************************************************************************** *****************************************************************************
* And now the modules code. * And now the modules code.
...@@ -2247,53 +2371,43 @@ static void isdn_cleanup_devfs(void) ...@@ -2247,53 +2371,43 @@ static void isdn_cleanup_devfs(void)
static int __init isdn_init(void) static int __init isdn_init(void)
{ {
int i; int i;
int retval;
char tmprev[50]; char tmprev[50];
if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) { dev = vmalloc(sizeof(*dev));
printk(KERN_WARNING "isdn: Could not allocate device-struct.\n"); if (!dev) {
return -EIO; retval = -ENOMEM;
goto err;
} }
memset((char *) dev, 0, sizeof(isdn_dev)); memset(dev, 0, sizeof(*dev));
init_timer(&dev->timer); init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct; dev->timer.function = isdn_timer_funct;
init_MUTEX(&dev->sem); init_MUTEX(&dev->sem);
init_waitqueue_head(&dev->info_waitq); init_waitqueue_head(&dev->info_waitq);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
dev->drvmap[i] = -1; slot[i].di = -1;
dev->chanmap[i] = -1; slot[i].ch = -1;
dev->m_idx[i] = -1; slot[i].m_idx = -1;
strcpy(dev->num[i], "???"); strcpy(isdn_slot_num(i), "???");
init_waitqueue_head(&dev->mdm.info[i].open_wait); init_waitqueue_head(&dev->mdm.info[i].open_wait);
init_waitqueue_head(&dev->mdm.info[i].close_wait); init_waitqueue_head(&dev->mdm.info[i].close_wait);
} }
if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops);
if (retval) {
printk(KERN_WARNING "isdn: Could not register control devices\n"); printk(KERN_WARNING "isdn: Could not register control devices\n");
vfree(dev); goto err_vfree;
return -EIO;
} }
isdn_init_devfs(); isdn_init_devfs();
if ((i = isdn_tty_modem_init()) < 0) { retval = isdn_tty_init();
if (retval < 0) {
printk(KERN_WARNING "isdn: Could not register tty devices\n"); printk(KERN_WARNING "isdn: Could not register tty devices\n");
if (i == -3) goto err_cleanup_devfs;
tty_unregister_driver(&dev->mdm.cua_modem);
if (i <= -2)
tty_unregister_driver(&dev->mdm.tty_modem);
vfree(dev);
isdn_cleanup_devfs();
unregister_chrdev(ISDN_MAJOR, "isdn");
return -EIO;
} }
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
if (isdn_ppp_init() < 0) { retval = isdn_ppp_init();
if (retval < 0) {
printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n"); printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
tty_unregister_driver(&dev->mdm.tty_modem); goto err_tty_modem;
tty_unregister_driver(&dev->mdm.cua_modem);
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
kfree(dev->mdm.info[i].xmit_buf - 4);
isdn_cleanup_devfs();
unregister_chrdev(ISDN_MAJOR, "isdn");
vfree(dev);
return -EIO;
} }
#endif /* CONFIG_ISDN_PPP */ #endif /* CONFIG_ISDN_PPP */
...@@ -2317,6 +2431,16 @@ static int __init isdn_init(void) ...@@ -2317,6 +2431,16 @@ static int __init isdn_init(void)
#endif #endif
isdn_info_update(); isdn_info_update();
return 0; return 0;
err_tty_modem:
isdn_tty_exit();
err_cleanup_devfs:
isdn_cleanup_devfs();
unregister_chrdev(ISDN_MAJOR, "isdn");
err_vfree:
vfree(dev);
err:
return retval;
} }
/* /*
...@@ -2325,46 +2449,24 @@ static int __init isdn_init(void) ...@@ -2325,46 +2449,24 @@ static int __init isdn_init(void)
static void __exit isdn_exit(void) static void __exit isdn_exit(void)
{ {
unsigned long flags; unsigned long flags;
int i;
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
isdn_ppp_cleanup(); isdn_ppp_cleanup();
#endif #endif
save_flags(flags); save_flags(flags);
cli(); cli();
if (isdn_net_rmall() < 0) { if (isdn_net_rmall() < 0)
printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n"); BUG();
restore_flags(flags);
return; isdn_tty_exit();
} if (unregister_chrdev(ISDN_MAJOR, "isdn"))
if (tty_unregister_driver(&dev->mdm.tty_modem)) { BUG();
printk(KERN_WARNING "isdn: ttyI-device busy, remove cancelled\n");
restore_flags(flags); isdn_cleanup_devfs();
return; del_timer(&dev->timer);
} restore_flags(flags);
if (tty_unregister_driver(&dev->mdm.cua_modem)) { /* call vfree with interrupts enabled, else it will hang */
printk(KERN_WARNING "isdn: cui-device busy, remove cancelled\n"); vfree(dev);
restore_flags(flags);
return;
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
isdn_tty_cleanup_xmit(&dev->mdm.info[i]);
kfree(dev->mdm.info[i].xmit_buf - 4);
#ifdef CONFIG_ISDN_TTY_FAX
kfree(dev->mdm.info[i].fax);
#endif
}
if (unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
restore_flags(flags);
} else {
isdn_cleanup_devfs();
del_timer(&dev->timer);
restore_flags(flags);
/* call vfree with interrupts enabled, else it will hang */
vfree(dev);
printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
}
} }
module_init(isdn_init); module_init(isdn_init);
......
...@@ -23,6 +23,32 @@ ...@@ -23,6 +23,32 @@
#undef ISDN_DEBUG_NET_DUMP #undef ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DIAL #undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL #undef ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_STATCALLB
#undef ISDN_DEBUG_COMMAND
#ifdef ISDN_DEBUG_NET_DIAL
#define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_dial(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_NET_ICALL
#define dbg_net_icall(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_icall(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_STATCALLB
#define dbg_statcallb(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_statcallb(arg...) do {} while (0)
#endif
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
/* Prototypes */ /* Prototypes */
extern void isdn_MOD_INC_USE_COUNT(void); extern void isdn_MOD_INC_USE_COUNT(void);
...@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void); ...@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void);
extern void isdn_lock_drivers(void); extern void isdn_lock_drivers(void);
extern void isdn_unlock_drivers(void); extern void isdn_unlock_drivers(void);
extern void isdn_free_channel(int di, int ch, int usage); extern void isdn_free_channel(int di, int ch, int usage);
extern void isdn_all_eaz(int di, int ch);
extern int isdn_command(isdn_ctrl *);
extern int isdn_dc2minor(int di, int ch); extern int isdn_dc2minor(int di, int ch);
extern void isdn_info_update(void); extern void isdn_info_update(void);
extern char *isdn_map_eaz2msn(char *msn, int di); extern char *isdn_map_eaz2msn(char *msn, int di);
extern void isdn_timer_ctrl(int tf, int onoff); extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch); extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **); extern int isdn_getnum(char **);
extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
extern int isdn_msncmp( const char *, const char *); extern int isdn_msncmp( const char *, const char *);
extern int isdn_add_channels(driver *, int, int, int); extern int isdn_add_channels(driver *, int, int, int);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern void isdn_dumppkt(char *, u_char *, int, int); extern void isdn_dumppkt(char *, u_char *, int, int);
#else
static inline void isdn_dumppkt(char *s, u_char *d, int l, int m) { }
#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 struct list_head isdn_net_devs;
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_all_eaz(int slot);
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 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_hdrlen(int slot);
extern int isdn_slot_driver(int slot);
extern int isdn_slot_channel(int slot);
extern int isdn_slot_usage(int slot);
extern void isdn_slot_set_usage(int slot, int usage);
extern char *isdn_slot_num(int slot);
extern int isdn_slot_m_idx(int slot);
extern void isdn_slot_set_m_idx(int slot, int midx);
extern void isdn_slot_set_rx_netdev(int sl, isdn_net_dev *nd);
extern void isdn_slot_set_st_netdev(int sl, isdn_net_dev *nd);
extern isdn_net_dev *isdn_slot_rx_netdev(int sl);
extern isdn_net_dev *isdn_slot_st_netdev(int sl);
...@@ -38,6 +38,27 @@ ...@@ -38,6 +38,27 @@
#include "isdn_concap.h" #include "isdn_concap.h"
#endif #endif
enum {
ST_NULL,
ST_OUT_WAIT_DCONN,
ST_OUT_WAIT_BCONN,
ST_IN_WAIT_DCONN,
ST_IN_WAIT_BCONN,
ST_ACTIVE,
ST_WAIT_BEFORE_CB,
};
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */
enum {
EV_NET_DIAL = 0x200,
EV_NET_TIMER_IN_DCONN = 0x201,
EV_NET_TIMER_IN_BCONN = 0x202,
EV_NET_TIMER_OUT_DCONN = 0x203,
EV_NET_TIMER_OUT_BCONN = 0x204,
EV_NET_TIMER_CB = 0x205,
};
LIST_HEAD(isdn_net_devs); /* Linked list of isdn_net_dev's */
/* /*
* Outline of new tbusy handling: * Outline of new tbusy handling:
...@@ -72,7 +93,7 @@ ...@@ -72,7 +93,7 @@
*/ */
static __inline__ int isdn_net_device_started(isdn_net_dev *n) static __inline__ int isdn_net_device_started(isdn_net_dev *n)
{ {
isdn_net_local *lp = n->local; isdn_net_local *lp = &n->local;
struct net_device *dev; struct net_device *dev;
if (lp->master) if (lp->master)
...@@ -179,10 +200,13 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp) ...@@ -179,10 +200,13 @@ 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 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);
static int isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg);
char *isdn_net_revision = "$Revision: 1.140.6.11 $"; char *isdn_net_revision = "$Revision: 1.140.6.11 $";
/* /*
...@@ -280,10 +304,9 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx) ...@@ -280,10 +304,9 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx)
save_flags(flags); save_flags(flags);
cli(); cli();
lp->flags |= ISDN_NET_CONNECTED; lp->flags |= ISDN_NET_CONNECTED;
lp->isdn_device = dev->drvmap[idx]; lp->isdn_slot = idx;
lp->isdn_channel = dev->chanmap[idx]; isdn_slot_set_rx_netdev(lp->isdn_slot, lp->netdev);
dev->rx_netdev[idx] = lp->netdev; isdn_slot_set_st_netdev(lp->isdn_slot, lp->netdev);
dev->st_netdev[idx] = lp->netdev;
restore_flags(flags); restore_flags(flags);
} }
...@@ -306,13 +329,14 @@ isdn_net_unbind_channel(isdn_net_local * lp) ...@@ -306,13 +329,14 @@ isdn_net_unbind_channel(isdn_net_local * lp)
*/ */
qdisc_reset(lp->netdev->dev.qdisc); qdisc_reset(lp->netdev->dev.qdisc);
} }
lp->dialstate = 0; lp->dialstate = ST_NULL;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; if (lp->isdn_slot >= 0) {
dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; isdn_slot_set_rx_netdev(lp->isdn_slot, NULL);
isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET); isdn_slot_set_st_netdev(lp->isdn_slot, NULL);
isdn_slot_free(lp->isdn_slot, ISDN_USAGE_NET);
}
lp->flags &= ~ISDN_NET_CONNECTED; lp->flags &= ~ISDN_NET_CONNECTED;
lp->isdn_device = -1; lp->isdn_slot = -1;
lp->isdn_channel = -1;
restore_flags(flags); restore_flags(flags);
} }
...@@ -335,12 +359,13 @@ unsigned long last_jiffies = -HZ; ...@@ -335,12 +359,13 @@ unsigned long last_jiffies = -HZ;
void void
isdn_net_autohup() isdn_net_autohup()
{ {
isdn_net_dev *p = dev->netdev; struct list_head *l;
int anymore; int anymore;
anymore = 0; anymore = 0;
while (p) { list_for_each(l, &isdn_net_devs) {
isdn_net_local *l = p->local; isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *l = &p->local;
if (jiffies == last_jiffies) if (jiffies == last_jiffies)
l->cps = l->transcount; l->cps = l->transcount;
else else
...@@ -348,9 +373,10 @@ isdn_net_autohup() ...@@ -348,9 +373,10 @@ isdn_net_autohup()
l->transcount = 0; l->transcount = 0;
if (dev->net_verbose > 3) if (dev->net_verbose > 3)
printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps); printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) { if ((l->flags & ISDN_NET_CONNECTED) && (l->dialstate == ST_ACTIVE)) {
anymore = 1; anymore = 1;
l->huptimer++; l->huptimer++;
printk("huptimer %d, onhtime %d, chargetime %d, chargeint %d\n", l->huptimer, l->onhtime, l->chargetime, l->chargeint);
/* /*
* if there is some dialmode where timeout-hangup * if there is some dialmode where timeout-hangup
* should _not_ be done, check for that here * should _not_ be done, check for that here
...@@ -363,8 +389,10 @@ isdn_net_autohup() ...@@ -363,8 +389,10 @@ isdn_net_autohup()
while (time_after(jiffies, l->chargetime + l->chargeint)) while (time_after(jiffies, l->chargetime + l->chargeint))
l->chargetime += l->chargeint; l->chargetime += l->chargeint;
if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ)) if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
if (l->outgoing || l->hupflags & ISDN_INHUP) if (l->outgoing || l->hupflags & ISDN_INHUP) {
HERE;
isdn_net_hangup(&p->dev); isdn_net_hangup(&p->dev);
}
} else if (l->outgoing) { } else if (l->outgoing) {
if (l->hupflags & ISDN_CHARGEHUP) { if (l->hupflags & ISDN_CHARGEHUP) {
if (l->hupflags & ISDN_WAITCHARGE) { if (l->hupflags & ISDN_WAITCHARGE) {
...@@ -378,8 +406,10 @@ isdn_net_autohup() ...@@ -378,8 +406,10 @@ isdn_net_autohup()
isdn_net_hangup(&p->dev); isdn_net_hangup(&p->dev);
} }
} }
} else if (l->hupflags & ISDN_INHUP) } else if (l->hupflags & ISDN_INHUP) {
HERE;
isdn_net_hangup(&p->dev); isdn_net_hangup(&p->dev);
}
} }
if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) { if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
...@@ -387,7 +417,6 @@ isdn_net_autohup() ...@@ -387,7 +417,6 @@ isdn_net_autohup()
break; break;
} }
} }
p = (isdn_net_dev *) p->next;
} }
last_jiffies = jiffies; last_jiffies = jiffies;
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore); isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
...@@ -398,6 +427,47 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp) ...@@ -398,6 +427,47 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
isdn_net_rm_from_bundle(lp); isdn_net_rm_from_bundle(lp);
} }
static void isdn_net_connected(isdn_net_local *lp)
{
#ifdef CONFIG_ISDN_X25
struct concap_proto *cprot = lp -> netdev -> cprot;
struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
#endif
lp->dialstate = ST_ACTIVE;
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
isdn_net_ciscohdlck_connected(lp);
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
if (lp->master) { /* is lp a slave? */
isdn_net_dev *nd = ((isdn_net_local *)lp->master->priv)->netdev;
isdn_net_add_to_bundle(nd, lp);
}
}
printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
lp->chargetime = jiffies;
/* reset dial-timeout */
lp->dialstarted = 0;
lp->dialwait_timer = 0;
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_wakeup_daemon(lp);
#endif
#ifdef CONFIG_ISDN_X25
/* try if there are generic concap receiver routines */
if( pops )
if( pops->connect_ind)
pops->connect_ind(cprot);
#endif /* CONFIG_ISDN_X25 */
/* ppp needs to do negotiations first */
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
isdn_net_device_wake_queue(lp);
}
/* /*
* Handle status-messages from ISDN-interfacecard. * Handle status-messages from ISDN-interfacecard.
* This function is called from within the main-status-dispatcher * This function is called from within the main-status-dispatcher
...@@ -407,443 +477,343 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp) ...@@ -407,443 +477,343 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
int int
isdn_net_stat_callback(int idx, isdn_ctrl *c) isdn_net_stat_callback(int idx, isdn_ctrl *c)
{ {
isdn_net_dev *p = dev->st_netdev[idx]; isdn_net_dev *p = isdn_slot_st_netdev(idx);
isdn_net_local *lp;
int cmd = c->command; int cmd = c->command;
if (p) { if (!p) {
isdn_net_local *lp = p->local; HERE;
#ifdef CONFIG_ISDN_X25 return 0;
struct concap_proto *cprot = lp -> netdev -> cprot; }
struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; lp = &p->local;
#endif
switch (cmd) {
case ISDN_STAT_BSENT:
/* A packet has successfully been sent out */
if ((lp->flags & ISDN_NET_CONNECTED) &&
(!lp->dialstate)) {
isdn_net_dec_frame_cnt(lp);
lp->stats.tx_packets++;
lp->stats.tx_bytes += c->parm.length;
}
return 1;
case ISDN_STAT_DCONN:
/* D-Channel is up */
switch (lp->dialstate) {
case 4:
case 7:
case 8:
lp->dialstate++;
return 1;
case 12:
lp->dialstate = 5;
return 1;
}
break;
case ISDN_STAT_DHUP:
/* Either D-Channel-hangup or error during dialout */
#ifdef CONFIG_ISDN_X25
/* If we are not connencted then dialing had
failed. If there are generic encap protocol
receiver routines signal the closure of
the link*/
if( !(lp->flags & ISDN_NET_CONNECTED)
&& pops && pops -> disconn_ind )
pops -> disconn_ind(cprot);
#endif /* CONFIG_ISDN_X25 */
if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
isdn_net_ciscohdlck_disconnected(lp);
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_free(lp);
#endif
isdn_net_lp_disconnected(lp);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
printk(KERN_INFO "%s: remote hangup\n", lp->name);
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
lp->charge);
isdn_net_unbind_channel(lp);
return 1;
}
break;
#ifdef CONFIG_ISDN_X25
case ISDN_STAT_BHUP:
/* B-Channel-hangup */
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if( pops && pops -> disconn_ind ){
pops -> disconn_ind(cprot);
return 1;
}
break;
#endif /* CONFIG_ISDN_X25 */
case ISDN_STAT_BCONN:
/* B-Channel is up */
isdn_net_zero_frame_cnt(lp);
switch (lp->dialstate) {
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 12:
if (lp->dialstate <= 6) {
dev->usage[idx] |= ISDN_USAGE_OUTGOING;
isdn_info_update();
} else
dev->rx_netdev[idx] = p;
lp->dialstate = 0;
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
isdn_net_ciscohdlck_connected(lp);
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
if (lp->master) { /* is lp a slave? */
isdn_net_dev *nd = ((isdn_net_local *)lp->master->priv)->netdev;
isdn_net_add_to_bundle(nd, lp);
}
}
printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
lp->chargetime = jiffies;
/* reset dial-timeout */
lp->dialstarted = 0;
lp->dialwait_timer = 0;
#ifdef CONFIG_ISDN_PPP return isdn_net_handle_event(lp, cmd, c);
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) }
isdn_ppp_wakeup_daemon(lp);
#endif static void
#ifdef CONFIG_ISDN_X25 isdn_net_dial_timer(unsigned long data)
/* try if there are generic concap receiver routines */ {
if( pops ) isdn_net_local *lp = (isdn_net_local *) data;
if( pops->connect_ind)
pops->connect_ind(cprot); if (!lp) {
#endif /* CONFIG_ISDN_X25 */ isdn_BUG();
/* ppp needs to do negotiations first */ return;
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
isdn_net_device_wake_queue(lp);
return 1;
}
break;
case ISDN_STAT_NODCH:
/* No D-Channel avail. */
if (lp->dialstate == 4) {
lp->dialstate--;
return 1;
}
break;
case ISDN_STAT_CINF:
/* Charge-info from TelCo. Calculate interval between
* charge-infos and set timestamp for last info for
* usage by isdn_net_autohup()
*/
lp->charge++;
if (lp->hupflags & ISDN_HAVECHARGE) {
lp->hupflags &= ~ISDN_WAITCHARGE;
lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
}
if (lp->hupflags & ISDN_WAITCHARGE)
lp->hupflags |= ISDN_HAVECHARGE;
lp->chargetime = jiffies;
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
lp->name, lp->chargetime);
return 1;
}
} }
return 0; 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
* 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;
int i;
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);
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(&p->dev);
break;
}
anymore = 1;
if(lp->dialtimeout > 0) save_flags(flags);
if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) { cli();
lp->dialstarted = jiffies; lp->dial = lp->phone[1];
lp->dialwait_timer = 0; restore_flags(flags);
}
lp->dialstate++; if (!lp->dial) {
/* Fall through */ printk(KERN_WARNING "%s: phone number deleted?\n",
case 2: lp->name);
/* Prepare dialing. Clear EAZ, then set EAZ. */ isdn_net_hangup(&lp->netdev->dev);
cmd.driver = lp->isdn_device; return 0;
cmd.arg = lp->isdn_channel; }
cmd.command = ISDN_CMD_CLREAZ; if (lp->dialtimeout > 0 &&
isdn_command(&cmd); (lp->dialstarted == 0 ||
sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver)); time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))) {
cmd.command = ISDN_CMD_SETEAZ; lp->dialstarted = jiffies;
isdn_command(&cmd); lp->dialwait_timer = 0;
lp->dialretry = 0; }
anymore = 1; lp->dialretry = 0;
lp->dialstate++; return do_dialout(lp);
/* Fall through */ }
case 3:
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment
* retry-counter.
*/
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(&p->dev, 0, s);
isdn_net_hangup(&p->dev);
break;
}
cmd.driver = lp->isdn_device;
cmd.command = ISDN_CMD_SETL2;
cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
isdn_command(&cmd);
cmd.driver = lp->isdn_device;
cmd.command = ISDN_CMD_SETL3;
cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
isdn_command(&cmd);
cmd.driver = lp->isdn_device;
cmd.arg = lp->isdn_channel;
save_flags(flags);
cli();
if (!lp->dial) {
restore_flags(flags);
printk(KERN_WARNING "%s: phone number deleted?\n",
lp->name);
isdn_net_hangup(&p->dev);
break;
}
if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
restore_flags(flags);
lp->dialstate = 4;
printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
} else {
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(&p->dev, 0, "dial: timed out");
isdn_net_hangup(&p->dev);
break;
}
cmd.driver = lp->isdn_device; /* Setup interface, dial current phone-number, switch to next number.
cmd.command = ISDN_CMD_DIAL; * If list of phone-numbers is exhausted, increment
cmd.parm.setup.si2 = 0; * retry-counter.
*/
/* check for DOV */ static int
phone_number = lp->dial->num; do_dialout(isdn_net_local *lp)
if ((*phone_number == 'v') || {
(*phone_number == 'V')) { /* DOV call */ unsigned long flags;
cmd.parm.setup.si1 = 1;
} else { /* DATA call */
cmd.parm.setup.si1 = 7;
}
strcpy(cmd.parm.setup.phone, phone_number); if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
/* char *s;
* Switch to next number or back to start if at end of list. if (dev->global_flags & ISDN_GLOBAL_STOPPED)
*/ s = "dial suppressed: isdn system stopped";
if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) { else
lp->dial = lp->phone[1]; s = "dial suppressed: dialmode `off'";
lp->dialretry++; isdn_net_unreachable(&lp->netdev->dev, 0, s);
isdn_net_hangup(&lp->netdev->dev);
return 0;
}
if (lp->dialretry > lp->dialmax) { save_flags(flags);
restore_flags(flags); cli();
if (lp->dialtimeout == 0) { if (!lp->dial) {
lp->dialwait_timer = jiffies + lp->dialwait; restore_flags(flags);
lp->dialstarted = 0; printk(KERN_WARNING "%s: phone number deleted?\n",
isdn_net_unreachable(&p->dev, 0, "dial: tried all numbers dialmax times"); lp->name);
} isdn_net_hangup(&lp->netdev->dev);
isdn_net_hangup(&p->dev); return 0;
break; }
} if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
} restore_flags(flags);
restore_flags(flags); lp->dialstate = ST_OUT_WAIT_DCONN;
sprintf(cmd.parm.setup.eazmsn, "%s", printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
isdn_map_eaz2msn(lp->msn, cmd.driver)); return 1;
i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel); } else {
if (i >= 0) { struct dial_info dial = {
strcpy(dev->num[i], cmd.parm.setup.phone); .l2_proto = lp->l2_proto,
dev->usage[i] |= ISDN_USAGE_OUTGOING; .l3_proto = lp->l3_proto,
isdn_info_update(); .si1 = 7,
} .si2 = 0,
printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name, .msn = lp->msn,
lp->dialretry, cmd.parm.setup.phone, .phone = lp->dial->num,
(cmd.parm.setup.si1 == 1) ? "DOV" : ""); };
lp->dtimer = 0; if(lp->dialtimeout > 0) {
#ifdef ISDN_DEBUG_NET_DIAL if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device, restore_flags(flags);
lp->isdn_channel); lp->dialwait_timer = jiffies + lp->dialwait;
#endif lp->dialstarted = 0;
isdn_command(&cmd); isdn_net_unreachable(&lp->netdev->dev, 0, "dial: timed out");
} isdn_net_hangup(&lp->netdev->dev);
lp->huptimer = 0; return 0;
lp->outgoing = 1; }
if (lp->chargeint) { }
lp->hupflags |= ISDN_HAVECHARGE; /*
lp->hupflags &= ~ISDN_WAITCHARGE; * Switch to next number or back to start if at end of list.
} else { */
lp->hupflags |= ISDN_WAITCHARGE; if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
lp->hupflags &= ~ISDN_HAVECHARGE; 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");
} }
anymore = 1; isdn_net_hangup(&lp->netdev->dev);
lp->dialstate = return 0;
(lp->cbdelay && }
(lp->flags & ISDN_NET_CBOUT)) ? 12 : 4; }
break; restore_flags(flags);
case 4: isdn_slot_dial(lp->isdn_slot, &dial);
/* Wait for D-Channel-connect. }
* If timeout, switch back to state 3. lp->huptimer = 0;
* Dialmax-handling moved to state 3. lp->outgoing = 1;
*/ if (lp->chargeint) {
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) lp->hupflags |= ISDN_HAVECHARGE;
lp->dialstate = 3; lp->hupflags &= ~ISDN_WAITCHARGE;
anymore = 1; } else {
break; lp->hupflags |= ISDN_WAITCHARGE;
case 5: lp->hupflags &= ~ISDN_HAVECHARGE;
/* Got D-Channel-Connect, send B-Channel-request */ }
cmd.driver = lp->isdn_device; if (lp->cbdelay && (lp->flags & ISDN_NET_CBOUT)) {
cmd.arg = lp->isdn_channel; lp->dial_timer.expires = jiffies + lp->cbdelay;
cmd.command = ISDN_CMD_ACCEPTB; lp->dial_event = EV_NET_TIMER_CB;
anymore = 1; } else {
lp->dtimer = 0; lp->dial_timer.expires = jiffies + 10 * HZ;
lp->dialstate++; lp->dial_event = EV_NET_TIMER_OUT_DCONN;
isdn_command(&cmd); }
break; lp->dialstate = ST_OUT_WAIT_DCONN;
case 6: add_timer(&lp->dial_timer);
/* Wait for B- or D-Channel-connect. If timeout, return 1;
* switch back to state 3. }
*/
#ifdef ISDN_DEBUG_NET_DIAL /* For EV_NET_DIAL, returns 1 if timer callback is needed
printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer); * For ISDN_STAT_*, returns 1 if event was for us
#endif */
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) static int
lp->dialstate = 3; isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
anymore = 1; {
break; #ifdef CONFIG_ISDN_X25
case 7: struct concap_proto *cprot = lp -> netdev -> cprot;
/* Got incoming Call, setup L2 and L3 protocols, struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
* then wait for D-Channel-connect
*/
#ifdef ISDN_DEBUG_NET_DIAL
printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
#endif #endif
cmd.driver = lp->isdn_device; isdn_net_dev *p = lp->netdev;
cmd.command = ISDN_CMD_SETL2; isdn_ctrl *c = arg;
cmd.arg = lp->isdn_channel + (lp->l2_proto << 8); isdn_ctrl cmd;
isdn_command(&cmd);
cmd.driver = lp->isdn_device; dbg_net_dial("%s: dialstate=%d pr=%#x\n", lp->name, lp->dialstate,pr);
cmd.command = ISDN_CMD_SETL3;
cmd.arg = lp->isdn_channel + (lp->l3_proto << 8); switch (lp->dialstate) {
isdn_command(&cmd); case ST_ACTIVE:
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15) switch (pr) {
isdn_net_hangup(&p->dev); case ISDN_STAT_BSENT:
else { /* A packet has successfully been sent out */
anymore = 1; if (lp->flags & ISDN_NET_CONNECTED) {
lp->dialstate++; isdn_net_dec_frame_cnt(lp);
} lp->stats.tx_packets++;
break; lp->stats.tx_bytes += c->parm.length;
case 9: return 1;
/* Got incoming D-Channel-Connect, send B-Channel-request */ }
cmd.driver = lp->isdn_device; break;
cmd.arg = lp->isdn_channel; case ISDN_STAT_DHUP:
cmd.command = ISDN_CMD_ACCEPTB; /* Either D-Channel-hangup or error during dialout */
isdn_command(&cmd); #ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
anymore = 1; /* If we are not connencted then dialing had
lp->dtimer = 0; failed. If there are generic encap protocol
lp->dialstate++; receiver routines signal the closure of
break; the link*/
case 8:
case 10: if (!(lp->flags & ISDN_NET_CONNECTED)
/* Wait for B- or D-channel-connect */ && pops && pops->disconn_ind)
#ifdef ISDN_DEBUG_NET_DIAL pops -> disconn_ind(cprot);
printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); #endif /* CONFIG_ISDN_X25 */
if (lp->flags & ISDN_NET_CONNECTED) {
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
isdn_net_ciscohdlck_disconnected(lp);
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_free(lp);
#endif #endif
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) isdn_net_lp_disconnected(lp);
isdn_net_hangup(&p->dev); isdn_slot_all_eaz(lp->isdn_slot);
else printk(KERN_INFO "%s: remote hangup\n", lp->name);
anymore = 1; printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
break; lp->charge);
case 11: isdn_net_unbind_channel(lp);
/* Callback Delay */ return 1;
if (lp->dtimer++ > lp->cbdelay) }
lp->dialstate = 1; break;
anymore = 1; #ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
break; case ISDN_STAT_BHUP:
case 12: /* B-Channel-hangup */
/* Remote does callback. Hangup after cbdelay, then wait for incoming /* try if there are generic encap protocol
* call (in state 4). receiver routines and signal the closure of
*/ the link */
if (lp->dtimer++ > lp->cbdelay) if( pops && pops -> disconn_ind ){
{ pops -> disconn_ind(cprot);
printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); return 1;
lp->dtimer = 0; }
lp->dialstate = 4; break;
cmd.driver = lp->isdn_device; #endif /* CONFIG_ISDN_X25 */
cmd.command = ISDN_CMD_HANGUP; case ISDN_STAT_CINF:
cmd.arg = lp->isdn_channel; /* Charge-info from TelCo. Calculate interval between
isdn_command(&cmd); * charge-infos and set timestamp for last info for
isdn_all_eaz(lp->isdn_device, lp->isdn_channel); * usage by isdn_net_autohup()
} */
anymore = 1; lp->charge++;
break; if (lp->hupflags & ISDN_HAVECHARGE) {
default: lp->hupflags &= ~ISDN_WAITCHARGE;
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n", lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
lp->dialstate, lp->name); }
if (lp->hupflags & ISDN_WAITCHARGE)
lp->hupflags |= ISDN_HAVECHARGE;
lp->chargetime = jiffies;
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
lp->name, lp->chargetime);
return 1;
}
break;
case ST_OUT_WAIT_DCONN:
switch (pr) {
case EV_NET_TIMER_OUT_DCONN:
/* try again */
do_dialout(lp);
return 1;
case EV_NET_TIMER_CB:
/* 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);
return 1;
case ISDN_STAT_DCONN:
/* Got D-Channel-Connect, send B-Channel-request */
del_timer(&lp->dial_timer);
lp->dialstate = ST_OUT_WAIT_BCONN;
isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
lp->dial_timer.expires = jiffies + 10 * HZ;
lp->dial_event = EV_NET_TIMER_OUT_BCONN;
add_timer(&lp->dial_timer);
return 1;
case ISDN_STAT_DHUP:
del_timer(&lp->dial_timer);
isdn_slot_all_eaz(lp->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", lp->name);
isdn_net_unbind_channel(lp);
return 1;
}
break;
case ST_OUT_WAIT_BCONN:
switch (pr) {
case EV_NET_TIMER_OUT_BCONN:
/* try again */
do_dialout(lp);
return 1;
case ISDN_STAT_BCONN:
del_timer(&lp->dial_timer);
isdn_slot_set_usage(lp->isdn_slot, isdn_slot_usage(lp->isdn_slot) | ISDN_USAGE_OUTGOING);
isdn_net_connected(lp);
return 1;
case ISDN_STAT_DHUP:
del_timer(&lp->dial_timer);
isdn_slot_all_eaz(lp->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", lp->name);
isdn_net_unbind_channel(lp);
return 1;
}
break;
case ST_IN_WAIT_DCONN:
switch (pr) {
case EV_NET_TIMER_IN_DCONN:
isdn_net_hangup(&p->dev);
return 1;
case ISDN_STAT_DCONN:
del_timer(&lp->dial_timer);
lp->dialstate = ST_IN_WAIT_BCONN;
isdn_slot_command(lp->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
lp->dial_timer.expires = jiffies + 10 * HZ;
lp->dial_event = EV_NET_TIMER_IN_BCONN;
add_timer(&lp->dial_timer);
return 1;
case ISDN_STAT_DHUP:
del_timer(&lp->dial_timer);
isdn_slot_all_eaz(lp->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", lp->name);
isdn_net_unbind_channel(lp);
return 1;
}
break;
case ST_IN_WAIT_BCONN:
switch (pr) {
case EV_NET_TIMER_IN_BCONN:
isdn_net_hangup(&p->dev);
break;
case ISDN_STAT_BCONN:
del_timer(&lp->dial_timer);
isdn_slot_set_rx_netdev(lp->isdn_slot, p);
isdn_net_connected(lp);
return 1;
case ISDN_STAT_DHUP:
del_timer(&lp->dial_timer);
isdn_slot_all_eaz(lp->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", lp->name);
isdn_net_unbind_channel(lp);
return 1;
} }
p = (isdn_net_dev *) p->next; break;
case ST_WAIT_BEFORE_CB:
switch (pr) {
case EV_NET_TIMER_CB:
/* Callback Delay */
init_dialout(lp);
return 1;
}
break;
default:
isdn_BUG();
break;
} }
isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore); printk("NOT HANDLED?\n");
return 0;
} }
/* /*
...@@ -883,12 +853,9 @@ isdn_net_hangup(struct net_device *d) ...@@ -883,12 +853,9 @@ isdn_net_hangup(struct net_device *d)
pops -> disconn_ind(cprot); pops -> disconn_ind(cprot);
#endif /* CONFIG_ISDN_X25 */ #endif /* CONFIG_ISDN_X25 */
cmd.driver = lp->isdn_device; isdn_slot_command(lp->isdn_slot, ISDN_CMD_HANGUP, &cmd);
cmd.command = ISDN_CMD_HANGUP;
cmd.arg = lp->isdn_channel;
isdn_command(&cmd);
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge); printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel); isdn_slot_all_eaz(lp->isdn_slot);
} }
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(lp);
} }
...@@ -1041,15 +1008,15 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb) ...@@ -1041,15 +1008,15 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
/* before obtaining the lock the caller should have checked that /* before obtaining the lock the caller should have checked that
the lp isn't busy */ the lp isn't busy */
if (isdn_net_lp_busy(lp)) { if (isdn_net_lp_busy(lp)) {
printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); isdn_BUG();
goto error; goto error;
} }
if (!(lp->flags & ISDN_NET_CONNECTED)) { if (!(lp->flags & ISDN_NET_CONNECTED)) {
printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); isdn_BUG();
goto error; goto error;
} }
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); ret = isdn_slot_write(lp->isdn_slot, skb);
if (ret != len) { if (ret != len) {
/* we should never get here */ /* we should never get here */
printk(KERN_WARNING "%s: HL driver queue full\n", lp->name); printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
...@@ -1137,7 +1104,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) ...@@ -1137,7 +1104,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
lp->sqfull = 0; lp->sqfull = 0;
} }
/* this is a hack to allow auto-hangup for slaves on moderate loads */ /* this is a hack to allow auto-hangup for slaves on moderate loads */
nd->queue = nd->local; nd->queue = &nd->local;
} }
return retv; return retv;
...@@ -1165,7 +1132,7 @@ void isdn_net_tx_timeout(struct net_device * ndev) ...@@ -1165,7 +1132,7 @@ void isdn_net_tx_timeout(struct net_device * ndev)
isdn_net_local *lp = (isdn_net_local *) ndev->priv; isdn_net_local *lp = (isdn_net_local *) ndev->priv;
printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate); printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
if (!lp->dialstate){ if (lp->dialstate == ST_ACTIVE){
lp->stats.tx_errors++; lp->stats.tx_errors++;
/* /*
* There is a certain probability that this currently * There is a certain probability that this currently
...@@ -1220,14 +1187,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1220,14 +1187,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
#endif #endif
/* auto-dialing xmit function */ /* auto-dialing xmit function */
{ {
#ifdef ISDN_DEBUG_NET_DUMP
u_char *buf;
#endif
isdn_net_adjust_hdr(skb, ndev); isdn_net_adjust_hdr(skb, ndev);
#ifdef ISDN_DEBUG_NET_DUMP isdn_dumppkt("S:", skb->data, skb->len, 40);
buf = skb->data;
isdn_dumppkt("S:", buf, skb->len, 40);
#endif
if (!(lp->flags & ISDN_NET_CONNECTED)) { if (!(lp->flags & ISDN_NET_CONNECTED)) {
int chi; int chi;
...@@ -1257,7 +1218,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1257,7 +1218,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
} }
/* Grab a free ISDN-Channel */ /* Grab a free ISDN-Channel */
if (((chi = if (((chi =
isdn_get_free_channel( isdn_get_free_slot(
ISDN_USAGE_NET, ISDN_USAGE_NET,
lp->l2_proto, lp->l2_proto,
lp->l3_proto, lp->l3_proto,
...@@ -1266,7 +1227,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1266,7 +1227,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
lp->msn) lp->msn)
) < 0) && ) < 0) &&
((chi = ((chi =
isdn_get_free_channel( isdn_get_free_slot(
ISDN_USAGE_NET, ISDN_USAGE_NET,
lp->l2_proto, lp->l2_proto,
lp->l3_proto, lp->l3_proto,
...@@ -1283,7 +1244,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1283,7 +1244,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* Log packet, which triggered dialing */ /* Log packet, which triggered dialing */
if (dev->net_verbose) if (dev->net_verbose)
isdn_net_log_skb(skb, lp); isdn_net_log_skb(skb, lp);
lp->dialstate = 1;
/* 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
...@@ -1296,14 +1256,14 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1296,14 +1256,14 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return 0; /* STN (skb to nirvana) ;) */ return 0; /* STN (skb to nirvana) ;) */
} }
restore_flags(flags); restore_flags(flags);
isdn_net_dial(); /* Initiate dialing */ init_dialout(lp);
netif_stop_queue(ndev); netif_stop_queue(ndev);
return 1; /* let upper layer requeue skb packet */ return 1; /* let upper layer requeue skb packet */
} }
#endif #endif
/* Initiate dialing */ /* Initiate dialing */
restore_flags(flags); restore_flags(flags);
isdn_net_dial(); init_dialout(lp);
isdn_net_device_stop_queue(lp); isdn_net_device_stop_queue(lp);
return 1; return 1;
} else { } else {
...@@ -1315,7 +1275,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1315,7 +1275,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
} else { } else {
/* Device is connected to an ISDN channel */ /* Device is connected to an ISDN channel */
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
if (!lp->dialstate) { if (lp->dialstate == ST_ACTIVE) {
/* ISDN connection is established, try sending */ /* ISDN connection is established, try sending */
int ret; int ret;
ret = (isdn_net_xmit(ndev, skb)); ret = (isdn_net_xmit(ndev, skb));
...@@ -1433,7 +1393,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev) ...@@ -1433,7 +1393,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff* static struct sk_buff*
isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len) isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
{ {
unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; unsigned short hl = isdn_slot_hdrlen(lp->isdn_slot);
struct sk_buff *skb; struct sk_buff *skb;
skb = alloc_skb(hl + len, GFP_ATOMIC); skb = alloc_skb(hl + len, GFP_ATOMIC);
...@@ -1523,8 +1483,8 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) ...@@ -1523,8 +1483,8 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
unsigned long last_cisco_myseq = lp->cisco_myseq; unsigned long last_cisco_myseq = lp->cisco_myseq;
int myseq_diff = 0; int myseq_diff = 0;
if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) { if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate != ST_ACTIVE) {
printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); isdn_BUG();
return; return;
} }
lp->cisco_myseq++; lp->cisco_myseq++;
...@@ -1814,9 +1774,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) ...@@ -1814,9 +1774,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
skb->dev = ndev; skb->dev = ndev;
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
skb->mac.raw = skb->data; skb->mac.raw = skb->data;
#ifdef ISDN_DEBUG_NET_DUMP
isdn_dumppkt("R:", skb->data, skb->len, 40); isdn_dumppkt("R:", skb->data, skb->len, 40);
#endif
switch (lp->p_encap) { switch (lp->p_encap) {
case ISDN_NET_ENCAP_ETHER: case ISDN_NET_ENCAP_ETHER:
/* Ethernet over ISDN */ /* Ethernet over ISDN */
...@@ -1893,12 +1851,12 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) ...@@ -1893,12 +1851,12 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
int int
isdn_net_rcv_skb(int idx, struct sk_buff *skb) isdn_net_rcv_skb(int idx, struct sk_buff *skb)
{ {
isdn_net_dev *p = dev->rx_netdev[idx]; isdn_net_dev *p = isdn_slot_rx_netdev(idx);
if (p) { if (p) {
isdn_net_local *lp = p->local; isdn_net_local *lp = &p->local;
if ((lp->flags & ISDN_NET_CONNECTED) && if ((lp->flags & ISDN_NET_CONNECTED) &&
(!lp->dialstate)) { (lp->dialstate == ST_ACTIVE)) {
isdn_net_receive(&p->dev, skb); isdn_net_receive(&p->dev, skb);
return 1; return 1;
} }
...@@ -2093,40 +2051,34 @@ isdn_net_init(struct net_device *ndev) ...@@ -2093,40 +2051,34 @@ isdn_net_init(struct net_device *ndev)
static void static void
isdn_net_swapbind(int drvidx) isdn_net_swapbind(int drvidx)
{ {
isdn_net_dev *p; struct list_head *l;
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: swapping ch of %d\n", drvidx);
printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx); list_for_each(l, &isdn_net_devs) {
#endif isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
p = dev->netdev; if (p->local.pre_device != drvidx)
while (p) { continue;
if (p->local->pre_device == drvidx)
switch (p->local->pre_channel) { switch (p->local.pre_channel) {
case 0: case 0:
p->local->pre_channel = 1; p->local.pre_channel = 1;
break; break;
case 1: case 1:
p->local->pre_channel = 0; p->local.pre_channel = 0;
break; break;
} }
p = (isdn_net_dev *) p->next;
} }
} }
static void static void
isdn_net_swap_usage(int i1, int i2) isdn_net_swap_usage(int i1, int i2)
{ {
int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE; int u1 = isdn_slot_usage(i1);
int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE; int u2 = isdn_slot_usage(i2);
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: usage of %d and %d\n", i1, i2);
printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2); isdn_slot_set_usage(i1, (u1 & ~ISDN_USAGE_EXCLUSIVE) | (u2 & ISDN_USAGE_EXCLUSIVE));
#endif isdn_slot_set_usage(i2, (u2 & ~ISDN_USAGE_EXCLUSIVE) | (u1 & ISDN_USAGE_EXCLUSIVE));
dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
dev->usage[i1] |= u2;
dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
dev->usage[i2] |= u1;
isdn_info_update();
} }
/* /*
...@@ -2155,12 +2107,14 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -2155,12 +2107,14 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
int wret; int wret;
int swapped; int swapped;
int sidx = 0; int sidx = 0;
isdn_net_dev *p; struct list_head *l;
isdn_net_phone *n; isdn_net_phone *n;
ulong flags; ulong flags;
char nr[32]; char nr[32];
char *my_eaz; char *my_eaz;
isdn_ctrl cmd;
int slot = isdn_dc2minor(di, ch);
/* Search name in netdev-chain */ /* Search name in netdev-chain */
save_flags(flags); save_flags(flags);
cli(); cli();
...@@ -2188,16 +2142,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -2188,16 +2142,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
return 0; return 0;
} }
n = (isdn_net_phone *) 0; n = (isdn_net_phone *) 0;
p = dev->netdev;
ematch = wret = swapped = 0; ematch = wret = swapped = 0;
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx, isdn_slot_usage(idx));
dev->usage[idx]);
#endif list_for_each(l, &isdn_net_devs) {
while (p) {
int matchret; int matchret;
isdn_net_local *lp = p->local; isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *lp = &p->local;
/* If last check has triggered as binding-swap, revert it */ /* If last check has triggered as binding-swap, revert it */
switch (swapped) { switch (swapped) {
...@@ -2210,7 +2163,7 @@ p = dev->netdev; ...@@ -2210,7 +2163,7 @@ p = dev->netdev;
} }
swapped = 0; swapped = 0;
/* check acceptable call types for DOV */ /* check acceptable call types for DOV */
my_eaz = isdn_map_eaz2msn(lp->msn, di); my_eaz = isdn_slot_map_eaz2msn(slot, lp->msn);
if (si1 == 1) { /* it's a DOV call, check if we allow it */ if (si1 == 1) { /* it's a DOV call, check if we allow it */
if (*my_eaz == 'v' || *my_eaz == 'V' || if (*my_eaz == 'v' || *my_eaz == 'V' ||
*my_eaz == 'b' || *my_eaz == 'B') *my_eaz == 'b' || *my_eaz == 'B')
...@@ -2231,22 +2184,18 @@ p = dev->netdev; ...@@ -2231,22 +2184,18 @@ p = dev->netdev;
/* Remember if more numbers eventually can match */ /* Remember if more numbers eventually can match */
if (matchret > wret) if (matchret > wret)
wret = matchret; wret = matchret;
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
lp->name, lp->msn, lp->flags, lp->dialstate); lp->name, lp->msn, lp->flags, lp->dialstate);
#endif
if ((!matchret) && /* EAZ is matching */ if ((!matchret) && /* EAZ is matching */
(((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */ (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
(USG_NONE(dev->usage[idx]))) || /* and ch. unused or */ (USG_NONE(isdn_slot_usage(idx)))) || /* and ch. unused or */
((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */ ((((lp->dialstate == ST_OUT_WAIT_DCONN) || (lp->dialstate == ST_OUT_WAIT_DCONN)) && /* if dialing */
(!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */ (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
))) )))
{ {
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: match1, pdev=%d pch=%d\n",
printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
lp->pre_device, lp->pre_channel); lp->pre_device, lp->pre_channel);
#endif if (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) {
if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
if ((lp->pre_channel != ch) || if ((lp->pre_channel != ch) ||
(lp->pre_device != di)) { (lp->pre_device != di)) {
/* Here we got a problem: /* Here we got a problem:
...@@ -2260,16 +2209,12 @@ p = dev->netdev; ...@@ -2260,16 +2209,12 @@ p = dev->netdev;
*/ */
if (ch == 0) { if (ch == 0) {
sidx = isdn_dc2minor(di, 1); sidx = isdn_dc2minor(di, 1);
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: ch is 0\n");
printk(KERN_DEBUG "n_fi: ch is 0\n"); if (USG_NONE(isdn_slot_usage(sidx))) {
#endif
if (USG_NONE(dev->usage[sidx])) {
/* Second Channel is free, now see if it is bound /* Second Channel is free, now see if it is bound
* exclusive too. */ * exclusive too. */
if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) { if (isdn_slot_usage(sidx) & ISDN_USAGE_EXCLUSIVE) {
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: 2nd channel is down and bound\n");
printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
#endif
/* Yes, swap bindings only, if the original /* Yes, swap bindings only, if the original
* binding is bound to channel 1 of this driver */ * binding is bound to channel 1 of this driver */
if ((lp->pre_device == di) && if ((lp->pre_device == di) &&
...@@ -2278,43 +2223,31 @@ p = dev->netdev; ...@@ -2278,43 +2223,31 @@ p = dev->netdev;
swapped = 1; swapped = 1;
} else { } else {
/* ... else iterate next device */ /* ... else iterate next device */
p = (isdn_net_dev *) p->next;
continue; continue;
} }
} else { } else {
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: 2nd channel is down and unbound\n");
printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
#endif
/* No, swap always and swap excl-usage also */ /* No, swap always and swap excl-usage also */
isdn_net_swap_usage(idx, sidx); isdn_net_swap_usage(idx, sidx);
isdn_net_swapbind(di); isdn_net_swapbind(di);
swapped = 2; swapped = 2;
} }
/* Now check for exclusive binding again */ /* Now check for exclusive binding again */
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: final check\n");
printk(KERN_DEBUG "n_fi: final check\n"); if ((isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) &&
#endif
if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
((lp->pre_channel != ch) || ((lp->pre_channel != ch) ||
(lp->pre_device != di))) { (lp->pre_device != di))) {
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: final check failed\n");
printk(KERN_DEBUG "n_fi: final check failed\n");
#endif
p = (isdn_net_dev *) p->next;
continue; continue;
} }
} }
} else { } else {
/* We are already on the second channel, so nothing to do */ /* We are already on the second channel, so nothing to do */
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: already on 2nd channel\n");
printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
#endif
} }
} }
} }
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: match2\n");
printk(KERN_DEBUG "n_fi: match2\n");
#endif
n = lp->phone[0]; n = lp->phone[0];
if (lp->flags & ISDN_NET_SECURE) { if (lp->flags & ISDN_NET_SECURE) {
while (n) { while (n) {
...@@ -2324,9 +2257,7 @@ p = dev->netdev; ...@@ -2324,9 +2257,7 @@ p = dev->netdev;
} }
} }
if (n || (!(lp->flags & ISDN_NET_SECURE))) { if (n || (!(lp->flags & ISDN_NET_SECURE))) {
#ifdef ISDN_DEBUG_NET_ICALL dbg_net_icall("n_fi: match3\n");
printk(KERN_DEBUG "n_fi: match3\n");
#endif
/* matching interface found */ /* matching interface found */
/* /*
...@@ -2370,7 +2301,6 @@ p = dev->netdev; ...@@ -2370,7 +2301,6 @@ p = dev->netdev;
/* Found parent, if it's offline iterate next device */ /* Found parent, if it's offline iterate next device */
printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED); printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
if (!(mlp->flags & ISDN_NET_CONNECTED)) { if (!(mlp->flags & ISDN_NET_CONNECTED)) {
p = (isdn_net_dev *) p->next;
continue; continue;
} }
} }
...@@ -2392,7 +2322,7 @@ p = dev->netdev; ...@@ -2392,7 +2322,7 @@ p = dev->netdev;
if (lp->phone[1]) { if (lp->phone[1]) {
/* Grab a free ISDN-Channel */ /* Grab a free ISDN-Channel */
if ((chi = if ((chi =
isdn_get_free_channel( isdn_get_free_slot(
ISDN_USAGE_NET, ISDN_USAGE_NET,
lp->l2_proto, lp->l2_proto,
lp->l3_proto, lp->l3_proto,
...@@ -2406,8 +2336,11 @@ p = dev->netdev; ...@@ -2406,8 +2336,11 @@ p = dev->netdev;
return 0; return 0;
} }
/* Setup dialstate. */ /* Setup dialstate. */
lp->dtimer = 0; lp->dial_timer.expires = jiffies + lp->cbdelay;
lp->dialstate = 11; lp->dial_event = EV_NET_TIMER_CB;
add_timer(&lp->dial_timer);
lp->dialstate = ST_WAIT_BEFORE_CB;
/* 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
...@@ -2430,30 +2363,39 @@ p = dev->netdev; ...@@ -2430,30 +2363,39 @@ p = dev->netdev;
eaz); eaz);
/* if this interface is dialing, it does it probably on a different /* if this interface is dialing, it does it probably on a different
device, so free this device */ device, so free this device */
if ((lp->dialstate == 4) || (lp->dialstate == 12)) { if (lp->dialstate == ST_OUT_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)
isdn_ppp_free(lp); isdn_ppp_free(lp);
#endif #endif
isdn_net_lp_disconnected(lp); isdn_net_lp_disconnected(lp);
isdn_free_channel(lp->isdn_device, lp->isdn_channel, isdn_slot_free(lp->isdn_slot,
ISDN_USAGE_NET); ISDN_USAGE_NET);
} }
dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; strcpy(isdn_slot_num(idx), nr);
dev->usage[idx] |= ISDN_USAGE_NET; isdn_slot_set_usage(idx, (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) | ISDN_USAGE_NET);
strcpy(dev->num[idx], nr); isdn_slot_set_st_netdev(idx, lp->netdev);
isdn_info_update(); lp->isdn_slot = slot;
dev->st_netdev[idx] = lp->netdev;
lp->isdn_device = di;
lp->isdn_channel = ch;
lp->ppp_slot = -1; lp->ppp_slot = -1;
lp->flags |= ISDN_NET_CONNECTED; lp->flags |= ISDN_NET_CONNECTED;
lp->dialstate = 7;
lp->dtimer = 0;
lp->outgoing = 0; lp->outgoing = 0;
lp->huptimer = 0; lp->huptimer = 0;
lp->hupflags |= ISDN_WAITCHARGE; lp->hupflags |= ISDN_WAITCHARGE;
lp->hupflags &= ~ISDN_HAVECHARGE; lp->hupflags &= ~ISDN_HAVECHARGE;
/* 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) { if (isdn_ppp_bind(lp) < 0) {
...@@ -2467,11 +2409,10 @@ p = dev->netdev; ...@@ -2467,11 +2409,10 @@ p = dev->netdev;
} }
} }
} }
p = (isdn_net_dev *) p->next;
} }
/* 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)
printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz); printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, slot, eaz);
restore_flags(flags); restore_flags(flags);
return (wret == 2)?5:0; return (wret == 2)?5:0;
} }
...@@ -2482,14 +2423,14 @@ p = dev->netdev; ...@@ -2482,14 +2423,14 @@ p = dev->netdev;
isdn_net_dev * isdn_net_dev *
isdn_net_findif(char *name) isdn_net_findif(char *name)
{ {
isdn_net_dev *p = dev->netdev; struct list_head *l;
while (p) { list_for_each(l, &isdn_net_devs) {
if (!strcmp(p->local->name, name)) isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
if (!strcmp(p->local.name, name))
return p; return p;
p = (isdn_net_dev *) p->next;
} }
return (isdn_net_dev *) NULL; return NULL;
} }
/* /*
...@@ -2500,7 +2441,7 @@ isdn_net_findif(char *name) ...@@ -2500,7 +2441,7 @@ 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) { if ((!(lp->flags & ISDN_NET_CONNECTED)) && lp->dialstate == ST_NULL) {
int chi; int chi;
if (lp->phone[1]) { if (lp->phone[1]) {
ulong flags; ulong flags;
...@@ -2509,7 +2450,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp) ...@@ -2509,7 +2450,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
/* Grab a free ISDN-Channel */ /* Grab a free ISDN-Channel */
if ((chi = if ((chi =
isdn_get_free_channel( isdn_get_free_slot(
ISDN_USAGE_NET, ISDN_USAGE_NET,
lp->l2_proto, lp->l2_proto,
lp->l3_proto, lp->l3_proto,
...@@ -2521,7 +2462,6 @@ isdn_net_force_dial_lp(isdn_net_local * lp) ...@@ -2521,7 +2462,6 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
restore_flags(flags); restore_flags(flags);
return -EAGAIN; return -EAGAIN;
} }
lp->dialstate = 1;
/* 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
...@@ -2534,7 +2474,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp) ...@@ -2534,7 +2474,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
#endif #endif
/* Initiate dialing */ /* Initiate dialing */
restore_flags(flags); restore_flags(flags);
isdn_net_dial(); init_dialout(lp);
return 0; return 0;
} else } else
return -EINVAL; return -EINVAL;
...@@ -2567,47 +2507,39 @@ isdn_net_force_dial(char *name) ...@@ -2567,47 +2507,39 @@ isdn_net_force_dial(char *name)
if (!p) if (!p)
return -ENODEV; return -ENODEV;
return (isdn_net_force_dial_lp(p->local)); return (isdn_net_force_dial_lp(&p->local));
} }
/* /*
* Allocate a new network-interface and initialize its data structures. * Allocate a new network-interface and initialize its data structures.
*/ */
char * int
isdn_net_new(char *name, struct net_device *master) isdn_net_new(char *name, struct net_device *master)
{ {
int retval;
isdn_net_dev *netdev; isdn_net_dev *netdev;
/* Avoid creating an existing interface */ /* Avoid creating an existing interface */
if (isdn_net_findif(name)) { if (isdn_net_findif(name)) {
printk(KERN_WARNING "isdn_net: interface %s already exists\n", name); printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
return NULL; return -EEXIST;
} }
if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { if (!(netdev = kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
return NULL; return -ENOMEM;
} }
memset(netdev, 0, sizeof(isdn_net_dev)); memset(netdev, 0, sizeof(isdn_net_dev));
if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) { strcpy(netdev->local.name, name);
printk(KERN_WARNING "isdn_net: Could not allocate device locals\n"); strcpy(netdev->dev.name, name);
kfree(netdev); netdev->dev.priv = &netdev->local;
return NULL;
}
memset(netdev->local, 0, sizeof(isdn_net_local));
if (name == NULL)
strcpy(netdev->local->name, " ");
else
strcpy(netdev->local->name, name);
strcpy(netdev->dev.name, netdev->local->name);
netdev->dev.priv = netdev->local;
netdev->dev.init = isdn_net_init; netdev->dev.init = isdn_net_init;
netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP; netdev->local.p_encap = ISDN_NET_ENCAP_RAWIP;
if (master) { if (master) {
/* Device shall be a slave */ /* Device shall be a slave */
struct net_device *p = (((isdn_net_local *) master->priv)->slave); struct net_device *p = (((isdn_net_local *) master->priv)->slave);
struct net_device *q = master; struct net_device *q = master;
netdev->local->master = master; netdev->local.master = master;
/* Put device at end of slave-chain */ /* Put device at end of slave-chain */
while (p) { while (p) {
q = p; q = p;
...@@ -2621,81 +2553,80 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -2621,81 +2553,80 @@ isdn_net_new(char *name, struct net_device *master)
*/ */
netdev->dev.tx_timeout = isdn_net_tx_timeout; netdev->dev.tx_timeout = isdn_net_tx_timeout;
netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT; netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
if (register_netdev(&netdev->dev) != 0) { retval = register_netdev(&netdev->dev);
if (retval) {
printk(KERN_WARNING "isdn_net: Could not register net-device\n"); printk(KERN_WARNING "isdn_net: Could not register net-device\n");
kfree(netdev->local);
kfree(netdev); kfree(netdev);
return NULL; return retval;
} }
} }
netdev->local->magic = ISDN_NET_MAGIC; netdev->local.magic = ISDN_NET_MAGIC;
netdev->queue = netdev->local; netdev->queue = &netdev->local;
spin_lock_init(&netdev->queue_lock); spin_lock_init(&netdev->queue_lock);
netdev->local->last = netdev->local; netdev->local.last = &netdev->local;
netdev->local->netdev = netdev; netdev->local.netdev = netdev;
netdev->local->next = netdev->local; netdev->local.next = &netdev->local;
netdev->local->tqueue.sync = 0; netdev->local.tqueue.sync = 0;
netdev->local->tqueue.routine = isdn_net_softint; netdev->local.tqueue.routine = isdn_net_softint;
netdev->local->tqueue.data = netdev->local; netdev->local.tqueue.data = &netdev->local;
spin_lock_init(&netdev->local->xmit_lock); spin_lock_init(&netdev->local.xmit_lock);
netdev->local->isdn_device = -1; netdev->local.isdn_slot = -1;
netdev->local->isdn_channel = -1; netdev->local.pre_device = -1;
netdev->local->pre_device = -1; netdev->local.pre_channel = -1;
netdev->local->pre_channel = -1; netdev->local.exclusive = -1;
netdev->local->exclusive = -1; netdev->local.ppp_slot = -1;
netdev->local->ppp_slot = -1; netdev->local.pppbind = -1;
netdev->local->pppbind = -1; skb_queue_head_init(&netdev->local.super_tx_queue);
skb_queue_head_init(&netdev->local->super_tx_queue); netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
netdev->local->l2_proto = ISDN_PROTO_L2_X75I; netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
netdev->local->l3_proto = ISDN_PROTO_L3_TRANS; netdev->local.triggercps = 6000;
netdev->local->triggercps = 6000; netdev->local.slavedelay = 10 * HZ;
netdev->local->slavedelay = 10 * HZ; netdev->local.hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
netdev->local->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */ netdev->local.onhtime = 10; /* Default hangup-time for saving costs
netdev->local->onhtime = 10; /* Default hangup-time for saving costs
of those who forget configuring this */ of those who forget configuring this */
netdev->local->dialmax = 1; netdev->local.dialmax = 1;
netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */ netdev->local.flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */
netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */ netdev->local.cbdelay = 5 * HZ; /* Wait 5 secs before Callback */
netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */ netdev->local.dialtimeout = -1; /* Infinite Dial-Timeout */
netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */ netdev->local.dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
netdev->local->dialstarted = 0; /* Jiffies of last dial-start */ netdev->local.dialstarted = 0; /* Jiffies of last dial-start */
netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */ netdev->local.dialwait_timer = 0; /* Jiffies of earliest next dial-start */
init_timer(&netdev->local.dial_timer);
netdev->local.dial_timer.data = (unsigned long) &netdev->local;
netdev->local.dial_timer.function = isdn_net_dial_timer;
/* Put into to netdev-chain */ /* Put into to netdev-chain */
netdev->next = (void *) dev->netdev; list_add(&netdev->global_list, &isdn_net_devs);
dev->netdev = netdev; return 0;
return netdev->dev.name;
} }
char * int
isdn_net_newslave(char *parm) isdn_net_newslave(char *parm)
{ {
char *p = strchr(parm, ','); char *p = strchr(parm, ',');
isdn_net_dev *n; isdn_net_dev *m;
char newname[10];
if (p) { /* Slave-Name MUST not be empty */
/* Slave-Name MUST not be empty */ if (!p || !p[1])
if (!strlen(p + 1)) return -EINVAL;
return NULL;
strcpy(newname, p + 1); *p = 0;
*p = 0; /* Master must already exist */
/* Master must already exist */ if (!(m = isdn_net_findif(parm)))
if (!(n = isdn_net_findif(parm))) return -ESRCH;
return NULL; /* Master must be a real interface, not a slave */
/* Master must be a real interface, not a slave */ if (m->local.master)
if (n->local->master) return -ENXIO;
return NULL; /* Master must not be started yet */
/* Master must not be started yet */ if (isdn_net_device_started(m))
if (isdn_net_device_started(n)) return -EBUSY;
return NULL;
return (isdn_net_new(newname, &(n->dev))); return isdn_net_new(p+1, &m->dev);
}
return NULL;
} }
/* /*
...@@ -2717,7 +2648,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2717,7 +2648,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
ulong flags; ulong flags;
#endif #endif
if (p) { if (p) {
isdn_net_local *lp = p->local; isdn_net_local *lp = &p->local;
/* See if any registered driver supports the features we want */ /* See if any registered driver supports the features we want */
features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) | features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
...@@ -2777,7 +2708,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2777,7 +2708,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
case ISDN_NET_ENCAP_X25IFACE: case ISDN_NET_ENCAP_X25IFACE:
#ifndef CONFIG_ISDN_X25 #ifndef CONFIG_ISDN_X25
printk(KERN_WARNING "%s: isdn-x25 support not configured\n", printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
p->local->name); p->local.name);
return -EINVAL; return -EINVAL;
#else #else
p->dev.type = ARPHRD_X25; /* change ARP type */ p->dev.type = ARPHRD_X25; /* change ARP type */
...@@ -2793,7 +2724,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2793,7 +2724,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
break; break;
printk(KERN_WARNING printk(KERN_WARNING
"%s: encapsulation protocol %d not supported\n", "%s: encapsulation protocol %d not supported\n",
p->local->name, cfg->p_encap); p->local.name, cfg->p_encap);
return -EINVAL; return -EINVAL;
} }
if (strlen(cfg->drvid)) { if (strlen(cfg->drvid)) {
...@@ -2830,7 +2761,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2830,7 +2761,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
/* If binding is exclusive, try to grab the channel */ /* If binding is exclusive, try to grab the channel */
save_flags(flags); save_flags(flags);
if ((i = isdn_get_free_channel(ISDN_USAGE_NET, if ((i = isdn_get_free_slot(ISDN_USAGE_NET,
lp->l2_proto, lp->l3_proto, drvidx, lp->l2_proto, lp->l3_proto, drvidx,
chidx, lp->msn)) < 0) { chidx, lp->msn)) < 0) {
/* Grab failed, because desired channel is in use */ /* Grab failed, because desired channel is in use */
...@@ -2839,8 +2770,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2839,8 +2770,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
return -EBUSY; return -EBUSY;
} }
/* All went ok, so update isdninfo */ /* All went ok, so update isdninfo */
dev->usage[i] = ISDN_USAGE_EXCLUSIVE; isdn_slot_set_usage(i, ISDN_USAGE_EXCLUSIVE);
isdn_info_update();
restore_flags(flags); restore_flags(flags);
lp->exclusive = i; lp->exclusive = i;
} else { } else {
...@@ -2860,7 +2790,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2860,7 +2790,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
lp->charge = cfg->charge; lp->charge = cfg->charge;
lp->l2_proto = cfg->l2_proto; lp->l2_proto = cfg->l2_proto;
lp->l3_proto = cfg->l3_proto; lp->l3_proto = cfg->l3_proto;
lp->cbdelay = cfg->cbdelay; lp->cbdelay = cfg->cbdelay * HZ / 5;
lp->dialmax = cfg->dialmax; lp->dialmax = cfg->dialmax;
lp->triggercps = cfg->triggercps; lp->triggercps = cfg->triggercps;
lp->slavedelay = cfg->slavedelay * HZ; lp->slavedelay = cfg->slavedelay * HZ;
...@@ -2944,7 +2874,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2944,7 +2874,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
isdn_net_dev *p = isdn_net_findif(cfg->name); isdn_net_dev *p = isdn_net_findif(cfg->name);
if (p) { if (p) {
isdn_net_local *lp = p->local; isdn_net_local *lp = &p->local;
strcpy(cfg->eaz, lp->msn); strcpy(cfg->eaz, lp->msn);
cfg->exclusive = lp->exclusive; cfg->exclusive = lp->exclusive;
...@@ -2968,7 +2898,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2968,7 +2898,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK; cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
cfg->chargehup = (lp->hupflags & 4) ? 1 : 0; cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
cfg->ihup = (lp->hupflags & 8) ? 1 : 0; cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
cfg->cbdelay = lp->cbdelay; cfg->cbdelay = lp->cbdelay * 5 / HZ;
cfg->dialmax = lp->dialmax; cfg->dialmax = lp->dialmax;
cfg->triggercps = lp->triggercps; cfg->triggercps = lp->triggercps;
cfg->slavedelay = lp->slavedelay / HZ; cfg->slavedelay = lp->slavedelay / HZ;
...@@ -3003,8 +2933,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) ...@@ -3003,8 +2933,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
strcpy(n->num, phone->phone); strcpy(n->num, phone->phone);
n->next = p->local->phone[phone->outgoing & 1]; n->next = p->local.phone[phone->outgoing & 1];
p->local->phone[phone->outgoing & 1] = n; p->local.phone[phone->outgoing & 1] = n;
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
...@@ -3026,7 +2956,7 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) ...@@ -3026,7 +2956,7 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
if (!p) if (!p)
return -ENODEV; return -ENODEV;
inout &= 1; inout &= 1;
for (n = p->local->phone[inout]; n; n = n->next) { for (n = p->local.phone[inout]; n; n = n->next) {
if (more) { if (more) {
put_user(' ', phones++); put_user(' ', phones++);
count++; count++;
...@@ -3051,7 +2981,7 @@ int ...@@ -3051,7 +2981,7 @@ int
isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *p = isdn_net_findif(phone->name);
int ch, dv, idx; int idx;
if (!p) return -ENODEV; if (!p) return -ENODEV;
/* /*
...@@ -3060,15 +2990,12 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) ...@@ -3060,15 +2990,12 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
* in (partially) wrong number copied to user. This race * in (partially) wrong number copied to user. This race
* currently ignored. * currently ignored.
*/ */
ch = p->local->isdn_channel; idx = p->local.isdn_slot;
dv = p->local->isdn_device; if (idx<0) return -ENOTCONN;
if(ch<0 && dv<0) return -ENOTCONN;
idx = isdn_dc2minor(dv, ch);
if (idx<0) return -ENODEV;
/* for pre-bound channels, we need this extra check */ /* for pre-bound channels, we need this extra check */
if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN; if (strncmp(isdn_slot_num(idx),"???",3) == 0 ) return -ENOTCONN;
strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN); strncpy(phone->phone,isdn_slot_num(idx),ISDN_MSNLEN);
phone->outgoing=USG_OUTGOING(dev->usage[idx]); phone->outgoing=USG_OUTGOING(isdn_slot_usage(idx));
if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT; if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
return 0; return 0;
} }
...@@ -3087,16 +3014,16 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone) ...@@ -3087,16 +3014,16 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
if (p) { if (p) {
save_flags(flags); save_flags(flags);
cli(); cli();
n = p->local->phone[inout]; n = p->local.phone[inout];
m = NULL; m = NULL;
while (n) { while (n) {
if (!strcmp(n->num, phone->phone)) { if (!strcmp(n->num, phone->phone)) {
if (p->local->dial == n) if (p->local.dial == n)
p->local->dial = n->next; p->local.dial = n->next;
if (m) if (m)
m->next = n->next; m->next = n->next;
else else
p->local->phone[inout] = n->next; p->local.phone[inout] = n->next;
kfree(n); kfree(n);
restore_flags(flags); restore_flags(flags);
return 0; return 0;
...@@ -3124,15 +3051,15 @@ isdn_net_rmallphone(isdn_net_dev * p) ...@@ -3124,15 +3051,15 @@ isdn_net_rmallphone(isdn_net_dev * p)
save_flags(flags); save_flags(flags);
cli(); cli();
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
n = p->local->phone[i]; n = p->local.phone[i];
while (n) { while (n) {
m = n->next; m = n->next;
kfree(n); kfree(n);
n = m; n = m;
} }
p->local->phone[i] = NULL; p->local.phone[i] = NULL;
} }
p->local->dial = NULL; p->local.dial = NULL;
restore_flags(flags); restore_flags(flags);
return 0; return 0;
} }
...@@ -3147,9 +3074,9 @@ isdn_net_force_hangup(char *name) ...@@ -3147,9 +3074,9 @@ isdn_net_force_hangup(char *name)
struct net_device *q; struct net_device *q;
if (p) { if (p) {
if (p->local->isdn_device < 0) if (p->local.isdn_slot < 0)
return 1; return 1;
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(q);
...@@ -3165,7 +3092,7 @@ isdn_net_force_hangup(char *name) ...@@ -3165,7 +3092,7 @@ isdn_net_force_hangup(char *name)
* Helper-function for isdn_net_rm: Do the real work. * Helper-function for isdn_net_rm: Do the real work.
*/ */
static int static int
isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) isdn_net_realrm(isdn_net_dev *p)
{ {
unsigned long flags; unsigned long flags;
...@@ -3182,42 +3109,37 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) ...@@ -3182,42 +3109,37 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
/* Free all phone-entries */ /* Free all phone-entries */
isdn_net_rmallphone(p); isdn_net_rmallphone(p);
/* If interface is bound exclusive, free channel-usage */ /* If interface is bound exclusive, free channel-usage */
if (p->local->exclusive != -1) if (p->local.exclusive != -1)
isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel); isdn_unexclusive_channel(p->local.pre_device, p->local.pre_channel);
if (p->local->master) { if (p->local.master) {
/* It's a slave-device, so update master's slave-pointer if necessary */ /* It's a slave-device, so update master's slave-pointer if necessary */
if (((isdn_net_local *) (p->local->master->priv))->slave == &p->dev) if (((isdn_net_local *) (p->local.master->priv))->slave == &p->dev)
((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave; ((isdn_net_local *) (p->local.master->priv))->slave = p->local.slave;
} else { } else {
/* Unregister only if it's a master-device */ /* Unregister only if it's a master-device */
p->dev.hard_header_cache = p->local->org_hhc; p->dev.hard_header_cache = p->local.org_hhc;
p->dev.header_cache_update = p->local->org_hcu; p->dev.header_cache_update = p->local.org_hcu;
unregister_netdev(&p->dev); unregister_netdev(&p->dev);
} }
/* Unlink device from chain */ /* Unlink device from chain */
if (q) list_del(&p->global_list);
q->next = p->next; if (p->local.slave) {
else
dev->netdev = p->next;
if (p->local->slave) {
/* If this interface has a slave, remove it also */ /* If this interface has a slave, remove it also */
char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name; char *slavename = ((isdn_net_local *) (p->local.slave->priv))->name;
isdn_net_dev *n = dev->netdev; struct list_head *l;
q = NULL;
while (n) { list_for_each(l, &isdn_net_devs) {
if (!strcmp(n->local->name, slavename)) { isdn_net_dev *n = list_entry(l, isdn_net_dev, global_list);
isdn_net_realrm(n, q); if (!strcmp(n->local.name, slavename)) {
isdn_net_realrm(n);
break; break;
} }
q = n;
n = (isdn_net_dev *) n->next;
} }
} }
/* If no more net-devices remain, disable auto-hangup timer */ /* If no more net-devices remain, disable auto-hangup timer */
if (dev->netdev == NULL) if (list_empty(&isdn_net_devs))
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
restore_flags(flags); restore_flags(flags);
kfree(p->local);
kfree(p); kfree(p);
return 0; return 0;
...@@ -3229,21 +3151,14 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) ...@@ -3229,21 +3151,14 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
int int
isdn_net_rm(char *name) isdn_net_rm(char *name)
{ {
isdn_net_dev *p; struct list_head *l;
isdn_net_dev *q;
/* Search name in netdev-chain */ /* Search name in netdev-chain */
p = dev->netdev; list_for_each(l, &isdn_net_devs) {
q = NULL; isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
while (p) { if (!strcmp(p->local.name, name))
if (!strcmp(p->local->name, name)) return isdn_net_realrm(p);
return (isdn_net_realrm(p, q));
q = p;
p = (isdn_net_dev *) p->next;
} }
/* If no more net-devices remain, disable auto-hangup timer */
if (dev->netdev == NULL)
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
return -ENODEV; return -ENODEV;
} }
...@@ -3259,16 +3174,17 @@ isdn_net_rmall(void) ...@@ -3259,16 +3174,17 @@ isdn_net_rmall(void)
/* Walk through netdev-chain */ /* Walk through netdev-chain */
save_flags(flags); save_flags(flags);
cli(); cli();
while (dev->netdev) { while (!list_empty(&isdn_net_devs)) {
if (!dev->netdev->local->master) { isdn_net_dev *p = list_entry(isdn_net_devs.next, isdn_net_dev, global_list);
/* Remove master-devices only, slaves get removed with their master */
if ((ret = isdn_net_realrm(dev->netdev, NULL))) { /* Remove master-devices only, slaves get removed with their master */
if (!p->local.master) {
if ((ret = isdn_net_realrm(p))) {
restore_flags(flags); restore_flags(flags);
return ret; return ret;
} }
} }
} }
dev->netdev = NULL;
restore_flags(flags); restore_flags(flags);
return 0; return 0;
} }
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#define CISCO_SLARP_REPLY 1 #define CISCO_SLARP_REPLY 1
#define CISCO_SLARP_KEEPALIVE 2 #define CISCO_SLARP_KEEPALIVE 2
extern char *isdn_net_new(char *, struct net_device *); extern int isdn_net_new(char *, struct net_device *);
extern char *isdn_net_newslave(char *); extern int isdn_net_newslave(char *);
extern int isdn_net_rm(char *); extern int isdn_net_rm(char *);
extern int isdn_net_rmall(void); extern int isdn_net_rmall(void);
extern int isdn_net_stat_callback(int, isdn_ctrl *); extern int isdn_net_stat_callback(int, isdn_ctrl *);
...@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); ...@@ -44,7 +44,6 @@ 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(struct net_device *);
extern void isdn_net_dial(void);
extern void isdn_net_autohup(void); extern void isdn_net_autohup(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 *);
...@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp) ...@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
if (master_lp->netdev->queue == lp) { if (master_lp->netdev->queue == lp) {
master_lp->netdev->queue = lp->next; master_lp->netdev->queue = lp->next;
if (lp->next == lp) { /* last in queue */ if (lp->next == lp) { /* last in queue */
master_lp->netdev->queue = master_lp->netdev->local; master_lp->netdev->queue = &master_lp->netdev->local;
} }
} }
lp->next = lp->last = lp; /* (re)set own pointers */ lp->next = lp->last = lp; /* (re)set own pointers */
......
...@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp) ...@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp)
save_flags(flags); save_flags(flags);
cli(); cli();
if (lp->pppbind < 0) { /* device bounded to ippp device ? */ if (lp->pppbind < 0) { /* device bounded to ippp device ? */
isdn_net_dev *net_dev = dev->netdev; struct list_head *l;
char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
memset(exclusive, 0, ISDN_MAX_CHANNELS); memset(exclusive, 0, ISDN_MAX_CHANNELS);
while (net_dev) { /* step through net devices to find exclusive minors */ /* step through net devices to find exclusive minors */
isdn_net_local *lp = net_dev->local; list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *lp = &p->local;
if (lp->pppbind >= 0) if (lp->pppbind >= 0)
exclusive[lp->pppbind] = 1; exclusive[lp->pppbind] = 1;
net_dev = net_dev->next;
} }
/* /*
* search a free device / slot * search a free device / slot
...@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
if (proto != PPP_LCP) if (proto != PPP_LCP)
lp->huptimer = 0; lp->huptimer = 0;
if (lp->isdn_device < 0 || lp->isdn_channel < 0) { if (lp->isdn_slot < 0) {
retval = 0; retval = 0;
goto out; goto out;
} }
if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && if ((dev->drv[isdn_slot_driver(lp->isdn_slot)]->flags & DRV_FLAG_RUNNING) &&
lp->dialstate == 0 && lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED)) { (lp->flags & ISDN_NET_CONNECTED)) {
unsigned short hl; unsigned short hl;
...@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
* sk_buff. old call to dev_alloc_skb only reserved * sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want * 16 bytes, now we are looking what the driver want
*/ */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; hl = isdn_slot_hdrlen(lp->isdn_slot);
skb = alloc_skb(hl+count, GFP_ATOMIC); skb = alloc_skb(hl+count, GFP_ATOMIC);
if (!skb) { if (!skb) {
printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
...@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf ...@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
int slot; int slot;
int proto; int proto;
if (net_dev->local->master) if (net_dev->local.master)
BUG(); // we're called with the master device always BUG(); // we're called with the master device always
slot = lp->ppp_slot; slot = lp->ppp_slot;
...@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
case PPP_VJC_UNCOMP: case PPP_VJC_UNCOMP:
if (is->debug & 0x20) if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (net_dev->local->ppp_slot < 0) { if (net_dev->local.ppp_slot < 0) {
printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
net_dev->local->ppp_slot); net_dev->local.ppp_slot);
goto drop_packet; goto drop_packet;
} }
if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { if (slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n"); printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
goto drop_packet; goto drop_packet;
} }
...@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
} }
skb_put(skb, skb_old->len + 128); skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len); memcpy(skb->data, skb_old->data, skb_old->len);
if (net_dev->local->ppp_slot < 0) { if (net_dev->local.ppp_slot < 0) {
printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
net_dev->local->ppp_slot); net_dev->local.ppp_slot);
goto drop_packet; goto drop_packet;
} }
pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
skb->data, skb_old->len); skb->data, skb_old->len);
kfree_skb(skb_old); kfree_skb(skb_old);
if (pkt_len < 0) if (pkt_len < 0)
...@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return; return;
drop_packet: drop_packet:
net_dev->local->stats.rx_dropped++; net_dev->local.stats.rx_dropped++;
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
* sk_buff. old call to dev_alloc_skb only reserved * sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want. * 16 bytes, now we are looking what the driver want.
*/ */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; hl = isdn_slot_hdrlen(lp->isdn_slot) + IPPP_MAX_HEADER;;
/* /*
* Note: hl might still be insufficient because the method * Note: hl might still be insufficient because the method
* above does not account for a possibible MPPP slave channel * above does not account for a possibible MPPP slave channel
...@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name) ...@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name)
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
return 1; return 1;
lp = ndev->local; lp = &ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED)) if (!(lp->flags & ISDN_NET_CONNECTED))
return 5; return 5;
...@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name) ...@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name)
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
return 1; return 1;
lp = ndev->local; lp = &ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED)) if (!(lp->flags & ISDN_NET_CONNECTED))
return 5; return 5;
...@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, ...@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
isdn_net_local *lp = is->lp; isdn_net_local *lp = is->lp;
/* Alloc large enough skb */ /* Alloc large enough skb */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; hl = isdn_slot_hdrlen(lp->isdn_slot);
skb = alloc_skb(len + hl + 16,GFP_ATOMIC); skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
if(!skb) { if(!skb) {
printk(KERN_WARNING printk(KERN_WARNING
......
...@@ -128,7 +128,7 @@ isdn_tty_readmodem(void) ...@@ -128,7 +128,7 @@ isdn_tty_readmodem(void)
modem_info *info; modem_info *info;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if ((midx = dev->m_idx[i]) >= 0) { if ((midx = isdn_slot_m_idx(i)) >= 0) {
info = &dev->mdm.info[midx]; info = &dev->mdm.info[midx];
if (info->online) { if (info->online) {
r = 0; r = 0;
...@@ -143,9 +143,9 @@ isdn_tty_readmodem(void) ...@@ -143,9 +143,9 @@ isdn_tty_readmodem(void)
if (c > 0) { if (c > 0) {
save_flags(flags); save_flags(flags);
cli(); cli();
r = isdn_readbchan(info->isdn_driver, info->isdn_channel, r = isdn_slot_readbchan(info->isdn_slot,
tty->flip.char_buf_ptr, tty->flip.char_buf_ptr,
tty->flip.flag_buf_ptr, c, 0); tty->flip.flag_buf_ptr, c);
/* CISCO AsyncPPP Hack */ /* CISCO AsyncPPP Hack */
if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP)) if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
memset(tty->flip.flag_buf_ptr, 0, r); memset(tty->flip.flag_buf_ptr, 0, r);
...@@ -182,7 +182,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb) ...@@ -182,7 +182,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
#endif #endif
modem_info *info; modem_info *info;
if ((midx = dev->m_idx[i]) < 0) { if ((midx = isdn_slot_m_idx(i)) < 0) {
/* if midx is invalid, packet is not for tty */ /* if midx is invalid, packet is not for tty */
return 0; return 0;
} }
...@@ -315,8 +315,7 @@ isdn_tty_tint(modem_info * info) ...@@ -315,8 +315,7 @@ isdn_tty_tint(modem_info * info)
if (!skb) if (!skb)
return; return;
len = skb->len; len = skb->len;
if ((slen = isdn_writebuf_skb_stub(info->isdn_driver, if ((slen = isdn_slot_write(info->isdn_slot, skb)) == len) {
info->isdn_channel, 1, skb)) == len) {
struct tty_struct *tty = info->tty; struct tty_struct *tty = info->tty;
info->send_outstanding++; info->send_outstanding++;
info->msr &= ~UART_MSR_CTS; info->msr &= ~UART_MSR_CTS;
...@@ -479,11 +478,11 @@ isdn_tty_senddown(modem_info * info) ...@@ -479,11 +478,11 @@ isdn_tty_senddown(modem_info * info)
atomic_inc(&info->xmit_lock); atomic_inc(&info->xmit_lock);
if (!(atomic_dec_and_test(&info->xmit_lock))) if (!(atomic_dec_and_test(&info->xmit_lock)))
return; return;
if (info->isdn_driver < 0) { if (info->isdn_slot < 0) {
info->xmit_count = 0; info->xmit_count = 0;
return; return;
} }
skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4; skb_res = isdn_slot_hdrlen(info->isdn_slot);
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
if (info->vonline & 2) if (info->vonline & 2)
audio_len = buflen * voice_cf[info->emu.vpar[3]]; audio_len = buflen * voice_cf[info->emu.vpar[3]];
...@@ -627,7 +626,6 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m) ...@@ -627,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;
...@@ -652,56 +650,34 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m) ...@@ -652,56 +650,34 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
m->mdmreg[REG_SI1I] = si2bit[si]; m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags); save_flags(flags);
cli(); cli();
i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); i = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
if (i < 0) { if (i < 0) {
restore_flags(flags); restore_flags(flags);
isdn_tty_modem_result(RESULT_NO_DIALTONE, info); isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else { } else {
info->isdn_driver = dev->drvmap[i]; struct dial_info dial = {
info->isdn_channel = dev->chanmap[i]; .l2_proto = l2,
info->drv_index = i; .l3_proto = m->mdmreg[REG_L3PROT],
dev->m_idx[i] = info->line; .si1 = si,
dev->usage[i] |= ISDN_USAGE_OUTGOING; .si2 = m->mdmreg[REG_SI2],
.msn = m->msn,
.phone = n,
};
info->isdn_slot = i;
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_info_update();
restore_flags(flags); restore_flags(flags);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_CLREAZ;
isdn_command(&cmd);
strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETEAZ;
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL2;
info->last_l2 = l2;
cmd.arg = info->isdn_channel + (l2 << 8);
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL3;
cmd.arg = info->isdn_channel + (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_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
sprintf(cmd.parm.setup.phone, "%s", n);
sprintf(cmd.parm.setup.eazmsn, "%s",
isdn_map_eaz2msn(m->msn, info->isdn_driver));
cmd.parm.setup.si1 = si;
cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
cmd.command = ISDN_CMD_DIAL;
info->dialing = 1; info->dialing = 1;
info->emu.carrierwait = 0; info->emu.carrierwait = 0;
strcpy(dev->num[i], n); isdn_slot_dial(info->isdn_slot, &dial);
isdn_info_update();
isdn_command(&cmd);
isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
} }
} }
...@@ -714,19 +690,15 @@ void ...@@ -714,19 +690,15 @@ void
isdn_tty_modem_hup(modem_info * info, int local) isdn_tty_modem_hup(modem_info * info, int local)
{ {
isdn_ctrl cmd; isdn_ctrl cmd;
int di, ch; int slot;
if (!info) if (!info)
return; return;
di = info->isdn_driver; slot = info->isdn_slot;
ch = info->isdn_channel; if (slot < 0)
if (di < 0 || ch < 0)
return; return;
info->isdn_driver = -1;
info->isdn_channel = -1;
#ifdef ISDN_DEBUG_MODEM_HUP #ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup ttyI%d\n", info->line); printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
#endif #endif
...@@ -768,21 +740,14 @@ isdn_tty_modem_hup(modem_info * info, int local) ...@@ -768,21 +740,14 @@ isdn_tty_modem_hup(modem_info * info, int local)
info->msr &= ~(UART_MSR_DCD | UART_MSR_RI); info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
info->lsr |= UART_LSR_TEMT; info->lsr |= UART_LSR_TEMT;
if (local) { if (local)
cmd.driver = di; isdn_slot_command(slot, ISDN_CMD_HANGUP, &cmd);
cmd.command = ISDN_CMD_HANGUP;
cmd.arg = ch;
isdn_command(&cmd);
}
isdn_all_eaz(di, ch); isdn_slot_all_eaz(slot);
info->emu.mdmreg[REG_RINGCNT] = 0; info->emu.mdmreg[REG_RINGCNT] = 0;
isdn_free_channel(di, ch, 0); isdn_slot_free(slot, 0);
isdn_slot_set_m_idx(slot, -1);
if (info->drv_index >= 0) { info->isdn_slot = -1;
dev->m_idx[info->drv_index] = -1;
info->drv_index = -1;
}
} }
/* /*
...@@ -812,11 +777,11 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m) ...@@ -812,11 +777,11 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
printk(KERN_DEBUG "Msusp ttyI%d\n", info->line); printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
#endif #endif
l = strlen(id); l = strlen(id);
if ((info->isdn_driver >= 0)) { if ((info->isdn_slot >= 0)) {
cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Length = l+18;
cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Command = CAPI_FACILITY;
cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.Subcommand = CAPI_REQ;
cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; cmd.parm.cmsg.adr.Controller = isdn_slot_driver(info->isdn_slot) + 1;
cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
cmd.parm.cmsg.para[1] = 0; cmd.parm.cmsg.para[1] = 0;
cmd.parm.cmsg.para[2] = l + 3; cmd.parm.cmsg.para[2] = l + 3;
...@@ -824,10 +789,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m) ...@@ -824,10 +789,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
cmd.parm.cmsg.para[4] = 0; cmd.parm.cmsg.para[4] = 0;
cmd.parm.cmsg.para[5] = l; cmd.parm.cmsg.para[5] = l;
strncpy(&cmd.parm.cmsg.para[6], id, l); strncpy(&cmd.parm.cmsg.para[6], id, l);
cmd.command = CAPI_PUT_MESSAGE; isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
isdn_command(&cmd);
} }
} }
...@@ -871,43 +833,26 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) ...@@ -871,43 +833,26 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
m->mdmreg[REG_SI1I] = si2bit[si]; m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags); save_flags(flags);
cli(); cli();
i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); i = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
if (i < 0) { if (i < 0) {
restore_flags(flags); restore_flags(flags);
isdn_tty_modem_result(RESULT_NO_DIALTONE, info); isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else { } else {
info->isdn_driver = dev->drvmap[i]; info->isdn_slot = i;
info->isdn_channel = dev->chanmap[i]; isdn_slot_set_m_idx(i, info->line);
info->drv_index = i; isdn_slot_set_usage(i, isdn_slot_usage(i) | ISDN_USAGE_OUTGOING);
dev->m_idx[i] = info->line;
dev->usage[i] |= ISDN_USAGE_OUTGOING;
info->last_dir = 1; info->last_dir = 1;
// strcpy(info->last_num, n); // strcpy(info->last_num, n);
isdn_info_update();
restore_flags(flags); restore_flags(flags);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_CLREAZ;
isdn_command(&cmd);
strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETEAZ;
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL2;
info->last_l2 = l2; info->last_l2 = l2;
cmd.arg = info->isdn_channel + (l2 << 8); cmd.arg = l2 << 8;
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.driver = info->isdn_driver; cmd.arg = m->mdmreg[REG_L3PROT] << 8;
cmd.command = ISDN_CMD_SETL3; isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Length = l+18;
cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Command = CAPI_FACILITY;
cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.Subcommand = CAPI_REQ;
cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; cmd.parm.cmsg.adr.Controller = isdn_slot_driver(info->isdn_slot) + 1;
cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
cmd.parm.cmsg.para[1] = 0; cmd.parm.cmsg.para[1] = 0;
cmd.parm.cmsg.para[2] = l+3; cmd.parm.cmsg.para[2] = l+3;
...@@ -915,11 +860,10 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) ...@@ -915,11 +860,10 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
cmd.parm.cmsg.para[4] = 0; cmd.parm.cmsg.para[4] = 0;
cmd.parm.cmsg.para[5] = l; cmd.parm.cmsg.para[5] = l;
strncpy(&cmd.parm.cmsg.para[6], id, l); strncpy(&cmd.parm.cmsg.para[6], id, l);
cmd.command =CAPI_PUT_MESSAGE;
info->dialing = 1; info->dialing = 1;
// strcpy(dev->num[i], n); // strcpy(dev->num[i], n);
isdn_info_update(); isdn_info_update();
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd);
isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
} }
} }
...@@ -965,51 +909,33 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg) ...@@ -965,51 +909,33 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
m->mdmreg[REG_SI1I] = si2bit[si]; m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags); save_flags(flags);
cli(); cli();
i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); i = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
if (i < 0) { if (i < 0) {
restore_flags(flags); restore_flags(flags);
isdn_tty_modem_result(RESULT_NO_DIALTONE, info); isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else { } else {
info->isdn_driver = dev->drvmap[i]; info->isdn_slot = i;
info->isdn_channel = dev->chanmap[i]; isdn_slot_set_m_idx(i, info->line);
info->drv_index = i; isdn_slot_set_usage(i, isdn_slot_usage(i) | ISDN_USAGE_OUTGOING);
dev->m_idx[i] = info->line;
dev->usage[i] |= ISDN_USAGE_OUTGOING;
info->last_dir = 1; info->last_dir = 1;
isdn_info_update();
restore_flags(flags); restore_flags(flags);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_CLREAZ;
isdn_command(&cmd);
strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETEAZ;
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL2;
info->last_l2 = l2; info->last_l2 = l2;
cmd.arg = info->isdn_channel + (l2 << 8); cmd.arg = l2 << 8;
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.driver = info->isdn_driver; cmd.arg = m->mdmreg[REG_L3PROT] << 8;
cmd.command = ISDN_CMD_SETL3; isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.parm.cmsg.Length = l+14; cmd.parm.cmsg.Length = l+14;
cmd.parm.cmsg.Command = CAPI_MANUFACTURER; cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.Subcommand = CAPI_REQ;
cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; cmd.parm.cmsg.adr.Controller = isdn_slot_driver(info->isdn_slot) + 1;
cmd.parm.cmsg.para[0] = l+1; cmd.parm.cmsg.para[0] = l+1;
strncpy(&cmd.parm.cmsg.para[1], msg, l); strncpy(&cmd.parm.cmsg.para[1], msg, l);
cmd.parm.cmsg.para[l+1] = 0xd; cmd.parm.cmsg.para[l+1] = 0xd;
cmd.command =CAPI_PUT_MESSAGE;
/* info->dialing = 1; /* info->dialing = 1;
strcpy(dev->num[i], n); strcpy(dev->num[i], n);
isdn_info_update(); isdn_info_update();
*/ */
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd);
} }
} }
...@@ -1173,6 +1099,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co ...@@ -1173,6 +1099,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
{ {
int c; int c;
int total = 0; int total = 0;
int di;
modem_info *info = (modem_info *) tty->driver_data; modem_info *info = (modem_info *) tty->driver_data;
atemu *m = &info->emu; atemu *m = &info->emu;
...@@ -1186,8 +1113,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co ...@@ -1186,8 +1113,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
c = count; c = count;
if (c > info->xmit_size - info->xmit_count) if (c > info->xmit_size - info->xmit_count)
c = info->xmit_size - info->xmit_count; c = info->xmit_size - info->xmit_count;
if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize) di = isdn_slot_driver(info->isdn_slot);
c = dev->drv[info->isdn_driver]->maxbufsize; if (di >= 0 && c > dev->drv[di]->maxbufsize)
c = dev->drv[di]->maxbufsize;
if (c <= 0) if (c <= 0)
break; break;
if ((info->online > 1) if ((info->online > 1)
...@@ -1247,12 +1175,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co ...@@ -1247,12 +1175,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
if (info->vonline & 4) { /* ETX seen */ if (info->vonline & 4) { /* ETX seen */
isdn_ctrl c; isdn_ctrl c;
c.command = ISDN_CMD_FAXCMD;
c.driver = info->isdn_driver;
c.arg = info->isdn_channel;
c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL; c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
c.parm.aux.subcmd = ETX; c.parm.aux.subcmd = ETX;
isdn_command(&c); isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
} }
info->vonline = 0; info->vonline = 0;
#ifdef ISDN_DEBUG_MODEM_VOICE #ifdef ISDN_DEBUG_MODEM_VOICE
...@@ -2015,10 +1940,10 @@ modem_write_profile(atemu * m) ...@@ -2015,10 +1940,10 @@ modem_write_profile(atemu * m)
} }
int int
isdn_tty_modem_init(void) isdn_tty_init(void)
{ {
modem *m; modem *m;
int i; int i, retval;
modem_info *info; modem_info *info;
m = &dev->mdm; m = &dev->mdm;
...@@ -2063,13 +1988,15 @@ isdn_tty_modem_init(void) ...@@ -2063,13 +1988,15 @@ isdn_tty_modem_init(void)
m->tty_modem.minor_start = 0; m->tty_modem.minor_start = 0;
m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT; m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT;
if (tty_register_driver(&m->tty_modem)) { retval = tty_register_driver(&m->tty_modem);
if (retval) {
printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n"); printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
return -1; goto err;
} }
if (tty_register_driver(&m->cua_modem)) { retval = tty_register_driver(&m->cua_modem);
if (retval) {
printk(KERN_WARNING "isdn_tty: Couldn't register modem-callout-device\n"); printk(KERN_WARNING "isdn_tty: Couldn't register modem-callout-device\n");
return -2; goto err_unregister_tty;
} }
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i]; info = &m->info[i];
...@@ -2098,24 +2025,58 @@ isdn_tty_modem_init(void) ...@@ -2098,24 +2025,58 @@ isdn_tty_modem_init(void)
info->normal_termios = m->tty_modem.init_termios; info->normal_termios = m->tty_modem.init_termios;
init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->close_wait);
info->isdn_driver = -1; info->isdn_slot = -1;
info->isdn_channel = -1;
info->drv_index = -1;
info->xmit_size = ISDN_SERIAL_XMIT_SIZE; info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
skb_queue_head_init(&info->xmit_queue); skb_queue_head_init(&info->xmit_queue);
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
skb_queue_head_init(&info->dtmf_queue); skb_queue_head_init(&info->dtmf_queue);
#endif #endif
if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) { info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL);
if (!info->xmit_buf) {
printk(KERN_ERR "Could not allocate modem xmit-buffer\n"); printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
return -3; #ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
goto err_unregister_cua;
} }
/* Make room for T.70 header */ /* Make room for T.70 header */
info->xmit_buf += 4; info->xmit_buf += 4;
} }
return 0; return 0;
err_unregister_cua:
for (i--; i >= 0; i--) {
info = &m->info[i];
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
kfree(info->xmit_buf - 4);
}
tty_unregister_driver(&dev->mdm.cua_modem);
err_unregister_tty:
tty_unregister_driver(&dev->mdm.tty_modem);
err:
return retval;
} }
void
isdn_tty_exit(void)
{
modem *m = &dev->mdm;
modem_info *info;
int i;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i];
isdn_tty_cleanup_xmit(info);
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
kfree(info->xmit_buf - 4);
}
tty_unregister_driver(&dev->mdm.cua_modem);
tty_unregister_driver(&dev->mdm.tty_modem);
}
/* /*
* isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx) * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
...@@ -2227,26 +2188,21 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) ...@@ -2227,26 +2188,21 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
#ifndef FIX_FILE_TRANSFER #ifndef FIX_FILE_TRANSFER
(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) && (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
#endif #endif
(info->isdn_driver == -1) && (info->isdn_slot == -1) &&
(info->isdn_channel == -1) && (USG_NONE(isdn_slot_usage(idx)))) {
(USG_NONE(dev->usage[idx]))) {
int matchret; int matchret;
if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret) if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
wret = matchret; wret = matchret;
if (!matchret) { /* EAZ is matching */ if (!matchret) { /* EAZ is matching */
info->isdn_driver = di; info->isdn_slot = idx;
info->isdn_channel = ch; isdn_slot_set_m_idx(idx, info->line);
info->drv_index = idx; strcpy(isdn_slot_num(idx), nr);
dev->m_idx[idx] = info->line;
dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
strcpy(dev->num[idx], nr);
strcpy(info->emu.cpn, eaz); strcpy(info->emu.cpn, eaz);
info->emu.mdmreg[REG_SI1I] = si2bit[si1]; info->emu.mdmreg[REG_SI1I] = si2bit[si1];
info->emu.mdmreg[REG_PLAN] = setup->plan; info->emu.mdmreg[REG_PLAN] = setup->plan;
info->emu.mdmreg[REG_SCREEN] = setup->screen; info->emu.mdmreg[REG_SCREEN] = setup->screen;
isdn_info_update(); isdn_slot_set_usage(idx, (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) | isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]));
restore_flags(flags); restore_flags(flags);
printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr, printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
info->line); info->line);
...@@ -2276,7 +2232,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) ...@@ -2276,7 +2232,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
if (i < 0) if (i < 0)
return 0; return 0;
if ((mi = dev->m_idx[i]) >= 0) { if ((mi = isdn_slot_m_idx(i)) >= 0) {
info = &dev->mdm.info[mi]; info = &dev->mdm.info[mi];
switch (c->command) { switch (c->command) {
case ISDN_STAT_CINF: case ISDN_STAT_CINF:
...@@ -2290,8 +2246,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) ...@@ -2290,8 +2246,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#ifdef ISDN_TTY_STAT_DEBUG #ifdef ISDN_TTY_STAT_DEBUG
printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line); printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
#endif #endif
if ((info->isdn_driver == c->driver) && if ((info->isdn_slot == isdn_dc2minor(c->driver, c->arg))) {
(info->isdn_channel == c->arg)) {
info->msr |= UART_MSR_CTS; info->msr |= UART_MSR_CTS;
if (info->send_outstanding) if (info->send_outstanding)
if (!(--info->send_outstanding)) if (!(--info->send_outstanding))
...@@ -2375,14 +2330,14 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) ...@@ -2375,14 +2330,14 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
info->last_dir = 0; info->last_dir = 0;
info->dialing = 0; info->dialing = 0;
info->rcvsched = 1; info->rcvsched = 1;
if (USG_MODEM(dev->usage[i])) { if (USG_MODEM(isdn_slot_usage(i))) {
if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) { if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
strcpy(info->emu.connmsg, c->parm.num); strcpy(info->emu.connmsg, c->parm.num);
isdn_tty_modem_result(RESULT_CONNECT, info); isdn_tty_modem_result(RESULT_CONNECT, info);
} else } else
isdn_tty_modem_result(RESULT_CONNECT64000, info); isdn_tty_modem_result(RESULT_CONNECT64000, info);
} }
if (USG_VOICE(dev->usage[i])) if (USG_VOICE(isdn_slot_usage(i)))
isdn_tty_modem_result(RESULT_VCON, info); isdn_tty_modem_result(RESULT_VCON, info);
return 1; return 1;
} }
...@@ -2421,7 +2376,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) ...@@ -2421,7 +2376,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#endif #endif
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &dev->mdm.info[i]; info = &dev->mdm.info[i];
if (info->isdn_driver == c->driver) { if (isdn_slot_driver(info->isdn_slot) == c->driver) {
if (info->online) if (info->online)
isdn_tty_modem_hup(info, 1); isdn_tty_modem_hup(info, 1);
} }
...@@ -2473,6 +2428,7 @@ isdn_tty_at_cout(char *msg, modem_info * info) ...@@ -2473,6 +2428,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
ulong flags; ulong flags;
struct sk_buff *skb = 0; struct sk_buff *skb = 0;
char *sp = 0; char *sp = 0;
int di,ch;
if (!msg) { if (!msg) {
printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n"); printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
...@@ -2488,8 +2444,9 @@ isdn_tty_at_cout(char *msg, modem_info * info) ...@@ -2488,8 +2444,9 @@ isdn_tty_at_cout(char *msg, modem_info * info)
/* use queue instead of direct flip, if online and */ /* use queue instead of direct flip, if online and */
/* data is in queue or flip buffer is full */ /* data is in queue or flip buffer is full */
di = isdn_slot_driver(info->isdn_slot); ch = isdn_slot_channel(info->isdn_slot);
if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) || if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
(!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) { (!skb_queue_empty(&dev->drv[di]->rpqueue[ch])))) {
skb = alloc_skb(strlen(msg) skb = alloc_skb(strlen(msg)
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
+ sizeof(isdn_audio_skb) + sizeof(isdn_audio_skb)
...@@ -2532,8 +2489,8 @@ isdn_tty_at_cout(char *msg, modem_info * info) ...@@ -2532,8 +2489,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
} }
} }
if (skb) { if (skb) {
__skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len; dev->drv[di]->rcvcount[ch] += skb->len;
restore_flags(flags); restore_flags(flags);
/* Schedule dequeuing */ /* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched)) if ((dev->modempoll) && (info->rcvsched))
...@@ -2551,7 +2508,7 @@ isdn_tty_at_cout(char *msg, modem_info * info) ...@@ -2551,7 +2508,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
static void static void
isdn_tty_on_hook(modem_info * info) isdn_tty_on_hook(modem_info * info)
{ {
if (info->isdn_channel >= 0) { if (info->isdn_slot >= 0) {
#ifdef ISDN_DEBUG_MODEM_HUP #ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n"); printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
#endif #endif
...@@ -2711,7 +2668,7 @@ isdn_tty_modem_result(int code, modem_info * info) ...@@ -2711,7 +2668,7 @@ isdn_tty_modem_result(int code, modem_info * info)
/* print CID, _before_ _every_ ring */ /* print CID, _before_ _every_ ring */
if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) { if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
isdn_tty_at_cout("\r\nCALLER NUMBER: ", info); isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
isdn_tty_at_cout(dev->num[info->drv_index], info); isdn_tty_at_cout(isdn_slot_num(info->isdn_slot), info);
if (m->mdmreg[REG_CDN] & BIT_CDN) { if (m->mdmreg[REG_CDN] & BIT_CDN) {
isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
isdn_tty_at_cout(info->emu.cpn, info); isdn_tty_at_cout(info->emu.cpn, info);
...@@ -2740,7 +2697,7 @@ isdn_tty_modem_result(int code, modem_info * info) ...@@ -2740,7 +2697,7 @@ isdn_tty_modem_result(int code, modem_info * info)
(m->mdmreg[REG_RINGCNT] == 1)) { (m->mdmreg[REG_RINGCNT] == 1)) {
isdn_tty_at_cout("\r\n", info); isdn_tty_at_cout("\r\n", info);
isdn_tty_at_cout("CALLER NUMBER: ", info); isdn_tty_at_cout("CALLER NUMBER: ", info);
isdn_tty_at_cout(dev->num[info->drv_index], info); isdn_tty_at_cout(isdn_slot_num(info->isdn_slot), info);
if (m->mdmreg[REG_CDN] & BIT_CDN) { if (m->mdmreg[REG_CDN] & BIT_CDN) {
isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
isdn_tty_at_cout(info->emu.cpn, info); isdn_tty_at_cout(info->emu.cpn, info);
...@@ -3252,7 +3209,7 @@ isdn_tty_cmd_ATA(modem_info * info) ...@@ -3252,7 +3209,7 @@ isdn_tty_cmd_ATA(modem_info * info)
if (info->msr & UART_MSR_RI) { if (info->msr & UART_MSR_RI) {
/* Accept incoming call */ /* Accept incoming call */
info->last_dir = 0; info->last_dir = 0;
strcpy(info->last_num, dev->num[info->drv_index]); strcpy(info->last_num, isdn_slot_num(info->isdn_slot));
m->mdmreg[REG_RINGCNT] = 0; m->mdmreg[REG_RINGCNT] = 0;
info->msr &= ~UART_MSR_RI; info->msr &= ~UART_MSR_RI;
l2 = m->mdmreg[REG_L2PROT]; l2 = m->mdmreg[REG_L2PROT];
...@@ -3266,27 +3223,20 @@ isdn_tty_cmd_ATA(modem_info * info) ...@@ -3266,27 +3223,20 @@ isdn_tty_cmd_ATA(modem_info * info)
l2 = ISDN_PROTO_L2_X75I; l2 = ISDN_PROTO_L2_X75I;
} }
#endif #endif
cmd.driver = info->isdn_driver; cmd.arg = l2 << 8;
cmd.command = ISDN_CMD_SETL2;
cmd.arg = info->isdn_channel + (l2 << 8);
info->last_l2 = l2; info->last_l2 = l2;
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.driver = info->isdn_driver; cmd.arg = m->mdmreg[REG_L3PROT] << 8;
cmd.command = ISDN_CMD_SETL3;
cmd.arg = info->isdn_channel + (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; cmd.parm.fax = info->fax;
info->fax->direction = ISDN_TTY_FAX_CONN_IN; info->fax->direction = ISDN_TTY_FAX_CONN_IN;
} }
#endif #endif
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_ACCEPTD;
info->dialing = 16; info->dialing = 16;
info->emu.carrierwait = 0; info->emu.carrierwait = 0;
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTD, &cmd);
isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
} else } else
isdn_tty_modem_result(RESULT_NO_ANSWER, info); isdn_tty_modem_result(RESULT_NO_ANSWER, info);
...@@ -3642,12 +3592,10 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info) ...@@ -3642,12 +3592,10 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
m->vpar[4] = par1; m->vpar[4] = par1;
m->vpar[5] = par2; m->vpar[5] = par2;
cmd.driver = info->isdn_driver; cmd.arg = ISDN_AUDIO_SETDD << 8;
cmd.command = ISDN_CMD_AUDIO;
cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
cmd.parm.num[0] = par1; cmd.parm.num[0] = par1;
cmd.parm.num[1] = par2; cmd.parm.num[1] = par2;
isdn_command(&cmd); isdn_slot_command(info->isdn_slot, ISDN_CMD_AUDIO, &cmd);
break; break;
} else } else
if (*p[0] == '?') { if (*p[0] == '?') {
...@@ -3973,8 +3921,8 @@ isdn_tty_modem_escape(void) ...@@ -3973,8 +3921,8 @@ isdn_tty_modem_escape(void)
int midx; int midx;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (USG_MODEM(dev->usage[i])) if (USG_MODEM(isdn_slot_usage(i)))
if ((midx = dev->m_idx[i]) >= 0) { if ((midx = isdn_slot_m_idx(i)) >= 0) {
modem_info *info = &dev->mdm.info[midx]; modem_info *info = &dev->mdm.info[midx];
if (info->online) { if (info->online) {
ton = 1; ton = 1;
......
...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void); ...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void); extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void); extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void); extern void isdn_tty_modem_xmit(void);
extern int isdn_tty_modem_init(void); extern int isdn_tty_init(void);
extern void isdn_tty_readmodem(void); extern void isdn_tty_readmodem(void);
extern int isdn_tty_find_icall(int, int, setup_parm *); extern int isdn_tty_find_icall(int, int, setup_parm *);
extern void isdn_tty_cleanup_xmit(modem_info *); extern void isdn_tty_cleanup_xmit(modem_info *);
...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *); ...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *); extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *); extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
#endif #endif
extern int isdn_tty_init(void);
extern void isdn_tty_exit(void);
...@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info) ...@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
case 2: /* +FCON */ case 2: /* +FCON */
/* Append CPN, if enabled */ /* Append CPN, if enabled */
if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) && if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) &&
(!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { (!(isdn_slot_usage(info->isdn_slot) & ISDN_USAGE_OUTGOING))) {
sprintf(rs, "/%s", m->cpn); sprintf(rs, "/%s", m->cpn);
isdn_tty_at_cout(rs, info); isdn_tty_at_cout(rs, info);
} }
...@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info) ...@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
default: default:
PARSE_ERROR1; PARSE_ERROR1;
} }
c.command = ISDN_CMD_FAXCMD;
#ifdef ISDN_TTY_FAX_CMD_DEBUG #ifdef ISDN_TTY_FAX_CMD_DEBUG
printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n", printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]); c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
#endif #endif
if (info->isdn_driver < 0) { if (info->isdn_slot < 0) {
save_flags(flags); save_flags(flags);
cli(); cli();
if ((c.parm.aux.subcmd == AT_EQ_VALUE) || if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
...@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info) ...@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
} }
/* get a temporary connection to the first free fax driver */ /* get a temporary connection to the first free fax driver */
i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, i = isdn_get_free_slot(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
if (i < 0) { if (i < 0) {
restore_flags(flags); restore_flags(flags);
PARSE_ERROR1; PARSE_ERROR1;
} }
info->isdn_driver = dev->drvmap[i]; info->isdn_slot = i;
info->isdn_channel = dev->chanmap[i]; isdn_slot_set_m_idx(i, info->line);
info->drv_index = i; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
dev->m_idx[i] = info->line; isdn_slot_free(info->isdn_slot, ISDN_USAGE_FAX);
c.driver = info->isdn_driver; isdn_slot_set_m_idx(i, -1);
c.arg = info->isdn_channel; info->isdn_slot = -1;
isdn_command(&c);
isdn_free_channel(info->isdn_driver, info->isdn_channel,
ISDN_USAGE_FAX);
info->isdn_driver = -1;
info->isdn_channel = -1;
if (info->drv_index >= 0) {
dev->m_idx[info->drv_index] = -1;
info->drv_index = -1;
}
restore_flags(flags); restore_flags(flags);
} else { } else {
c.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
c.arg = info->isdn_channel;
isdn_command(&c);
} }
return 1; return 1;
} }
...@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
printk(KERN_DEBUG "isdn_tty: Fax FDR\n"); printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
#endif #endif
f->code = ISDN_TTY_FAX_DR; f->code = ISDN_TTY_FAX_DR;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_B) { if (f->phase == ISDN_FAX_PHASE_B) {
f->phase = ISDN_FAX_PHASE_C; f->phase = ISDN_FAX_PHASE_C;
} else if (f->phase == ISDN_FAX_PHASE_D) { } else if (f->phase == ISDN_FAX_PHASE_D) {
...@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
#endif #endif
if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) { if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
f->code = ISDN_TTY_FAX_DT; f->code = ISDN_TTY_FAX_DT;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_D) { if (f->phase == ISDN_FAX_PHASE_D) {
f->phase = ISDN_FAX_PHASE_C; f->phase = ISDN_FAX_PHASE_C;
isdn_tty_fax_modem_result(7, info); /* CONNECT */ isdn_tty_fax_modem_result(7, info); /* CONNECT */
...@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
f->fet = par; f->fet = par;
f->code = ISDN_TTY_FAX_ET; f->code = ISDN_TTY_FAX_ET;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
#ifdef ISDN_TTY_FAX_STAT_DEBUG #ifdef ISDN_TTY_FAX_STAT_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par); printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
#endif #endif
......
...@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb) ...@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
} }
int int
isdn_v110_stat_callback(int idx, isdn_ctrl * c) isdn_v110_stat_callback(struct isdn_v110 *iv110, isdn_ctrl *c)
{ {
isdn_v110_stream *v = NULL; isdn_v110_stream *v = NULL;
int i; int i;
int ret; int ret;
if (idx < 0)
return 0;
switch (c->command) { switch (c->command) {
case ISDN_STAT_BSENT: case ISDN_STAT_BSENT:
/* Keep the send-queue of the driver filled /* Keep the send-queue of the driver filled
...@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
* send down an Idle-Frame (or an Sync-Frame, if * send down an Idle-Frame (or an Sync-Frame, if
* v->SyncInit != 0). * v->SyncInit != 0).
*/ */
if (!(v = dev->v110[idx])) if (!(v = iv110->v110))
return 0; return 0;
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
if (v->skbidle > 0) { if (v->skbidle > 0) {
v->skbidle--; v->skbidle--;
ret = 1; ret = 1;
...@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
} else } else
break; break;
} }
atomic_dec(&dev->v110use[idx]); atomic_dec(&iv110->v110use);
return ret; return ret;
case ISDN_STAT_DHUP: case ISDN_STAT_DHUP:
case ISDN_STAT_BHUP: case ISDN_STAT_BHUP:
while (1) { while (1) {
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
if (atomic_dec_and_test(&dev->v110use[idx])) { if (atomic_dec_and_test(&iv110->v110use)) {
isdn_v110_close(dev->v110[idx]); isdn_v110_close(iv110->v110);
dev->v110[idx] = NULL; iv110->v110 = NULL;
break; break;
} }
sti(); sti();
} }
break; break;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) { if (iv110->v110emu && (iv110->v110 == NULL)) {
int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen; int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
int maxsize = dev->drv[c->driver]->interface->maxbufsize; int maxsize = dev->drv[c->driver]->interface->maxbufsize;
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
switch (dev->v110emu[idx]) { switch (iv110->v110emu) {
case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11096:
dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_9600, hdrlen, maxsize);
break; break;
case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11019:
dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_19200, hdrlen, maxsize);
break; break;
case ISDN_PROTO_L2_V11038: case ISDN_PROTO_L2_V11038:
dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_38400, hdrlen, maxsize);
break; break;
default:; default:;
} }
if ((v = dev->v110[idx])) { if ((v = iv110->v110)) {
while (v->SyncInit) { while (v->SyncInit) {
struct sk_buff *skb = isdn_v110_sync(v); struct sk_buff *skb = isdn_v110_sync(v);
if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
...@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
v->skbidle++; v->skbidle++;
} }
} else } else
printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx); printk(KERN_WARNING "isdn_v110: Couldn't open stream\n");
atomic_dec(&dev->v110use[idx]); atomic_dec(&iv110->v110use);
} }
break; break;
default: default:
......
...@@ -9,8 +9,14 @@ ...@@ -9,8 +9,14 @@
* *
*/ */
#ifndef _isdn_v110_h_ #ifndef ISDN_V110_H
#define _isdn_v110_h_ #define ISDN_V110_H
struct isdn_v110 {
int v110emu; /* V.110 emulator-mode 0=none */
atomic_t v110use; /* Usage-Semaphore for stream */
isdn_v110_stream *v110; /* V.110 private data */
};
/* /*
* isdn_v110_encode will take raw data and encode it using V.110 * isdn_v110_encode will take raw data and encode it using V.110
...@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); ...@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
*/ */
extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
extern int isdn_v110_stat_callback(int, isdn_ctrl *); extern int isdn_v110_stat_callback(struct isdn_v110 *v110, isdn_ctrl *);
extern void isdn_v110_close(isdn_v110_stream * v); extern void isdn_v110_close(isdn_v110_stream * v);
#endif #endif
...@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) ...@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
int i; int i;
static char nphone[30]; static char nphone[30];
if (!card) {
printk("BUG!!!\n");
return "";
}
switch (card->ptype) { switch (card->ptype) {
case ISDN_PTYPE_EURO: case ISDN_PTYPE_EURO:
if (caller) { if (caller) {
...@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) ...@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
return (&phone[strlen(phone) - 1]); return (&phone[strlen(phone) - 1]);
break; break;
} }
return ("\0"); return "";
} }
/* /*
...@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card) ...@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card)
isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1), isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1),
cmd.parm.setup.si1, cmd.parm.setup.si1,
cmd.parm.setup.si2, cmd.parm.setup.si2,
isdnloop_vstphone(card->rcard[ch], isdnloop_vstphone(card->rcard[ch - 1],
cmd.parm.setup.phone, 0)); cmd.parm.setup.phone, 0));
isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1); isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1);
/* Fall through */ /* Fall through */
......
...@@ -245,18 +245,12 @@ typedef struct { ...@@ -245,18 +245,12 @@ 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_NETDIAL 16
#define ISDN_TIMER_NETHANGUP 32 #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_NETHANGUP | \
ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER) ISDN_TIMER_CARRIER)
/* Timeout-Values for isdn_net_dial() */
#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
/* GLOBAL_FLAGS */ /* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1 #define ISDN_GLOBAL_STOPPED 1
...@@ -291,9 +285,10 @@ typedef struct { ...@@ -291,9 +285,10 @@ typedef struct {
typedef struct isdn_net_local_s { typedef struct isdn_net_local_s {
ulong magic; ulong magic;
char name[10]; /* Name of device */ char name[10]; /* Name of device */
struct timer_list dial_timer; /* dial timeout */
int dial_event; /* event in case of timer expiry */
struct net_device_stats stats; /* Ethernet Statistics */ struct net_device_stats stats; /* Ethernet Statistics */
int isdn_device; /* Index to isdn-device */ int isdn_slot; /* Index to isdn device/channel */
int isdn_channel; /* Index to isdn-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 */
int pre_channel; /* Preselected isdn-channel */ int pre_channel; /* Preselected isdn-channel */
...@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s { ...@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s {
int dialretry; /* Counter for Dialout-retries */ int dialretry; /* Counter for Dialout-retries */
int dialmax; /* Max. Number of Dial-retries */ int dialmax; /* Max. Number of Dial-retries */
int cbdelay; /* Delay before Callback starts */ int cbdelay; /* Delay before Callback starts */
int dtimer; /* Timeout-counter for dialing */
char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */ char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
u_char cbhup; /* Flag: Reject Call before Callback*/ u_char cbhup; /* Flag: Reject Call before Callback*/
u_char dialstate; /* State for dialing */ u_char dialstate; /* State for dialing */
...@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s { ...@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s {
/* the interface itself */ /* the interface itself */
typedef struct isdn_net_dev_s { typedef struct isdn_net_dev_s {
isdn_net_local *local; isdn_net_local local;
isdn_net_local *queue; /* circular list of all bundled isdn_net_local *queue; /* circular list of all bundled
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 list_head global_list; /* global list of all isdn_net_devs */
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
...@@ -480,9 +474,7 @@ typedef struct modem_info { ...@@ -480,9 +474,7 @@ typedef struct modem_info {
/* 2 = B-Channel is up, deliver d.*/ /* 2 = B-Channel is up, deliver d.*/
int dialing; /* Dial in progress or ATA */ int dialing; /* Dial in progress or ATA */
int rcvsched; /* Receive needs schedule */ int rcvsched; /* Receive needs schedule */
int isdn_driver; /* Index to isdn-driver */ int isdn_slot; /* Index to isdn-driver/channel */
int isdn_channel; /* Index to isdn-channel */
int drv_index; /* Index to dev->usage */
int ncarrier; /* Flag: schedule NO CARRIER */ int ncarrier; /* Flag: schedule NO CARRIER */
unsigned char last_cause[8]; /* Last cause message */ unsigned char last_cause[8]; /* Last cause message */
unsigned char last_num[ISDN_MSNLEN]; unsigned char last_num[ISDN_MSNLEN];
...@@ -608,24 +600,10 @@ typedef struct isdn_devt { ...@@ -608,24 +600,10 @@ typedef struct isdn_devt {
infostruct *infochain; /* List of open info-devs. */ infostruct *infochain; /* List of open info-devs. */
wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */ wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */
struct timer_list timer; /* Misc.-function Timer */ struct timer_list timer; /* Misc.-function Timer */
int chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel */
int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */
int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */
char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
/* Remote number of active ch.*/
int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */
driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */ driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */
isdn_net_dev *netdev; /* Linked list of net-if's */
char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */ char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */
struct task_struct *profd; /* For iprofd */ struct task_struct *profd; /* For iprofd */
modem mdm; /* tty-driver-data */ modem mdm; /* tty-driver-data */
isdn_net_dev *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers */
isdn_net_dev *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers */
ulong ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes */
ulong obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes */
int v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
atomic_t v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
struct semaphore sem; /* serialize list access*/ struct semaphore sem; /* serialize list access*/
unsigned long global_features; unsigned long global_features;
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
......
...@@ -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;
......
...@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
{ {
struct mm_struct * mm = current->mm; struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev; struct vm_area_struct * vma, * prev;
struct inode *inode = NULL;
unsigned int vm_flags; unsigned int vm_flags;
int correct_wcount = 0; int correct_wcount = 0;
int error; int error;
...@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
} }
if (file) { if (file) {
inode = file->f_dentry->d_inode;
switch (flags & MAP_TYPE) { switch (flags & MAP_TYPE) {
case MAP_SHARED: case MAP_SHARED:
if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE)) if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE))
return -EACCES; return -EACCES;
/* Make sure we don't allow writing to an append-only file.. */ /* Make sure we don't allow writing to an append-only file.. */
if (IS_APPEND(file->f_dentry->d_inode) && (file->f_mode & FMODE_WRITE)) if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE))
return -EACCES; return -EACCES;
/* make sure there are no mandatory locks on the file. */ /* make sure there are no mandatory locks on the file. */
if (locks_verify_locked(file->f_dentry->d_inode)) if (locks_verify_locked(inode))
return -EAGAIN; return -EAGAIN;
vm_flags |= VM_SHARED | VM_MAYSHARE; vm_flags |= VM_SHARED | VM_MAYSHARE;
...@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
vma_link(mm, vma, prev, rb_link, rb_parent); vma_link(mm, vma, prev, rb_link, rb_parent);
if (correct_wcount) if (correct_wcount)
atomic_inc(&file->f_dentry->d_inode->i_writecount); atomic_inc(&inode->i_writecount);
out: out:
mm->total_vm += len >> PAGE_SHIFT; mm->total_vm += len >> PAGE_SHIFT;
...@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unmap_and_free_vma: unmap_and_free_vma:
if (correct_wcount) if (correct_wcount)
atomic_inc(&file->f_dentry->d_inode->i_writecount); atomic_inc(&inode->i_writecount);
vma->vm_file = NULL; vma->vm_file = NULL;
fput(file); fput(file);
...@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr, ...@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
return prev ? prev->vm_next : vma; return prev ? prev->vm_next : vma;
} }
#ifdef ARCH_STACK_GROWSUP
/* /*
* vma is the first one with address < vma->vm_end, * vma is the first one with address > vma->vm_end. Have to extend vma.
* and even address < vma->vm_start. Have to extend vma.
*/ */
int expand_stack(struct vm_area_struct * vma, unsigned long address) int expand_stack(struct vm_area_struct * vma, unsigned long address)
{ {
unsigned long grow; unsigned long grow;
if (!(vma->vm_flags & VM_GROWSUP))
return -EFAULT;
/* /*
* vma->vm_start/vm_end cannot change under us because the caller * vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in write mode. We need to get * is required to hold the mmap_sem in read mode. We need to get
* the spinlock only before relocating the vma range ourself. * the spinlock only before relocating the vma range ourself.
*/ */
address += 4 + PAGE_SIZE - 1;
address &= PAGE_MASK; address &= PAGE_MASK;
spin_lock(&vma->vm_mm->page_table_lock); spin_lock(&vma->vm_mm->page_table_lock);
grow = (vma->vm_start - address) >> PAGE_SHIFT; grow = (address - vma->vm_end) >> PAGE_SHIFT;
/* Overcommit.. */ /* Overcommit.. */
if(!vm_enough_memory(grow)) { if (!vm_enough_memory(grow)) {
spin_unlock(&vma->vm_mm->page_table_lock); spin_unlock(&vma->vm_mm->page_table_lock);
return -ENOMEM; return -ENOMEM;
} }
if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
current->rlim[RLIMIT_AS].rlim_cur) { current->rlim[RLIMIT_AS].rlim_cur) {
spin_unlock(&vma->vm_mm->page_table_lock); spin_unlock(&vma->vm_mm->page_table_lock);
vm_unacct_memory(grow); vm_unacct_memory(grow);
return -ENOMEM; return -ENOMEM;
} }
vma->vm_start = address; vma->vm_end = address;
vma->vm_pgoff -= grow;
vma->vm_mm->total_vm += grow; vma->vm_mm->total_vm += grow;
if (vma->vm_flags & VM_LOCKED) if (vma->vm_flags & VM_LOCKED)
vma->vm_mm->locked_vm += grow; vma->vm_mm->locked_vm += grow;
...@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address) ...@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
return 0; return 0;
} }
#ifdef ARCH_STACK_GROWSUP
struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr)
{ {
struct vm_area_struct *vma, *prev; struct vm_area_struct *vma, *prev;
...@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add ...@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add
return prev; return prev;
} }
#else #else
/*
* vma is the first one with address < vma->vm_start. Have to extend vma.
*/
int expand_stack(struct vm_area_struct * vma, unsigned long address)
{
unsigned long grow;
/*
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in read mode. We need to get
* the spinlock only before relocating the vma range ourself.
*/
address &= PAGE_MASK;
spin_lock(&vma->vm_mm->page_table_lock);
grow = (vma->vm_start - address) >> PAGE_SHIFT;
/* Overcommit.. */
if (!vm_enough_memory(grow)) {
spin_unlock(&vma->vm_mm->page_table_lock);
return -ENOMEM;
}
if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
current->rlim[RLIMIT_AS].rlim_cur) {
spin_unlock(&vma->vm_mm->page_table_lock);
vm_unacct_memory(grow);
return -ENOMEM;
}
vma->vm_start = address;
vma->vm_pgoff -= grow;
vma->vm_mm->total_vm += grow;
if (vma->vm_flags & VM_LOCKED)
vma->vm_mm->locked_vm += grow;
spin_unlock(&vma->vm_mm->page_table_lock);
return 0;
}
struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr)
{ {
struct vm_area_struct * vma; struct vm_area_struct * vma;
......
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