diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/src/bsc_hack.c openbsc/src/bsc_hack.c
--- openbsc.orig/src/bsc_hack.c	2009-03-28 11:36:37.000000000 +0100
+++ openbsc/src/bsc_hack.c	2009-04-18 06:58:34.000000000 +0200
@@ -53,8 +53,11 @@
 /* MCC and MNC for the Location Area Identifier */
 static int MCC = 1;
 static int MNC = 1;
+static int LAC = 1;
 static int ARFCN = HARDCODED_ARFCN;
 static enum gsm_bts_type BTS_TYPE = GSM_BTS_TYPE_BS11;
+static int cardnr = 0;
+static int release_l2 = 0;
 static const char *database_name = "hlr.sqlite3";
 
 /* The following definitions are for OM and NM packets that we cannot yet
@@ -901,7 +904,7 @@
 	gsmnet->name_long = "OpenBSC";
 	gsmnet->name_short = "OpenBSC";
 	bts = &gsmnet->bts[0];
-	bts->location_area_code = 1;
+	bts->location_area_code = LAC;
 	bts->trx[0].arfcn = ARFCN;
 
 	/* Control Channel Description */
@@ -920,7 +923,7 @@
 
 	/* E1 mISDN input setup */
 	if (BTS_TYPE == GSM_BTS_TYPE_BS11)
-		return e1_config(bts);
+		return e1_config(bts, cardnr, release_l2);
 	else
 		return ia_config(bts);
 }
@@ -952,14 +955,17 @@
 	printf("  Some useful help...\n");
 	printf("  -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
 	printf("  -s --disable-color\n");
-	printf("  -n --network-code number(MNC) \n");
+	printf("  -n --network-code number (MNC) \n");
 	printf("  -c --country-code number (MCC) \n");
+	printf("  -L --location-area-code number (LAC) \n");
 	printf("  -f --arfcn number The frequency ARFCN\n");
 	printf("  -l --database db-name The database to use\n");
 	printf("  -a --authorize-everyone Allow everyone into the network.\n");
 	printf("  -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
 	printf("  -p --pcap file  The filename of the pcap file\n");
 	printf("  -t --bts-type type The BTS type (bs11, nanobts900, nanobts1800)\n");
+	printf("  -C --cardnr number  For bs11 select E1 card number other than 0\n");
+	printf("  -R --release-l2 Releases mISDN layer 2 after exit, to unload driver.\n");
 	printf("  -h --help this text\n");
 }
 
@@ -973,16 +979,19 @@
 			{"disable-color", 0, 0, 's'},
 			{"network-code", 1, 0, 'n'},
 			{"country-code", 1, 0, 'c'},
+			{"location-area-code", 1, 0, 'L'},
 			{"database", 1, 0, 'l'},
 			{"authorize-everyone", 0, 0, 'a'},
 			{"reject-cause", 1, 0, 'r'},
 			{"pcap", 1, 0, 'p'},
 			{"arfcn", 1, 0, 'f'},
 			{"bts-type", 1, 0, 't'},
+			{"cardnr", 1, 0, 'C'},
+			{"release-l2", 0, 0, 'R'},
 			{0, 0, 0, 0}
 		};
 
-		c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:",
+		c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:",
 				long_options, &option_index);
 		if (c == -1)
 			break;
@@ -1004,6 +1013,9 @@
 		case 'c':
 			MCC = atoi(optarg);
 			break;
+		case 'L':
+			LAC = atoi(optarg);
+			break;
 		case 'f':
 			ARFCN = atoi(optarg);
 			break;
@@ -1022,6 +1034,12 @@
 		case 't':
 			BTS_TYPE = parse_btstype(optarg);
 			break;
+		case 'C':
+			cardnr = atoi(optarg);
+			break;
+		case 'R':
+			release_l2 = 1;
+			break;
 		default:
 			/* ignore */
 			break;
diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/src/e1_config.c openbsc/src/e1_config.c
--- openbsc.orig/src/e1_config.c	2009-03-28 11:36:37.000000000 +0100
+++ openbsc/src/e1_config.c	2009-04-19 13:24:20.000000000 +0200
@@ -15,7 +15,7 @@
 #define TEI_RSL		1
 
 /* do some compiled-in configuration for our BTS/E1 setup */
