patch-2.3.14 linux/drivers/isdn/isdn_common.c
Next file: linux/drivers/isdn/isdn_common.h
Previous file: linux/drivers/isdn/isdn_cards.c
Back to the patch index
Back to the overall index
- Lines: 450
- Date:
Thu Aug 12 09:42:33 1999
- Orig file:
v2.3.13/linux/drivers/isdn/isdn_common.c
- Orig date:
Sun May 23 10:03:42 1999
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.75 1999/04/18 14:06:47 fritz Exp $
+/* $Id: isdn_common.c,v 1.86 1999/07/31 12:59:42 armin Exp $
* Linux ISDN subsystem, common used functions (linklevel).
*
@@ -21,6 +21,51 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_common.c,v $
+ * Revision 1.86 1999/07/31 12:59:42 armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.85 1999/07/29 16:58:35 armin
+ * Bugfix: DLE handling in isdn_readbchan()
+ *
+ * Revision 1.84 1999/07/25 16:21:10 keil
+ * fix number matching
+ *
+ * Revision 1.83 1999/07/13 21:02:05 werner
+ * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH)
+ *
+ * Revision 1.82 1999/07/12 21:06:50 werner
+ * Fixed problem when loading more than one driver temporary
+ *
+ * Revision 1.81 1999/07/11 17:14:09 armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.80 1999/07/07 10:14:00 detabc
+ * remove unused messages
+ *
+ * Revision 1.79 1999/07/05 23:51:30 werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 1.78 1999/07/05 20:21:15 werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.77 1999/07/01 08:29:50 keil
+ * compatibility to 2.3 kernel
+ *
+ * Revision 1.76 1999/06/29 16:16:44 calle
+ * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
+ * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
+ * isdnlog should check returncode of read(2) calls.
+ *
* Revision 1.75 1999/04/18 14:06:47 fritz
* Removed TIMRU stuff.
*
@@ -65,16 +110,6 @@
* brute force fix to avoid Ugh's in isdn_tty_write()
* cleaned up some dead code
*
- * Revision 1.65 1998/06/07 00:20:00 fritz
- * abc cleanup.
- *
- * Revision 1.64 1998/06/02 12:10:03 detabc
- * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
- * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
- *
- * Revision 1.63 1998/05/03 17:40:38 detabc
- * Include abc-extension-support for >= 2.1.x Kernels in
- * isdn_net.c and isdn_common.c. alpha-test OK and running !
*
* Revision 1.62 1998/04/14 16:28:43 he
* Fixed user space access with interrupts off and remaining
@@ -335,6 +370,9 @@
#ifdef CONFIG_ISDN_AUDIO
#include "isdn_audio.h"
#endif
+#ifdef CONFIG_ISDN_DIVERSION
+#include <linux/isdn_divertif.h>
+#endif CONFIG_ISDN_DIVERSION
#include "isdn_v110.h"
#include "isdn_cards.h"
@@ -343,7 +381,7 @@
isdn_dev *dev = (isdn_dev *) 0;
-static char *isdn_revision = "$Revision: 1.75 $";
+static char *isdn_revision = "$Revision: 1.86 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
@@ -359,6 +397,11 @@
#endif
extern char *isdn_v110_revision;
+#ifdef CONFIG_ISDN_DIVERSION
+isdn_divert_if *divert_if = NULL; /* interface to diversion module */
+#endif CONFIG_ISDN_DIVERSION
+
+
static int isdn_writebuf_stub(int, int, const u_char *, int, int);
void
@@ -449,6 +492,8 @@
register int reverse;
register int nostar = 1;
+ if (!(*s) && !(*p))
+ return(1);
for (; *p; s++, p++)
switch (*p) {
case '\\':
@@ -760,7 +805,7 @@
return 0;
}
/* Try to find a network-interface which will accept incoming call */
- r = isdn_net_find_icall(di, c->arg, i, c->parm.setup);
+ r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup));
switch (r) {
case 0:
/* No network-device replies.
@@ -768,7 +813,13 @@
* These return 0 on no match, 1 on match and
* 3 on eventually match, if CID is longer.
*/
- retval = isdn_tty_find_icall(di, c->arg, c->parm.setup);
+ if (c->command == ISDN_STAT_ICALL)
+ if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval);
+#ifdef CONFIG_ISDN_DIVERSION
+ if (divert_if)
+ if ((retval = divert_if->stat_callback(c)))
+ return(retval); /* processed */
+#endif CONFIG_ISDN_DIVERSION
if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
/* No tty responding */
cmd.driver = di;
@@ -831,6 +882,20 @@
printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
dev->drvid[di], c->arg, c->parm.num);
isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+ if (divert_if)
+ divert_if->stat_callback(c);
+#endif CONFIG_ISDN_DIVERSION
+ break;
+ case ISDN_STAT_DISPLAY:
+#ifdef ISDN_DEBUG_STATCALLB
+ printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
+#endif
+ isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+ if (divert_if)
+ divert_if->stat_callback(c);
+#endif CONFIG_ISDN_DIVERSION
break;
case ISDN_STAT_DCONN:
if (i < 0)
@@ -869,6 +934,11 @@
isdn_v110_stat_callback(i, c);
if (isdn_tty_stat_callback(i, c))
break;
+#ifdef CONFIG_ISDN_DIVERSION
+ if (divert_if)
+ divert_if->stat_callback(c);
+#endif CONFIG_ISDN_DIVERSION
+ break;
break;
case ISDN_STAT_BCONN:
if (i < 0)
@@ -924,7 +994,34 @@
return -1;
isdn_info_update();
break;
+ case ISDN_STAT_DISCH:
+ save_flags(flags);
+ cli();
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+ if ((dev->drvmap[i] == di) &&
+ (dev->chanmap[i] == c->arg)) {
+ if (c->parm.num[0])
+ dev->usage[i] &= ~ISDN_USAGE_DISABLED;
+ else
+ if (USG_NONE(dev->usage[i])) {
+ dev->usage[i] |= ISDN_USAGE_DISABLED;
+ }
+ else
+ retval = -1;
+ break;
+ }
+ restore_flags(flags);
+ isdn_info_update();
+ break;
case ISDN_STAT_UNLOAD:
+ while (dev->drv[di]->locks > 0) {
+ isdn_ctrl cmd;
+ cmd.driver = di;
+ cmd.arg = 0;
+ cmd.command = ISDN_CMD_UNLOCK;
+ isdn_command(&cmd);
+ dev->drv[di]->locks--;
+ }
save_flags(flags);
cli();
isdn_tty_stat_callback(i, c);
@@ -932,6 +1029,7 @@
if (dev->drvmap[i] == di) {
dev->drvmap[i] = -1;
dev->chanmap[i] = -1;
+ dev->usage[i] &= ~ISDN_USAGE_DISABLED;
}
dev->drivers--;
dev->channels -= dev->drv[di]->channels;
@@ -941,7 +1039,7 @@
isdn_free_queue(&dev->drv[di]->rpqueue[i]);
kfree(dev->drv[di]->rpqueue);
kfree(dev->drv[di]->rcv_waitq);
-#if LINUX_VERSION_CODE < 131841
+#ifndef COMPAT_HAS_NEW_WAITQ
kfree(dev->drv[di]->snd_waitq);
#endif
kfree(dev->drv[di]);
@@ -954,6 +1052,22 @@
break;
case CAPI_PUT_MESSAGE:
return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
+#ifdef CONFIG_ISDN_TTY_FAX
+ case ISDN_STAT_FAXIND:
+ isdn_tty_stat_callback(i, c);
+ break;
+#endif
+#ifdef CONFIG_ISDN_AUDIO
+ case ISDN_STAT_AUDIO:
+ isdn_tty_stat_callback(i, c);
+ break;
+#endif
+#ifdef CONFIG_ISDN_DIVERSION
+ case ISDN_STAT_PROT:
+ case ISDN_STAT_REDIR:
+ if (divert_if)
+ return(divert_if->stat_callback(c));
+#endif CONFIG_ISDN_DIVERSION
default:
return -1;
}
@@ -989,10 +1103,10 @@
* of the mapping (di,ch)<->minor, happen during the sleep? --he
*/
int
-#if LINUX_VERSION_CODE < 131841
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
+#else
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
#endif
{
int left;
@@ -1021,7 +1135,7 @@
if (ISDN_AUDIO_SKB_LOCK(skb))
break;
ISDN_AUDIO_SKB_LOCK(skb) = 1;
- if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+ if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
char *p = skb->data;
unsigned long DLEmask = (1 << channel);
@@ -1320,11 +1434,11 @@
return mask;
}
if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
- poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
if (drvidx < 0) {
- printk(KERN_ERR "isdn_common: isdn_poll 1 -> what the hell\n");
- return POLLERR;
+ /* driver deregistered while file open */
+ return POLLHUP;
}
+ poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
mask = POLLOUT | POLLWRNORM;
if (dev->drv[drvidx]->stavail) {
mask |= POLLIN | POLLRDNORM;
@@ -1938,6 +2052,8 @@
if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
((pre_dev != d) || (pre_chan != dev->chanmap[i])))
continue;
+ if (dev->usage[i] & ISDN_USAGE_DISABLED)
+ continue; /* usage not allowed */
if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
if (((dev->drv[d]->interface->features & features) == features) ||
(((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
@@ -2132,13 +2248,12 @@
int j, k, m;
ulong flags;
-#if LINUX_VERSION_CODE >= 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
init_waitqueue_head(&d->st_waitq);
#endif
if (d->flags & DRV_FLAG_RUNNING)
return -1;
- if (n < 1)
- return 0;
+ if (n < 1) return 0;
m = (adding) ? d->channels + n : n;
@@ -2185,13 +2300,13 @@
if ((adding) && (d->rcv_waitq))
kfree(d->rcv_waitq);
-#if LINUX_VERSION_CODE < 131841
- if (!(d->rcv_waitq = (struct wait_queue **)
- kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
d->rcv_waitq = (wait_queue_head_t *)
kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
if (!d->rcv_waitq) {
+#else
+ if (!(d->rcv_waitq = (struct wait_queue **)
+ kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
#endif
printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
if (!adding) {
@@ -2201,7 +2316,13 @@
}
return -1;
}
-#if LINUX_VERSION_CODE < 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
+ d->snd_waitq = d->rcv_waitq + m;
+ for (j = 0; j < m; j++) {
+ init_waitqueue_head(&d->rcv_waitq[m]);
+ init_waitqueue_head(&d->snd_waitq[m]);
+ }
+#else
memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m);
if ((adding) && (d->snd_waitq))
@@ -2218,12 +2339,6 @@
return -1;
}
memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m);
-#else
- d->snd_waitq = d->rcv_waitq + m;
- for (j = 0; j < m; j++) {
- init_waitqueue_head(&d->rcv_waitq[m]);
- init_waitqueue_head(&d->snd_waitq[m]);
- }
#endif
dev->channels += n;
@@ -2245,6 +2360,60 @@
* Low-level-driver registration
*/
+
+#ifdef CONFIG_ISDN_DIVERSION
+extern isdn_divert_if *divert_if;
+
+static char *map_drvname(int di)
+{
+ if ((di < 0) || (di >= ISDN_MAX_DRIVERS))
+ return(NULL);
+ return(dev->drvid[di]); /* driver name */
+} /* map_drvname */
+
+static int map_namedrv(char *id)
+{ int i;
+
+ for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+ { if (!strcmp(dev->drvid[i],id))
+ return(i);
+ }
+ return(-1);
+} /* map_namedrv */
+
+int DIVERT_REG_NAME(isdn_divert_if *i_div)
+{
+ if (i_div->if_magic != DIVERT_IF_MAGIC)
+ return(DIVERT_VER_ERR);
+ switch (i_div->cmd)
+ {
+ case DIVERT_CMD_REL:
+ if (divert_if != i_div)
+ return(DIVERT_REL_ERR);
+ divert_if = NULL; /* free interface */
+ MOD_DEC_USE_COUNT;
+ return(DIVERT_NO_ERR);
+
+ case DIVERT_CMD_REG:
+ if (divert_if)
+ return(DIVERT_REG_ERR);
+ i_div->ll_cmd = isdn_command; /* set command function */
+ i_div->drv_to_name = map_drvname;
+ i_div->name_to_drv = map_namedrv;
+ MOD_INC_USE_COUNT;
+ divert_if = i_div; /* remember interface */
+ return(DIVERT_NO_ERR);
+
+ default:
+ return(DIVERT_CMD_ERR);
+ }
+} /* DIVERT_REG_NAME */
+
+EXPORT_SYMBOL(DIVERT_REG_NAME);
+
+#endif CONFIG_ISDN_DIVERSION
+
+
EXPORT_SYMBOL(register_isdn);
EXPORT_SYMBOL(register_isdn_module);
EXPORT_SYMBOL(unregister_isdn_module);
@@ -2352,18 +2521,18 @@
memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
-#if LINUX_VERSION_CODE < 131841
- dev->sem = MUTEX;
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
init_MUTEX(&dev->sem);
init_waitqueue_head(&dev->info_waitq);
+#else
+ dev->sem = MUTEX;
#endif
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], "???");
-#if LINUX_VERSION_CODE >= 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
init_waitqueue_head(&dev->mdm.info[i].open_wait);
init_waitqueue_head(&dev->mdm.info[i].close_wait);
#endif
@@ -2452,6 +2621,9 @@
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");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)