diff options
-rw-r--r-- | src/osmo-bts-octphy/l1_if.c | 27 | ||||
-rw-r--r-- | src/osmo-bts-octphy/l1_oml.c | 112 |
2 files changed, 126 insertions, 13 deletions
diff --git a/src/osmo-bts-octphy/l1_if.c b/src/osmo-bts-octphy/l1_if.c index cb792d79..e4ab5385 100644 --- a/src/osmo-bts-octphy/l1_if.c +++ b/src/osmo-bts-octphy/l1_if.c @@ -329,11 +329,30 @@ int l1if_activate_rf(struct gsm_bts_trx *trx, int on) return 0; } -static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config pchan, +static enum gsm_phys_chan_config pick_pchan(struct gsm_bts_trx_ts *ts) +{ + switch (ts->pchan) { + case GSM_PCHAN_TCH_F_PDCH: + if (ts->flags & TS_F_PDCH_ACTIVE) + return GSM_PCHAN_PDCH; + return GSM_PCHAN_TCH_F; + case GSM_PCHAN_TCH_F_TCH_H_PDCH: + return ts->dyn.pchan_is; + default: + return ts->pchan; + } +} + +static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts, tOCTVC1_GSM_SAPI_ENUM sapi, uint8_t subCh, uint8_t u8Tn, uint32_t u32Fn) { uint8_t cbits = 0; + enum gsm_phys_chan_config pchan = pick_pchan(ts); + + OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); + OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); + switch (sapi) { case cOCTVC1_GSM_SAPI_ENUM_BCCH: cbits = 0x10; @@ -476,7 +495,7 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, if (!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_PDCH(chan_nr)) subCh = l1sap_chan2ss(chan_nr); } else if (L1SAP_IS_CHAN_TCHF(chan_nr) || L1SAP_IS_CHAN_PDCH(chan_nr)) { - if (trx->ts[u8Tn].pchan == GSM_PCHAN_PDCH) { + if (ts_is_pdch(&trx->ts[u8Tn])) { if (L1SAP_IS_PTCCH(u32Fn)) { sapi = cOCTVC1_GSM_SAPI_ENUM_PTCCH; } else { @@ -932,7 +951,7 @@ static int handle_ph_readytosend_ind(struct octphy_hdl *fl1, get_value_string(octphy_l1sapi_names, sapi)); /* in case we need to forward primitive to common part */ - chan_nr = chan_nr_by_sapi(trx->ts[ts_num].pchan, sapi, sc, ts_num, fn); + chan_nr = chan_nr_by_sapi(&trx->ts[ts_num], sapi, sc, ts_num, fn); if (chan_nr) { if (sapi == cOCTVC1_GSM_SAPI_ENUM_SACCH) link_id = LID_SACCH; @@ -1053,7 +1072,7 @@ static int handle_ph_data_ind(struct octphy_hdl *fl1, fn = data_ind->Data.ulFrameNumber; /* chan_nr and link_id */ - chan_nr = chan_nr_by_sapi(trx->ts[ts_num].pchan, sapi, sc, ts_num, fn); + chan_nr = chan_nr_by_sapi(&trx->ts[ts_num], sapi, sc, ts_num, fn); if (!chan_nr) { LOGP(DL1C, LOGL_ERROR, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", diff --git a/src/osmo-bts-octphy/l1_oml.c b/src/osmo-bts-octphy/l1_oml.c index 03ff5476..d1d5bf6a 100644 --- a/src/osmo-bts-octphy/l1_oml.c +++ b/src/osmo-bts-octphy/l1_oml.c @@ -1406,21 +1406,24 @@ static int pchan_act_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *d return opstart_compl(mo); } -static int ts_connect(struct gsm_bts_trx_ts *ts) +static int ts_connect_as(struct gsm_bts_trx_ts *ts, + enum gsm_phys_chan_config pchan, + l1if_compl_cb * cb, void *data) { struct phy_instance *pinst = trx_phy_instance(ts->trx); struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; struct msgb *msg = l1p_msgb_alloc(); tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *oc = - (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *) oc; + (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *) oc; - oc = (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *) msgb_put(msg, sizeof(*oc)); + oc = (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD*) + msgb_put(msg, sizeof(*oc)); l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, cOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CID); oc->TrxId.byTrxId = pinst->u.octphy.trx_id; oc->PchId.byTimeslotNb = ts->nr; - oc->ulChannelType = pchan_to_logChComb[ts->pchan]; + oc->ulChannelType = pchan_to_logChComb[pchan]; /* TODO: how should we know the payload type here? Also, why * would the payload type have to be the same for both halves of @@ -1436,11 +1439,71 @@ static int ts_connect(struct gsm_bts_trx_ts *ts) } LOGP(DL1C, LOGL_INFO, "PCHAN-ACT.req(trx=%u, ts=%u, chcomb=%u)\n", - ts->trx->nr, ts->nr, ts->pchan); + ts->trx->nr, ts->nr, pchan); mOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD_SWAP(oc); - return l1if_req_compl(fl1h, msg, pchan_act_compl_cb, NULL); + return l1if_req_compl(fl1h, msg, cb, data); +} + +/* Dynamic timeslots: Disconnect callback, reports completed disconnection + * to higher layers */ +static int ts_disconnect_cb(struct octphy_hdl *fl1, struct msgb *resp, + void *data) +{ + tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_RSP *ar = + (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_RSP *) resp->l2h; + uint8_t ts_nr; + struct gsm_bts_trx *trx; + struct gsm_bts_trx_ts *ts; + + trx = trx_by_l1h(fl1, ar->TrxId.byTrxId); + ts_nr = ar->PchId.byTimeslotNb; + ts = &trx->ts[ts_nr]; + + cb_ts_disconnected(ts); + + return 0; +} + +/* Dynamic timeslots: Connect callback, reports completed disconnection to + * higher layers */ +static int ts_connect_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) +{ + tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *ar = + (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *) resp->l2h; + uint8_t ts_nr; + struct gsm_bts_trx *trx; + struct gsm_bts_trx_ts *ts; + + /* in a completion call-back, we take msgb ownership and must + * release it before returning */ + + mOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP_SWAP(ar); + trx = trx_by_l1h(fl1, ar->TrxId.byTrxId); + ts_nr = ar->PchId.byTimeslotNb; + OSMO_ASSERT(ts_nr <= ARRAY_SIZE(trx->ts)); + + ts = &trx->ts[ts_nr]; + + LOGP(DL1C, LOGL_INFO, "PCHAN-ACT.conf(trx=%u, ts=%u, chcomb=%u) = %s\n", + ts->trx->nr, ts->nr, ts->pchan, + octvc1_rc2string(ar->Header.ulReturnCode)); + + if (ar->Header.ulReturnCode != cOCTVC1_RC_OK) { + LOGP(DL1C, LOGL_ERROR, + "PCHAN-ACT failed: %s\n\n", + octvc1_rc2string(ar->Header.ulReturnCode)); + LOGP(DL1C, LOGL_ERROR, "Exiting... \n\n"); + msgb_free(resp); + exit(-1); + } + + msgb_free(resp); + + cb_ts_connected(ts); + + return 0; } /*********************************************************************** @@ -1583,13 +1646,15 @@ int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj) { int rc = -1; + struct gsm_bts_trx_ts *ts; switch (mo->obj_class) { case NM_OC_RADIO_CARRIER: rc = trx_init(obj); break; case NM_OC_CHANNEL: - rc = ts_connect(obj); + ts = (struct gsm_bts_trx_ts*) obj; + rc = ts_connect_as(ts, ts->pchan, pchan_act_compl_cb, NULL); break; case NM_OC_BTS: case NM_OC_SITE_MANAGER: @@ -1614,11 +1679,40 @@ int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) { - return -ENOTSUP; + struct phy_instance *pinst = trx_phy_instance(ts->trx); + struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; + struct msgb *msg = l1p_msgb_alloc(); + tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD *oc = + (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD *) oc; + + oc = (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD *) + msgb_put(msg, sizeof(*oc)); + l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, + cOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CID); + + oc->TrxId.byTrxId = pinst->u.octphy.trx_id; + oc->PchId.byTimeslotNb = ts->nr; + + LOGP(DL1C, LOGL_INFO, "PCHAN-DEACT.req(trx=%u, ts=%u, chcomb=%u)\n", + ts->trx->nr, ts->nr, ts->pchan); + + mOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD_SWAP(oc); + + return l1if_req_compl(fl1h, msg, ts_disconnect_cb, NULL); } int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) { - return -ENOTSUP; + if (as_pchan == GSM_PCHAN_TCH_F_PDCH + || as_pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { + LOGP(DL1C, LOGL_ERROR, + "%s Requested TS connect as %s," + " expected a specific pchan instead\n", + gsm_ts_and_pchan_name(ts), gsm_pchan_name(as_pchan)); + exit(1); + return -EINVAL; + } + + return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL); } |