patch-2.1.92 linux/drivers/isdn/isdn_tty.c

Next file: linux/drivers/isdn/isdn_v110.c
Previous file: linux/drivers/isdn/isdn_syms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.91/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.41 1997/05/27 15:17:31 fritz Exp $
+/* $Id: isdn_tty.c,v 1.47 1998/02/22 19:44:14 fritz Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -20,6 +20,35 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.47  1998/02/22 19:44:14  fritz
+ * Bugfixes and improvements regarding V.110, V.110 now running.
+ *
+ * Revision 1.46  1998/02/20 17:23:08  fritz
+ * Changes for recent kernels.
+ * Merged in contributions by Thomas Pfeiffer (V.110 T.70+ Extended FAX stuff)
+ * Added symbolic constants for Modem-Registers.
+ *
+ * Revision 1.45  1998/01/31 22:07:49  keil
+ * changes for newer kernels
+ *
+ * Revision 1.44  1998/01/31 19:30:02  calle
+ * Merged changes from and for 2.1.82, not tested only compiled ...
+ *
+ * Revision 1.43  1997/10/09 21:29:04  fritz
+ * New HL<->LL interface:
+ *   New BSENT callback with nr. of bytes included.
+ *   Sending without ACK.
+ *   New L1 error status (not yet in use).
+ *   Cleaned up obsolete structures.
+ * Implemented Cisco-SLARP.
+ * Changed local net-interface data to be dynamically allocated.
+ * Removed old 2.0 compatibility stuff.
+ *
+ * Revision 1.42  1997/10/01 09:20:49  fritz
+ * Removed old compatibility stuff for 2.0.X kernels.
+ * From now on, this code is for 2.1.X ONLY!
+ * Old stuff is still in the separate branch.
+ *
  * Revision 1.41  1997/05/27 15:17:31  fritz
  * Added changes for recent 2.1.x kernels:
  *   changed return type of isdn_close
@@ -199,6 +228,8 @@
 #define VBUFX (VBUF/16)
 #endif
 
+#define FIX_FILE_TRANSFER
+
 /* Prototypes */
 
 static int isdn_tty_edit_at(const char *, int, modem_info *, int);
@@ -223,12 +254,63 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.41 $";
+char *isdn_tty_revision = "$Revision: 1.47 $";
 
 #define DLE 0x10
 #define ETX 0x03
 #define DC4 0x14
 
+/*
+ * Definition of some special Registers of AT-Emulator
+ */
+#define REG_RINGATA   0
+#define REG_RINGCNT   1
+#define REG_ESC       2
+#define REG_CR        3
+#define REG_LF        4
+#define REG_BS        5
+
+#define REG_RESP     12
+#define BIT_RESP      1
+#define REG_RESPNUM  12
+#define BIT_RESPNUM   2
+#define REG_ECHO     12
+#define BIT_ECHO      4
+#define REG_DCD      12
+#define BIT_DCD       8
+#define REG_CTS      12
+#define BIT_CTS      16
+#define REG_DTRR     12
+#define BIT_DTRR     32
+#define REG_DSR      12
+#define BIT_DSR      64
+#define REG_CPPP     12
+#define BIT_CPPP    128
+
+#define REG_DELXMT   13
+#define BIT_DELXMT    1
+#define REG_T70      13
+#define BIT_T70       2
+#define BIT_T70_EXT  32
+#define REG_DTRHUP   13
+#define BIT_DTRHUP    4
+#define REG_RESPXT   13
+#define BIT_RESPXT    8
+#define REG_CIDONCE  13
+#define BIT_CIDONCE  16
+#define REG_RUNG     13
+#define BIT_RUNG     64
+
+#define REG_L2PROT   14
+#define REG_L3PROT   15
+#define REG_PSIZE    16
+#define REG_WSIZE    17
+#define REG_SI1      18
+#define REG_SI2      19
+#define REG_SI1I     20
+#define REG_PLAN     21
+#define REG_SCREEN   22
+
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
  * to stuff incoming data directly into a tty's flip-buffer. This
  * is done to speed up tty-receiving if the receive-queue is empty.
@@ -272,10 +354,9 @@
 #ifdef CONFIG_ISDN_AUDIO
 					}
 #endif
-					if (info->emu.mdmreg[12] & 128)
+					if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
 						tty->flip.flag_buf_ptr[len - 1] = 0xff;
 					queue_task(&tty->flip.tqueue, &tq_timer);
-					SET_SKB_FREE(skb);
 					kfree_skb(skb);
 					return 1;
 				}
@@ -319,7 +400,7 @@
 									   tty->flip.char_buf_ptr,
 									   tty->flip.flag_buf_ptr, c, 0);
 							/* CISCO AsyncPPP Hack */
-							if (!(info->emu.mdmreg[12] & 128))
+							if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
 								memset(tty->flip.flag_buf_ptr, 0, r);
 							tty->flip.count += r;
 							tty->flip.flag_buf_ptr += r;
@@ -371,19 +452,26 @@
 #endif
 		) {
 		/* If Modem not listening, drop data */
-		SET_SKB_FREE(skb);
 		kfree_skb(skb);
 		return 1;
 	}
