mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bts.git
synced 2025-11-05 06:33:26 +00:00
Compare commits
2 Commits
master
...
laforge/po
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0bf5de82d | ||
|
|
feee8d52bd |
@@ -37,4 +37,8 @@ int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
|
|||||||
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
|
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
|
||||||
uint8_t cause);
|
uint8_t cause);
|
||||||
|
|
||||||
|
/* Configure LAPDm T200 timers for this lchan according to OML */
|
||||||
|
int oml_set_lchan_t200(struct gsm_lchan *lchan);
|
||||||
|
extern const uint8_t oml_default_t200_ms[7];
|
||||||
|
|
||||||
#endif // _OML_H */
|
#endif // _OML_H */
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ int bts_init(struct gsm_bts *bts)
|
|||||||
btsb->max_ta = 63;
|
btsb->max_ta = 63;
|
||||||
btsb->ny1 = 4;
|
btsb->ny1 = 4;
|
||||||
btsb->t3105_ms = 300;
|
btsb->t3105_ms = 300;
|
||||||
|
memcpy(btsb->t200_ms, oml_default_t200_ms, sizeof(btsb->t200_ms));
|
||||||
|
|
||||||
/* default RADIO_LINK_TIMEOUT */
|
/* default RADIO_LINK_TIMEOUT */
|
||||||
btsb->radio_link_timeout = 32;
|
btsb->radio_link_timeout = 32;
|
||||||
@@ -260,6 +261,7 @@ int lchan_init_lapdm(struct gsm_lchan *lchan)
|
|||||||
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
||||||
lapdm_channel_set_l1(lc, NULL, lchan);
|
lapdm_channel_set_l1(lc, NULL, lchan);
|
||||||
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
||||||
|
oml_set_lchan_t200(lchan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -386,11 +386,69 @@ static const uint8_t abis_nm_t200_mult[] = {
|
|||||||
[T200_FACCH_F] = 5,
|
[T200_FACCH_F] = 5,
|
||||||
[T200_FACCH_H] = 5,
|
[T200_FACCH_H] = 5,
|
||||||
[T200_SACCH_TCH_SAPI0] = 10,
|
[T200_SACCH_TCH_SAPI0] = 10,
|
||||||
[T200_SACCH_SDCCH] = 10,
|
[T200_SACCH_SDCCH] = 10,
|
||||||
[T200_SDCCH_SAPI3] = 5,
|
[T200_SDCCH_SAPI3] = 5,
|
||||||
[T200_SACCH_TCH_SAPI3] = 10
|
[T200_SACCH_TCH_SAPI3] = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* the below defaults correpsond to the libocmocore default of 1s for
|
||||||
|
* DCCH and 2s for ACCH. The BSC should overried this via OML anyway. */
|
||||||
|
const uint8_t oml_default_t200_ms[7] = {
|
||||||
|
[T200_SDCCH] = 1000/5,
|
||||||
|
[T200_FACCH_F] = 1000/5,
|
||||||
|
[T200_FACCH_H] = 1000/5,
|
||||||
|
[T200_SACCH_TCH_SAPI0] = 2000/10,
|
||||||
|
[T200_SACCH_SDCCH] = 2000/10,
|
||||||
|
[T200_SDCCH_SAPI3] = 1000/5,
|
||||||
|
[T200_SACCH_TCH_SAPI3] = 2000/10,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dl_set_t200(struct lapdm_datalink *dl, unsigned int t200_msec)
|
||||||
|
{
|
||||||
|
dl->dl.t200_sec = t200_msec / 1000;
|
||||||
|
dl->dl.t200_usec = t200_msec % 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure LAPDm T200 timers for this lchan according to OML */
|
||||||
|
int oml_set_lchan_t200(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
struct lapdm_channel *lc = &lchan->lapdm_ch;
|
||||||
|
unsigned int t200_dcch, t200_dcch_sapi3, t200_acch, t200_acch_sapi3;
|
||||||
|
|
||||||
|
/* set T200 for main and associated channel */
|
||||||
|
switch (lchan->type) {
|
||||||
|
case GSM_LCHAN_SDCCH:
|
||||||
|
t200_dcch = btsb->t200_ms[T200_SDCCH];
|
||||||
|
t200_dcch_sapi3 = btsb->t200_ms[T200_SDCCH_SAPI3];
|
||||||
|
t200_acch = btsb->t200_ms[T200_SACCH_SDCCH];
|
||||||
|
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_SDCCH];
|
||||||
|
break;
|
||||||
|
case GSM_LCHAN_TCH_F:
|
||||||
|
t200_dcch = btsb->t200_ms[T200_FACCH_F];
|
||||||
|
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_F];
|
||||||
|
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
|
||||||
|
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
|
||||||
|
break;
|
||||||
|
case GSM_LCHAN_TCH_H:
|
||||||
|
t200_dcch = btsb->t200_ms[T200_FACCH_H];
|
||||||
|
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_H];
|
||||||
|
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
|
||||||
|
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI0], t200_dcch);
|
||||||
|
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI3], t200_dcch_sapi3);
|
||||||
|
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI0], t200_acch);
|
||||||
|
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI3], t200_acch_sapi3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 8.6.1 Set BTS Attributes has been received */
|
/* 8.6.1 Set BTS Attributes has been received */
|
||||||
static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
|||||||
|
|
||||||
if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
|
if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
|
||||||
return 0;
|
return 0;
|
||||||
if (lchan->ms_power_ctrl.fixed)
|
if (!lchan->power_control.ul.dynamic)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* The phone hasn't reached the power level yet */
|
/* The phone hasn't reached the power level yet */
|
||||||
|
|||||||
@@ -719,13 +719,27 @@ static int encr_info2lchan(struct gsm_lchan *lchan,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_power_control(struct gsm_power_control *pc,
|
||||||
|
const uint8_t *ie_val, unsigned int ie_len)
|
||||||
|
{
|
||||||
|
if (ie_len < 3)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pc->rxlev.lower = ie_val[0] & 0x3f;
|
||||||
|
pc->rxlev.upper = ie_val[1] & 0x3f;
|
||||||
|
pc->rxqual.lower = (ie_val[2] >> 4) & 7;
|
||||||
|
pc->rxqual.upper = ie_val[2] & 7;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 8.4.1 CHANnel ACTIVation is received */
|
/* 8.4.1 CHANnel ACTIVation is received */
|
||||||
static int rsl_rx_chan_activ(struct msgb *msg)
|
static int rsl_rx_chan_activ(struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);
|
struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);
|
||||||
struct gsm_lchan *lchan = msg->lchan;
|
struct gsm_lchan *lchan = msg->lchan;
|
||||||
struct rsl_ie_chan_mode *cm;
|
struct rsl_ie_chan_mode *cm;
|
||||||
struct tlv_parsed tp;
|
struct tlv_parsed tp, tp_eie;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -739,7 +753,7 @@ static int rsl_rx_chan_activ(struct msgb *msg)
|
|||||||
/* Initialize channel defaults */
|
/* Initialize channel defaults */
|
||||||
lchan->ms_power = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0);
|
lchan->ms_power = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0);
|
||||||
lchan->ms_power_ctrl.current = lchan->ms_power;
|
lchan->ms_power_ctrl.current = lchan->ms_power;
|
||||||
lchan->ms_power_ctrl.fixed = 0;
|
lchan->power_control.ul.dynamic = 0;
|
||||||
|
|
||||||
rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
|
rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
|
||||||
|
|
||||||
@@ -777,20 +791,50 @@ static int rsl_rx_chan_activ(struct msgb *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 9.3.4 BS Power */
|
/* 9.3.4 BS Power */
|
||||||
if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
|
if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER)) {
|
||||||
lchan->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
|
lchan->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
|
||||||
|
lchan->power_control.dl.static_level = lchan->bs_power;
|
||||||
|
lchan->power_control.dl.dynamic = 0;
|
||||||
|
}
|
||||||
/* 9.3.13 MS Power */
|
/* 9.3.13 MS Power */
|
||||||
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) {
|
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) {
|
||||||
lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER);
|
lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER);
|
||||||
lchan->ms_power_ctrl.current = lchan->ms_power;
|
lchan->power_control.ul.static_level = lchan->ms_power;
|
||||||
lchan->ms_power_ctrl.fixed = 0;
|
lchan->power_control.ul.dynamic = 0;
|
||||||
}
|
}
|
||||||
/* 9.3.24 Timing Advance */
|
/* 9.3.24 Timing Advance */
|
||||||
if (TLVP_PRESENT(&tp, RSL_IE_TIMING_ADVANCE))
|
if (TLVP_PRESENT(&tp, RSL_IE_TIMING_ADVANCE))
|
||||||
lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE);
|
lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE);
|
||||||
|
|
||||||
/* 9.3.32 BS Power Parameters */
|
/* 9.3.32 BS Power Parameters */
|
||||||
|
if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) {
|
||||||
|
rsl_ipac_eie_tlv_parse(&tp_eie,
|
||||||
|
TLVP_VAL(&tp, RSL_IE_BS_POWER_PARAM),
|
||||||
|
TLVP_LEN(&tp, RSL_IE_BS_POWER_PARAM));
|
||||||
|
if (TLVP_PRESENT(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)) {
|
||||||
|
parse_power_control(&lchan->power_control.dl,
|
||||||
|
TLVP_VAL(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL),
|
||||||
|
TLVP_LEN(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL));
|
||||||
|
}
|
||||||
|
/* if this IE is present, we use dynamic control */
|
||||||
|
lchan->power_control.dl.dynamic = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* 9.3.31 MS Power Parameters */
|
/* 9.3.31 MS Power Parameters */
|
||||||
|
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) {
|
||||||
|
rsl_ipac_eie_tlv_parse(&tp_eie,
|
||||||
|
TLVP_VAL(&tp, RSL_IE_MS_POWER_PARAM),
|
||||||
|
TLVP_LEN(&tp, RSL_IE_MS_POWER_PARAM));
|
||||||
|
if (TLVP_PRESENT(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)) {
|
||||||
|
parse_power_control(&lchan->power_control.ul,
|
||||||
|
TLVP_VAL(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL),
|
||||||
|
TLVP_LEN(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL));
|
||||||
|
}
|
||||||
|
/* if this IE is present, we use dynamic control */
|
||||||
|
lchan->power_control.ul.dynamic = 1;
|
||||||
|
lchan->ms_power_ctrl.current = lchan->ms_power;
|
||||||
|
}
|
||||||
|
|
||||||
/* 9.3.16 Physical Context */
|
/* 9.3.16 Physical Context */
|
||||||
|
|
||||||
/* 9.3.29 SACCH Information */
|
/* 9.3.29 SACCH Information */
|
||||||
@@ -1121,19 +1165,38 @@ static int rsl_rx_mode_modif(struct msgb *msg)
|
|||||||
static int rsl_rx_ms_pwr_ctrl(struct msgb *msg)
|
static int rsl_rx_ms_pwr_ctrl(struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct gsm_lchan *lchan = msg->lchan;
|
struct gsm_lchan *lchan = msg->lchan;
|
||||||
struct tlv_parsed tp;
|
struct tlv_parsed tp, tp_eie;
|
||||||
|
|
||||||
rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
|
rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
|
||||||
|
/* 9.3.13 MS Power */
|
||||||
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) {
|
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) {
|
||||||
uint8_t pwr = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F;
|
lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F;
|
||||||
lchan->ms_power_ctrl.fixed = 1;
|
lchan->power_control.ul.static_level = lchan->ms_power;
|
||||||
lchan->ms_power_ctrl.current = pwr;
|
lchan->power_control.ul.dynamic = 0;
|
||||||
|
lchan->ms_power_ctrl.current = lchan->ms_power;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 9.3.31 MS Power Parameters */
|
||||||
|
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) {
|
||||||
|
rsl_ipac_eie_tlv_parse(&tp_eie,
|
||||||
|
TLVP_VAL(&tp, RSL_IE_MS_POWER_PARAM),
|
||||||
|
TLVP_LEN(&tp, RSL_IE_MS_POWER_PARAM));
|
||||||
|
if (TLVP_PRESENT(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)) {
|
||||||
|
parse_power_control(&lchan->power_control.ul,
|
||||||
|
TLVP_VAL(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL),
|
||||||
|
TLVP_LEN(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL));
|
||||||
|
}
|
||||||
|
/* if this IE is present, we use dynamic control */
|
||||||
|
lchan->power_control.ul.dynamic = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lchan->power_control.ul.dynamic == 0) {
|
||||||
LOGP(DRSL, LOGL_NOTICE, "%s forcing power to %d\n",
|
LOGP(DRSL, LOGL_NOTICE, "%s forcing power to %d\n",
|
||||||
gsm_lchan_name(lchan), lchan->ms_power_ctrl.current);
|
gsm_lchan_name(lchan), lchan->ms_power_ctrl.current);
|
||||||
bts_model_adjst_ms_pwr(lchan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bts_model_adjst_ms_pwr(lchan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user