diff -ur linux/include/linux/isdn.h linux.ext/include/linux/isdn.h
--- linux/include/linux/isdn.h	Sat Sep  1 17:37:17 2001
+++ linux.ext/include/linux/isdn.h	Sat Sep  1 19:09:30 2001
@@ -571,6 +571,10 @@
 	int maxsize;                   /* maxbufsize of lowlevel driver        */
 	unsigned char *encodebuf;      /* temporary buffer for encoding        */
 	unsigned char decodebuf[V110_BUFSIZE]; /* incomplete V110 matrices     */
+	long tx_busy;                  /* transmitter busy (output flow
+					  controlled by incoming X bits) */
+	int nfill;                     /* No. of fill bits per character,
+					  in addition to start and stop bit */
 } isdn_v110_stream;
 
 /*========================= End of V.110 stuff =============================*/
diff -ur linux/include/linux/isdnif.h linux.ext/include/linux/isdnif.h
--- linux/include/linux/isdnif.h	Sat Sep  1 17:21:41 2001
+++ linux.ext/include/linux/isdnif.h	Sat Sep  1 18:52:01 2001
@@ -1,4 +1,3 @@
-
 /* $Id: isdnif.h,v 1.37.6.5 2001/06/11 22:08:38 kai Exp $
 
  * Linux ISDN subsystem
@@ -54,6 +53,8 @@
 #define ISDN_PROTO_L2_MODEM  10  /* Analog Modem on Board */
 #define ISDN_PROTO_L2_FAX    11  /* Fax Group 2/3         */
 #define ISDN_PROTO_L2_HDLC_56K 12   /* HDLC 56k                          */
+#define ISDN_PROTO_L2_V11012 13   /* V.110 bitrate adaption 12000 Baud */
+#define ISDN_PROTO_L2_V11014 14 /* V.110 bitrate adaption 14400 Baud */
 #define ISDN_PROTO_L2_MAX    15  /* Max. 16 Protocols                 */
 
 /*
@@ -256,6 +257,8 @@
 #define ISDN_FEATURE_L2_MODEM   (0x0001 << ISDN_PROTO_L2_MODEM)
 #define ISDN_FEATURE_L2_FAX	(0x0001 << ISDN_PROTO_L2_FAX)
 #define ISDN_FEATURE_L2_HDLC_56K (0x0001 << ISDN_PROTO_L2_HDLC_56K)
+#define ISDN_FEATURE_L2_V11012  (0x0001 << ISDN_PROTO_L2_V11012)
+#define ISDN_FEATURE_L2_V11014  (0x0001 << ISDN_PROTO_L2_V11014)
 
 #define ISDN_FEATURE_L2_MASK    (0x0FFFF) /* Max. 16 protocols */
 #define ISDN_FEATURE_L2_SHIFT   (0)
diff -ur linux/drivers/isdn/isdn_common.c linux.ext/drivers/isdn/isdn_common.c
--- linux/drivers/isdn/isdn_common.c	Fri Aug 31 23:37:38 2001
+++ linux.ext/drivers/isdn/isdn_common.c	Sat Sep  1 18:53:02 2001
@@ -376,6 +376,8 @@
 			case ISDN_PROTO_L2_V11096:
 			case ISDN_PROTO_L2_V11019:
 			case ISDN_PROTO_L2_V11038:
+			case ISDN_PROTO_L2_V11012:
+			case ISDN_PROTO_L2_V11014:
 			/* If V.110 requested, but not supported by
 			 * HL-driver, set emulator-flag and change
 			 * Layer-2 to transparent
@@ -1770,7 +1772,7 @@
  * Find an unused ISDN-channel, whose feature-flags match the
  * given L2- and L3-protocols.
  */
-#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
+#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11012|ISDN_FEATURE_L2_V11014|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
 
 int
 isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
@@ -1785,7 +1787,7 @@
 	cli();
 	features = ((1 << l2_proto) | (0x10000 << l3_proto));
 	vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