-	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)))
-			skb_pull(skb, 4);
+	if (info->emu.mdmreg[REG_T70] & BIT_T70) {
+		if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) {
+			/* T.70 decoding: throw away the T.70 header (2 or 4 bytes)   */
+			if (skb->data[0] == 3) /* pure data packet -> 4 byte headers  */
+				skb_pull(skb, 4);
+			else
+				if (skb->data[0] == 1) /* keepalive packet -> 2 byte hdr  */
+					skb_pull(skb, 2);
+		} else
+			/* 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)))
+				skb_pull(skb, 4);
+	}
 #ifdef CONFIG_ISDN_AUDIO
 	if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
 		printk(KERN_WARNING
 		       "isdn_audio: insufficient skb_headroom, dropping\n");
-		SET_SKB_FREE(skb);
 		kfree_skb(skb);
 		return 1;
 	}
@@ -454,16 +542,12 @@
 	save_flags(flags);
 	cli();
 	if (skb_queue_len(&info->xmit_queue))
-		while ((skb = skb_dequeue(&info->xmit_queue))) {
-			SET_SKB_FREE(skb);
+		while ((skb = skb_dequeue(&info->xmit_queue)))
 			kfree_skb(skb);
-		}
 #ifdef CONFIG_ISDN_AUDIO
 	if (skb_queue_len(&info->dtmf_queue))
-		while ((skb = skb_dequeue(&info->dtmf_queue))) {
-			SET_SKB_FREE(skb);
+		while ((skb = skb_dequeue(&info->dtmf_queue)))
 			kfree_skb(skb);
-		}
 #endif
 	restore_flags(flags);
 }
@@ -479,7 +563,7 @@
 		return;
 	len = skb->len;
 	if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
-					   info->isdn_channel, skb)) == len) {
+					   info->isdn_channel, 1, skb)) == len) {
 		struct tty_struct *tty = info->tty;
 		info->send_outstanding++;
 		info->msr |= UART_MSR_CTS;
@@ -492,7 +576,6 @@
 	}
 	if (slen < 0) {
 		/* Error: no channel, already shutdown, or wrong parameter */
-		SET_SKB_FREE(skb);
 		dev_kfree_skb(skb);
 		return;
 	}
@@ -590,7 +673,7 @@
 
 	while (c--) {
 		if (from_user)
-			GET_USER(ch, buf);
+			get_user(ch, buf);
 		else
 			ch = *buf;
 		if ((ch != 0x11) && (ch != 0x13))
@@ -640,7 +723,7 @@
 		restore_flags(flags);
 		return;
 	}
-	if ((info->emu.mdmreg[12] & 0x10) != 0)
+	if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
 		info->msr &= ~UART_MSR_CTS;
 	info->lsr &= ~UART_LSR_TEMT;
 	if (info->isdn_driver < 0) {
@@ -710,10 +793,13 @@
 		}
 	}
 #endif                          /* CONFIG_ISDN_AUDIO */
-	SET_SKB_FREE(skb);
-	if (info->emu.mdmreg[13] & 2)
+	if (info->emu.mdmreg[REG_T70] & BIT_T70) {
 		/* Add T.70 simplified header */
-		memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
+		if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT)
+			memcpy(skb_push(skb, 2), "\1\0", 2);
+		else
+			memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
+	}
 	skb_queue_tail(&info->xmit_queue, skb);
 }
 
@@ -761,27 +847,27 @@
 {
 	int usg = ISDN_USAGE_MODEM;
 	int si = 7;
-	int l2 = m->mdmreg[14];
+	int l2 = m->mdmreg[REG_L2PROT];
 	isdn_ctrl cmd;
 	ulong flags;
 	int i;
 	int j;
 
 	for (j = 7; j >= 0; j--)
-		if (m->mdmreg[18] & (1 << j)) {
+		if (m->mdmreg[REG_SI1] & (1 << j)) {
 			si = bit2si[j];
 			break;
 		}
 #ifdef CONFIG_ISDN_AUDIO
 	if (si == 1) {
-		l2 = 4;
+		l2 = ISDN_PROTO_L2_TRANS;
 		usg = ISDN_USAGE_VOICE;
 	}
 #endif
-	m->mdmreg[20] = si2bit[si];
+	m->mdmreg[REG_SI1I] = si2bit[si];
 	save_flags(flags);
 	cli();
-	i = isdn_get_free_channel(usg, l2, m->mdmreg[15], -1, -1);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
 	if (i < 0) {
 		restore_flags(flags);
 		isdn_tty_modem_result(6, info);
@@ -798,32 +884,32 @@
 		cmd.driver = info->isdn_driver;
 		cmd.arg = info->isdn_channel;
 		cmd.command = ISDN_CMD_CLREAZ;
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		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;
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		isdn_command(&cmd);
 		cmd.driver = info->isdn_driver;
 		cmd.command = ISDN_CMD_SETL2;
 		info->last_l2 = l2;
 		cmd.arg = info->isdn_channel + (l2 << 8);
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		isdn_command(&cmd);
 		cmd.driver = info->isdn_driver;
 		cmd.command = ISDN_CMD_SETL3;
-		cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		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[19];
+		cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
 		cmd.command = ISDN_CMD_DIAL;
 		info->dialing = 1;
 		strcpy(dev->num[i], n);
 		isdn_info_update();
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		isdn_command(&cmd);
 	}
 }
 
@@ -865,6 +951,9 @@
 		info->adpcmr = NULL;
 	}
 #endif
