Merge branch 'master' into sms
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h
index 9e4d590..a2a01d3 100644
--- a/openbsc/include/openbsc/abis_rsl.h
+++ b/openbsc/include/openbsc/abis_rsl.h
@@ -266,16 +266,23 @@
 } __attribute__ ((packed));
 #define RSL_CMOD_DTXu		0x01	/* uplink */
 #define RSL_CMOD_DTXd		0x02	/* downlink */
-#define RSL_CMOD_SPD_SPEECH	0x01
-#define RSL_CMOD_SPD_DATA	0x02
-#define RSL_CMOD_SPD_SIGN	0x03
+enum rsl_cmod_spd {
+	RSL_CMOD_SPD_SPEECH	= 0x01,
+	RSL_CMOD_SPD_DATA	= 0x02,
+	RSL_CMOD_SPD_SIGN	= 0x03,
+};
 #define RSL_CMOD_CRT_SDCCH	0x01
 #define RSL_CMOD_CRT_TCH_Bm	0x08	/* full-rate */
 #define RSL_CMOD_CRT_TCH_Lm	0x09	/* half-rate */
 /* FIXME: More CRT types */
+/* Speech */
 #define RSL_CMOD_SP_GSM1	0x01
 #define RSL_CMOD_SP_GSM2	0x11
 #define RSL_CMOD_SP_GSM3	0x21
+/* Data */
+#define RSL_CMOD_SP_NT_14k5	0x58
+#define RSL_CMOD_SP_NT_12k0	0x50
+#define RSL_CMOD_SP_NT_6k0	0x51
 
 /* Chapter 9.3.5 */
 struct rsl_ie_chan_ident {
@@ -459,7 +466,7 @@
 		      u_int8_t bs_power, u_int8_t ms_power,
 		      u_int8_t ta);
 int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, 
-			    u_int8_t ta, u_int8_t mode);
+			    u_int8_t ta);
 int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
 int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
 		   u_int8_t *ms_ident, u_int8_t chan_needed);
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 2ed95f3..c93540b 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -48,14 +48,16 @@
 	u_int8_t mode;
 } __attribute__ ((packed));
 
-#define GSM48_CMODE_SIGN	0x00
-#define GSM48_CMODE_SPEECH_V1	0x01
-#define GSM48_CMODE_SPEECH_EFR	0x21
-#define GSM48_CMODE_SPEECH_AMR	0x41
-#define GSM48_CMODE_DATA_14k5	0x0f
-#define GSM48_CMODE_DATA_12k0	0x03
-#define GSM48_CMODE_DATA_6k0	0x0b
-#define GSM48_CMODE_DATA_3k6	0x23
+enum gsm48_chan_mode {
+	GSM48_CMODE_SIGN	= 0x00,
+	GSM48_CMODE_SPEECH_V1	= 0x01,
+	GSM48_CMODE_SPEECH_EFR	= 0x21,
+	GSM48_CMODE_SPEECH_AMR	= 0x41,
+	GSM48_CMODE_DATA_14k5	= 0x0f,
+	GSM48_CMODE_DATA_12k0	= 0x03,
+	GSM48_CMODE_DATA_6k0	= 0x0b,
+	GSM48_CMODE_DATA_3k6	= 0x23,
+};
 
 /* Chapter 9.1.18 */
 struct gsm48_imm_ass {
@@ -642,6 +644,34 @@
 #define SBIT(a) (1 << a)
 #define ALL_STATES 0xffffffff
 
+/* GSM 04.08 Bearer Capability: Information Transfer Capability */
+enum gsm48_bcap_itcap {
+	GSM48_BCAP_ITCAP_SPEECH		= 0,
+	GSM48_BCAP_ITCAP_UNR_DIG_INF	= 1,
+	GSM48_BCAP_ITCAP_3k1_AUDIO	= 2,
+	GSM48_BCAP_ITCAP_FAX_G3		= 3,
+	GSM48_BCAP_ITCAP_OTHER		= 5,
+	GSM48_BCAP_ITCAP_RESERVED	= 7,
+};
+
+/* GSM 04.08 Bearer Capability: Transfer Mode */
+enum gsm48_bcap_tmod {
+	GSM48_BCAP_TMOD_CIRCUIT		= 0,
+	GSM48_BCAP_TMOD_PACKET		= 1,
+};
+
+/* GSM 04.08 Bearer Capability: Coding Standard */
+enum gsm48_bcap_coding {
+	GSM48_BCAP_CODING_GSM_STD	= 0,
+};
+
+/* GSM 04.08 Bearer Capability: Radio Channel Requirements */
+enum gsm48_bcap_rrq {
+	GSM48_BCAP_RRQ_FR_ONLY	= 1,
+	GSM48_BCAP_RRQ_DUAL_HR	= 2,
+	GSM48_BCAP_RRQ_DUAL_FR	= 3,
+};
+
 struct msgb;
 struct gsm_bts;
 struct gsm_subscriber;
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index f23c440..50d24b6 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -41,6 +41,7 @@
 
 #include <openbsc/timer.h>
 #include <openbsc/gsm_04_08.h>
+#include <openbsc/abis_rsl.h>
 #include <openbsc/mncc.h>
 #include <openbsc/tlv.h>
 
@@ -127,8 +128,10 @@
 	u_int8_t nr;
 	/* The logical channel type */
 	enum gsm_chan_t type;
+	/* RSL channel mode */
+	enum rsl_cmod_spd rsl_cmode;
 	/* If TCH, traffic channel mode */
-	enum gsm_chan_t tch_mode;
+	enum gsm48_chan_mode tch_mode;
 	/* Power levels for MS and BTS */
 	u_int8_t bs_power;
 	u_int8_t ms_power;
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index 6aa1917..68d76ab 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -108,13 +108,14 @@
 #define MNCC_F_KEYPAD		0x1000
 #define MNCC_F_SIGNAL		0x2000
 
+/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
 struct gsm_mncc_bearer_cap {
-	int		transfer;
-	int 		mode;
-	int		coding;
-	int		radio;
-	int		speech_ctm;
-	int		speech_ver[8];
+	int		transfer;	/* Information Transfer Capability */
+	int 		mode;		/* Transfer Mode */
+	int		coding;		/* Coding Standard */
+	int		radio;		/* Radio Channel Requirement */
+	int		speech_ctm;	/* CTM text telephony indication */
+	int		speech_ver[8];	/* Speech version indication */
 };
 
 struct gsm_mncc_number {
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 56c3f71..eb43bd5 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -530,6 +530,62 @@
 	return abis_rsl_sendmsg(msg);
 }
 
+static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
+				   struct gsm_lchan *lchan)
+{
+	memset(cm, 0, sizeof(cm));
+
+	/* FIXME: what to do with data calls ? */
+	cm->dtx_dtu = 0x00;
+
+	/* set TCH Speech/Data */
+	cm->spd_ind = lchan->rsl_cmode;
+
+	switch (lchan->type) {
+	case GSM_LCHAN_SDCCH:
+		cm->chan_rt = RSL_CMOD_CRT_SDCCH;
+		break;
+	case GSM_LCHAN_TCH_F:
+		cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
+		break;
+	case GSM_LCHAN_TCH_H:
+		cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
+		break;
+	case GSM_LCHAN_NONE:
+	case GSM_LCHAN_UNKNOWN:
+	default:
+		return -EINVAL;
+	}
+
+	switch (lchan->tch_mode) {
+	case GSM48_CMODE_SIGN:
+		cm->chan_rate = 0;
+		break;
+	case GSM48_CMODE_SPEECH_V1:
+		cm->chan_rate = RSL_CMOD_SP_GSM1;
+		break;
+	case GSM48_CMODE_SPEECH_EFR:
+		cm->chan_rate = RSL_CMOD_SP_GSM2;
+		break;
+	case GSM48_CMODE_SPEECH_AMR:
+		cm->chan_rate = RSL_CMOD_SP_GSM3;
+		break;
+	case GSM48_CMODE_DATA_14k5:
+		cm->chan_rate = RSL_CMOD_SP_NT_14k5;
+		break;
+	case GSM48_CMODE_DATA_12k0:
+		cm->chan_rate = RSL_CMOD_SP_NT_12k0;
+		break;
+	case GSM48_CMODE_DATA_6k0:
+		cm->chan_rate = RSL_CMOD_SP_NT_6k0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /* Chapter 8.4.1 */
 #if 0
 int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
@@ -567,45 +623,20 @@
 #endif
 
 int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, 
-			    u_int8_t ta, u_int8_t mode)
+			    u_int8_t ta)
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg;
+	int rc;
 
 	u_int8_t chan_nr = lchan2chan_nr(lchan);
 	u_int16_t arfcn = lchan->ts->trx->arfcn;
 	struct rsl_ie_chan_mode cm;
 	struct rsl_ie_chan_ident ci;
 
-	memset(&cm, 0, sizeof(cm));
-	/* FIXME: what to do with data calls ? */
-	cm.dtx_dtu = 0x00;
-	switch (lchan->type) {
-	case GSM_LCHAN_SDCCH:
-		cm.spd_ind = RSL_CMOD_SPD_SIGN;
-		cm.chan_rt = RSL_CMOD_CRT_SDCCH;
-		cm.chan_rate = 0x00;
-		break;
-	case GSM_LCHAN_TCH_F:
-		cm.chan_rt = RSL_CMOD_CRT_TCH_Bm;
-		switch (mode) {
-		case RSL_CMOD_SPD_SIGN:
-			cm.spd_ind = RSL_CMOD_SPD_SIGN;
-			cm.chan_rate = 0x00;
-			break;
-		case RSL_CMOD_SPD_SPEECH:
-			cm.spd_ind = RSL_CMOD_SPD_SPEECH;
-			cm.chan_rate = RSL_CMOD_SP_GSM2;
-			break;
-		}
-		break;
-	case GSM_LCHAN_TCH_H:
-		DEBUGP(DRSL, "Unimplemented TCH_H activation\n");
-		return -1;
-	case GSM_LCHAN_UNKNOWN:
-	case GSM_LCHAN_NONE:
-		return -1;
-	}
+	rc = channel_mode_from_lchan(&cm, lchan);
+	if (rc < 0)
+		return rc;
 
 	memset(&ci, 0, sizeof(ci));
 	ci.chan_desc.iei = 0x64;
@@ -637,40 +668,19 @@
 	return abis_rsl_sendmsg(msg);
 }
 
-/* Chapter 8.4.9 */
+/* Chapter 8.4.9: Modify channel mode on BTS side */
 int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg;
+	int rc;
 
 	u_int8_t chan_nr = lchan2chan_nr(lchan);
 	struct rsl_ie_chan_mode cm;
 
-	memset(&cm, 0, sizeof(cm));
-
-	/* FIXME: what to do with data calls ? */
-	cm.dtx_dtu = 0x00;
-	switch (lchan->type) {
-	/* todo more modes */
-	case GSM_LCHAN_TCH_F:
-		cm.spd_ind = RSL_CMOD_SPD_SPEECH;
-		cm.chan_rt = RSL_CMOD_CRT_TCH_Bm;
-		switch(lchan->tch_mode) {
-		case GSM48_CMODE_SPEECH_V1:
-			cm.chan_rate = RSL_CMOD_SP_GSM1;
-			break;
-		case GSM48_CMODE_SPEECH_EFR:
-			cm.chan_rate = RSL_CMOD_SP_GSM2;
-			break;
-		default:
-			DEBUGP(DRSL, "Unimplemented channel modification\n");
-			return -1;
-		}
-		break;
-	default:
-		DEBUGP(DRSL, "Unimplemented channel modification\n");
-		return -1;
-	}
+	rc = channel_mode_from_lchan(&cm, lchan);
+	if (rc < 0)
+		return rc;
 
 	msg = rsl_msgb_alloc();
 	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
@@ -1080,7 +1090,8 @@
 	subch = lchan->nr;
 	
 	lchan->ms_power = lchan->bs_power = 0x0f; /* 30dB reduction */
-	rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, RSL_CMOD_SPD_SIGN);
+	lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
+	rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
 
 	/* create IMMEDIATE ASSIGN 04.08 messge */
 	memset(&ia, 0, sizeof(ia));