-		     ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038));
+		     ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11012|ISDN_FEATURE_L2_V11014|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038));
 	/* If Layer-2 protocol is V.110, accept drivers with
 	 * transparent feature even if these don't support V.110
 	 * because we can emulate this in linklevel.
@@ -1919,6 +1921,10 @@
 
 	if (dev->v110[idx]) {
 		atomic_inc(&dev->v110use[idx]);
+		if(dev->v110[idx]->tx_busy){
+			atomic_dec(&dev->v110use[idx]);
+			return 0;
+		};
 		nskb = isdn_v110_encode(dev->v110[idx], skb);
 		atomic_dec(&dev->v110use[idx]);
 		if (!nskb)
diff -ur linux/drivers/isdn/isdn_tty.c linux.ext/drivers/isdn/isdn_tty.c
--- linux/drivers/isdn/isdn_tty.c	Fri Aug 31 23:37:13 2001
+++ linux.ext/drivers/isdn/isdn_tty.c	Sat Sep  1 17:27:06 2001
@@ -2767,6 +2767,12 @@
 						case ISDN_PROTO_L2_V11038:
 							isdn_tty_at_cout("/V110/38400", info);
 							break;
+						case ISDN_PROTO_L2_V11012:
+							isdn_tty_at_cout("/V110/12000", info);
+							break;
+						case ISDN_PROTO_L2_V11014:
+							isdn_tty_at_cout("/V110/14400", info);
+							break;
 					}
 					if (m->mdmreg[REG_T70] & BIT_T70) {
 						isdn_tty_at_cout("/T.70", info);
@@ -2886,6 +2892,12 @@
 		case ISDN_PROTO_L2_V11038:
 			isdn_tty_at_cout("V.110 38400 Baud", info);
 			break;
+		case ISDN_PROTO_L2_V11012:
+			isdn_tty_at_cout("V.110 12000 Baud", info);
+			break;
+		case ISDN_PROTO_L2_V11014:
+			isdn_tty_at_cout("V.110 14400 Baud", info);
+			break;
 		case ISDN_PROTO_L2_TRANS:
 			isdn_tty_at_cout("transparent", info);
 			break;
@@ -2956,6 +2968,8 @@
 				case ISDN_PROTO_L2_V11096:
 				case ISDN_PROTO_L2_V11019:
 				case ISDN_PROTO_L2_V11038:
+				case ISDN_PROTO_L2_V11012:
+				case ISDN_PROTO_L2_V11014:
 					info->xmit_size /= 10;		
 			}
 			break;
@@ -3049,6 +3063,16 @@
 					m->mdmreg[REG_SI2] = 198; /* no existing standard for this */
 					info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
 					break;
+				case 12000:
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11012;
+					m->mdmreg[REG_SI2] = 199; /*base rate*/
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
+					break;
+				case 14400:
+					m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11014;
+					m->mdmreg[REG_SI2] = 198; /* also used by 38400 */
+					info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
+					break;
 				default:
 					PARSE_ERROR1;
 			}
@@ -3150,6 +3174,8 @@
 				case ISDN_PROTO_L2_V11096:
 				case ISDN_PROTO_L2_V11019:
 				case ISDN_PROTO_L2_V11038:
+				case ISDN_PROTO_L2_V11012:
+				case ISDN_PROTO_L2_V11014:
 					info->xmit_size /= 10;		
 			}
 			break;
diff -ur linux/drivers/isdn/isdn_v110.c linux.ext/drivers/isdn/isdn_v110.c
--- linux/drivers/isdn/isdn_v110.c	Tue Aug  7 17:08:50 2001
+++ linux.ext/drivers/isdn/isdn_v110.c	Sat Sep  1 17:35:39 2001
@@ -4,6 +4,8 @@
  *
  * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
  *
+ * X-bit output flow control and fractional bit rates by Henner Eisen
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -95,12 +97,17 @@
 
 /* isdn_v110_open allocates and initializes private V.110 data
  * structures and returns a pointer to these.
+ * key corresponds to the frame (base) baud rate, user_rate is the effective
+ * baud rate to be emulated/adapted by V.110.
+ * user_rate must be <= data bit baud rate of V.110 frame. 
  */
 static isdn_v110_stream *
-isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
+isdn_v110_open(unsigned char key, int hdrlen, int maxsize, unsigned int user_rate)
 {
 	int i;
 	isdn_v110_stream *v;
+	const int bpc = 10; /* transmission of = (1 start + 1 stop + 8 data)
+			       bits per character is emulated with user_rate */
 
 	if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
 		return NULL;
@@ -112,21 +119,29 @@
 
 	v->nbytes = 8 / v->nbits;
 	v->decodelen = 0;
+	v->nfill = 0;
 
 	switch (key) {
 		case V110_38400:
 			v->OnlineFrame = V110_OnMatrix_38400;
 			v->OfflineFrame = V110_OffMatrix_38400;
+			v->nfill = ((bpc+1)*38400 - 1) / user_rate  -  bpc;
 			break;
 		case V110_19200:
 			v->OnlineFrame = V110_OnMatrix_19200;
 			v->OfflineFrame = V110_OffMatrix_19200;
+			v->nfill = ((bpc+1)*19200 - 1) / user_rate  -  bpc;
 			break;
 		default:
 			v->OnlineFrame = V110_OnMatrix_9600;
 			v->OfflineFrame = V110_OffMatrix_9600;
+			v->nfill = ((bpc+1)*9600 - 1) / user_rate  -  bpc;
 			break;
 	}
+	if(v->nfill<0){
+		printk(KERN_WARNING "isdn_v110: user_rate > frame rate\n");
+		v->nfill=0;
+	}
 	v->framelen = v->nbytes * 10;
 	v->SyncInit = 5;
 	v->introducer = 0;
@@ -193,7 +208,7 @@
 
 /* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where
    len is the number of matrix-lines. len must be a multiple of 10, i.e.
-   only complete matices must be given.
+   only complete matrices must be given.
    From these, netto data is extracted and returned in buf. The return-value
    is the bytecount of the decoded data.
  */
@@ -206,6 +221,7 @@
 	int introducer = v->introducer;
 	int dbit = v->dbit;
 	unsigned char b = v->b;
+	int xbit_val = 0;
 
 	while (line < len) {    /* Are we done with all lines of the matrix? */
 		if ((line % 10) == 0) {	/* the 0. line of the matrix is always 0 ! */
@@ -233,6 +249,11 @@
 				mbit >>= 1;	/* no -> take next */
 				continue;
 			}       /* otherwise start with leftmost bit in the next line */
+			if((line%10) == 7){
+				/* extract last xbit value contained in
+				 * current column for tx flow control */
+				xbit_val = m[line] & 0x01;
+			}
 			mbit = 64;
 			line++;
 			continue;
@@ -254,6 +275,7 @@
 	v->introducer = introducer;
 	v->dbit = dbit;
 	v->b = b;
+	v->tx_busy = xbit_val;
 	return buflen;          /* return number of bytes in the output buffer */
 }
 
@@ -333,14 +355,13 @@
    matrix-lines generated.
  */
 static int
-EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen)
+EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen, unsigned int nfill)
 {
 	int line = 0;
 	int i = 0;
 	int mbit = 128;
 	int dbit = 1;
-	int introducer = 3;
-	int ibit[] = {0, 1, 1};
+	int introducer = 2+nfill;
 
 	while ((i < len) && (line < mlen)) {	/* while we still have input data */
 		switch (line % 10) {	/* in which line of the matrix are we? */
@@ -372,7 +393,7 @@
 		}
 		if (introducer) {	/* set 110 sequence ? */
 			introducer--;	/* set on digit less */
-			m[line] |= ibit[introducer] ? mbit : 0;	/* set corresponding bit */
+			m[line] |= (introducer>0) ? mbit : 0;	/* set corresponding bit */
 			mbit >>= 1;	/* bit of matrix line  >> 1 */
 			goto next_bit;	/* and go on there */
 		}               /* else push data bits into the matrix! */
@@ -381,7 +402,7 @@
 			dbit = 1;	/* then go on with first bit of  */
 			i++;            /* next byte in input buffer */
 			if (i < len)	/* input buffer done ? */
-				introducer = 3;	/* no, write introducer 110 */
+				introducer = 2+nfill;	/* no, write introducer 110 */
 			else {  /* input buffer done ! */
 				m[line] |= (mbit - 1) & 0xfe;	/* set remaining bits in line to 1 */
 				break;
@@ -484,7 +505,14 @@
 		return NULL;
 	}
 	rlen = skb->len;
+#if 0
 	nframes = (rlen + 3) / 4;
+#else
+	/* (No. of characters)*(bits per character)   / (data bits per frame)
+	 *                                      rounded to next upper integer*/
+	nframes =        (rlen*(10+v->nfill)    + 47) / 48;
+	/* The 10 is valid for 8 bit / no parity characters only */
+#endif
 	v110buf = v->encodebuf;
 	if ((nframes * 40) > v->maxsize) {
 		size = v->maxsize;
@@ -501,7 +529,7 @@
 		*((int *)skb_push(nskb, sizeof(int))) = 0;
 		return nskb;
 	}
-	mlen = EncodeMatrix(skb->data, rlen, v110buf, size);
+	mlen = EncodeMatrix(skb->data, rlen, v110buf, size, v->nfill);
 	/* now distribute 2 or 4 bits each to the output stream! */
 	rbuf = skb_put(nskb, size);
 	olen = 0;
@@ -592,13 +620,19 @@
 				atomic_inc(&dev->v110use[idx]);
 				switch (dev->v110emu[idx]) {
 					case ISDN_PROTO_L2_V11096:
-						dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize);
+						dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize,9600);
 						break;
 					case ISDN_PROTO_L2_V11019:
-						dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize);
+						dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize,19200);
+						break;
+					case ISDN_PROTO_L2_V11012:
+						dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize,12000);
+						break;
+					case ISDN_PROTO_L2_V11014:
+						dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize,14400);
 						break;
 					case ISDN_PROTO_L2_V11038:
-						dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize);
+						dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize,38400);
 						break;
 					default:;
 				}