+	if ((info->msr & UART_MSR_RI) &&
+		(info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
+		isdn_tty_modem_result(12, info);
 	info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
 	info->lsr |= UART_LSR_TEMT;
 	if (info->isdn_driver >= 0) {
@@ -872,11 +961,11 @@
 			cmd.driver = info->isdn_driver;
 			cmd.command = ISDN_CMD_HANGUP;
 			cmd.arg = info->isdn_channel;
-			dev->drv[info->isdn_driver]->interface->command(&cmd);
+			isdn_command(&cmd);
 		}
 		isdn_all_eaz(info->isdn_driver, info->isdn_channel);
-		info->emu.mdmreg[1] = 0;
-		usage = (info->emu.mdmreg[20] == 1) ?
+		info->emu.mdmreg[REG_RINGCNT] = 0;
+		usage = (info->emu.mdmreg[REG_SI1I] == 1) ?
 		    ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
 		isdn_free_channel(info->isdn_driver, info->isdn_channel,
 				  usage);
@@ -937,7 +1026,7 @@
 		isdn_tty_modem_ncarrier(info);
 	} else {
 		info->mcr &= ~UART_MCR_DTR;
-		if (info->emu.mdmreg[13] & 4) {
+		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
 #ifdef ISDN_DEBUG_MODEM_HUP
 			printk(KERN_DEBUG "Mhup in changespeed\n");
 #endif
@@ -1020,7 +1109,7 @@
 	info->msr &= ~UART_MSR_RI;
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
 		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
-		if (info->emu.mdmreg[13] & 4) {
+		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
 			isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
 			printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
@@ -1047,8 +1136,8 @@
 static int
 isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
 {
-	int c,
-	 total = 0;
+	int c;
+	int total = 0;
 	ulong flags;
 	modem_info *info = (modem_info *) tty->driver_data;
 
@@ -1074,7 +1163,7 @@
 #ifdef CONFIG_ISDN_AUDIO
 			if (!info->vonline)
 #endif
-				isdn_tty_check_esc(buf, m->mdmreg[2], c,
+				isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
 						   &(m->pluscount),
 						   &(m->lastplus),
 						   from_user);
@@ -1116,7 +1205,7 @@
 			} else
 #endif
 				info->xmit_count += c;
-			if (m->mdmreg[13] & 1) {
+			if (m->mdmreg[REG_DELXMT] & BIT_DELXMT) {
 				isdn_tty_senddown(info);
 				isdn_tty_tint(info);
 			}
@@ -1304,7 +1393,7 @@
 	uint arg;
 	int pre_dtr;
 
-	GET_USER(arg, (uint *) value);
+	get_user(arg, (uint *) value);
 	switch (cmd) {
 		case TIOCMBIS:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
@@ -1327,7 +1416,7 @@
 			}
 			if (arg & TIOCM_DTR) {
 				info->mcr &= ~UART_MCR_DTR;
-				if (info->emu.mdmreg[13] & 4) {
+				if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
 					isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
 					printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
@@ -1348,7 +1437,7 @@
 			       | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
 			if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
 				if (!(info->mcr & UART_MCR_DTR)) {
-					if (info->emu.mdmreg[13] & 4) {
+					if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
 						isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
 						printk(KERN_DEBUG "Mhup in TIOCMSET\n");
@@ -1414,7 +1503,7 @@
 			error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
 			if (error)
 				return error;
-			GET_USER(arg, (ulong *) arg);
+			get_user(arg, (ulong *) arg);
 			tty->termios->c_cflag =
 			    ((tty->termios->c_cflag & ~CLOCAL) |
 			     (arg ? CLOCAL : 0));
@@ -1443,7 +1532,6 @@
 				return error;
 			else
 				return isdn_tty_get_lsr_info(info, (uint *) arg);
-
 		default:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
@@ -1823,10 +1911,10 @@
 isdn_tty_modem_reset_regs(modem_info * info, int force)
 {
 	atemu *m = &info->emu;
-	if ((m->mdmreg[12] & 32) || force) {
+	if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
 		memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
 		memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
-		info->xmit_size = m->mdmreg[16] * 16;
+		info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
 	}
 #ifdef CONFIG_ISDN_AUDIO
 	isdn_tty_modem_reset_vpar(m);
@@ -1881,6 +1969,7 @@
 	m->tty_modem.stop = NULL;
 	m->tty_modem.start = NULL;
 	m->tty_modem.hangup = isdn_tty_hangup;
+	m->tty_modem.driver_name = "isdn_tty";
 	/*
 	 * The callout device is just like normal device except for
 	 * major number and the subtype code.
@@ -1905,7 +1994,7 @@
 		sprintf(info->last_num, "none");
 		info->last_dir = 0;
 		info->last_lhup = 1;
-		info->last_l2 = 0;
+		info->last_l2 = -1;
 		info->last_si = 0;
 		isdn_tty_reset_profile(&info->emu);
 		isdn_tty_modem_reset_regs(info, 1);
@@ -1927,7 +2016,7 @@
 #ifdef CONFIG_ISDN_AUDIO
 		skb_queue_head_init(&info->dtmf_queue);
 #endif
-		if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_SIZE + 5, GFP_KERNEL))) {
+		if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) {
 			printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
 			return -3;
 		}
@@ -1977,12 +2066,12 @@
 #ifdef ISDN_DEBUG_MODEM_ICALL
 		printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
 		       info->emu.msn, isdn_map_eaz2msn(info->emu.msn, di),
-		       info->emu.mdmreg[18], info->emu.mdmreg[19]);
+		       info->emu.mdmreg[REG_SI1], info->emu.mdmreg[REG_SI2]);
 #endif
 		if ((!strcmp(isdn_map_eaz2msn(info->emu.msn, di),
-			     eaz)) &&	/* EAZ is matching      */
-		    (info->emu.mdmreg[18] & si2bit[si1]) &&	/* SI1 is matching      */
-		    ((info->emu.mdmreg[19] == si2) || !si2)) {	/* SI2 is matching or 0 */
+			     eaz)) &&	                          /* EAZ is matching */
+		    (info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
+		    (info->emu.mdmreg[REG_SI2] == si2)) {	  /* SI2 is matching */
 			idx = isdn_dc2minor(di, ch);
 #ifdef ISDN_DEBUG_MODEM_ICALL
 			printk(KERN_DEBUG "m_fi: match1\n");
@@ -1990,7 +2079,10 @@
 			       info->flags, info->isdn_driver, info->isdn_channel,
 			       dev->usage[idx]);
 #endif
-			if ((info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
+			if (
+#ifndef FIX_FILE_TRANSFER
+				(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
+#endif
 			    (info->isdn_driver == -1) &&
 			    (info->isdn_channel == -1) &&
 			    (USG_NONE(dev->usage[idx]))) {
@@ -2001,9 +2093,9 @@
 				dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
 				dev->usage[idx] |= (si1 == 1) ? ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
 				strcpy(dev->num[idx], nr);
-				info->emu.mdmreg[20] = si2bit[si1];
-				info->emu.mdmreg[21] = setup.plan;
-				info->emu.mdmreg[22] = setup.screen;
+				info->emu.mdmreg[REG_SI1I] = si2bit[si1];
+				info->emu.mdmreg[REG_PLAN] = setup.plan;
+				info->emu.mdmreg[REG_SCREEN] = setup.screen;
 				isdn_info_update();
 				restore_flags(flags);
 				printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
@@ -2029,12 +2121,20 @@
 {
 	int mi;
 	modem_info *info;
+	char *e;
 
 	if (i < 0)
 		return 0;
 	if ((mi = dev->m_idx[i]) >= 0) {
 		info = &dev->mdm.info[mi];
 		switch (c->command) {
+                        case ISDN_STAT_CINF:
+                                printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
+                                info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
+                                if (e == c->parm.num)
+					info->emu.charge = 0;
+				
+                                break;			
 			case ISDN_STAT_BSENT:
 #ifdef ISDN_TTY_STAT_DEBUG
 				printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
@@ -2093,6 +2193,7 @@
 				 */
 				if (TTY_IS_ACTIVE(info)) {
 					info->msr |= UART_MSR_DCD;
+					info->emu.charge = 0;
 					if (info->dialing) {
 						info->dialing = 0;
 						info->last_dir = 1;
@@ -2184,13 +2285,13 @@
 	for (p = msg; *p; p++) {
 		switch (*p) {
 			case '\r':
-				c = m->mdmreg[3];
+				c = m->mdmreg[REG_CR];
 				break;
 			case '\n':
-				c = m->mdmreg[4];
+				c = m->mdmreg[REG_LF];
 				break;
 			case '\b':
-				c = m->mdmreg[5];
+				c = m->mdmreg[REG_BS];
 				break;
 			default:
 				c = *p;
@@ -2293,14 +2394,14 @@
 	static char *msg[] =
 	{"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
 	 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
-	 "RINGING", "NO MSN/EAZ", "VCON"};
+	 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
 	ulong flags;
 	char s[10];
 
 	switch (code) {
 		case 2:
-			m->mdmreg[1]++;	/* RING */
-			if (m->mdmreg[1] == m->mdmreg[0])
+			m->mdmreg[REG_RINGCNT]++;	/* RING */
+			if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
 				/* Automatically accept incoming call */
 				isdn_tty_cmd_ATA(info);
 			break;
@@ -2313,7 +2414,7 @@
 #endif
 			save_flags(flags);
 			cli();
-			m->mdmreg[1] = 0;
+			m->mdmreg[REG_RINGCNT] = 0;
 			del_timer(&info->nc_timer);
 			info->ncarrier = 0;
 			if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
@@ -2356,15 +2457,19 @@
 				info->online = 1;
 			break;
 	}
-	if (m->mdmreg[12] & 1) {
+	if (m->mdmreg[REG_RESP] & BIT_RESP) {
 		/* Show results */
 		isdn_tty_at_cout("\r\n", info);
-		if (m->mdmreg[12] & 2) {
+		if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
 			/* Show numeric results */
 			sprintf(s, "%d", code);
 			isdn_tty_at_cout(s, info);
 		} else {
-			if ((code == 2) && (!(m->mdmreg[13] & 16))) {
+			if ((code == 2) &&
+				(m->mdmreg[REG_RUNG] & BIT_RUNG) &&
+				(m->mdmreg[REG_RINGCNT] > 1))
+				return;
+			if ((code == 2) && (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE))) {
 				isdn_tty_at_cout("CALLER NUMBER: ", info);
 				isdn_tty_at_cout(dev->num[info->drv_index], info);
 				isdn_tty_at_cout("\r\n", info);
@@ -2373,7 +2478,8 @@
 			switch (code) {
 				case 2:
 					/* Print CID only once, _after_ 1.st RING */
-					if ((m->mdmreg[13] & 16) && (m->mdmreg[1] == 1)) {
+					if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
+					    (m->mdmreg[REG_RINGCNT] == 1)) {
 						isdn_tty_at_cout("\r\n", info);
 						isdn_tty_at_cout("CALLER NUMBER: ", info);
 						isdn_tty_at_cout(dev->num[info->drv_index], info);
@@ -2383,18 +2489,39 @@
 				case 6:
 				case 7:
 				case 8:
-					m->mdmreg[1] = 0;
+					m->mdmreg[REG_RINGCNT] = 0;
 					/* Append Cause-Message if enabled */
-					if (m->mdmreg[13] & 8) {
+					if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
 						sprintf(s, "/%s", info->last_cause);
 						isdn_tty_at_cout(s, info);
 					}
 					break;
 				case 5:
 					/* Append Protocol to CONNECT message */
-					isdn_tty_at_cout((m->mdmreg[14] != 3) ? "/X.75" : "/HDLC", info);
-					if (m->mdmreg[13] & 2)
+					switch (m->mdmreg[REG_L2PROT]) {
+						case ISDN_PROTO_L2_X75I:
+						case ISDN_PROTO_L2_X75UI:
+						case ISDN_PROTO_L2_X75BUI:
+							isdn_tty_at_cout("/X.75", info);
+							break;
+						case ISDN_PROTO_L2_HDLC:
+							isdn_tty_at_cout("/HDLC", info);
+							break;
+						case ISDN_PROTO_L2_V11096:
+							isdn_tty_at_cout("/V110/9600", info);
+							break;
+						case ISDN_PROTO_L2_V11019:
+							isdn_tty_at_cout("/V110/19200", info);
+							break;
+						case ISDN_PROTO_L2_V11038:
+							isdn_tty_at_cout("/V110/38400", info);
+							break;
+					}
+					if (m->mdmreg[REG_T70] & BIT_T70) {
 						isdn_tty_at_cout("/T.70", info);
+						if (m->mdmreg[REG_T70] & BIT_T70_EXT)
+							isdn_tty_at_cout("+", info);
+					}
 					break;
 			}
 		}
@@ -2479,16 +2606,25 @@
 	isdn_tty_at_cout("    Layer-2 Protocol: ", info);
 	switch (info->last_l2) {
 		case ISDN_PROTO_L2_X75I:
-			isdn_tty_at_cout("x75i", info);
+			isdn_tty_at_cout("X.75i", info);
 			break;
 		case ISDN_PROTO_L2_X75UI:
-			isdn_tty_at_cout("x75ui", info);
+			isdn_tty_at_cout("X.75ui", info);
 			break;
 		case ISDN_PROTO_L2_X75BUI:
-			isdn_tty_at_cout("x75bui", info);
+			isdn_tty_at_cout("X.75bui", info);
 			break;
 		case ISDN_PROTO_L2_HDLC:
-			isdn_tty_at_cout("hdlc", info);
+			isdn_tty_at_cout("HDLC", info);
+			break;
+		case ISDN_PROTO_L2_V11096:
+			isdn_tty_at_cout("V.110 9600 Baud", info);
+			break;
+		case ISDN_PROTO_L2_V11019:
+			isdn_tty_at_cout("V.110 19200 Baud", info);
+			break;
+		case ISDN_PROTO_L2_V11038:
+			isdn_tty_at_cout("V.110 38400 Baud", info);
 			break;
 		case ISDN_PROTO_L2_TRANS:
 			isdn_tty_at_cout("transparent", info);
@@ -2497,7 +2633,12 @@
 			isdn_tty_at_cout("unknown", info);
 			break;
 	}
-	isdn_tty_at_cout((m->mdmreg[13] & 2) ? "/t.70\r\n" : "\r\n", info);
+	if (m->mdmreg[REG_T70] & BIT_T70) {
+		isdn_tty_at_cout("/T.70", info);
+		if (m->mdmreg[REG_T70] & BIT_T70_EXT)
+			isdn_tty_at_cout("+", info);
+	}
+	isdn_tty_at_cout("\r\n", info);
 	isdn_tty_at_cout("    Service:          ", info);
 	switch (info->last_si) {
 		case 1:
@@ -2535,30 +2676,36 @@
 			/* &B - Set Buffersize */
 			p[0]++;
 			i = isdn_getnum(p);
-			if ((i < 0) || (i > ISDN_SERIAL_XMIT_SIZE))
+			if ((i < 0) || (i > ISDN_SERIAL_XMIT_MAX))
 				PARSE_ERROR1;
 #ifdef CONFIG_ISDN_AUDIO
-			if ((m->mdmreg[18] & 1) && (i > VBUF))
+			if ((m->mdmreg[REG_SI1] & 1) && (i > VBUF))
 				PARSE_ERROR1;
 #endif
-			m->mdmreg[16] = i / 16;
-			info->xmit_size = m->mdmreg[16] * 16;
+			m->mdmreg[REG_PSIZE] = i / 16;
+			info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
+			switch (m->mdmreg[REG_L2PROT]) {
+				case ISDN_PROTO_L2_V11096:
+				case ISDN_PROTO_L2_V11019:
+				case ISDN_PROTO_L2_V11038:
+					info->xmit_size /= 10;		
+			}
 			break;
 		case 'D':
 			/* &D - Set DCD-Low-behavior */
 			p[0]++;
 			switch (isdn_getnum(p)) {
 				case 0:
-					m->mdmreg[13] &= ~4;
-					m->mdmreg[12] &= ~32;
+					m->mdmreg[REG_DTRHUP] &= ~BIT_DTRHUP;
+					m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
 					break;
 				case 2:
-					m->mdmreg[13] |= 4;
-					m->mdmreg[12] &= ~32;
+					m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
+					m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
 					break;
 				case 3:
-					m->mdmreg[13] |= 4;
-					m->mdmreg[12] |= 32;
+					m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
+					m->mdmreg[REG_DTRR] |= BIT_DTRR;
 					break;
 				default:
 					PARSE_ERROR1
@@ -2575,12 +2722,46 @@
 			isdn_tty_reset_profile(m);
 			isdn_tty_modem_reset_regs(info, 1);
 			break;
+		case 'R':
+			/* &R - Set V.110 bitrate adaption */
+			p[0]++;
+			i = isdn_getnum(p);
+			switch (i) {
+				case 0:
+					/* Switch off V.110, back to X.75 */
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
+					m->mdmreg[REG_SI2] = 0;
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
+					break;
+				case 9600:
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11096;
+					m->mdmreg[REG_SI2] = 197;
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
+					break;
+				case 19200:
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11019;
+					m->mdmreg[REG_SI2] = 199;
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
+					break;
+				case 38400:
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11038;
+					m->mdmreg[REG_SI2] = 198; /* no existing standard for this */
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
+					break;
+				default:
+					PARSE_ERROR1;
+			}
+			/* Switch off T.70 */
+			m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
+			/* Set Service 7 */
+			m->mdmreg[REG_SI1] |= 4;
+			break;
 		case 'S':
 			/* &S - Set Windowsize */
 			p[0]++;
 			i = isdn_getnum(p);
 			if ((i > 0) && (i < 9))
-				m->mdmreg[17] = i;
+				m->mdmreg[REG_WSIZE] = i;
 			else
 				PARSE_ERROR1;
 			break;
@@ -2610,19 +2791,27 @@
 			}
 			break;
 		case 'X':
-			/* &X - Switch to BTX-Mode */
+			/* &X - Switch to BTX-Mode and T.70 */
 			p[0]++;
 			switch (isdn_getnum(p)) {
 				case 0:
-					m->mdmreg[13] &= ~2;
-					info->xmit_size = m->mdmreg[16] * 16;
+					m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
 					break;
 				case 1:
-					m->mdmreg[13] |= 2;
-					m->mdmreg[14] = 0;
+					m->mdmreg[REG_T70] |= BIT_T70;
+					m->mdmreg[REG_T70] &= ~BIT_T70_EXT;
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
+					info->xmit_size = 112;
+					m->mdmreg[REG_SI1] = 4;
+					m->mdmreg[REG_SI2] = 0;
+					break;
+				case 2:
+					m->mdmreg[REG_T70] |= (BIT_T70 | BIT_T70_EXT);
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
 					info->xmit_size = 112;
-					m->mdmreg[18] = 4;
-					m->mdmreg[19] = 0;
+					m->mdmreg[REG_SI1] = 4;
+					m->mdmreg[REG_SI2] = 0;
 					break;
 				default:
 					PARSE_ERROR1;
@@ -2639,22 +2828,28 @@
 {
 	/* Some plausibility checks */
 	switch (mreg) {
-		case 14:
-			if (mval > ISDN_PROTO_L2_TRANS)
+		case REG_L2PROT:
+			if (mval > ISDN_PROTO_L2_MAX)
 				return 1;
 			break;
-		case 16:
-			if ((mval * 16) > ISDN_SERIAL_XMIT_SIZE)
+		case REG_PSIZE:
+			if ((mval * 16) > ISDN_SERIAL_XMIT_MAX)
 				return 1;
 #ifdef CONFIG_ISDN_AUDIO
-			if ((m->mdmreg[18] & 1) && (mval > VBUFX))
+			if ((m->mdmreg[REG_SI1] & 1) && (mval > VBUFX))
 				return 1;
 #endif
 			info->xmit_size = mval * 16;
+			switch (m->mdmreg[REG_L2PROT]) {
+				case ISDN_PROTO_L2_V11096:
+				case ISDN_PROTO_L2_V11019:
+				case ISDN_PROTO_L2_V11038:
+					info->xmit_size /= 10;		
+			}
 			break;
-		case 20:
-		case 21:
-		case 22:
+		case REG_SI1I:
+		case REG_PLAN:
+		case REG_SCREEN:
 			/* readonly registers */
 			return 1;
 	}
@@ -2741,31 +2936,31 @@
 		/* Accept incoming call */
 		info->last_dir = 0;
 		strcpy(info->last_num, dev->num[info->drv_index]);
-		m->mdmreg[1] = 0;
+		m->mdmreg[REG_RINGCNT] = 0;
 		info->msr &= ~UART_MSR_RI;
-		l2 = m->mdmreg[14];
+		l2 = m->mdmreg[REG_L2PROT];
 #ifdef CONFIG_ISDN_AUDIO
 		/* If more than one bit set in reg18, autoselect Layer2 */
-		if ((m->mdmreg[18] & m->mdmreg[20]) != m->mdmreg[18]) {
-			if (m->mdmreg[20] == 1)
-				l2 = 4;
+		if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
+			if (m->mdmreg[REG_SI1I] == 1)
+				l2 = ISDN_PROTO_L2_TRANS;
 			else
-				l2 = 0;
+				l2 = ISDN_PROTO_L2_X75I;
 		}
 #endif
 		cmd.driver = info->isdn_driver;
 		cmd.command = ISDN_CMD_SETL2;
 		cmd.arg = info->isdn_channel + (l2 << 8);
 		info->last_l2 = l2;
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		isdn_command(&cmd);
 		cmd.driver = info->isdn_driver;
 		cmd.command = ISDN_CMD_SETL3;
-		cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
-		dev->drv[info->isdn_driver]->interface->command(&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.command = ISDN_CMD_ACCEPTD;
-		dev->drv[info->isdn_driver]->interface->command(&cmd);
+		isdn_command(&cmd);
 	} else
 		isdn_tty_modem_result(8, info);
 }
@@ -2787,7 +2982,7 @@
 			case '?':
 				p[0]++;
 				sprintf(rs, "\r\n%d",
-					(m->mdmreg[18] & 1) ? 8 : 0);
+					(m->mdmreg[REG_SI1] & 1) ? 8 : 0);
 				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
@@ -2795,18 +2990,22 @@
 				switch (*p[0]) {
 					case '0':
 						p[0]++;
-						m->mdmreg[18] = 4;
+						m->mdmreg[REG_SI1] = 4;
 						info->xmit_size =
-						    m->mdmreg[16] * 16;
+						    m->mdmreg[REG_PSIZE] * 16;
+						break;
+					case '2':
+						printk(KERN_DEBUG "isdn_tty: FCLASS=2\n");
+						p[0]++;
 						break;
 					case '8':
 						p[0]++;
-						m->mdmreg[18] = 5;
+						m->mdmreg[REG_SI1] = 5;
 						info->xmit_size = VBUF;
 						break;
 					case '?':
 						p[0]++;
-						isdn_tty_at_cout("\r\n0,8",
+						isdn_tty_at_cout("\r\n0,2,8",
 								 info);
 						break;
 					default:
@@ -2824,7 +3023,7 @@
 			case '?':
 				p[0]++;
 				sprintf(rs, "\r\n%d",
-					m->mdmreg[0]);
+					m->mdmreg[REG_RINGATA]);
 				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
@@ -2832,13 +3031,100 @@
 				par = isdn_getnum(p);
 				if ((par < 0) || (par > 255))
 					PARSE_ERROR1;
-				m->mdmreg[0] = par;
+				m->mdmreg[REG_RINGATA] = par;
 				break;
 			default:
 				PARSE_ERROR1;
 		}
 		return 0;
 	}
+        if (!strncmp(p[0], "TBC=", 4)) { /* UNKLAR !! */
+                p[0] += 4;
+                printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
+                switch (*p[0]) {
+                        case '0':
+                                p[0]++;
+                                break;
+                        default:
+                                PARSE_ERROR1;
+                }
+                return 0;
+        }
+        if (!strncmp(p[0], "BOR=", 4)) { /* UNKLAR !! */
+                p[0] += 4;
+                printk(KERN_DEBUG "isdn_tty: Fax FBOR=%c\n", *p[0]);
+                switch (*p[0]) {
+                        case '0':
+                                p[0]++;
+                                break;
+                        default:
+                                PARSE_ERROR1;
+                }
+                return 0;
+        }
+        if (!strncmp(p[0], "DCC=", 4)) { /* SETUP irgendwie !! */
+		int i, val[]={0,0,0,0,0,0,0,0};
+
+                p[0] += 4;
+                if (*p[0] == '?') {
+			isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0,1),(0),(0),(0-7)",info);
+			p[0]++;
+                } else {
+			for (i=0; (*p[0]>='0') && (*p[0]<='9'); i++) {
+				val[i] = *p[0] - 48;
+				p[0]++;
+				if (*p[0] == ',')
+					p[0]++;
+			}
+			printk(KERN_DEBUG "isdn_tty: Fax Setup values=%d,%d,%d,%d,%d,%d,%d,%d\n",
+			       val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
+                }
+                return 0;
+        }
+        if (!strncmp(p[0], "LID=", 4)) { /* set sender ID !! */
+		char senderID[80];
+		int i;
+
+                p[0] += 4;
+                if (*p[0] =='"')
+			p[0]++;
+                for(i=0; (*p[0]) && (*p[0] != '"'); i++)
+			senderID[i] = *p[0]++;
+                senderID[i] = 0;
+                if (*p[0] =='"')
+			p[0]++;
+                printk(KERN_DEBUG "isdn_tty: Fax sender=>%s<\n", senderID);
+                return 0;
+        }
+        if (!strncmp(p[0], "MFR?", 4)) {
+                p[0] += 4;
+                printk(KERN_DEBUG "isdn_tty: FMFR?\n");
+                isdn_tty_at_cout("\r\nISDNfax", info);
+                return 0;
+        }
+        if (!strncmp(p[0], "MDL?", 4)) {
+                p[0] += 4;
+                printk(KERN_DEBUG "isdn_tty: FMDL?\n");
+                isdn_tty_at_cout("\r\nAVM-B1", info);
+                return 0;
+        }
+        if (!strncmp(p[0], "AP=?", 4)) {
+                p[0] += 4;
+                printk(KERN_DEBUG "isdn_tty: FAP=?\n");
+                return 0;
+        }
+        if (!strncmp(p[0], "PHCTO=", 6)) {
+		/* beim trace mit dem zyxel folgt der wert 30 ;*/
+                p[0] += 6;
+                printk(KERN_DEBUG "isdn_tty: FPHCTO=%s\n", p[0]);
+                return 0;
+        }
+        if (!strncmp(p[0], "CR=", 3)) {
+                p[0] += 3;
+                printk(KERN_DEBUG "isdn_tty: FCR=%s\n", p[0]);
+                return 0;
+        }
+        printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
 	PARSE_ERROR1;
 }
 
@@ -3110,10 +3396,10 @@
 				p++;
 				switch (isdn_getnum(&p)) {
 					case 0:
-						m->mdmreg[12] &= ~4;
+						m->mdmreg[REG_ECHO] &= ~BIT_ECHO;
 						break;
 					case 1:
-						m->mdmreg[12] |= 4;
+						m->mdmreg[REG_ECHO] |= BIT_ECHO;
 						break;
 					default:
 						PARSE_ERROR;
@@ -3149,6 +3435,11 @@
 						p++;
 						isdn_tty_report(info);
 						break;
+					case '3':
+                                                p++;
+                                                sprintf(ds, "\r\n%d", info->emu.charge);
+                                                isdn_tty_at_cout(ds, info);
+                                                break;
 					default:
 				}
 				break;
@@ -3166,10 +3457,10 @@
 				p++;
 				switch (isdn_getnum(&p)) {
 					case 0:
-						m->mdmreg[12] |= 1;
+						m->mdmreg[REG_RESP] |= BIT_RESP;
 						break;
 					case 1:
-						m->mdmreg[12] &= ~1;
+						m->mdmreg[REG_RESP] &= ~BIT_RESP;
 						break;
 					default:
 						PARSE_ERROR;
@@ -3186,10 +3477,10 @@
 				p++;
 				switch (isdn_getnum(&p)) {
 					case 0:
-						m->mdmreg[12] |= 2;
+						m->mdmreg[REG_RESP] |= BIT_RESPNUM;
 						break;
 					case 1:
-						m->mdmreg[12] &= ~2;
+						m->mdmreg[REG_RESP] &= ~BIT_RESPNUM;
 						break;
 					default:
 						PARSE_ERROR;
@@ -3210,7 +3501,7 @@
 							return;
 						break;
 					case 'V':
-						if (!(m->mdmreg[18] & 1))
+						if (!(m->mdmreg[REG_SI1] & 1))
 							PARSE_ERROR;
 						p++;
 						if (isdn_tty_cmd_PLUSV(&p, info))
@@ -3261,14 +3552,14 @@
 
 	for (cnt = count; cnt > 0; p++, cnt--) {
 		if (user)
-			GET_USER(c, p);
+			get_user(c, p);
 		else
 			c = *p;
 		total++;
-		if (c == m->mdmreg[3] || c == m->mdmreg[4]) {
+		if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) {
 			/* Separator (CR oder LF) */
 			m->mdmcmd[m->mdmcmdl] = 0;
-			if (m->mdmreg[12] & 4) {
+			if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
 				eb[0] = c;
 				eb[1] = 0;
 				isdn_tty_at_cout(eb, info);
@@ -3278,18 +3569,18 @@
 			m->mdmcmdl = 0;
 			continue;
 		}
-		if (c == m->mdmreg[5] && m->mdmreg[5] < 128) {
+		if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) {
 			/* Backspace-Funktion */
 			if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
 				if (m->mdmcmdl)
 					m->mdmcmdl--;
-				if (m->mdmreg[12] & 4)
+				if (m->mdmreg[REG_ECHO] & BIT_ECHO)
 					isdn_tty_at_cout("\b", info);
 			}
 			continue;
 		}
 		if (cmdchar(c)) {
-			if (m->mdmreg[12] & 4) {
+			if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
 				eb[0] = c;
 				eb[1] = 0;
 				isdn_tty_at_cout(eb, info);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov