patch-pre2.0.10 linux/drivers/isdn/isdn_common.c

Next file: linux/drivers/isdn/isdn_common.h
Previous file: linux/drivers/char/ftape/kernel-interface.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.9/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.14 1996/05/18 01:36:55 fritz Exp $
+/* $Id: isdn_common.c,v 1.15 1996/05/31 01:10:54 fritz Exp $
  *
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -21,6 +21,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_common.c,v $
+ * Revision 1.15  1996/05/31 01:10:54  fritz
+ * Bugfixes:
+ *   Lowlevel modules did not get locked correctly.
+ *   Did show wrong revision when initializing.
+ *   Minor fixes in ioctl code.
+ *   sk_buff did not get freed, if error in writebuf_stub.
+ *
  * Revision 1.14  1996/05/18 01:36:55  fritz
  * Added spelling corrections and some minor changes
  * to stay in sync with kernel.
@@ -102,7 +109,7 @@
 isdn_dev *dev = (isdn_dev *) 0;
 
 static int  has_exported = 0;
-static char *isdn_revision      = "$Revision: 1.14 $";
+static char *isdn_revision      = "$Revision: 1.15 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -265,29 +272,22 @@
                 }
                 info  = &dev->mdm.info[midx];
                 if ((info->online < 2) &&
-                    (info->vonline != 1)) {
+                    (!(info->vonline & 1))) {
                         /* If Modem not listening, drop data */
                         isdn_trash_skb(skb, FREE_READ);
                         return;
                 }
                 if (info->emu.mdmreg[13] & 2)
                         /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
-                        if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1))) {
-#ifdef ISDN_DEBUG_MODEM_DUMP
-                                isdn_dumppkt("T70strip1:", skb->data, skb->len, skb->len);
-#endif
+                        if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1)))
                                 skb_pull(skb,4);
-#ifdef ISDN_DEBUG_MODEM_DUMP
-                                isdn_dumppkt("T70strip2:", skb->data, skb->len, skb->len);
-#endif
-                        }
                 /* The users field of an sk_buff is used in a special way
                  * with tty's incoming data:
                  *   users is set to the number of DLE codes when in audio mode.
                  */
                 skb->users = 0;
 #ifdef CONFIG_ISDN_AUDIO
-                if (info->vonline == 1) {
+                if (info->vonline & 1) {
                         int ifmt = 1;
                         /* voice conversion/compression */
                         switch (info->emu.vpar[3]) {
@@ -405,6 +405,10 @@
                         }
 
 			/* 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->num);
 			switch (r) {
                                 case 0:
@@ -416,6 +420,7 @@
                                                 info->msr |= UART_MSR_RI;
                                                 isdn_tty_modem_result(2, info);
                                                 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
+                                                return 0;
                                         } else if (dev->drv[di]->reject_bus) {
                                                 cmd.driver = di;
                                                 cmd.arg = c->arg;
@@ -430,6 +435,7 @@
                                         cmd.arg = c->arg;
                                         cmd.command = ISDN_CMD_ACCEPTD;
                                         dev->drv[di]->interface->command(&cmd);
+                                        return 0;
                                         break;
                                 case 2:	/* For calling back, first reject incoming call ... */
                                 case 3:	/* Interface found, but down, reject call actively  */
@@ -444,7 +450,12 @@
                                 case 4:
                                         /* ... then start callback. */
                                         isdn_net_dial();
+                                        return 0;
 			}
+                        cmd.driver = di;
+                        cmd.arg = c->arg;
+                        cmd.command = ISDN_CMD_UNLOCK;
+                        dev->drv[di]->interface->command(&cmd);
                         return 0;
                         break;
                 case ISDN_STAT_CINF:
@@ -615,10 +626,19 @@
                                 if (dev->drvmap[i] == di) {
                                         dev->drvmap[i] = -1;
                                         dev->chanmap[i] = -1;
-                                        dev->mdm.info[i].isdn_driver = -1;
-                                        dev->mdm.info[i].isdn_channel = -1;
-                                        isdn_info_update();
                                 }
+                        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+                                modem_info *info = &dev->mdm.info[i];
+                                
+                                if (info->isdn_driver == di) {
+                                        info->isdn_driver = -1;
+                                        info->isdn_channel = -1;
+                                        if (info->online) {
+                                                isdn_tty_modem_result(3, info);
+                                                isdn_tty_modem_hup(info);
+                                        }
+                                }
+                        }
                         dev->drivers--;
                         dev->channels -= dev->drv[di]->channels;
                         kfree(dev->drv[di]->rcverr);
@@ -1014,7 +1034,7 @@
 			restore_flags(flags);
 			return ret;
 		}
-		memcpy_tofs((char *) &cfg, src, sizeof(cfg));
+		memcpy_fromfs((char *) &cfg, src, sizeof(cfg));
 		src += sizeof(cfg);
 		if (!isdn_net_new(cfg.name, NULL)) {
 			restore_flags(flags);
@@ -1264,9 +1284,9 @@
                         case IIOCNETDNM:
                                 /* Delete a phone-number of a network-interface */
                                 if (arg) {
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
+                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_delphone(&phone);
                                 } else
                                         return -EINVAL;
@@ -1589,10 +1609,10 @@
 	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)
@@ -1607,9 +1627,6 @@
 		printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
                 return;
 	}
-	if (!dev->channels)
-		return;
-	MOD_DEC_USE_COUNT;
 	if (minor < ISDN_MINOR_CTRL) {
 		drvidx = isdn_minor2drv(minor);
 		if (drvidx < 0)
@@ -1675,6 +1692,7 @@
 	int i;
 	ulong flags;
 	ulong features;
+        isdn_ctrl cmd;
 
 	save_flags(flags);
 	cli();
@@ -1692,6 +1710,10 @@
 						dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
 						dev->usage[i] |= usage;
 						isdn_info_update();
+                                                cmd.driver = i;
+                                                cmd.arg = 0;
+                                                cmd.command = ISDN_CMD_LOCK;
+                                                (void) dev->drv[i]->interface->command(&cmd);
 						restore_flags(flags);
 						return i;
 					} else {
@@ -1699,6 +1721,10 @@
 							dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
 							dev->usage[i] |= usage;
 							isdn_info_update();
+                                                        cmd.driver = i;
+                                                        cmd.arg = 0;
+                                                        cmd.command = ISDN_CMD_LOCK;
+                                                        (void) dev->drv[i]->interface->command(&cmd);
 							restore_flags(flags);
 							return i;
 						}
@@ -1717,6 +1743,7 @@
 {
 	int i;
 	ulong flags;
+	isdn_ctrl cmd;
 
 	save_flags(flags);
 	cli();
@@ -1730,6 +1757,10 @@
                         dev->obytes[i] = 0;
 			isdn_info_update();
                         isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
+                        cmd.driver = di;
+                        cmd.arg = ch;
+                        cmd.command = ISDN_CMD_UNLOCK;
+                        (void) dev->drv[di]->interface->command(&cmd);
                         restore_flags(flags);
 			return;
 		}
@@ -1810,6 +1841,8 @@
 
                 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx,
                                                                 chan, skb);
+                if (ret <= 0)
+                        kfree_skb(skb, FREE_WRITE);
         }
         if (ret > 0)
                 dev->obytes[isdn_dc2minor(drvidx,chan)] += ret;
@@ -1831,9 +1864,9 @@
         if (dev->drv[drvidx]->interface->writebuf_skb) 
 		ret = dev->drv[drvidx]->interface->
 			writebuf_skb(drvidx, chan, skb);
-	else {	      
+	else {
 		if ((ret = dev->drv[drvidx]->interface->
-                     writebuf(drvidx,chan,skb->data,skb->len,0))==skb->len)
+                     writebuf(drvidx,chan,skb->data,skb->len,0)) == skb->len)
 		        dev_kfree_skb(skb, FREE_WRITE);
         }
         if (ret > 0)
@@ -1970,15 +2003,15 @@
 
 static char *isdn_getrev(const char *revision)
 {
-	static char rev[20];
+	char *rev;
 	char *p;
 
 	if ((p = strchr(revision, ':'))) {
-		strcpy(rev, p + 2);
+		rev = p + 2;
 		p = strchr(rev, '$');
 		*--p = 0;
 	} else
-		strcpy(rev, "???");
+		rev = "???";
 	return rev;
 }
 
@@ -2000,6 +2033,11 @@
 int isdn_init(void)
 {
 	int i;
+        char irev[50];
+        char trev[50];
+        char nrev[50];
+        char prev[50];
+        char arev[50];
 
 	sti();
 	if (!(dev = (isdn_dev *) kmalloc(sizeof(isdn_dev), GFP_KERNEL))) {
@@ -2007,9 +2045,8 @@
 		return -EIO;
 	}
 	memset((char *) dev, 0, sizeof(isdn_dev));
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-		dev->drvmap[i] = -1;
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		dev->drvmap[i] = -1;
 		dev->chanmap[i] = -1;
 		dev->m_idx[i] = -1;
 		strcpy(dev->num[i], "???");
@@ -2035,7 +2072,7 @@
 		tty_unregister_driver(&dev->mdm.tty_modem);
 		tty_unregister_driver(&dev->mdm.cua_modem);
 		for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-			kfree(dev->mdm.info[i].xmit_buf);
+			kfree(dev->mdm.info[i].xmit_buf - 4);
 		unregister_chrdev(ISDN_MAJOR, "isdn");
 		kfree(dev);
 		return -EIO;
@@ -2045,11 +2082,16 @@
         if (!has_exported)
                 isdn_export_syms();
 
-	printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(isdn_revision));
-        printk("%s/", isdn_getrev(isdn_tty_revision));
-        printk("%s/", isdn_getrev(isdn_net_revision));
-        printk("%s/", isdn_getrev(isdn_ppp_revision));
-        printk("%s", isdn_getrev(isdn_audio_revision));
+        strcpy(irev,isdn_revision);
+        strcpy(trev,isdn_tty_revision);
+        strcpy(nrev,isdn_net_revision);
+        strcpy(prev,isdn_ppp_revision);
+        strcpy(arev,isdn_audio_revision);
+	printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(irev));
+        printk("%s/", isdn_getrev(trev));
+        printk("%s/", isdn_getrev(nrev));
+        printk("%s/", isdn_getrev(prev));
+        printk("%s", isdn_getrev(arev));
 
 #ifdef MODULE
 	printk(" loaded\n");
@@ -2092,7 +2134,7 @@
 	}
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                 isdn_tty_cleanup_xmit(&dev->mdm.info[i]);
-		kfree(dev->mdm.info[i].xmit_buf);
+                kfree(dev->mdm.info[i].xmit_buf - 4);
         }
 	if (unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
 		printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this