-int e1_config(struct gsm_bts *bts)
+int e1_config(struct gsm_bts *bts, int cardnr, int l2_release)
 {
 	struct e1inp_line *line;
 	struct e1inp_ts *sign_ts;
@@ -29,7 +29,7 @@
 	/* create E1 timeslots for signalling and TRAU frames */
 	e1inp_ts_config(&line->ts[1-1], line, E1INP_TS_TYPE_SIGN);
 	e1inp_ts_config(&line->ts[2-1], line, E1INP_TS_TYPE_TRAU);
-	//e1inp_ts_config(&line->ts[3-1], line, E1INP_TS_TYPE_TRAU);
+	e1inp_ts_config(&line->ts[3-1], line, E1INP_TS_TYPE_TRAU);
 
 	/* create signalling links for TS1 */
 	sign_ts = &line->ts[1-1];
@@ -47,13 +47,11 @@
 	subch_demux_activate(&line->ts[2-1].trau.demux, 2);
 	subch_demux_activate(&line->ts[2-1].trau.demux, 3);
 
-#if 0
 	/* enable subchannel demuxer on TS3 */
 	subch_demux_activate(&line->ts[3-1].trau.demux, 0);
 	subch_demux_activate(&line->ts[3-1].trau.demux, 1);
 	subch_demux_activate(&line->ts[3-1].trau.demux, 2);
 	subch_demux_activate(&line->ts[3-1].trau.demux, 3);
-#endif
 
 #ifdef HAVE_TRX1
 	/* create E1 timeslots for TRAU frames of TRX1 */
@@ -68,7 +66,7 @@
 	bts->trx[1].rsl_link = rsl_link;
 #endif
 
-	return mi_setup(0, line);
+	return mi_setup(cardnr, line, l2_release);
 }
 
 /* do some compiled-in configuration for our BTS/E1 setup */
diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/src/e1_input.c openbsc/src/e1_input.c
--- openbsc.orig/src/e1_input.c	2009-03-28 11:36:37.000000000 +0100
+++ openbsc/src/e1_input.c	2009-04-19 13:20:00.000000000 +0200
@@ -31,12 +31,10 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
-#include <mISDNif.h>
+//#include <mISDNuser/mISDNif.h>
 
-//#define AF_COMPATIBILITY_FUNC
-//#include <compat_af_isdn.h>
-#define AF_ISDN 34
-#define PF_ISDN AF_ISDN
+//#define MISDN_OLD_AF_COMPATIBILITY
+//#include <mISDNuser/compat_af_isdn.h>
 
 #include <openbsc/select.h>
 #include <openbsc/msgb.h>
@@ -223,6 +221,7 @@
 {
 	struct e1inp_sign_link *sign_link;
 	struct e1inp_driver *e1inp_driver;
+	struct e1inp_ts *e1i_ts;
 
 	msg->l2h = msg->data;
 
@@ -232,11 +231,16 @@
 	}
 
 	sign_link = msg->trx->rsl_link;
+	e1i_ts = sign_link->ts;
+
+	if (!timer_pending(&e1i_ts->sign.tx_timer)) {
+		/* notify the driver we have something to write */
+		e1inp_driver = sign_link->ts->line->driver;
+		e1inp_driver->want_write(e1i_ts);
+	}
+
 	msgb_enqueue(&sign_link->tx_list, msg);
 
-	/* notify the driver we have something to write */
-	e1inp_driver = sign_link->ts->line->driver;
-	e1inp_driver->want_write(sign_link->ts);
 
 	return 0;
 }
@@ -245,6 +249,7 @@
 {
 	struct e1inp_sign_link *sign_link;
 	struct e1inp_driver *e1inp_driver;
+	struct e1inp_ts *e1i_ts;
 
 	msg->l2h = msg->data;
 
@@ -254,11 +259,15 @@
 	}
 
 	sign_link = msg->trx->bts->oml_link;
-	msgb_enqueue(&sign_link->tx_list, msg);
+	e1i_ts = sign_link->ts;
 
-	/* notify the driver we have something to write */
-	e1inp_driver = sign_link->ts->line->driver;
-	e1inp_driver->want_write(sign_link->ts);
+	if (!timer_pending(&e1i_ts->sign.tx_timer)) {
+		/* notify the driver we have something to write */
+		e1inp_driver = sign_link->ts->line->driver;
+		e1inp_driver->want_write(e1i_ts);
+	}
+
+	msgb_enqueue(&sign_link->tx_list, msg);
 
 	return 0;
 }
diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/src/input/misdn.c openbsc/src/input/misdn.c
--- openbsc.orig/src/input/misdn.c	2009-03-28 11:36:36.000000000 +0100
+++ openbsc/src/input/misdn.c	2009-04-19 13:20:20.000000000 +0200
@@ -32,12 +32,11 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
-#include <mISDNif.h>
+#include <mISDNuser/mISDNif.h>
 
-//#define AF_COMPATIBILITY_FUNC
-//#include <compat_af_isdn.h>
-#define AF_ISDN 34
-#define PF_ISDN AF_ISDN
+#define MISDN_OLD_AF_COMPATIBILITY
+#define AF_COMPATIBILITY_FUNC
+#include <mISDNuser/compat_af_isdn.h>
 
 #include <openbsc/select.h>
 #include <openbsc/msgb.h>
@@ -114,8 +113,10 @@
 		return ret;
 	}
 
-	if (alen != sizeof(l2addr))
+	if (alen != sizeof(l2addr)) {
+		fprintf(stderr, "error len\n");
 		return -EINVAL;
+	}
 
 	msgb_put(msg, ret);
 
@@ -129,7 +130,7 @@
 	case DL_INFORMATION_IND:
 		/* mISDN tells us which channel number is allocated for this
 		 * tuple of (SAPI, TEI). */
-		DEBUGP(DMI, "use channel(%d) sapi(%d) tei(%d) for now\n",
+		DEBUGP(DMI, "DL_INFORMATION_IND: channel(%d) sapi(%d) tei(%d)\n",
 			l2addr.channel, l2addr.sapi, l2addr.tei);
 		link = e1inp_lookup_sign_link(e1i_ts, l2addr.tei, l2addr.sapi);
 		if (!link) {
@@ -140,10 +141,16 @@
 		/* save the channel number in the driver private struct */
 		link->driver.misdn.channel = l2addr.channel;
 		break;
-	case MPH_ACTIVATE_IND:
+//	case MPH_ACTIVATE_IND:
+	case DL_ESTABLISH_IND:
+		DEBUGP(DMI, "DL_ESTABLISH_IND: channel(%d) sapi(%d) tei(%d)\n",
+		l2addr.channel, l2addr.sapi, l2addr.tei);
 		ret = e1inp_event(e1i_ts, EVT_E1_TEI_UP, l2addr.tei, l2addr.sapi);
 		break;
-	case MPH_DEACTIVATE_IND:
+//	case MPH_DEACTIVATE_IND:
+	case DL_RELEASE_IND:
+		DEBUGP(DMI, "DL_RELEASE_IND: channel(%d) sapi(%d) tei(%d)\n",
+		l2addr.channel, l2addr.sapi, l2addr.tei);
 		ret = e1inp_event(e1i_ts, EVT_E1_TEI_DN, l2addr.tei, l2addr.sapi);
 		break;
 	case DL_DATA_IND:
@@ -157,6 +164,27 @@
 	return ret;
 }
 
+static int ts_want_write(struct e1inp_ts *e1i_ts)
+{
+	/* We never include the mISDN B-Channel FD into the
+	 * writeset, since it doesn't support poll() based
+	 * write flow control */		
+	if (e1i_ts->type == E1INP_TS_TYPE_TRAU)
+		return 0;
+
+	e1i_ts->driver.misdn.fd.when |= BSC_FD_WRITE;
+
+	return 0;
+}
+
+static void timeout_ts1_write(void *data)
+{
+	struct e1inp_ts *e1i_ts = (struct e1inp_ts *)data;
+
+	/* trigger write of ts1, due to tx delay timer */
+	ts_want_write(e1i_ts);
+}
+
 static int handle_ts1_write(struct bsc_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
@@ -169,10 +197,12 @@
 	u_int8_t *l2_data;
 	int ret;
 
+	bfd->when &= ~BSC_FD_WRITE;
+	
 	/* get the next msg for this timeslot */
 	msg = e1inp_tx_ts(e1i_ts, &sign_link);
 	if (!msg) {
-		bfd->when &= ~BSC_FD_WRITE;
+		/* no message after tx delay timer */
 		return 0;
 	}
 
@@ -182,8 +212,8 @@
 	hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh));
 	hh->prim = DL_DATA_REQ;
 