@@ -1244,7 +1255,6 @@
 
 static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
 {
-#if 0
 	switch (tch_mode) {
 	case GSM48_CMODE_SPEECH_V1:
 		return 0x00;
@@ -1254,12 +1264,9 @@
 		return 0x02;
 	/* FIXME: Type1 half-rate and type3 half-rate */
 	}
+	DEBUGPC(DRSL, "Cannot determine ip.access speech mode for "
+		"tch_mode == 0x%02x\n", tch_mode);
 	return 0;
-#else
-	/* hard-code EFR for now, since tch_mode is not correct at this
-	 * point in time */
-	return 0x01;
-#endif
 }
 
 /* ip.access specific RSL extensions */
@@ -1267,19 +1274,20 @@
 {
 	struct msgb *msg = rsl_msgb_alloc();
 	struct abis_rsl_dchan_hdr *dh;
-	u_int8_t speech_mode_s;
+	u_int8_t speech_mode;
 
 	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
 	init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
 	dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
 	dh->chan_nr = lchan2chan_nr(lchan);
 
-	speech_mode_s = ipa_smod_s_for_tch_mode(lchan->tch_mode);
 	/* 0x1- == receive-only, 0x-1 == EFR codec */
-	msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 0x10 | speech_mode_s);
+	speech_mode = 0x10 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
+	msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
 
-	DEBUGPC(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND\n",
-		gsm_ts_name(lchan->ts), dh->chan_nr);
+	DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
+		"speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
+		dh->chan_nr, speech_mode);
 
 	msg->trx = lchan->ts->trx;
 
@@ -1292,7 +1300,7 @@
 	struct msgb *msg = rsl_msgb_alloc();
 	struct abis_rsl_dchan_hdr *dh;
 	u_int8_t *att_f8, *att_ip, *att_port;
-	u_int8_t speech_mode_s;
+	u_int8_t speech_mode;
 	struct in_addr ia;
 
 	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
@@ -1300,11 +1308,14 @@
 	dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
 	dh->chan_nr = lchan2chan_nr(lchan);
 
+	/* 0x0- == both directions, 0x-1 == EFR codec */
+	speech_mode = 0x00 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
+
 	ia.s_addr = htonl(ip);
-	DEBUGP(DRSL, "IPAC_CONNECT channel=%s chan_nr=0x%02x "
-		"IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d\n",
+	DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_CONNECT "
+		"IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
 		gsm_ts_name(lchan->ts), dh->chan_nr,
-		inet_ntoa(ia), port, rtp_payload2, conn_id);
+		inet_ntoa(ia), port, rtp_payload2, conn_id, speech_mode);
 
 	att_f8 = msgb_put(msg, sizeof(conn_id)+1);
 	att_f8[0] = RSL_IE_IPAC_CONN_ID;
@@ -1324,9 +1335,7 @@
 	att_port[1] = port >> 8;
 	att_port[2] = port & 0xff;
 
-	speech_mode_s = ipa_smod_s_for_tch_mode(lchan->tch_mode);
-	/* 0x0- == both directions, 0x-1 == EFR codec */
-	msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 0x00 | speech_mode_s);
+	msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
 	if (rtp_payload2)
 		msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
 	
diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c
index ee8bd1f..b762f8c 100644
--- a/openbsc/src/bsc_hack.c
+++ b/openbsc/src/bsc_hack.c
@@ -61,6 +61,7 @@
 static int ARFCN = HARDCODED_ARFCN;
 static int cardnr = 0;
 static int release_l2 = 0;
+static int bs11_has_trx1 = 0;
 static enum gsm_bts_type BTS_TYPE = GSM_BTS_TYPE_BS11;
 static enum gsm_band BAND = GSM_BAND_900;
 static const char *database_name = "hlr.sqlite3";
@@ -531,13 +532,6 @@
 	abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x01);
 	abis_nm_set_channel_attr(&trx->ts[0], NM_CHANC_SDCCH_CBCH);
 
-#ifdef HAVE_TRX1
-	/* TRX 1 */
-	abis_nm_conn_terr_sign(&bts->trx[1], 0, 1, 0xff);
-	/* FIXME: TRX ATTRIBUTE */
-	abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x02);
-#endif
-
 	/* SET CHANNEL ATTRIBUTE TS1 */
 	abis_nm_set_channel_attr(&trx->ts[1], NM_CHANC_TCHFull);
 	/* Connect traffic of bts0/trx0/ts1 to e1_0/ts2/b */
@@ -573,6 +567,69 @@
 	/* Connect traffic of bts0/trx0/ts7 to e1_0/ts3/d */
 	abis_nm_conn_terr_traf(&trx->ts[7], 0, 3, 3);
 
+	trx = gsm_bts_trx_num(bts, 1);
+	if (trx) {	
+		u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
+		u_int8_t arfcn_low = trx->arfcn & 0xff;
+		u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
+		memcpy(trx1_attr_radio, bs11_attr_radio,
+			sizeof(trx1_attr_radio));
+
+		/* patch ARFCN into TRX Attributes */
+		trx1_attr_radio[2] &= 0xf0;
+		trx1_attr_radio[2] |= arfcn_high;
+		trx1_attr_radio[3] = arfcn_low;
+	
+		/* Connect signalling of TRX1 to e1_0/ts1/64kbps */
+		abis_nm_conn_terr_sign(trx, 0, 1, 0xff);
+		/* FIXME: TRX ATTRIBUTE */
+		abis_nm_set_radio_attr(trx, trx1_attr_radio,
+					sizeof(trx1_attr_radio));
+
+		/* Use TEI 2 for signalling */
+		abis_nm_establish_tei(bts, 1, 0, 1, 0xff, 0x02);
+
+		/* SET CHANNEL ATTRIBUTE TS1 */
+		abis_nm_set_channel_attr(&trx->ts[1], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts1 to e1_0/ts4/a */
+		abis_nm_conn_terr_traf(&trx->ts[1], 0, 4, 0);
+	
+		/* SET CHANNEL ATTRIBUTE TS1 */
+		abis_nm_set_channel_attr(&trx->ts[1], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts1 to e1_0/ts4/b */
+		abis_nm_conn_terr_traf(&trx->ts[1], 0, 4, 1);
+	
+		/* SET CHANNEL ATTRIBUTE TS2 */
+		abis_nm_set_channel_attr(&trx->ts[2], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts2 to e1_0/ts4/c */
+		abis_nm_conn_terr_traf(&trx->ts[2], 0, 4, 2);
+
+		/* SET CHANNEL ATTRIBUTE TS3 */
+		abis_nm_set_channel_attr(&trx->ts[3], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts3 to e1_0/ts4/d */
+		abis_nm_conn_terr_traf(&trx->ts[3], 0, 4, 3);
+
+		/* SET CHANNEL ATTRIBUTE TS4 */
+		abis_nm_set_channel_attr(&trx->ts[4], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts4 to e1_0/ts5/a */
+		abis_nm_conn_terr_traf(&trx->ts[4], 0, 5, 0);
+
+		/* SET CHANNEL ATTRIBUTE TS5 */
+		abis_nm_set_channel_attr(&trx->ts[5], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts5 to e1_0/ts5/b */
+		abis_nm_conn_terr_traf(&trx->ts[5], 0, 5, 1);
+
+		/* SET CHANNEL ATTRIBUTE TS6 */
+		abis_nm_set_channel_attr(&trx->ts[6], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts6 to e1_0/ts5/c */
+		abis_nm_conn_terr_traf(&trx->ts[6], 0, 5, 2);
+
+		/* SET CHANNEL ATTRIBUTE TS7 */
+		abis_nm_set_channel_attr(&trx->ts[7], NM_CHANC_TCHFull);
+		/* Connect traffic of bts0/trx0/ts7 to e1_0/ts5/d */
+		abis_nm_conn_terr_traf(&trx->ts[7], 0, 5, 3);
+	}
+
 	/* end DB transmission */
 	abis_nm_bs11_db_transmission(bts, 0);
 
@@ -962,18 +1019,20 @@
 		set_ts_e1link(&trx->ts[5], 0, 3, 1);
 		set_ts_e1link(&trx->ts[6], 0, 3, 2);
 		set_ts_e1link(&trx->ts[7], 0, 3, 3);
-#ifdef HAVE_TRX1
+
 		/* TRX 1 */
-		trx = &bts->trx[1];
-		set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
-		set_ts_e1link(&trx->ts[1], 0, 2, 1);
-		set_ts_e1link(&trx->ts[2], 0, 2, 2);
-		set_ts_e1link(&trx->ts[3], 0, 2, 3);
-		set_ts_e1link(&trx->ts[4], 0, 3, 0);
-		set_ts_e1link(&trx->ts[5], 0, 3, 1);
-		set_ts_e1link(&trx->ts[6], 0, 3, 2);
-		set_ts_e1link(&trx->ts[7], 0, 3, 3);
-#endif
+		trx = gsm_bts_trx_num(bts, 1);
+		if (trx) {
+			trx = gsm_bts_trx_num(bts, 1);
+			set_ts_e1link(&trx->ts[0], 0, 4, 0);
+			set_ts_e1link(&trx->ts[1], 0, 4, 1);
+			set_ts_e1link(&trx->ts[2], 0, 4, 2);
+			set_ts_e1link(&trx->ts[3], 0, 4, 3);
+			set_ts_e1link(&trx->ts[4], 0, 5, 0);
+			set_ts_e1link(&trx->ts[5], 0, 5, 1);
+			set_ts_e1link(&trx->ts[6], 0, 5, 2);
+			set_ts_e1link(&trx->ts[7], 0, 5, 3);
+		}
 	}
 
 	return 0;
@@ -1028,6 +1087,13 @@
 	/* E1 mISDN input setup */
 	if (BTS_TYPE == GSM_BTS_TYPE_BS11) {
 		struct gsm_bts *bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
+
+		if (bs11_has_trx1) {
+			struct gsm_bts_trx *trx1;
+			trx1 = gsm_bts_trx_alloc(bts);
+			trx1->arfcn = ARFCN + 2;
+		}
+
 		bootstrap_bts(bts);
 
 		gsmnet->num_bts = 1;
@@ -1115,10 +1181,11 @@
 			{"tsc", 1, 0, 'S'},
 			{"bsic", 1, 0, 'B'},
 			{"rtp-proxy", 0, 0, 'P'},
+			{"trx1", 0, 0, '1'},
 			{0, 0, 0, 0}
 		};
 
-		c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:i:S:B:P",
+		c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:i:S:B:P1",
 				long_options, &option_index);
 		if (c == -1)
 			break;
@@ -1192,6 +1259,9 @@
 		case 'P':
 			ipacc_rtp_direct = 0;
 			break;
+		case '1':
+			bs11_has_trx1 = 1;
+			break;
 		}
 		default:
 			/* ignore */
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index fe16815..e3d6ae6 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -73,20 +73,34 @@
 
 		/* the following constraints are pure policy,
 		 * no requirement to put this restriction in place */
-		switch (pchan) {
-		case GSM_PCHAN_CCCH:
-		case GSM_PCHAN_CCCH_SDCCH4:
-			from = 0; to = 0;
-			break;
-		case GSM_PCHAN_SDCCH8_SACCH8C:
-			from = 1; to = 1;
-			break;
-		case GSM_PCHAN_TCH_F:
-		case GSM_PCHAN_TCH_H:
-			from = 2; to = 7;
-			break;
-		default:
-			return NULL;
+		if (trx == bts->c0) {
+			/* On the first TRX we run one CCCH and one SDCCH8 */
+			switch (pchan) {
+			case GSM_PCHAN_CCCH:
+			case GSM_PCHAN_CCCH_SDCCH4:
+				from = 0; to = 0;
+				break;
+			case GSM_PCHAN_SDCCH8_SACCH8C:
+				from = 1; to = 1;
+				break;
+			case GSM_PCHAN_TCH_F:
+			case GSM_PCHAN_TCH_H:
+				from = 2; to = 7;
+				break;
+			default:
+				return NULL;
+			}
+		} else {
+			/* Every secondary TRX is configured for TCH/F
+			 * and TCH/H only */
+			switch (pchan) {
+			case GSM_PCHAN_TCH_F:
+			case GSM_PCHAN_TCH_H:
+				from = 0; to = 7;
+				break;
+			default:
+				return NULL;
+			}
 		}
 
 		for (j = from; j <= to; j++) {
diff --git a/openbsc/src/e1_config.c b/openbsc/src/e1_config.c
index 9c9f40c..addc9fe 100644
--- a/openbsc/src/e1_config.c
+++ b/openbsc/src/e1_config.c
@@ -24,6 +24,7 @@
 	struct e1inp_line *line;
 	struct e1inp_ts *sign_ts;
 	struct e1inp_sign_link *oml_link, *rsl_link;
+	struct gsm_bts_trx *trx = bts->c0;
 
 	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
 	if (!line)
@@ -37,13 +38,13 @@
 	/* create signalling links for TS1 */
 	sign_ts = &line->ts[1-1];
 	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
-					  bts->c0, TEI_OML, SAPI_OML);
+					  trx, TEI_OML, SAPI_OML);
 	rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
-					  bts->c0, TEI_RSL, SAPI_RSL);
+					  trx, TEI_RSL, SAPI_RSL);
 
 	/* create back-links from bts/trx */
 	bts->oml_link = oml_link;
-	bts->c0->rsl_link = rsl_link;
+	trx->rsl_link = rsl_link;
 
 	/* enable subchannel demuxer on TS2 */
 	subch_demux_activate(&line->ts[2-1].trau.demux, 1);
@@ -56,18 +57,31 @@
 	subch_demux_activate(&line->ts[3-1].trau.demux, 2);
 	subch_demux_activate(&line->ts[3-1].trau.demux, 3);
 
-#ifdef HAVE_TRX1
-	/* create E1 timeslots for TRAU frames of TRX1 */
-	e1inp_ts_config(&line->ts[4-1], line, E1INP_TS_TYPE_TRAU);
-	e1inp_ts_config(&line->ts[5-1], line, E1INP_TS_TYPE_TRAU);
+	trx = gsm_bts_trx_num(bts, 1);
+	if (trx) {
+		/* create E1 timeslots for TRAU frames of TRX1 */
+		e1inp_ts_config(&line->ts[4-1], line, E1INP_TS_TYPE_TRAU);
+		e1inp_ts_config(&line->ts[5-1], line, E1INP_TS_TYPE_TRAU);
 
-	/* create RSL signalling link for TRX1 */
-	sign_ts = &line->ts[1-1];
-	rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
-					  &bts->trx[1], TEI_RSL+1, SAPI_RSL);
-	/* create back-links from trx */
-	bts->trx[1].rsl_link = rsl_link;
-#endif
+		/* create RSL signalling link for TRX1 */
+		sign_ts = &line->ts[1-1];
+		rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
+					  trx, TEI_RSL+1, SAPI_RSL);
+		/* create back-links from trx */
+		trx->rsl_link = rsl_link;
+
+		/* enable subchannel demuxer on TS2 */
+		subch_demux_activate(&line->ts[4-1].trau.demux, 0);
+		subch_demux_activate(&line->ts[4-1].trau.demux, 1);
+		subch_demux_activate(&line->ts[4-1].trau.demux, 2);
+		subch_demux_activate(&line->ts[4-1].trau.demux, 3);
+
+		/* enable subchannel demuxer on TS3 */
+		subch_demux_activate(&line->ts[5-1].trau.demux, 0);
+		subch_demux_activate(&line->ts[5-1].trau.demux, 1);
+		subch_demux_activate(&line->ts[5-1].trau.demux, 2);
+		subch_demux_activate(&line->ts[5-1].trau.demux, 3);
+	}
 
 	return mi_setup(cardnr, line, release_l2);
 }
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 690c591..ae44527 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -1278,7 +1278,7 @@
 	return gsm0408_authorize(lchan, msg);
 }
 
-/* 9.1.5 Channel mode modify */
+/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
 int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
@@ -1744,6 +1744,9 @@
 		break;
 	case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
 		DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
+		/* We've successfully modified the MS side of the channel,
+		 * now go on to modify the BTS side of the channel */
+		msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
 		rc = rsl_chan_mode_modify_req(msg->lchan);
 		break;
 	case GSM48_MT_RR_STATUS:
@@ -1948,8 +1951,6 @@
 			}
 			/* send SETUP request to called party */
 			gsm48_cc_tx_setup(transt, &transt->cc.msg);
-			if (is_ipaccess_bts(lchan->ts->trx->bts))
-				rsl_ipacc_bind(lchan);
 			break;
 		case GSM_PAGING_EXPIRED:
 			DEBUGP(DCC, "Paging subscr %s expired!\n",
@@ -2317,14 +2318,14 @@
 			     TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
 	}
 
-	if (is_ipaccess_bts(msg->trx->bts))
-		rsl_ipacc_bind(msg->lchan);
-
 	new_cc_state(trans, GSM_CSTATE_INITIATED);
 
 	/* indicate setup to MNCC */
 	mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
 
+	/* MNCC code will modify the channel asynchronously, we should
+	 * ipaccess-bind only after the modification has been made to the
+	 * lchan->tch_mode */
 	return 0;
 }
 
@@ -3294,8 +3295,19 @@
 static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
 {
 	struct gsm_mncc *mode = arg;
+	int rc;
 
-	return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
+	rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
+	if (rc < 0)
+		return rc;
+
+	/* FIXME: we not only need to do this after mode modify, but
+	 * also after channel activation */
+	if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
+	    mode->lchan_mode != GSM48_CMODE_SIGN)
+		rc = rsl_ipacc_bind(trans->lchan);
+
+	return rc;
 }
 
 static struct downstate {
diff --git a/openbsc/src/rtp_proxy.c b/openbsc/src/rtp_proxy.c
index 158145b..a581b9f 100644
--- a/openbsc/src/rtp_proxy.c
+++ b/openbsc/src/rtp_proxy.c
@@ -57,7 +57,7 @@
 	
 #define RTCP_IE_CNAME	1
 
-/* iterate over all chunks in one RTCP message, kook for CNAME IEs and
+/* iterate over all chunks in one RTCP message, look for CNAME IEs and
  * replace all of those with 'new_cname' */
 static int rtcp_sdes_cname_mangle(struct msgb *msg, struct rtcp_hdr *rh,
 				  u_int16_t *rtcp_len, const char *new_cname)
diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c
index 94a5c2a..e9b3652 100644
--- a/openbsc/src/vty/command.c
+++ b/openbsc/src/vty/command.c
@@ -45,6 +45,7 @@
 //#include "workqueue.h"
 
 #include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
 
 /* Command vector which includes some level of command lists. Normally
    each daemon maintains each own cmdvec. */
diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c
index 6962aa3..a248e60 100644
--- a/openbsc/tests/db/db_test.c
+++ b/openbsc/tests/db/db_test.c
@@ -66,32 +66,32 @@
 	struct gsm_subscriber *alice_db;
 
 	char *alice_imsi = "3243245432345";
-	alice = db_create_subscriber(alice_imsi);
+	alice = db_create_subscriber(NULL, alice_imsi);
 	db_sync_subscriber(alice);
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi);
+	alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice->imsi);
 	COMPARE(alice, alice_db);
 	subscr_put(alice_db);
 	subscr_put(alice);
 
 	alice_imsi = "3693245423445";
-	alice = db_create_subscriber(alice_imsi);
+	alice = db_create_subscriber(NULL, alice_imsi);
 	db_subscriber_assoc_imei(alice, "1234567890");
 	db_subscriber_alloc_tmsi(alice);
 	alice->lac=42;
 	db_sync_subscriber(alice);
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice_imsi);
+	alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi);
 	COMPARE(alice, alice_db);
 	subscr_put(alice);
 	subscr_put(alice_db);
 
 	alice_imsi = "9993245423445";
-	alice = db_create_subscriber(alice_imsi);
+	alice = db_create_subscriber(NULL, alice_imsi);
 	db_subscriber_alloc_tmsi(alice);
 	alice->lac=42;
 	db_sync_subscriber(alice);
 	db_subscriber_assoc_imei(alice, "1234567890");
 	db_subscriber_assoc_imei(alice, "6543560920");
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice_imsi);
+	alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi);
 	COMPARE(alice, alice_db);
 	subscr_put(alice);
 	subscr_put(alice_db);