176 lines
3.8 KiB
C
176 lines
3.8 KiB
C
#include <stdint.h>
|
|
|
|
#include <osmocom/core/linuxlist.h>
|
|
#include <osmocom/core/talloc.h>
|
|
#include <osmocom/core/fsm.h>
|
|
|
|
#include <osmo-bts/bts.h>
|
|
#include <osmo-bts/gsm_data.h>
|
|
#include <osmo-bts/phy_link.h>
|
|
#include <osmo-bts/oml.h>
|
|
#include <osmo-bts/logging.h>
|
|
#include <osmo-bts/bts_model.h>
|
|
#include <osmo-bts/nm_common_fsm.h>
|
|
|
|
static LLIST_HEAD(g_phy_links);
|
|
|
|
struct phy_link *phy_link_by_num(int num)
|
|
{
|
|
struct phy_link *plink;
|
|
|
|
llist_for_each_entry(plink, &g_phy_links, list) {
|
|
if (plink->num == num)
|
|
return plink;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct phy_link *phy_link_create(void *ctx, int num)
|
|
{
|
|
struct phy_link *plink;
|
|
|
|
if (phy_link_by_num(num))
|
|
return NULL;
|
|
|
|
plink = talloc_zero(ctx, struct phy_link);
|
|
plink->num = num;
|
|
plink->state = PHY_LINK_SHUTDOWN;
|
|
INIT_LLIST_HEAD(&plink->instances);
|
|
llist_add_tail(&plink->list, &g_phy_links);
|
|
|
|
bts_model_phy_link_set_defaults(plink);
|
|
|
|
return plink;
|
|
}
|
|
|
|
const struct value_string phy_link_state_vals[] = {
|
|
{ PHY_LINK_SHUTDOWN, "shutdown" },
|
|
{ PHY_LINK_CONNECTING, "connecting" },
|
|
{ PHY_LINK_CONNECTED, "connected" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
|
|
{
|
|
struct phy_instance *pinst;
|
|
|
|
LOGPPHL(plink, DL1C, LOGL_INFO, "PHY link state change %s -> %s\n",
|
|
get_value_string(phy_link_state_vals, plink->state),
|
|
get_value_string(phy_link_state_vals, state));
|
|
|
|
plink->state = state;
|
|
|
|
/* notify all TRX associated with this phy */
|
|
llist_for_each_entry(pinst, &plink->instances, list) {
|
|
struct gsm_bts_trx *trx = pinst->trx;
|
|
if (!trx)
|
|
continue;
|
|
|
|
osmo_fsm_inst_dispatch(trx->mo.fi,
|
|
state == PHY_LINK_CONNECTED ? NM_EV_PHYLINK_UP :
|
|
NM_EV_PHYLINK_DOWN,
|
|
NULL);
|
|
osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi,
|
|
state == PHY_LINK_CONNECTED ? NM_EV_PHYLINK_UP :
|
|
NM_EV_PHYLINK_DOWN,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
enum phy_link_state phy_link_state_get(struct phy_link *plink)
|
|
{
|
|
return plink->state;
|
|
}
|
|
|
|
const char *phy_link_state_name(enum phy_link_state state)
|
|
{
|
|
return get_value_string(phy_link_state_vals, state);
|
|
}
|
|
|
|
struct phy_instance *phy_instance_by_num(const struct phy_link *plink, int num)
|
|
{
|
|
struct phy_instance *pinst;
|
|
|
|
llist_for_each_entry(pinst, &plink->instances, list) {
|
|
if (pinst->num == num)
|
|
return pinst;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
struct phy_instance *phy_instance_create(struct phy_link *plink, int num)
|
|
{
|
|
struct phy_instance *pinst;
|
|
|
|
if (phy_instance_by_num(plink, num))
|
|
return NULL;
|
|
|
|
pinst = talloc_zero(plink, struct phy_instance);
|
|
pinst->num = num;
|
|
pinst->phy_link = plink;
|
|
llist_add_tail(&pinst->list, &plink->instances);
|
|
|
|
bts_model_phy_instance_set_defaults(pinst);
|
|
|
|
return pinst;
|
|
}
|
|
|
|
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx)
|
|
{
|
|
trx->role_bts.l1h = pinst;
|
|
pinst->trx = trx;
|
|
}
|
|
|
|
void phy_instance_destroy(struct phy_instance *pinst)
|
|
{
|
|
/* remove from list of instances in the link */
|
|
llist_del(&pinst->list);
|
|
|
|
/* remove reverse link from TRX */
|
|
OSMO_ASSERT(pinst->trx->role_bts.l1h == pinst);
|
|
pinst->trx->role_bts.l1h = NULL;
|
|
pinst->trx = NULL;
|
|
|
|
talloc_free(pinst);
|
|
}
|
|
|
|
void phy_link_destroy(struct phy_link *plink)
|
|
{
|
|
struct phy_instance *pinst, *pinst2;
|
|
|
|
llist_for_each_entry_safe(pinst, pinst2, &plink->instances, list)
|
|
phy_instance_destroy(pinst);
|
|
|
|
talloc_free(plink);
|
|
}
|
|
|
|
static char name_buf[32];
|
|
const char *phy_link_name(struct phy_link *plink)
|
|
{
|
|
snprintf(name_buf, sizeof(name_buf), "phy%u", plink->num);
|
|
return name_buf;
|
|
}
|
|
|
|
int phy_links_open(void)
|
|
{
|
|
struct phy_link *plink;
|
|
|
|
llist_for_each_entry(plink, &g_phy_links, list) {
|
|
int rc;
|
|
|
|
rc = bts_model_phy_link_open(plink);
|
|
if (rc < 0)
|
|
return rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char *phy_instance_name(struct phy_instance *pinst)
|
|
{
|
|
snprintf(name_buf, sizeof(name_buf), "phy%u.%u", pinst->phy_link->num,
|
|
pinst->num);
|
|
return name_buf;
|
|
}
|