-	DEBUGP(DMI, "TX TEI(%d): %s\n", sign_link->tei,
-		hexdump(l2_data, msg->len - MISDN_HEADER_LEN));
+	DEBUGP(DMI, "TX TEI(%d) SAPI(%d): %s\n", sign_link->tei,
+		sign_link->sapi, hexdump(l2_data, msg->len - MISDN_HEADER_LEN));
 
 	/* construct the sockaddr */
 	sa.family = AF_ISDN;
@@ -193,10 +223,14 @@
 
 	ret = sendto(bfd->fd, msg->data, msg->len, 0,
 		     (struct sockaddr *)&sa, sizeof(sa));
+	if (ret < 0)
+		fprintf(stderr, "sendto failed %d\n", ret);
 	msgb_free(msg);
 
-	/* FIXME: this has to go */
-	usleep(100000);
+	/* set tx delay timer for next event */
+	e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
+	e1i_ts->sign.tx_timer.data = e1i_ts;
+	schedule_timer(&e1i_ts->sign.tx_timer, 0, 50000);
 
 	return ret;
 }
@@ -253,8 +287,9 @@
 
 	msgb_put(msg, ret);
 
-	DEBUGP(DMIB, "<= BCHAN len = %d, prim(0x%x) id(0x%x): %s\n",
-		ret, hh->prim, hh->id, get_prim_name(hh->prim));
+	if (hh->prim != PH_CONTROL_IND)
+		DEBUGP(DMIB, "<= BCHAN len = %d, prim(0x%x) id(0x%x): %s\n",
+			ret, hh->prim, hh->id, get_prim_name(hh->prim));
 
 	switch (hh->prim) {
 	case PH_DATA_IND:
@@ -332,28 +367,16 @@
 	return ret;
 }
 
-static int ts_want_write(struct e1inp_ts *e1i_ts)
-{
-	/* We never include the mISDN B-Channel FD into the
-	 * writeset, since it doesn't support poll() based
-	 * write flow control */		
-	if (e1i_ts->type == E1INP_TS_TYPE_TRAU)
-		return 0;
-
-	e1i_ts->driver.misdn.fd.when |= BSC_FD_WRITE;
-
-	return 0;
-}
-
 struct e1inp_driver misdn_driver = {
 	.name = "mISDNuser",
 	.want_write = ts_want_write,
 };
 
-static int mi_e1_setup(struct e1inp_line *line)
+static int mi_e1_setup(struct e1inp_line *line, int release_l2)
 {
 	struct mi_e1_handle *e1h = line->driver_data;
 	int ts, ret;
+	int	clean = 1;
 
 	/* TS0 is CRC4, don't need any fd for it */
 	for (ts = 1; ts < NUM_E1_TS; ts++) {
@@ -384,8 +407,8 @@
 		}
 
 		if (bfd->fd < 0) {
-			fprintf(stderr, "could not open socket %s\n",
-				strerror(errno));
+			fprintf(stderr, "%s could not open socket %s\n",
+				__func__, strerror(errno));
 			return bfd->fd;
 		}
 
@@ -395,8 +418,6 @@
 		switch (e1i_ts->type) {
 		case E1INP_TS_TYPE_SIGN:
 			addr.channel = 0;
-			/* SAPI not supported yet in kernel */
-			//addr.sapi = e1inp_ts->sign.sapi;
 			addr.sapi = 0;
 			addr.tei = GROUP_TEI;
 			break;
@@ -415,6 +436,13 @@
 				strerror(errno));
 			return -EIO;
 		}
+		if (e1i_ts->type == E1INP_TS_TYPE_SIGN && release_l2) {
+			ret = ioctl(bfd->fd, IMCLEAR_L2, &clean);
+       			if (ret < 0) {
+				fprintf(stderr, "could not send IOCTL IMCLEAN_L2 %s\n", strerror(errno));
+				return -EIO;
+			}
+		}
 
 		/* FIXME: only activate B-Channels once we start to
 		 * use them to conserve CPU power */
@@ -432,12 +460,14 @@
 	return 0;
 }
 
-int mi_setup(int cardnr,  struct e1inp_line *line)
+int mi_setup(int cardnr,  struct e1inp_line *line, int release_l2)
 {
 	struct mi_e1_handle *e1h;
 	int sk, ret, cnt;
 	struct mISDN_devinfo devinfo;
 
+	init_af_isdn();
+
 	/* register the driver with the core */
 	/* FIXME: do this in the plugin initializer function */
 	ret = e1inp_driver_register(&misdn_driver);
@@ -457,7 +487,7 @@
 	/* open the ISDN card device */
 	sk = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
 	if (sk < 0) {
-		fprintf(stderr, "could not open socket %s\n", strerror(errno));
+		fprintf(stderr, "%s could not open socket %s\n", __func__, strerror(errno));
 		return sk;
 	}
 
@@ -484,9 +514,20 @@
 	fprintf(stdout, "        protocol:       %d\n", devinfo.protocol);
 	fprintf(stdout, "        nrbchan:        %d\n", devinfo.nrbchan);
 	fprintf(stdout, "        name:           %s\n", devinfo.name);
+#else
+	printf("using device %d\n", e1h->cardnr);
 #endif
 
-	ret = mi_e1_setup(line);
+	if (!(devinfo.Dprotocols & (1 << ISDN_P_NT_E1))) {
+		fprintf(stderr, "error: card is not of type E1 (NT-mode)\n");
+		return -EINVAL;
+	}
+	if (devinfo.nrbchan != 30) {
+		fprintf(stderr, "error: E1 card has no 30 B-channels\n");
+		return -EINVAL;
+	}
+
+	ret = mi_e1_setup(line, release_l2);
 	if (ret)
 		return ret;
 
diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/src/subchan_demux.c openbsc/src/subchan_demux.c
--- openbsc.orig/src/subchan_demux.c	2009-02-23 17:58:34.000000000 +0100
+++ openbsc/src/subchan_demux.c	2009-04-19 13:30:08.000000000 +0200
@@ -100,7 +100,7 @@
 			if (!(dmx->chan_activ & (1 << c)))
 				continue;
 
-			inbits = inbyte >> ((3-c)*2);
+			inbits = inbyte >> (c << 1);
 
 			/* two bits for each subchannel */
 			if (inbits & 0x01)
@@ -230,10 +230,10 @@
 	int rc;
 
 	/* combine two bits of every subchan */
-	rc = get_subch_bits(mx, 3, &bits[0], 2);
-	rc = get_subch_bits(mx, 2, &bits[2], 2);
-	rc = get_subch_bits(mx, 1, &bits[4], 2);
-	rc = get_subch_bits(mx, 0, &bits[6], 2);
+	rc = get_subch_bits(mx, 0, &bits[0], 2);
+	rc = get_subch_bits(mx, 1, &bits[2], 2);
+	rc = get_subch_bits(mx, 2, &bits[4], 2);
+	rc = get_subch_bits(mx, 3, &bits[6], 2);
 
 	*byte = compact_bits(bits);
 
diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/include/openbsc/e1_input.h openbsc/include/openbsc/e1_input.h
--- openbsc.orig/include/openbsc/e1_input.h	2009-03-28 11:36:36.000000000 +0100
+++ openbsc/include/openbsc/e1_input.h	2009-04-19 12:46:37.000000000 +0200
@@ -63,7 +63,10 @@
 
 	union {
 		struct {
+			/* list of all signalling links on this TS */
 			struct llist_head sign_links;
+			/* timer when to dequeue next frame */
+			struct timer_list tx_timer;
 		} sign;
 		struct {
 			/* subchannel demuxer for frames from E1 */
@@ -142,7 +145,7 @@
 struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr);
 
 /* e1_config.c */
-int e1_config(struct gsm_bts *bts);
+int e1_config(struct gsm_bts *bts, int card, int l2_release);
 int ia_config(struct gsm_bts *bts);
 int ipaccess_setup(struct e1inp_line *line);
 
diff -Nur -x '*.Po' -x 'Makefile*' -x '*~' -x '*rej' -x '*.o' openbsc.orig/include/openbsc/misdn.h openbsc/include/openbsc/misdn.h
--- openbsc.orig/include/openbsc/misdn.h	2009-03-28 11:36:36.000000000 +0100
+++ openbsc/include/openbsc/misdn.h	2009-04-19 12:48:28.000000000 +0200
@@ -22,7 +22,7 @@
 
 #include "e1_input.h"
 
-int mi_setup(int cardnr,  struct e1inp_line *line);
+int mi_setup(int cardnr,  struct e1inp_line *line, int l2_release);
 void mi_set_pcap_fd(int fd);
 int _abis_nm_sendmsg(struct msgb *msg);
 
