patch-2.0.36 linux/drivers/isdn/isdn_common.c
Next file: linux/drivers/isdn/isdn_common.h
Previous file: linux/drivers/isdn/isdn_cards.h
Back to the patch index
Back to the overall index
- Lines: 1042
- Date:
Sun Nov 15 10:32:59 1998
- Orig file:
v2.0.35/linux/drivers/isdn/isdn_common.c
- Orig date:
Tue Aug 5 11:05:16 1997
diff -u --recursive --new-file v2.0.35/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.c,v 1.44 1997/05/27 15:17:23 fritz Exp $
+/* $Id: isdn_common.c,v 1.44.2.9 1998/11/06 00:07:25 fritz Exp $
* Linux ISDN subsystem, common used functions (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
*
@@ -21,6 +21,43 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_common.c,v $
+ * Revision 1.44.2.9 1998/11/06 00:07:25 fritz
+ * Bugfix: loading additional driver while /dev/isdnctrl opened resulted in
+ * wrong module usage count after closing /dev/isdnctrl.
+ *
+ * Revision 1.44.2.8 1998/11/05 22:11:43 fritz
+ * Changed mail-address.
+ *
+ * Revision 1.44.2.7 1998/11/04 17:22:40 fritz
+ * Replaced broken lowlevel-driver locking.
+ *
+ * Revision 1.44.2.6 1998/11/03 14:30:56 fritz
+ * Reduced stack usage in various functions.
+ * Adapted statemachine to work with certified HiSax.
+ * Some fixes in callback handling.
+ *
+ * Revision 1.44.2.5 1998/10/25 15:48:04 fritz
+ * Misc bugfixes and adaptions to new HiSax
+ *
+ * Revision 1.44.2.4 1998/06/07 13:47:44 fritz
+ * ABC cleanup
+ *
+ * Revision 1.44.2.2 1998/03/16 09:55:44 cal
+ * Merged in TimRu-patches. Still needs validation in conjunction with ABC-patches.
+ *
+ * Revision 1.44.2.1 1998/03/07 23:35:03 detabc
+ * added the abc-extension to the linux isdn-kernel
+ * for kernel-version 2.0.xx
+ * DO NOT USE FOR HIGHER KERNELS-VERSIONS
+ * all source-lines are switched with the define CONFIG_ISDN_WITH_ABC
+ * (make config and answer ABC-Ext. Support (Compress,TCP-Keepalive ...) with yes
+ *
+ * you need also a modified isdnctrl-source the switch on the
+ * features of the abc-extension
+ *
+ * please use carefully. more detail will be follow.
+ * thanks
+ *
* Revision 1.44 1997/05/27 15:17:23 fritz
* Added changes for recent 2.1.x kernels:
* changed return type of isdn_close
@@ -218,7 +255,7 @@
isdn_dev *dev = (isdn_dev *) 0;
-static char *isdn_revision = "$Revision: 1.44 $";
+static char *isdn_revision = "$Revision: 1.44.2.9 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
@@ -238,16 +275,39 @@
void
isdn_MOD_INC_USE_COUNT(void)
{
+ int i;
+
MOD_INC_USE_COUNT;
+ for (i = 0; i < dev->drivers; i++) {
+ isdn_ctrl cmd;
+
+ cmd.driver = i;
+ cmd.arg = 0;
+ cmd.command = ISDN_CMD_LOCK;
+ isdn_command(&cmd);
+ dev->drv[i]->locks++;
+ }
}
void
isdn_MOD_DEC_USE_COUNT(void)
{
+ int i;
+
MOD_DEC_USE_COUNT;
+ for (i = 0; i < dev->drivers; i++)
+ if (dev->drv[i]->locks > 0) {
+ isdn_ctrl cmd;
+
+ cmd.driver = i;
+ cmd.arg = 0;
+ cmd.command = ISDN_CMD_UNLOCK;
+ isdn_command(&cmd);
+ dev->drv[i]->locks--;
+ }
}
-#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
+#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) || defined(CONFIG_ISDN_TIMEOUT_RULES)
void
isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
{
@@ -329,6 +389,7 @@
#endif
}
}
+
if (tf) {
int flags;
@@ -392,6 +453,15 @@
isdn_trash_skb(skb, FREE_READ);
}
+/*
+ * Intercept command from Linklevel to Lowlevel.
+ */
+int
+isdn_command(isdn_ctrl *cmd)
+{
+ return dev->drv[cmd->driver]->interface->command(cmd);
+}
+
void
isdn_all_eaz(int di, int ch)
{
@@ -403,7 +473,7 @@
cmd.arg = ch;
cmd.command = ISDN_CMD_SETEAZ;
cmd.parm.num[0] = '\0';
- (void) dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
}
static int
@@ -424,7 +494,7 @@
return -1;
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- if (isdn_net_stat_callback(i, c->command))
+ if (isdn_net_stat_callback(i, c))
return 0;
if (isdn_tty_stat_callback(i, c))
return 0;
@@ -438,13 +508,13 @@
wake_up_interruptible(&dev->drv[di]->st_waitq);
break;
case ISDN_STAT_RUN:
- dev->drv[di]->running = 1;
+ dev->drv[di]->flags |= DRV_FLAG_RUNNING;
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (dev->drvmap[i] == di)
isdn_all_eaz(di, dev->chanmap[i]);
break;
case ISDN_STAT_STOP:
- dev->drv[di]->running = 0;
+ dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
break;
case ISDN_STAT_ICALL:
if (i < 0)
@@ -456,27 +526,23 @@
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_HANGUP;
- dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
return 0;
}
/* Try to find a network-interface which will accept incoming call */
- cmd.driver = di;
- cmd.arg = c->arg;
- cmd.command = ISDN_CMD_LOCK;
- dev->drv[di]->interface->command(&cmd);
- r = isdn_net_find_icall(di, c->arg, i, c->parm.setup);
+ r = isdn_net_find_icall(di, c, i);
switch (r) {
case 0:
/* No network-device replies.
* Try ttyI's
*/
- if (isdn_tty_find_icall(di, c->arg, c->parm.setup) >= 0)
+ if (isdn_tty_find_icall(di, c) >= 0)
retval = 1;
- else if (dev->drv[di]->reject_bus) {
+ else if (dev->drv[di]->flags & DRV_FLAG_REJBUS) {
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_HANGUP;
- dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
retval = 2;
}
break;
@@ -486,7 +552,7 @@
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_ACCEPTD;
- dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
retval = 1;
break;
case 2: /* For calling back, first reject incoming call ... */
@@ -496,7 +562,7 @@
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_HANGUP;
- dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
if (r == 3)
break;
/* Fall through */
@@ -505,12 +571,6 @@
isdn_net_dial();
break;
}
- if (retval != 1) {
- cmd.driver = di;
- cmd.arg = c->arg;
- cmd.command = ISDN_CMD_UNLOCK;
- dev->drv[di]->interface->command(&cmd);
- }
return retval;
break;
case ISDN_STAT_CINF:
@@ -522,7 +582,7 @@
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
if (strcmp(c->parm.num, "0"))
- isdn_net_stat_callback(i, c->command);
+ isdn_net_stat_callback(i, c);
break;
case ISDN_STAT_CAUSE:
#ifdef ISDN_DEBUG_STATCALLB
@@ -541,14 +601,14 @@
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
/* Find any net-device, waiting for D-channel setup */
- if (isdn_net_stat_callback(i, c->command))
+ if (isdn_net_stat_callback(i, c))
break;
/* Find any ttyI, waiting for D-channel setup */
if (isdn_tty_stat_callback(i, c)) {
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_ACCEPTB;
- dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
break;
}
break;
@@ -560,10 +620,10 @@
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- dev->drv[di]->flags &= ~(1 << (c->arg));
+ dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update();
/* Signal hangup to network-devices */
- if (isdn_net_stat_callback(i, c->command))
+ if (isdn_net_stat_callback(i, c))
break;
if (isdn_tty_stat_callback(i, c))
break;
@@ -577,9 +637,9 @@
/* Signal B-channel-connect to network-devices */
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- dev->drv[di]->flags |= (1 << (c->arg));
+ dev->drv[di]->online |= (1 << (c->arg));
isdn_info_update();
- if (isdn_net_stat_callback(i, c->command))
+ if (isdn_net_stat_callback(i, c))
break;
if (isdn_tty_stat_callback(i, c))
break;
@@ -592,7 +652,7 @@
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- dev->drv[di]->flags &= ~(1 << (c->arg));
+ dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update();
if (isdn_tty_stat_callback(i, c))
break;
@@ -605,7 +665,7 @@
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- if (isdn_net_stat_callback(i, c->command))
+ if (isdn_net_stat_callback(i, c))
break;
if (isdn_tty_stat_callback(i, c))
break;
@@ -817,7 +877,7 @@
p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
if (dev->drv[i]) {
- sprintf(p, "%ld ", dev->drv[i]->flags);
+ sprintf(p, "%ld ", dev->drv[i]->online);
p = istatbuf + strlen(istatbuf);
} else {
sprintf(p, "? ");
@@ -880,7 +940,7 @@
drvidx = isdn_minor2drv(minor);
if (drvidx < 0)
return -ENODEV;
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
chidx = isdn_minor2chan(minor);
save_flags(flags);
@@ -943,7 +1003,7 @@
drvidx = isdn_minor2drv(minor);
if (drvidx < 0)
return -ENODEV;
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
chidx = isdn_minor2chan(minor);
while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
@@ -957,7 +1017,7 @@
/*
* We want to use the isdnctrl device to load the firmware
*
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
*/
if (dev->drv[drvidx]->interface->writecmd)
@@ -1044,136 +1104,13 @@
}
#endif
-static int
-isdn_set_allcfg(char *src)
-{
- int ret;
- int i;
- ulong flags;
- isdn_net_ioctl_cfg cfg;
+typedef union {
+ char name[10];
+ char bname[22];
+ isdn_ioctl_struct iocts;
isdn_net_ioctl_phone phone;
-
- if ((ret = isdn_net_rmall()))
- return ret;
- if ((ret = copy_from_user((char *) &i, src, sizeof(int))))
- return ret;
- save_flags(flags);
- cli();
- src += sizeof(int);
- while (i) {
- int phone_len;
- int out_flag;
-
- if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) {
- restore_flags(flags);
- return ret;
- }
- src += sizeof(cfg);
- if (!isdn_net_new(cfg.name, NULL)) {
- restore_flags(flags);
- return -EIO;
- }
- if ((ret = isdn_net_setcfg(&cfg))) {
- restore_flags(flags);
- return ret;
- }
- phone_len = out_flag = 0;
- while (out_flag < 2) {
- if ((ret = verify_area(VERIFY_READ, src, 1))) {
- restore_flags(flags);
- return ret;
- }
- GET_USER(phone.phone[phone_len], src++);
- if ((phone.phone[phone_len] == ' ') ||
- (phone.phone[phone_len] == '\0')) {
- if (phone_len) {
- phone.phone[phone_len] = '\0';
- strcpy(phone.name, cfg.name);
- phone.outgoing = out_flag;
- if ((ret = isdn_net_addphone(&phone))) {
- restore_flags(flags);
- return ret;
- }
- } else
- out_flag++;
- phone_len = 0;
- }
- if (++phone_len >= sizeof(phone.phone))
- printk(KERN_WARNING
- "%s: IIOCSETSET phone number too long, ignored\n",
- cfg.name);
- }
- i--;
- }
- restore_flags(flags);
- return 0;
-}
-
-static int
-isdn_get_allcfg(char *dest)
-{
isdn_net_ioctl_cfg cfg;
- isdn_net_ioctl_phone phone;
- isdn_net_dev *p;
- ulong flags;
- int ret;
-
- /* Walk through netdev-chain */
- save_flags(flags);
- cli();
- p = dev->netdev;
- while (p) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200))) {
- restore_flags(flags);
- return ret;
- }
- strcpy(cfg.eaz, p->local.msn);
- cfg.exclusive = p->local.exclusive;
- if (p->local.pre_device >= 0) {
- sprintf(cfg.drvid, "%s,%d", dev->drvid[p->local.pre_device],
- p->local.pre_channel);
- } else
- cfg.drvid[0] = '\0';
- cfg.onhtime = p->local.onhtime;
- cfg.charge = p->local.charge;
- cfg.l2_proto = p->local.l2_proto;
- cfg.l3_proto = p->local.l3_proto;
- cfg.p_encap = p->local.p_encap;
- cfg.secure = (p->local.flags & ISDN_NET_SECURE) ? 1 : 0;
- cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
- cfg.chargehup = (p->local.hupflags & ISDN_CHARGEHUP) ? 1 : 0;
- cfg.ihup = (p->local.hupflags & ISDN_INHUP) ? 1 : 0;
- cfg.chargeint = p->local.chargeint;
- if (copy_to_user(dest, p->local.name, 10)) {
- restore_flags(flags);
- return -EFAULT;
- }
- dest += 10;
- if (copy_to_user(dest, (char *) &cfg, sizeof(cfg))) {
- restore_flags(flags);
- return -EFAULT;
- }
- dest += sizeof(cfg);
- strcpy(phone.name, p->local.name);
- phone.outgoing = 0;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
- return ret;
- } else
- dest += ret;
- strcpy(phone.name, p->local.name);
- phone.outgoing = 1;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
- return ret;
- } else
- dest += ret;
- put_user(0, dest);
- p = p->next;
- }
- restore_flags(flags);
- return 0;
-}
+} iocpar_t;
static int
isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1186,19 +1123,15 @@
int i;
char *p;
char *s;
- union iocpar {
- char name[10];
- char bname[22];
- isdn_ioctl_struct iocts;
- isdn_net_ioctl_phone phone;
- isdn_net_ioctl_cfg cfg;
- } iocpar;
-
-#define name iocpar.name
-#define bname iocpar.bname
-#define iocts iocpar.iocts
-#define phone iocpar.phone
-#define cfg iocpar.cfg
+ iocpar_t *iocpar;
+
+#define name iocpar->name
+#define bname iocpar->bname
+#define iocts iocpar->iocts
+#define phone iocpar->phone
+#define cfg iocpar->cfg
+
+#define RETURN(r) ({ ret = r; kfree(iocpar); return ret; })
if (minor == ISDN_MINOR_STATUS) {
switch (cmd) {
@@ -1232,127 +1165,131 @@
if (drvidx < 0)
return -ENODEV;
chidx = isdn_minor2chan(minor);
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
return 0;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
+ if ((iocpar = (iocpar_t *)kmalloc(sizeof(iocpar_t), GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING "isdn: Out of memory in isdn_ioctl\n");
+ return -ENOMEM;
+ }
switch (cmd) {
#ifdef CONFIG_NETDEVICES
case IIOCNETAIF:
/* Add a network-interface */
if (arg) {
if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ RETURN(ret);
s = name;
} else
s = NULL;
if ((s = isdn_net_new(s, NULL))) {
if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
+ RETURN(ret);
+ RETURN(0);
} else
- return -ENODEV;
+ RETURN(-ENODEV);
case IIOCNETASL:
/* Add a slave to a network-interface */
if (arg) {
if ((ret = copy_from_user(bname, (char *) arg, sizeof(bname) - 1)))
- return ret;
+ RETURN(ret);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
if ((s = isdn_net_newslave(bname))) {
if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
+ RETURN(ret);
+ RETURN(0);
} else
- return -ENODEV;
+ RETURN(-ENODEV);
case IIOCNETDIF:
/* Delete a network-interface */
if (arg) {
if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_net_rm(name);
+ RETURN(ret);
+ RETURN(isdn_net_rm(name));
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCNETSCF:
/* Set configurable parameters of a network-interface */
if (arg) {
if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
- return ret;
- return isdn_net_setcfg(&cfg);
+ RETURN(ret);
+ RETURN(isdn_net_setcfg(&cfg));
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCNETGCF:
/* Get configurable parameters of a network-interface */
if (arg) {
if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
- return ret;
+ RETURN(ret);
if (!(ret = isdn_net_getcfg(&cfg))) {
if ((ret = copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))))
- return ret;
+ RETURN(ret);
}
- return ret;
+ RETURN(ret);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCNETANM:
/* Add a phone-number to a network-interface */
if (arg) {
if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_addphone(&phone);
+ RETURN(ret);
+ RETURN(isdn_net_addphone(&phone));
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCNETGNM:
/* Get list of phone-numbers of a network-interface */
if (arg) {
if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_getphones(&phone, (char *) arg);
+ RETURN(ret);
+ RETURN(isdn_net_getphones(&phone, (char *) arg));
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCNETDNM:
/* Delete a phone-number of a network-interface */
if (arg) {
if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_delphone(&phone);
+ RETURN(ret);
+ RETURN(isdn_net_delphone(&phone));
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCNETDIL:
/* Force dialing of a network-interface */
if (arg) {
if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_net_force_dial(name);
+ RETURN(ret);
+ RETURN(isdn_net_force_dial(name));
} else
- return -EINVAL;
+ RETURN(-EINVAL);
#ifdef CONFIG_ISDN_PPP
case IIOCNETALN:
if (!arg)
- return -EINVAL;
+ RETURN(-EINVAL);
if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_ppp_dial_slave(name);
+ RETURN(ret);
+ RETURN(isdn_ppp_dial_slave(name));
case IIOCNETDLN:
if (!arg)
- return -EINVAL;
+ RETURN(-EINVAL);
if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_ppp_hangup_slave(name);
+ RETURN(ret);
+ RETURN(isdn_ppp_hangup_slave(name));
#endif
case IIOCNETHUP:
/* Force hangup of a network-interface */
if (!arg)
- return -EINVAL;
+ RETURN(-EINVAL);
if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_net_force_hangup(name);
+ RETURN(ret);
+ RETURN(isdn_net_force_hangup(name));
break;
#endif /* CONFIG_NETDEVICES */
case IIOCSETVER:
dev->net_verbose = arg;
printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
- return 0;
+ RETURN(0);
case IIOCSETGST:
if (arg)
dev->global_flags |= ISDN_GLOBAL_STOPPED;
@@ -1360,7 +1297,7 @@
dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
printk(KERN_INFO "isdn: Global Mode %s\n",
(dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
- return 0;
+ RETURN(0);
case IIOCSETBRJ:
drvidx = -1;
if (arg) {
@@ -1368,7 +1305,7 @@
char *p;
if ((ret = copy_from_user((char *) &iocts, (char *) arg,
sizeof(isdn_ioctl_struct))))
- return ret;
+ RETURN(ret);
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1381,28 +1318,15 @@
}
}
if (drvidx == -1)
- return -ENODEV;
- dev->drv[drvidx]->reject_bus = iocts.arg;
- return 0;
- case IIOCGETSET:
- /* Get complete setup (all network-interfaces and profile-
- settings of all tty-devices */
- if (arg)
- return (isdn_get_allcfg((char *) arg));
- else
- return -EINVAL;
- break;
- case IIOCSETSET:
- /* Set complete setup (all network-interfaces and profile-
- settings of all tty-devices */
- if (arg)
- return (isdn_set_allcfg((char *) arg));
+ RETURN(-ENODEV);
+ if (iocts.arg)
+ dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
else
- return -EINVAL;
- break;
+ dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+ RETURN(0);
case IIOCSIGPRF:
dev->profd = current;
- return 0;
+ RETURN(0);
break;
case IIOCGETPRF:
/* Get all Modem-Profiles */
@@ -1413,20 +1337,20 @@
if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
(ISDN_MODEM_ANZREG + ISDN_MSNLEN)
* ISDN_MAX_CHANNELS)))
- return ret;
+ RETURN(ret);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if (copy_to_user(p, dev->mdm.info[i].emu.profile,
ISDN_MODEM_ANZREG))
- return -EFAULT;
+ RETURN(-EFAULT);
p += ISDN_MODEM_ANZREG;
if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
- return -EFAULT;
+ RETURN(-EFAULT);
p += ISDN_MSNLEN;
}
- return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
+ RETURN((ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
break;
case IIOCSETPRF:
/* Set all Modem-Profiles */
@@ -1437,20 +1361,20 @@
if ((ret = verify_area(VERIFY_READ, (void *) arg,
(ISDN_MODEM_ANZREG + ISDN_MSNLEN)
* ISDN_MAX_CHANNELS)))
- return ret;
+ RETURN(ret);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if ((ret = copy_from_user(dev->mdm.info[i].emu.profile, p,
ISDN_MODEM_ANZREG)))
- return ret;
+ RETURN(ret);
p += ISDN_MODEM_ANZREG;
if ((ret = copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)))
- return ret;
+ RETURN(ret);
p += ISDN_MSNLEN;
}
- return 0;
+ RETURN(0);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
break;
case IIOCSETMAP:
case IIOCGETMAP:
@@ -1460,7 +1384,7 @@
if ((ret = copy_from_user((char *) &iocts,
(char *) arg,
sizeof(isdn_ioctl_struct))))
- return ret;
+ RETURN(ret);
if (strlen(iocts.drvid)) {
drvidx = -1;
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1471,7 +1395,7 @@
} else
drvidx = 0;
if (drvidx == -1)
- return -ENODEV;
+ RETURN(-ENODEV);
if (cmd == IIOCSETMAP) {
int loop = 1;
@@ -1482,7 +1406,7 @@
while (1) {
if ((ret = verify_area(VERIFY_READ, p, 1)))
- return ret;
+ RETURN(ret);
GET_USER(bname[j], p++);
switch (bname[j]) {
case '\0':
@@ -1510,31 +1434,31 @@
dev->drv[drvidx]->msn2eaz[i] : "-",
(i < 9) ? "," : "\0");
if ((ret = copy_to_user(p, bname, strlen(bname) + 1)))
- return ret;
+ RETURN(ret);
p += strlen(bname);
}
}
- return 0;
+ RETURN(0);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
case IIOCDBGVAR:
if (arg) {
if ((ret = copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))))
- return ret;
- return 0;
+ RETURN(ret);
+ RETURN(0);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
break;
default:
if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
else
- return -EINVAL;
+ RETURN(-EINVAL);
if (arg) {
int i;
char *p;
if ((ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))))
- return ret;
+ RETURN(ret);
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1547,21 +1471,21 @@
} else
drvidx = 0;
if (drvidx == -1)
- return -ENODEV;
+ RETURN(-ENODEV);
if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(isdn_ioctl_struct))))
- return ret;
+ RETURN(ret);
c.driver = drvidx;
c.command = ISDN_CMD_IOCTL;
c.arg = cmd;
memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
- ret = dev->drv[drvidx]->interface->command(&c);
+ ret = isdn_command(&c);
memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
if ((copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))))
- return -EFAULT;
- return ret;
+ RETURN(-EFAULT);
+ RETURN(ret);
} else
- return -EINVAL;
+ RETURN(-EINVAL);
}
}
#ifdef CONFIG_ISDN_PPP
@@ -1575,6 +1499,8 @@
#undef iocts
#undef phone
#undef cfg
+
+#undef RETURN
}
/*
@@ -1588,7 +1514,6 @@
uint minor = MINOR(ino->i_rdev);
int drvidx;
int chidx;
- isdn_ctrl c;
if (minor == ISDN_MINOR_STATUS) {
infostruct *p;
@@ -1611,31 +1536,25 @@
if (drvidx < 0)
return -ENODEV;
chidx = isdn_minor2chan(minor);
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
- if (!(dev->drv[drvidx]->flags & (1 << chidx)))
+ if (!(dev->drv[drvidx]->online & (1 << chidx)))
return -ENODEV;
- c.command = ISDN_CMD_LOCK;
- c.driver = drvidx;
- (void) dev->drv[drvidx]->interface->command(&c);
- MOD_INC_USE_COUNT;
+ isdn_MOD_INC_USE_COUNT();
return 0;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
if (drvidx < 0)
return -ENODEV;
- c.command = ISDN_CMD_LOCK;
- c.driver = drvidx;
- MOD_INC_USE_COUNT;
- (void) dev->drv[drvidx]->interface->command(&c);
+ isdn_MOD_INC_USE_COUNT();
return 0;
}
#ifdef CONFIG_ISDN_PPP
if (minor <= ISDN_MINOR_PPPMAX) {
int ret;
if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep)))
- MOD_INC_USE_COUNT;
+ isdn_MOD_INC_USE_COUNT();
return ret;
}
#endif
@@ -1646,13 +1565,13 @@
isdn_close(struct inode *ino, struct file *filep)
{
uint minor = MINOR(ino->i_rdev);
- int drvidx;
- isdn_ctrl c;
- MOD_DEC_USE_COUNT;
if (minor == ISDN_MINOR_STATUS) {
infostruct *p = dev->infochain;
infostruct *q = NULL;
+
+
+ MOD_DEC_USE_COUNT;
while (p) {
if (p->private == (char *) &(filep->private_data)) {
if (q)
@@ -1668,24 +1587,12 @@
printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
return CLOSEVAL;
}
- if (minor < ISDN_MINOR_CTRL) {
- drvidx = isdn_minor2drv(minor);
- if (drvidx < 0)
- return CLOSEVAL;
- c.command = ISDN_CMD_UNLOCK;
- c.driver = drvidx;
- (void) dev->drv[drvidx]->interface->command(&c);
+ isdn_MOD_DEC_USE_COUNT();
+ if (minor < ISDN_MINOR_CTRL)
return CLOSEVAL;
- }
if (minor <= ISDN_MINOR_CTRLMAX) {
- drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
- if (drvidx < 0)
- return CLOSEVAL;
if (dev->profd == current)
dev->profd = NULL;
- c.command = ISDN_CMD_UNLOCK;
- c.driver = drvidx;
- (void) dev->drv[drvidx]->interface->command(&c);
return CLOSEVAL;
}
#ifdef CONFIG_ISDN_PPP
@@ -1739,7 +1646,6 @@
int i;
ulong flags;
ulong features;
- isdn_ctrl cmd;
save_flags(flags);
cli();
@@ -1751,16 +1657,12 @@
if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
((pre_dev != d) || (pre_chan != dev->chanmap[i])))
continue;
- if ((dev->drv[d]->running)) {
+ if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
if ((dev->drv[d]->interface->features & features) == features) {
if ((pre_dev < 0) || (pre_chan < 0)) {
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
- cmd.driver = d;
- cmd.arg = 0;
- cmd.command = ISDN_CMD_LOCK;
- (void) dev->drv[d]->interface->command(&cmd);
restore_flags(flags);
return i;
} else {
@@ -1768,10 +1670,6 @@
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
- cmd.driver = d;
- cmd.arg = 0;
- cmd.command = ISDN_CMD_LOCK;
- (void) dev->drv[d]->interface->command(&cmd);
restore_flags(flags);
return i;
}
@@ -1807,11 +1705,12 @@
isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
cmd.driver = di;
cmd.arg = ch;
- cmd.command = ISDN_CMD_UNLOCK;
+ cmd.command = ISDN_CMD_HANGUP;
restore_flags(flags);
- (void) dev->drv[di]->interface->command(&cmd);
+ isdn_command(&cmd);
return;
}
+ printk(KERN_DEBUG "Unmatched free_channel d=%d c=%d u=%d\n", di, ch, usage);
restore_flags(flags);
}
@@ -2007,12 +1906,11 @@
}
memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * n);
d->channels = n;
- d->loaded = 1;
d->maxbufsize = i->maxbufsize;
d->pktcount = 0;
d->stavail = 0;
- d->running = 0;
- d->flags = 0;
+ d->flags = DRV_FLAG_LOADED;
+ d->online = 0;
d->interface = i;
for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
if (!dev->drv[drvidx])
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov