<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/19298">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Move struct gsm_bts_trx: gsm-data.* => bts_trx.*<br><br>See rant fro similar recent commit moving stuff to bts.*.<br><br>Change-Id: I11758ca3d255d849d77bd068f24bb68bde1f89a5<br>---<br>M include/osmocom/bsc/Makefile.am<br>M include/osmocom/bsc/bts.h<br>A include/osmocom/bsc/bts_trx.h<br>M include/osmocom/bsc/gsm_data.h<br>M src/ipaccess/Makefile.am<br>M src/ipaccess/network_listen.c<br>M src/osmo-bsc/Makefile.am<br>M src/osmo-bsc/abis_nm.c<br>M src/osmo-bsc/bsc_subscr_conn_fsm.c<br>A src/osmo-bsc/bts_trx.c<br>M src/osmo-bsc/gsm_data.c<br>M src/utils/Makefile.am<br>M tests/abis/Makefile.am<br>M tests/bsc/Makefile.am<br>M tests/gsm0408/Makefile.am<br>M tests/handover/Makefile.am<br>M tests/nanobts_omlattr/Makefile.am<br>17 files changed, 398 insertions(+), 331 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/98/19298/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/Makefile.am b/include/osmocom/bsc/Makefile.am</span><br><span>index 4d2df20..c2a82ce 100644</span><br><span>--- a/include/osmocom/bsc/Makefile.am</span><br><span>+++ b/include/osmocom/bsc/Makefile.am</span><br><span>@@ -11,6 +11,7 @@</span><br><span>     bsc_subscr_conn_fsm.h \</span><br><span>      bss.h \</span><br><span>      bts.h \</span><br><span style="color: hsl(120, 100%, 40%);">+       bts_trx.h \</span><br><span>  bts_ipaccess_nanobts_omlattr.h \</span><br><span>     chan_alloc.h \</span><br><span>       codec_pref.h \</span><br><span>diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h</span><br><span>index b38c11a..9b89f4f 100644</span><br><span>--- a/include/osmocom/bsc/bts.h</span><br><span>+++ b/include/osmocom/bsc/bts.h</span><br><span>@@ -13,6 +13,7 @@</span><br><span> #include <osmocom/abis/e1_input.h></span><br><span> </span><br><span> #include "osmocom/bsc/gsm_data.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "osmocom/bsc/bts_trx.h"</span><br><span> </span><br><span> enum bts_counter_id {</span><br><span>  BTS_CTR_CHREQ_TOTAL,</span><br><span>diff --git a/include/osmocom/bsc/bts_trx.h b/include/osmocom/bsc/bts_trx.h</span><br><span>new file mode 100644</span><br><span>index 0000000..7e64439</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/bsc/bts_trx.h</span><br><span>@@ -0,0 +1,92 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bitvec.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/tlv.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/abis/e1_input.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "osmocom/bsc/gsm_data.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_bts;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRX_NR_TS        8</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* One TRX in a BTS */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_bts_trx {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* list header in bts->trx_list */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm_bts *bts;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* number of this TRX in the BTS */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t nr;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* human readable name / description */</span><br><span style="color: hsl(120, 100%, 40%);">+       char *description;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* how do we talk RSL with this TRX? */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_e1_subslot rsl_e1_link;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t rsl_tei;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct e1inp_sign_link *rsl_link;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Timeout for initiating the RSL connection. */</span><br><span style="color: hsl(120, 100%, 40%);">+      struct osmo_timer_list rsl_connect_timeout;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */</span><br><span style="color: hsl(120, 100%, 40%);">+    struct e1inp_sign_link *oml_link;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_abis_mo mo;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct tlv_parsed nm_attr;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct gsm_abis_mo mo;</span><br><span style="color: hsl(120, 100%, 40%);">+        } bb_transc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t arfcn;</span><br><span style="color: hsl(120, 100%, 40%);">+       int nominal_power;              /* in dBm */</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int max_power_red;     /* in actual dB */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  union {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct gsm_abis_mo mo;</span><br><span style="color: hsl(120, 100%, 40%);">+                        } bbsig;</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct gsm_abis_mo mo;</span><br><span style="color: hsl(120, 100%, 40%);">+                        } pa;</span><br><span style="color: hsl(120, 100%, 40%);">+         } bs11;</span><br><span style="color: hsl(120, 100%, 40%);">+               struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      unsigned int test_state;</span><br><span style="color: hsl(120, 100%, 40%);">+                      uint8_t test_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct rxlev_stats rxlev_stat;</span><br><span style="color: hsl(120, 100%, 40%);">+                } ipaccess;</span><br><span style="color: hsl(120, 100%, 40%);">+           struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct om2k_mo om2k_mo;</span><br><span style="color: hsl(120, 100%, 40%);">+                       } trxc;</span><br><span style="color: hsl(120, 100%, 40%);">+                       struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct om2k_mo om2k_mo;</span><br><span style="color: hsl(120, 100%, 40%);">+                       } rx;</span><br><span style="color: hsl(120, 100%, 40%);">+                 struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct om2k_mo om2k_mo;</span><br><span style="color: hsl(120, 100%, 40%);">+                       } tx;</span><br><span style="color: hsl(120, 100%, 40%);">+         } rbs2000;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gsm_bts_trx_ts ts[TRX_NR_TS];</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm_trx_name(const struct gsm_bts_trx *trx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,</span><br><span style="color: hsl(120, 100%, 40%);">+                              int *rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gsm_trx_lock_rf(struct gsm_bts_trx *trx, bool locked, const char *reason);</span><br><span style="color: hsl(120, 100%, 40%);">+bool trx_is_usable(const struct gsm_bts_trx *trx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gsm_trx_all_ts_dispatch(struct gsm_bts_trx *trx, uint32_t ts_ev, void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan);</span><br><span style="color: hsl(120, 100%, 40%);">+bool trx_has_valid_pchan_config(const struct gsm_bts_trx *trx);</span><br><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index f90bfa7..e85be70 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -40,6 +40,7 @@</span><br><span> struct gsm0808_cell_id;</span><br><span> struct osmo_mgcpc_ep;</span><br><span> struct gsm_bts;</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_bts_trx;</span><br><span> </span><br><span> /** annotations for msgb ownership */</span><br><span> #define __uses</span><br><span>@@ -330,7 +331,6 @@</span><br><span>    use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */</span><br><span> #define CCCH_LCHAN 4</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define TRX_NR_TS        8</span><br><span> #define TS_MAX_LCHAN       8</span><br><span> </span><br><span> #define HARDCODED_ARFCN 123</span><br><span>@@ -713,66 +713,6 @@</span><br><span>  struct gsm_lchan lchan[TS_MAX_LCHAN];</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* One TRX in a BTS */</span><br><span style="color: hsl(0, 100%, 40%);">-struct gsm_bts_trx {</span><br><span style="color: hsl(0, 100%, 40%);">-       /* list header in bts->trx_list */</span><br><span style="color: hsl(0, 100%, 40%);">-   struct llist_head list;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm_bts *bts;</span><br><span style="color: hsl(0, 100%, 40%);">-    /* number of this TRX in the BTS */</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t nr;</span><br><span style="color: hsl(0, 100%, 40%);">-     /* human readable name / description */</span><br><span style="color: hsl(0, 100%, 40%);">- char *description;</span><br><span style="color: hsl(0, 100%, 40%);">-      /* how do we talk RSL with this TRX? */</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm_e1_subslot rsl_e1_link;</span><br><span style="color: hsl(0, 100%, 40%);">-      uint8_t rsl_tei;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct e1inp_sign_link *rsl_link;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Timeout for initiating the RSL connection. */</span><br><span style="color: hsl(0, 100%, 40%);">-        struct osmo_timer_list rsl_connect_timeout;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     /* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */</span><br><span style="color: hsl(0, 100%, 40%);">-      struct e1inp_sign_link *oml_link;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       struct gsm_abis_mo mo;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct tlv_parsed nm_attr;</span><br><span style="color: hsl(0, 100%, 40%);">-      struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                struct gsm_abis_mo mo;</span><br><span style="color: hsl(0, 100%, 40%);">-  } bb_transc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    uint16_t arfcn;</span><br><span style="color: hsl(0, 100%, 40%);">- int nominal_power;              /* in dBm */</span><br><span style="color: hsl(0, 100%, 40%);">-    unsigned int max_power_red;     /* in actual dB */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      union {</span><br><span style="color: hsl(0, 100%, 40%);">-         struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                                struct gsm_abis_mo mo;</span><br><span style="color: hsl(0, 100%, 40%);">-                  } bbsig;</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                                struct gsm_abis_mo mo;</span><br><span style="color: hsl(0, 100%, 40%);">-                  } pa;</span><br><span style="color: hsl(0, 100%, 40%);">-           } bs11;</span><br><span style="color: hsl(0, 100%, 40%);">-         struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                        unsigned int test_state;</span><br><span style="color: hsl(0, 100%, 40%);">-                        uint8_t test_nr;</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct rxlev_stats rxlev_stat;</span><br><span style="color: hsl(0, 100%, 40%);">-          } ipaccess;</span><br><span style="color: hsl(0, 100%, 40%);">-             struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                                struct om2k_mo om2k_mo;</span><br><span style="color: hsl(0, 100%, 40%);">-                 } trxc;</span><br><span style="color: hsl(0, 100%, 40%);">-                 struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                                struct om2k_mo om2k_mo;</span><br><span style="color: hsl(0, 100%, 40%);">-                 } rx;</span><br><span style="color: hsl(0, 100%, 40%);">-                   struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                                struct om2k_mo om2k_mo;</span><br><span style="color: hsl(0, 100%, 40%);">-                 } tx;</span><br><span style="color: hsl(0, 100%, 40%);">-           } rbs2000;</span><br><span style="color: hsl(0, 100%, 40%);">-      };</span><br><span style="color: hsl(0, 100%, 40%);">-      struct gsm_bts_trx_ts ts[TRX_NR_TS];</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0])</span><br><span> </span><br><span> /*</span><br><span>@@ -962,8 +902,6 @@</span><br><span>                             const struct gsm0808_cell_id *cell_id,</span><br><span>                               int match_idx);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> extern const struct value_string gsm_chreq_descs[];</span><br><span> extern const struct value_string gsm_pchant_names[];</span><br><span> extern const struct value_string gsm_pchant_descs[];</span><br><span>@@ -974,7 +912,6 @@</span><br><span> enum gsm_phys_chan_config gsm_pchan_parse(const char *name);</span><br><span> const char *gsm_lchant_name(enum gsm_chan_t c);</span><br><span> const char *gsm_chreq_name(enum gsm_chreq_reason_t c);</span><br><span style="color: hsl(0, 100%, 40%);">-char *gsm_trx_name(const struct gsm_bts_trx *trx);</span><br><span> char *gsm_ts_name(const struct gsm_bts_trx_ts *ts);</span><br><span> char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts);</span><br><span> char *gsm_lchan_name_compute(const struct gsm_lchan *lchan);</span><br><span>@@ -1007,9 +944,6 @@</span><br><span> </span><br><span> uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,</span><br><span style="color: hsl(0, 100%, 40%);">-                                   int *rc);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);</span><br><span> uint8_t pchan_subslots(enum gsm_phys_chan_config pchan);</span><br><span> bool ts_is_tch(struct gsm_bts_trx_ts *ts);</span><br><span>@@ -1255,7 +1189,6 @@</span><br><span> void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr,</span><br><span>                uint8_t e1_ts, uint8_t e1_ts_ss);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gsm_trx_lock_rf(struct gsm_bts_trx *trx, bool locked, const char *reason);</span><br><span> int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx);</span><br><span> int gsm_bts_set_system_infos(struct gsm_bts *bts);</span><br><span> </span><br><span>@@ -1265,17 +1198,11 @@</span><br><span> /* control interface handling */</span><br><span> int bsc_base_ctrl_cmds_install(void);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-bool trx_is_usable(const struct gsm_bts_trx *trx);</span><br><span> bool ts_is_usable(const struct gsm_bts_trx_ts *ts);</span><br><span> </span><br><span> int gsm_lchan_type_by_pchan(enum gsm_phys_chan_config pchan);</span><br><span> enum gsm_phys_chan_config gsm_pchan_by_lchan_type(enum gsm_chan_t type);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gsm_trx_all_ts_dispatch(struct gsm_bts_trx *trx, uint32_t ts_ev, void *data);</span><br><span style="color: hsl(0, 100%, 40%);">-int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-bool trx_has_valid_pchan_config(const struct gsm_bts_trx *trx);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> enum gsm48_rr_cause bsc_gsm48_rr_cause_from_gsm0808_cause(enum gsm0808_cause c);</span><br><span> enum gsm48_rr_cause bsc_gsm48_rr_cause_from_rsl_cause(uint8_t c);</span><br><span> </span><br><span>diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am</span><br><span>index 273530c..a1812a9 100644</span><br><span>--- a/src/ipaccess/Makefile.am</span><br><span>+++ b/src/ipaccess/Makefile.am</span><br><span>@@ -47,6 +47,7 @@</span><br><span> # FIXME: resolve the bogus dependencies patched around here:</span><br><span> ipaccess_config_LDADD = \</span><br><span>         $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.o \</span><br><span>@@ -61,7 +62,9 @@</span><br><span>    $(NULL)</span><br><span> </span><br><span> ipaccess_proxy_LDADD = \</span><br><span style="color: hsl(120, 100%, 40%);">+       $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(OSMO_LIBS) \</span><br><span>       $(NULL)</span><br><span>diff --git a/src/ipaccess/network_listen.c b/src/ipaccess/network_listen.c</span><br><span>index bbaf798..e9f5c93 100644</span><br><span>--- a/src/ipaccess/network_listen.c</span><br><span>+++ b/src/ipaccess/network_listen.c</span><br><span>@@ -34,6 +34,7 @@</span><br><span> #include <osmocom/gsm/gsm48_ie.h></span><br><span> </span><br><span> #include <osmocom/bsc/gsm_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bts_trx.h></span><br><span> #include <osmocom/bsc/abis_nm.h></span><br><span> #include <osmocom/bsc/signal.h></span><br><span> #include <osmocom/bsc/debug.h></span><br><span>diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am</span><br><span>index f66421a..231707c 100644</span><br><span>--- a/src/osmo-bsc/Makefile.am</span><br><span>+++ b/src/osmo-bsc/Makefile.am</span><br><span>@@ -44,6 +44,7 @@</span><br><span>   bsc_subscriber.c \</span><br><span>   bsc_vty.c \</span><br><span>  bts.c \</span><br><span style="color: hsl(120, 100%, 40%);">+       bts_trx.c \</span><br><span>  bts_ericsson_rbs2000.c \</span><br><span>     bts_init.c \</span><br><span>         bts_ipaccess_nanobts.c \</span><br><span>diff --git a/src/osmo-bsc/abis_nm.c b/src/osmo-bsc/abis_nm.c</span><br><span>index 19eed8c..d88ce24 100644</span><br><span>--- a/src/osmo-bsc/abis_nm.c</span><br><span>+++ b/src/osmo-bsc/abis_nm.c</span><br><span>@@ -3020,26 +3020,6 @@</span><br><span>       memcpy(&_buf->rac, &ci, sizeof(ci));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void gsm_trx_lock_rf(struct gsm_bts_trx *trx, bool locked, const char *reason)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!trx->bts || !trx->bts->oml_link) {</span><br><span style="color: hsl(0, 100%, 40%);">-                /* Set initial state which will be sent when BTS connects. */</span><br><span style="color: hsl(0, 100%, 40%);">-           trx->mo.nm_state.administrative = new_state;</span><br><span style="color: hsl(0, 100%, 40%);">-         return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       LOG_TRX(trx, DNM, LOGL_NOTICE, "Requesting administrative state change %s -> %s [%s]\n",</span><br><span style="color: hsl(0, 100%, 40%);">-        get_value_string(abis_nm_adm_state_names, trx->mo.nm_state.administrative),</span><br><span style="color: hsl(0, 100%, 40%);">-          get_value_string(abis_nm_adm_state_names, new_state), reason);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER,</span><br><span style="color: hsl(0, 100%, 40%);">-                       trx->bts->bts_nr, trx->nr, 0xff,</span><br><span style="color: hsl(0, 100%, 40%);">-                       new_state);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static const struct value_string ipacc_testres_names[] = {</span><br><span>     { NM_IPACC_TESTRES_SUCCESS,     "SUCCESS" },</span><br><span>       { NM_IPACC_TESTRES_TIMEOUT,     "TIMEOUT" },</span><br><span>diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>index 72f2474..9b1fb3f 100644</span><br><span>--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>@@ -28,6 +28,7 @@</span><br><span> #include <osmocom/bsc/a_reset.h></span><br><span> #include <osmocom/bsc/gsm_08_08.h></span><br><span> #include <osmocom/bsc/gsm_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bts.h></span><br><span> #include <osmocom/bsc/handover_fsm.h></span><br><span> #include <osmocom/bsc/lchan_fsm.h></span><br><span> #include <osmocom/bsc/lchan_rtp_fsm.h></span><br><span>diff --git a/src/osmo-bsc/bts_trx.c b/src/osmo-bsc/bts_trx.c</span><br><span>new file mode 100644</span><br><span>index 0000000..15d5b59</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bsc/bts_trx.c</span><br><span>@@ -0,0 +1,288 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/abis_nm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/gsm_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bts.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bts_trx.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/timeslot_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/abis_nm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/lchan_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/debug.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);</span><br><span style="color: hsl(120, 100%, 40%);">+       int k;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!trx)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        trx->bts = bts;</span><br><span style="color: hsl(120, 100%, 40%);">+    trx->nr = bts->num_trx++;</span><br><span style="color: hsl(120, 100%, 40%);">+       trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,</span><br><span style="color: hsl(120, 100%, 40%);">+                    bts->nr, trx->nr, 0xff);</span><br><span style="color: hsl(120, 100%, 40%);">+    gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,</span><br><span style="color: hsl(120, 100%, 40%);">+                   bts->nr, trx->nr, 0xff);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (k = 0; k < TRX_NR_TS; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          struct gsm_bts_trx_ts *ts = &trx->ts[k];</span><br><span style="color: hsl(120, 100%, 40%);">+               int l;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            ts->trx = trx;</span><br><span style="color: hsl(120, 100%, 40%);">+             ts->nr = k;</span><br><span style="color: hsl(120, 100%, 40%);">+                ts->pchan_from_config = ts->pchan_on_init = ts->pchan_is = GSM_PCHAN_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+           ts->tsc = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            ts_fsm_alloc(ts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,</span><br><span style="color: hsl(120, 100%, 40%);">+                           bts->nr, trx->nr, ts->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);</span><br><span style="color: hsl(120, 100%, 40%);">+          ts->hopping.arfcns.data = ts->hopping.arfcns_data;</span><br><span style="color: hsl(120, 100%, 40%);">+              ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);</span><br><span style="color: hsl(120, 100%, 40%);">+          ts->hopping.ma.data = ts->hopping.ma_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            for (l = 0; l < TS_MAX_LCHAN; l++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+                      char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+                   lchan = &ts->lchan[l];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       lchan->ts = ts;</span><br><span style="color: hsl(120, 100%, 40%);">+                    lchan->nr = l;</span><br><span style="color: hsl(120, 100%, 40%);">+                     lchan->type = GSM_LCHAN_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    name = gsm_lchan_name_compute(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                 lchan->name = talloc_strdup(trx, name);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (trx->nr != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+          trx->nominal_power = bts->c0->nominal_power;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       llist_add_tail(&trx->list, &bts->trx_list);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return trx;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char ts2str[255];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm_trx_name(const struct gsm_bts_trx *trx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!trx)</span><br><span style="color: hsl(120, 100%, 40%);">+             snprintf(ts2str, sizeof(ts2str), "(trx=NULL)");</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",</span><br><span style="color: hsl(120, 100%, 40%);">+                  trx->bts->nr, trx->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return ts2str;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* determine logical channel based on TRX and channel number IE */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,</span><br><span style="color: hsl(120, 100%, 40%);">+                            int *rc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t ts_nr = chan_nr & 0x07;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t cbits = chan_nr >> 3;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t lch_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];</span><br><span style="color: hsl(120, 100%, 40%);">+   bool ok;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               *rc = -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (cbits == 0x01) {</span><br><span style="color: hsl(120, 100%, 40%);">+          lch_idx = 0;    /* TCH/F */</span><br><span style="color: hsl(120, 100%, 40%);">+           ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_F)</span><br><span style="color: hsl(120, 100%, 40%);">+                      || ts->pchan_on_init == GSM_PCHAN_PDCH; /* PDCH? really? */</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if ((cbits & 0x1e) == 0x02) {</span><br><span style="color: hsl(120, 100%, 40%);">+              lch_idx = cbits & 0x1;      /* TCH/H */</span><br><span style="color: hsl(120, 100%, 40%);">+           ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_H);</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if ((cbits & 0x1c) == 0x04) {</span><br><span style="color: hsl(120, 100%, 40%);">+              lch_idx = cbits & 0x3;      /* SDCCH/4 */</span><br><span style="color: hsl(120, 100%, 40%);">+         ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_CCCH_SDCCH4);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if ((cbits & 0x18) == 0x08) {</span><br><span style="color: hsl(120, 100%, 40%);">+              lch_idx = cbits & 0x7;      /* SDCCH/8 */</span><br><span style="color: hsl(120, 100%, 40%);">+         ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_SDCCH8_SACCH8C);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {</span><br><span style="color: hsl(120, 100%, 40%);">+         lch_idx = 0; /* CCCH? */</span><br><span style="color: hsl(120, 100%, 40%);">+              ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_CCCH);</span><br><span style="color: hsl(120, 100%, 40%);">+              /* FIXME: we should not return first sdcch4 !!! */</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if ((chan_nr & RSL_CHAN_NR_MASK) == RSL_CHAN_OSMO_PDCH) {</span><br><span style="color: hsl(120, 100%, 40%);">+          lch_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+          ok = (ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc && ok)</span><br><span style="color: hsl(120, 100%, 40%);">+         *rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return &ts->lchan[lch_idx];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gsm_trx_lock_rf(struct gsm_bts_trx *trx, bool locked, const char *reason)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!trx->bts || !trx->bts->oml_link) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Set initial state which will be sent when BTS connects. */</span><br><span style="color: hsl(120, 100%, 40%);">+         trx->mo.nm_state.administrative = new_state;</span><br><span style="color: hsl(120, 100%, 40%);">+               return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   LOG_TRX(trx, DNM, LOGL_NOTICE, "Requesting administrative state change %s -> %s [%s]\n",</span><br><span style="color: hsl(120, 100%, 40%);">+      get_value_string(abis_nm_adm_state_names, trx->mo.nm_state.administrative),</span><br><span style="color: hsl(120, 100%, 40%);">+        get_value_string(abis_nm_adm_state_names, new_state), reason);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER,</span><br><span style="color: hsl(120, 100%, 40%);">+                             trx->bts->bts_nr, trx->nr, 0xff,</span><br><span style="color: hsl(120, 100%, 40%);">+                             new_state);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool trx_is_usable(const struct gsm_bts_trx *trx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME: How does this behave for BS-11 ? */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (is_ipaccess_bts(trx->bts)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!nm_is_running(&trx->mo.nm_state) ||</span><br><span style="color: hsl(120, 100%, 40%);">+                   !nm_is_running(&trx->bb_transc.mo.nm_state))</span><br><span style="color: hsl(120, 100%, 40%);">+                       return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (is_ericsson_bts(trx->bts)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* The OM2000 -> 12.21 mapping we do doesn't have separate bb_transc MO */</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!nm_is_running(&trx->mo.nm_state))</span><br><span style="color: hsl(120, 100%, 40%);">+                 return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gsm_trx_all_ts_dispatch(struct gsm_bts_trx *trx, uint32_t ts_ev, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             struct gsm_bts_trx_ts *ts = &trx->ts[i];</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_fsm_inst_dispatch(ts->fi, ts_ev, data);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gsm_bts_trx_ts *ts;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      int j;</span><br><span style="color: hsl(120, 100%, 40%);">+        int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!trx_is_usable(trx))</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (j = 0; j < ARRAY_SIZE(trx->ts); j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ts = &trx->ts[j];</span><br><span style="color: hsl(120, 100%, 40%);">+              if (!ts_is_usable(ts))</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ts->pchan_is == GSM_PCHAN_PDCH) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Dynamic timeslots in PDCH mode will become TCH if needed. */</span><br><span style="color: hsl(120, 100%, 40%);">+                       switch (ts->pchan_on_init) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       case GSM_PCHAN_TCH_F_PDCH:</span><br><span style="color: hsl(120, 100%, 40%);">+                            if (pchan == GSM_PCHAN_TCH_F)</span><br><span style="color: hsl(120, 100%, 40%);">+                                 count++;</span><br><span style="color: hsl(120, 100%, 40%);">+                              continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   case GSM_PCHAN_TCH_F_TCH_H_PDCH:</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (pchan == GSM_PCHAN_TCH_F)</span><br><span style="color: hsl(120, 100%, 40%);">+                                 count++;</span><br><span style="color: hsl(120, 100%, 40%);">+                              else if (pchan == GSM_PCHAN_TCH_H)</span><br><span style="color: hsl(120, 100%, 40%);">+                                    count += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                           continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   default:</span><br><span style="color: hsl(120, 100%, 40%);">+                              /* Not dynamic, not applicable. */</span><br><span style="color: hsl(120, 100%, 40%);">+                            continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ts->pchan_is != pchan)</span><br><span style="color: hsl(120, 100%, 40%);">+                 continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           ts_for_each_lchan(lchan, ts) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (lchan_state_is(lchan, LCHAN_ST_UNUSED))</span><br><span style="color: hsl(120, 100%, 40%);">+                           count++;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return count;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool trx_has_valid_pchan_config(const struct gsm_bts_trx *trx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ bool combined = false;</span><br><span style="color: hsl(120, 100%, 40%);">+        bool result = true;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Iterate over all timeslots */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < 8; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          const struct gsm_bts_trx_ts *ts = &trx->ts[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               switch (ts->pchan_from_config) {</span><br><span style="color: hsl(120, 100%, 40%);">+           case GSM_PCHAN_CCCH_SDCCH4_CBCH:</span><br><span style="color: hsl(120, 100%, 40%);">+              case GSM_PCHAN_CCCH_SDCCH4:</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* CCCH+SDCCH4 can only be configured on TS0 */</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (i > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               LOGP(DNM, LOGL_ERROR, "Combined CCCH is not allowed "</span><br><span style="color: hsl(120, 100%, 40%);">+                                                     "on TS%u > 0\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+                               result = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (i == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                           combined = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* fall-through */</span><br><span style="color: hsl(120, 100%, 40%);">+            case GSM_PCHAN_CCCH:</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* 3GPP TS 45.002, Table 3, CCCH: TS (0, 2, 4, 6) */</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (i % 2 != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             LOGP(DNM, LOGL_ERROR, "%s is not allowed on odd TS%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 gsm_pchan_name(ts->pchan_from_config), i);</span><br><span style="color: hsl(120, 100%, 40%);">+                            result = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* There can be no more CCCHs if TS0/C0 is combined */</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (i > 0 && combined) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           LOGP(DNM, LOGL_ERROR, "%s is not allowed on TS%u, "</span><br><span style="color: hsl(120, 100%, 40%);">+                              "because TS0 is using combined channel configuration\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    gsm_pchan_name(ts->pchan_from_config), i);</span><br><span style="color: hsl(120, 100%, 40%);">+                            result = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* CCCH on TS0 is mandatory for C0 */</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (trx->bts->c0 == trx && i == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            LOGP(DNM, LOGL_ERROR, "TS0 on C0 must be CCCH/BCCH\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                             result = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return result;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c</span><br><span>index 5daee26..c0c8cf6 100644</span><br><span>--- a/src/osmo-bsc/gsm_data.c</span><br><span>+++ b/src/osmo-bsc/gsm_data.c</span><br><span>@@ -290,79 +290,8 @@</span><br><span>    return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);</span><br><span style="color: hsl(0, 100%, 40%);">- int k;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!trx)</span><br><span style="color: hsl(0, 100%, 40%);">-               return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    trx->bts = bts;</span><br><span style="color: hsl(0, 100%, 40%);">-      trx->nr = bts->num_trx++;</span><br><span style="color: hsl(0, 100%, 40%);">- trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,</span><br><span style="color: hsl(0, 100%, 40%);">-              bts->nr, trx->nr, 0xff);</span><br><span style="color: hsl(0, 100%, 40%);">-      gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,</span><br><span style="color: hsl(0, 100%, 40%);">-             bts->nr, trx->nr, 0xff);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      for (k = 0; k < TRX_NR_TS; k++) {</span><br><span style="color: hsl(0, 100%, 40%);">-            struct gsm_bts_trx_ts *ts = &trx->ts[k];</span><br><span style="color: hsl(0, 100%, 40%);">-         int l;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          ts->trx = trx;</span><br><span style="color: hsl(0, 100%, 40%);">-               ts->nr = k;</span><br><span style="color: hsl(0, 100%, 40%);">-          ts->pchan_from_config = ts->pchan_on_init = ts->pchan_is = GSM_PCHAN_NONE;</span><br><span style="color: hsl(0, 100%, 40%);">-             ts->tsc = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                ts_fsm_alloc(ts);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,</span><br><span style="color: hsl(0, 100%, 40%);">-                     bts->nr, trx->nr, ts->nr);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);</span><br><span style="color: hsl(0, 100%, 40%);">-            ts->hopping.arfcns.data = ts->hopping.arfcns_data;</span><br><span style="color: hsl(0, 100%, 40%);">-                ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);</span><br><span style="color: hsl(0, 100%, 40%);">-            ts->hopping.ma.data = ts->hopping.ma_data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                for (l = 0; l < TS_MAX_LCHAN; l++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 struct gsm_lchan *lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-                        char *name;</span><br><span style="color: hsl(0, 100%, 40%);">-                     lchan = &ts->lchan[l];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                   lchan->ts = ts;</span><br><span style="color: hsl(0, 100%, 40%);">-                      lchan->nr = l;</span><br><span style="color: hsl(0, 100%, 40%);">-                       lchan->type = GSM_LCHAN_NONE;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                        name = gsm_lchan_name_compute(lchan);</span><br><span style="color: hsl(0, 100%, 40%);">-                   lchan->name = talloc_strdup(trx, name);</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (trx->nr != 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            trx->nominal_power = bts->c0->nominal_power;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   llist_add_tail(&trx->list, &bts->trx_list);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return trx;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static char ts2str[255];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-char *gsm_trx_name(const struct gsm_bts_trx *trx)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!trx)</span><br><span style="color: hsl(0, 100%, 40%);">-               snprintf(ts2str, sizeof(ts2str), "(trx=NULL)");</span><br><span style="color: hsl(0, 100%, 40%);">-       else</span><br><span style="color: hsl(0, 100%, 40%);">-            snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",</span><br><span style="color: hsl(0, 100%, 40%);">-                    trx->bts->nr, trx->nr);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return ts2str;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> char *gsm_ts_name(const struct gsm_bts_trx_ts *ts)</span><br><span> {</span><br><span>   snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",</span><br><span>@@ -620,48 +549,6 @@</span><br><span>   return gsm_pchan2chan_nr(lchan->ts->pchan_is, lchan->ts->nr, lchan->nr);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* determine logical channel based on TRX and channel number IE */</span><br><span style="color: hsl(0, 100%, 40%);">-struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,</span><br><span style="color: hsl(0, 100%, 40%);">-                             int *rc)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    uint8_t ts_nr = chan_nr & 0x07;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t cbits = chan_nr >> 3;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t lch_idx;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];</span><br><span style="color: hsl(0, 100%, 40%);">-     bool ok;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (rc)</span><br><span style="color: hsl(0, 100%, 40%);">-         *rc = -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (cbits == 0x01) {</span><br><span style="color: hsl(0, 100%, 40%);">-            lch_idx = 0;    /* TCH/F */</span><br><span style="color: hsl(0, 100%, 40%);">-             ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_F)</span><br><span style="color: hsl(0, 100%, 40%);">-                        || ts->pchan_on_init == GSM_PCHAN_PDCH; /* PDCH? really? */</span><br><span style="color: hsl(0, 100%, 40%);">-  } else if ((cbits & 0x1e) == 0x02) {</span><br><span style="color: hsl(0, 100%, 40%);">-                lch_idx = cbits & 0x1;      /* TCH/H */</span><br><span style="color: hsl(0, 100%, 40%);">-             ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_H);</span><br><span style="color: hsl(0, 100%, 40%);">-       } else if ((cbits & 0x1c) == 0x04) {</span><br><span style="color: hsl(0, 100%, 40%);">-                lch_idx = cbits & 0x3;      /* SDCCH/4 */</span><br><span style="color: hsl(0, 100%, 40%);">-           ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_CCCH_SDCCH4);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if ((cbits & 0x18) == 0x08) {</span><br><span style="color: hsl(0, 100%, 40%);">-                lch_idx = cbits & 0x7;      /* SDCCH/8 */</span><br><span style="color: hsl(0, 100%, 40%);">-           ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_SDCCH8_SACCH8C);</span><br><span style="color: hsl(0, 100%, 40%);">-      } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {</span><br><span style="color: hsl(0, 100%, 40%);">-           lch_idx = 0; /* CCCH? */</span><br><span style="color: hsl(0, 100%, 40%);">-                ok = ts_is_capable_of_pchan(ts, GSM_PCHAN_CCCH);</span><br><span style="color: hsl(0, 100%, 40%);">-                /* FIXME: we should not return first sdcch4 !!! */</span><br><span style="color: hsl(0, 100%, 40%);">-      } else if ((chan_nr & RSL_CHAN_NR_MASK) == RSL_CHAN_OSMO_PDCH) {</span><br><span style="color: hsl(0, 100%, 40%);">-            lch_idx = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-            ok = (ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH);</span><br><span style="color: hsl(0, 100%, 40%);">-      } else</span><br><span style="color: hsl(0, 100%, 40%);">-          return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (rc && ok)</span><br><span style="color: hsl(0, 100%, 40%);">-           *rc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        return &ts->lchan[lch_idx];</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static const uint8_t subslots_per_pchan[] = {</span><br><span>         [GSM_PCHAN_NONE] = 0,</span><br><span>        [GSM_PCHAN_CCCH] = 0,</span><br><span>@@ -708,31 +595,6 @@</span><br><span>         return conn->lchan->ts->trx->bts;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-bool trx_is_usable(const struct gsm_bts_trx *trx)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        /* FIXME: How does this behave for BS-11 ? */</span><br><span style="color: hsl(0, 100%, 40%);">-   if (is_ipaccess_bts(trx->bts)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!nm_is_running(&trx->mo.nm_state) ||</span><br><span style="color: hsl(0, 100%, 40%);">-             !nm_is_running(&trx->bb_transc.mo.nm_state))</span><br><span style="color: hsl(0, 100%, 40%);">-                 return false;</span><br><span style="color: hsl(0, 100%, 40%);">-   } else if (is_ericsson_bts(trx->bts)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              /* The OM2000 -> 12.21 mapping we do doesn't have separate bb_transc MO */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!nm_is_running(&trx->mo.nm_state))</span><br><span style="color: hsl(0, 100%, 40%);">-                   return false;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return true;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void gsm_trx_all_ts_dispatch(struct gsm_bts_trx *trx, uint32_t ts_ev, void *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int i;</span><br><span style="color: hsl(0, 100%, 40%);">-  for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               struct gsm_bts_trx_ts *ts = &trx->ts[i];</span><br><span style="color: hsl(0, 100%, 40%);">-         osmo_fsm_inst_dispatch(ts->fi, ts_ev, data);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static void _chan_desc_fill_tail(struct gsm48_chan_desc *cd, const struct gsm_lchan *lchan)</span><br><span> {</span><br><span>       if (!lchan->ts->hopping.enabled) {</span><br><span>@@ -950,54 +812,6 @@</span><br><span>      }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct gsm_bts_trx_ts *ts;</span><br><span style="color: hsl(0, 100%, 40%);">-      struct gsm_lchan *lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-        int j;</span><br><span style="color: hsl(0, 100%, 40%);">-  int count = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!trx_is_usable(trx))</span><br><span style="color: hsl(0, 100%, 40%);">-                return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       for (j = 0; j < ARRAY_SIZE(trx->ts); j++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ts = &trx->ts[j];</span><br><span style="color: hsl(0, 100%, 40%);">-                if (!ts_is_usable(ts))</span><br><span style="color: hsl(0, 100%, 40%);">-                  continue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               if (ts->pchan_is == GSM_PCHAN_PDCH) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* Dynamic timeslots in PDCH mode will become TCH if needed. */</span><br><span style="color: hsl(0, 100%, 40%);">-                 switch (ts->pchan_on_init) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 case GSM_PCHAN_TCH_F_PDCH:</span><br><span style="color: hsl(0, 100%, 40%);">-                              if (pchan == GSM_PCHAN_TCH_F)</span><br><span style="color: hsl(0, 100%, 40%);">-                                   count++;</span><br><span style="color: hsl(0, 100%, 40%);">-                                continue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                       case GSM_PCHAN_TCH_F_TCH_H_PDCH:</span><br><span style="color: hsl(0, 100%, 40%);">-                                if (pchan == GSM_PCHAN_TCH_F)</span><br><span style="color: hsl(0, 100%, 40%);">-                                   count++;</span><br><span style="color: hsl(0, 100%, 40%);">-                                else if (pchan == GSM_PCHAN_TCH_H)</span><br><span style="color: hsl(0, 100%, 40%);">-                                      count += 2;</span><br><span style="color: hsl(0, 100%, 40%);">-                             continue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                       default:</span><br><span style="color: hsl(0, 100%, 40%);">-                                /* Not dynamic, not applicable. */</span><br><span style="color: hsl(0, 100%, 40%);">-                              continue;</span><br><span style="color: hsl(0, 100%, 40%);">-                       }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               if (ts->pchan_is != pchan)</span><br><span style="color: hsl(0, 100%, 40%);">-                   continue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ts_for_each_lchan(lchan, ts) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  if (lchan_state_is(lchan, LCHAN_ST_UNUSED))</span><br><span style="color: hsl(0, 100%, 40%);">-                             count++;</span><br><span style="color: hsl(0, 100%, 40%);">-                }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return count;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> bool ts_is_usable(const struct gsm_bts_trx_ts *ts)</span><br><span> {</span><br><span>    if (!trx_is_usable(ts->trx)) {</span><br><span>@@ -1095,57 +909,6 @@</span><br><span>    {}</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-bool trx_has_valid_pchan_config(const struct gsm_bts_trx *trx)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     bool combined = false;</span><br><span style="color: hsl(0, 100%, 40%);">-  bool result = true;</span><br><span style="color: hsl(0, 100%, 40%);">-     unsigned int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Iterate over all timeslots */</span><br><span style="color: hsl(0, 100%, 40%);">-        for (i = 0; i < 8; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-            const struct gsm_bts_trx_ts *ts = &trx->ts[i];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-           switch (ts->pchan_from_config) {</span><br><span style="color: hsl(0, 100%, 40%);">-             case GSM_PCHAN_CCCH_SDCCH4_CBCH:</span><br><span style="color: hsl(0, 100%, 40%);">-                case GSM_PCHAN_CCCH_SDCCH4:</span><br><span style="color: hsl(0, 100%, 40%);">-                     /* CCCH+SDCCH4 can only be configured on TS0 */</span><br><span style="color: hsl(0, 100%, 40%);">-                 if (i > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                         LOGP(DNM, LOGL_ERROR, "Combined CCCH is not allowed "</span><br><span style="color: hsl(0, 100%, 40%);">-                                               "on TS%u > 0\n", i);</span><br><span style="color: hsl(0, 100%, 40%);">-                         result = false;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (i == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                             combined = true;</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* fall-through */</span><br><span style="color: hsl(0, 100%, 40%);">-              case GSM_PCHAN_CCCH:</span><br><span style="color: hsl(0, 100%, 40%);">-                    /* 3GPP TS 45.002, Table 3, CCCH: TS (0, 2, 4, 6) */</span><br><span style="color: hsl(0, 100%, 40%);">-                    if (i % 2 != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                               LOGP(DNM, LOGL_ERROR, "%s is not allowed on odd TS%u\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                                   gsm_pchan_name(ts->pchan_from_config), i);</span><br><span style="color: hsl(0, 100%, 40%);">-                              result = false;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                       /* There can be no more CCCHs if TS0/C0 is combined */</span><br><span style="color: hsl(0, 100%, 40%);">-                  if (i > 0 && combined) {</span><br><span style="color: hsl(0, 100%, 40%);">-                             LOGP(DNM, LOGL_ERROR, "%s is not allowed on TS%u, "</span><br><span style="color: hsl(0, 100%, 40%);">-                                "because TS0 is using combined channel configuration\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                              gsm_pchan_name(ts->pchan_from_config), i);</span><br><span style="color: hsl(0, 100%, 40%);">-                              result = false;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          default:</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* CCCH on TS0 is mandatory for C0 */</span><br><span style="color: hsl(0, 100%, 40%);">-                   if (trx->bts->c0 == trx && i == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              LOGP(DNM, LOGL_ERROR, "TS0 on C0 must be CCCH/BCCH\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                               result = false;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return result;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* This may be specific to RR Channel Release, and the mappings were chosen by pure naive guessing without a proper</span><br><span>  * specification available. */</span><br><span> enum gsm48_rr_cause bsc_gsm48_rr_cause_from_gsm0808_cause(enum gsm0808_cause c)</span><br><span>diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am</span><br><span>index 6696679..653ed97 100644</span><br><span>--- a/src/utils/Makefile.am</span><br><span>+++ b/src/utils/Makefile.am</span><br><span>@@ -49,6 +49,7 @@</span><br><span> bs11_config_LDADD = \</span><br><span>    $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts_siemens_bs11.o \</span><br><span>    $(top_builddir)/src/osmo-bsc/e1_config.o \</span><br><span>   $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>@@ -118,7 +119,9 @@</span><br><span>      $(NULL)</span><br><span> </span><br><span> meas_json_LDADD = \</span><br><span style="color: hsl(120, 100%, 40%);">+    $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(LIBOSMOCORE_LIBS) \</span><br><span>        $(LIBOSMOGSM_LIBS) \</span><br><span>diff --git a/tests/abis/Makefile.am b/tests/abis/Makefile.am</span><br><span>index a01f56a..5f81ceb 100644</span><br><span>--- a/tests/abis/Makefile.am</span><br><span>+++ b/tests/abis/Makefile.am</span><br><span>@@ -27,6 +27,7 @@</span><br><span> abis_test_LDADD = \</span><br><span>         $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(top_builddir)/src/osmo-bsc/net_init.o \</span><br><span>    $(LIBOSMOCORE_LIBS) \</span><br><span>diff --git a/tests/bsc/Makefile.am b/tests/bsc/Makefile.am</span><br><span>index 7ea002e..012bd79 100644</span><br><span>--- a/tests/bsc/Makefile.am</span><br><span>+++ b/tests/bsc/Makefile.am</span><br><span>@@ -38,6 +38,7 @@</span><br><span>   $(top_builddir)/src/osmo-bsc/osmo_bsc_filter.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bsc_subscriber.o \</span><br><span>      $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(top_builddir)/src/osmo-bsc/handover_cfg.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/handover_logic.o \</span><br><span>diff --git a/tests/gsm0408/Makefile.am b/tests/gsm0408/Makefile.am</span><br><span>index 21b7873..790f3aa 100644</span><br><span>--- a/tests/gsm0408/Makefile.am</span><br><span>+++ b/tests/gsm0408/Makefile.am</span><br><span>@@ -23,9 +23,11 @@</span><br><span>        $(NULL)</span><br><span> </span><br><span> gsm0408_test_LDADD = \</span><br><span style="color: hsl(120, 100%, 40%);">+ $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_04_08_rr.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/arfcn_range_encode.o \</span><br><span>  $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(top_builddir)/src/osmo-bsc/net_init.o \</span><br><span>    $(top_builddir)/src/osmo-bsc/rest_octets.o \</span><br><span>diff --git a/tests/handover/Makefile.am b/tests/handover/Makefile.am</span><br><span>index 571b7a9..661b3d2 100644</span><br><span>--- a/tests/handover/Makefile.am</span><br><span>+++ b/tests/handover/Makefile.am</span><br><span>@@ -58,6 +58,7 @@</span><br><span>        $(top_builddir)/src/osmo-bsc/bsc_subscriber.o \</span><br><span>      $(top_builddir)/src/osmo-bsc/bsc_vty.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/bts_unknown.o \</span><br><span>diff --git a/tests/nanobts_omlattr/Makefile.am b/tests/nanobts_omlattr/Makefile.am</span><br><span>index 93fdbe8..5a627ff 100644</span><br><span>--- a/tests/nanobts_omlattr/Makefile.am</span><br><span>+++ b/tests/nanobts_omlattr/Makefile.am</span><br><span>@@ -26,6 +26,7 @@</span><br><span>    $(top_builddir)/src/osmo-bsc/abis_nm.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/bts.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/osmo-bsc/bts_trx.o \</span><br><span>     $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(LIBOSMOCORE_LIBS) \</span><br><span>        $(LIBOSMOGSM_LIBS) \</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/19298">change 19298</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bsc/+/19298"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I11758ca3d255d849d77bd068f24bb68bde1f89a5 </div>
<div style="display:none"> Gerrit-Change-Number: 19298 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>