Introduce new phy_link and phy_instance abstraction
This way we can model a flexible mapping between any number of PHYs, each having multiple instances, and then map BTSs with TRXx on top of those PHYs.
This commit is contained in:
parent
f58542899a
commit
d784e50747
|
@ -20,9 +20,13 @@ log stderr
|
|||
line vty
|
||||
no login
|
||||
!
|
||||
phy 0
|
||||
octphy hw-addr 00:0C:90:2e:80:1e
|
||||
octphy net-device eth0.2342
|
||||
instance 0
|
||||
bts 0
|
||||
band 1800
|
||||
ipa unit-id 1234 0
|
||||
oml remote-ip 127.0.0.1
|
||||
phy-hw-addr 00:0C:90:2e:80:1e
|
||||
phy-netdev eth0.2342
|
||||
trx 0
|
||||
phy 0 instance 0
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
== OsmoBTS PHY interface abstraction
|
||||
|
||||
The OsmoBTS PHY interface serves as an abstraction layer between given
|
||||
PHY hardware and the actual logical transceivers (TRXs) of a BTS inside
|
||||
the OsmoBTS code base.
|
||||
|
||||
|
||||
=== PHY link
|
||||
|
||||
A PHY link is a physical connection / link towards a given PHY. This
|
||||
might be, for example,
|
||||
|
||||
* a set of file descriptors to device nodes in the /dev/ directory
|
||||
(sysmobts, litecell15)
|
||||
* a packet socket for sending raw Ethernet frames to an OCTPHY
|
||||
* a set of UDP sockets for interacting with OsmoTRX
|
||||
|
||||
Each PHY interface has a set of attribute/parameters and a list of 1 to
|
||||
n PHY instances.
|
||||
|
||||
PHY links are numbered 0..n globally inside OsmoBTS.
|
||||
|
||||
Each PHY link is configured via the VTY using its individual top-level
|
||||
vty node. Given the different bts-model / phy specific properties, the
|
||||
VTY configuration options (if any) of the PHY instance differ between
|
||||
BTS models.
|
||||
|
||||
The PHY links and instances must be configured above the BTS/TRX nodes
|
||||
in the configuration file. If the file is saved via the VTY, the code
|
||||
automatically ensures this.
|
||||
|
||||
|
||||
=== PHY instance
|
||||
|
||||
A PHY instance is an instance of a PHY, accessed via a PHY link.
|
||||
|
||||
In the case of osmo-bts-sysmo and osmo-bts-trx, there is only one
|
||||
instance in every PHY link. This is due to the fact that the API inside
|
||||
that PHY link does not permit for distinguishing multiple different
|
||||
logical TRXs.
|
||||
|
||||
Other PHY implementations like the OCTPHY however do support addressing
|
||||
multiple PHY instances via a single PHY link.
|
||||
|
||||
PHY instances are numbered 0..n inside each PHY link.
|
||||
|
||||
Each PHY instance is configured via the VTY as a separate node beneath each
|
||||
PHY link. Given the different bts-model / phy specific properties, the
|
||||
VTY configuration options (if any) of the PHY instance differ between
|
||||
BTS models.
|
||||
|
||||
|
||||
=== Mapping PHY instances to TRXs
|
||||
|
||||
Each TRX node in the VTY must use the 'phy N instance M' command in
|
||||
order to specify which PHY instance is allocated to this specific TRX.
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
== start-up / sequencing during OsmoBTS start
|
||||
|
||||
The start-up procedure of OsmoBTS can be described as follows:
|
||||
|
||||
|===
|
||||
| bts-specific | main() |
|
||||
| common | bts_main() | initialization of talloc contexts
|
||||
| common | bts_log_init() | initialization of logging
|
||||
| common | handle_options() | common option parsing
|
||||
| bts-specific | bts_model_handle_options() | model-specific option parsing
|
||||
| common | gsm_bts_alloc() | allocation of BTS/TRX/TS data structures
|
||||
| common | vty_init() | Initialziation of VTY core, libosmo-abis and osmo-bts VTY
|
||||
| common | main() | Setting of scheduler RR priority (if configured)
|
||||
| common | main() | Initialization of GSMTAP (if configured)
|
||||
| common | bts_init() | configuration of defaults in bts/trx/s object
|
||||
| bts-specific | bts_model_init | ?
|
||||
| common | abis_init() | Initialization of libosmo-abis
|
||||
| common | vty_read_config_file() | Reading of configuration file
|
||||
| bts-specific | bts_model_phy_link_set_defaults() | Called for every PHY link created
|
||||
| bts-specific | bts_model_phy_instance_set_defaults() | Called for every PHY Instance created
|
||||
| common | bts_controlif_setup() | Initialization of Control Interface
|
||||
| bts-specific | bts_model_ctrl_cmds_install()
|
||||
| common | telnet_init() | Initialization of telnet interface
|
||||
| common | pcu_sock_init() | Initializaiton of PCU socket
|
||||
| common | main() | Installation of signal handlers
|
||||
| common | abis_open() | Start of the A-bis connection to BSC
|
||||
| common | phy_links_open() | Iterate over list of configured PHY links
|
||||
| bts-specific | bts_model_phy_link_open() | Open each of the configured PHY links
|
||||
| common | write_pid_file() | Generate the pid file
|
||||
| common | osmo_daemonize() | Fork as daemon in background (if configured)
|
||||
| common | bts_main() | Run main loop until global variable quit >= 2
|
||||
| bts-specific | bts_model_oml_estab() | Called by core once OML link is established
|
||||
| bts-specific | bts_model_check_oml() | called each time OML sets some attributes on a MO, checks if attributes are valid
|
||||
| bts-specific | bts_model_apply_oml() | called each time OML sets some attributes on a MO, stores attribute contents in data structures
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_BTS, NM_OC_SITE_MANAGER, NM_OC_GPRS_NSE, NM_OC_GPRS_CELL, NMO_OC_GPRS_NSVC
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_RADIO_CARRIER for each trx
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_BASEB_TRANSC for each trx
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_CHANNEL for each timeslot on each trx
|
||||
| bts-specific | bts_model_change_power() | change transmit power for each trx (power ramp-up/ramp-down
|
||||
|
||||
| bts-specific | bts_model_abis_close() | called when either one of the RSL links or the OML link are down
|
|
@ -1,4 +1,4 @@
|
|||
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \
|
||||
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
|
||||
handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
|
||||
power_control.h scheduler.h scheduler_backend.h
|
||||
power_control.h scheduler.h scheduler_backend.h phy_link.h
|
||||
|
|
|
@ -21,12 +21,12 @@ void destroy_bts(struct gsm_bts *bts);
|
|||
int work_bts(struct gsm_bts *bts);
|
||||
int bts_link_estab(struct gsm_bts *bts);
|
||||
int trx_link_estab(struct gsm_bts_trx *trx);
|
||||
int trx_set_available(struct gsm_bts_trx *trx, int avail);
|
||||
void bts_new_si(void *arg);
|
||||
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
|
||||
|
||||
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
|
||||
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
|
||||
void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||
int bts_agch_max_queue_length(int T, int bcch_conf);
|
||||
int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
|
||||
int is_ag_res);
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
struct phy_link;
|
||||
struct phy_instance;
|
||||
|
||||
/* BTS model specific functions needed by the common code */
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts);
|
||||
|
@ -32,6 +35,8 @@ int bts_model_vty_init(struct gsm_bts *bts);
|
|||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx);
|
||||
void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink);
|
||||
void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst);
|
||||
|
||||
int bts_model_oml_estab(struct gsm_bts *bts);
|
||||
|
||||
|
@ -47,4 +52,7 @@ int bts_model_ctrl_cmds_install(struct gsm_bts *bts);
|
|||
int bts_model_handle_options(int argc, char **argv);
|
||||
void bts_model_print_help();
|
||||
|
||||
void bts_model_phy_link_set_defaults(struct phy_link *plink);
|
||||
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,21 +119,6 @@ enum lchan_ciph_state {
|
|||
|
||||
#include "openbsc/gsm_data_shared.h"
|
||||
|
||||
struct femtol1_hdl;
|
||||
|
||||
static inline struct femtol1_hdl *trx_femtol1_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
struct trx_l1h;
|
||||
|
||||
static inline struct trx_l1h *trx_l1h_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
|
||||
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state);
|
||||
|
||||
/* cipher code */
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
struct gsm_bts_trx;
|
||||
|
||||
enum phy_link_type {
|
||||
PHY_LINK_T_NONE,
|
||||
PHY_LINK_T_SYSMOBTS,
|
||||
PHY_LINK_T_OSMOTRX,
|
||||
};
|
||||
|
||||
enum phy_link_state {
|
||||
PHY_LINK_SHUTDOWN,
|
||||
PHY_LINK_CONNECTING,
|
||||
PHY_LINK_CONNECTED,
|
||||
};
|
||||
|
||||
/* A PHY link represents the connection to a given PHYsical layer
|
||||
* implementation. That PHY link contains 1...N PHY instances, one for
|
||||
* each TRX */
|
||||
struct phy_link {
|
||||
struct llist_head list;
|
||||
int num;
|
||||
enum phy_link_type type;
|
||||
enum phy_link_state state;
|
||||
struct llist_head instances;
|
||||
char *description;
|
||||
union {
|
||||
struct {
|
||||
} sysmobts;
|
||||
struct {
|
||||
char *transceiver_ip;
|
||||
uint16_t base_port_local;
|
||||
uint16_t base_port_remote;
|
||||
struct osmo_fd trx_ofd_clk;
|
||||
|
||||
uint32_t clock_advance;
|
||||
uint32_t rts_advance;
|
||||
|
||||
int rxgain_valid;
|
||||
int rxgain;
|
||||
int rxgain_sent;
|
||||
|
||||
int power_valid;
|
||||
int power;
|
||||
int power_oml;
|
||||
int power_sent;
|
||||
} osmotrx;
|
||||
struct {
|
||||
/* MAC address of the PHY */
|
||||
struct sockaddr_ll phy_addr;
|
||||
/* Network device name */
|
||||
char *netdev_name;
|
||||
|
||||
/* configuration */
|
||||
uint32_t rf_port_index;
|
||||
uint32_t rx_gain_db;
|
||||
uint32_t tx_atten_db;
|
||||
|
||||
struct octphy_hdl *hdl;
|
||||
} octphy;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct phy_instance {
|
||||
/* liked inside phy_link.linstances */
|
||||
struct llist_head list;
|
||||
int num;
|
||||
char *description;
|
||||
|
||||
/* pointer to the PHY link to which we belong */
|
||||
struct phy_link *phy_link;
|
||||
|
||||
/* back-pointer to the TRX to which we're associated */
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
union {
|
||||
struct {
|
||||
} sysmobts;
|
||||
struct {
|
||||
struct trx_l1h *hdl;
|
||||
} osmotrx;
|
||||
struct {
|
||||
/* logical transceiver number within one PHY */
|
||||
uint32_t trx_id;
|
||||
} octphy;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct phy_link *phy_link_by_num(int num);
|
||||
struct phy_link *phy_link_create(void *ctx, int num);
|
||||
void phy_link_destroy(struct phy_link *plink);
|
||||
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state);
|
||||
int phy_links_open(void);
|
||||
|
||||
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
|
||||
struct phy_instance *phy_instance_create(struct phy_link *plink, int num);
|
||||
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx);
|
||||
void phy_instance_destroy(struct phy_instance *pinst);
|
||||
const char *phy_instance_name(struct phy_instance *pinst);
|
||||
|
||||
void phy_user_statechg_notif(struct phy_instance *pinst, enum phy_link_state link_state);
|
||||
|
||||
static inline struct phy_instance *trx_phy_instance(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
int bts_model_phy_link_open(struct phy_link *plink);
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef TRX_SCHEDULER_H
|
||||
#define TRX_SCHEDULER_H
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
/* These types define the different channels on a multiframe.
|
||||
* Each channel has queues and can be activated individually.
|
||||
*/
|
||||
|
@ -133,7 +135,7 @@ extern uint32_t transceiver_last_fn;
|
|||
|
||||
|
||||
/*! \brief Initialize the scheudler data structures */
|
||||
int trx_sched_init(struct l1sched_trx *l1t);
|
||||
int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx);
|
||||
|
||||
/*! \brief De-initialize the scheudler data structures */
|
||||
void trx_sched_exit(struct l1sched_trx *l1t);
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
#include <osmocom/vty/command.h>
|
||||
|
||||
enum bts_vty_node {
|
||||
BTS_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
/* PHY_NODE must come before BTS node to ensure the phy
|
||||
* instances are created at the time the TRX nodes want to refer
|
||||
* to them */
|
||||
PHY_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
PHY_INST_NODE,
|
||||
BTS_NODE,
|
||||
TRX_NODE,
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,6 @@ libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
|
|||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
|
||||
l1sap.c cbch.c power_control.c main.c
|
||||
l1sap.c cbch.c power_control.c main.c phy_link.c
|
||||
|
||||
libl1sched_a_SOURCES = scheduler.c
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
|
||||
static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||
|
||||
struct gsm_network bts_gsmnet = {
|
||||
.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
|
||||
|
@ -72,6 +73,8 @@ static int bts_signal_cbfn(unsigned int subsys, unsigned int signal,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize the BTS (and TRX) data structures, called before config
|
||||
* file reading */
|
||||
int bts_init(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb;
|
||||
|
@ -255,6 +258,31 @@ int trx_link_estab(struct gsm_bts_trx *trx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* set the availability of the TRX (used by PHY driver) */
|
||||
int trx_set_available(struct gsm_bts_trx *trx, int avail)
|
||||
{
|
||||
int tn;
|
||||
|
||||
LOGP(DSUM, LOGL_INFO, "TRX(%d): Setting available = %d\n",
|
||||
trx->nr, avail);
|
||||
if (avail) {
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
|
||||
oml_mo_tx_sw_act_rep(&trx->mo);
|
||||
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK);
|
||||
oml_mo_tx_sw_act_rep(&trx->bb_transc.mo);
|
||||
|
||||
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
|
||||
} else {
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OFF_LINE);
|
||||
|
||||
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lchan_init_lapdm(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct lapdm_channel *lc = &lchan->lapdm_ch;
|
||||
|
@ -310,7 +338,7 @@ int bts_agch_max_queue_length(int T, int bcch_conf)
|
|||
return (T + 2 * S) * ccch_rach_ratio256 / 256;
|
||||
}
|
||||
|
||||
void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
||||
static void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct gsm48_system_information_type_3 *si3;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <osmocom/core/gsmtap.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
@ -284,6 +285,19 @@ int bts_main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (!phy_link_by_num(0)) {
|
||||
fprintf(stderr, "You need to configure at last phy0\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (!trx->role_bts.l1h) {
|
||||
fprintf(stderr, "TRX %u has no associated PHY instance\n",
|
||||
trx->nr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
write_pid_file("osmo-bts");
|
||||
|
||||
bts_controlif_setup(bts);
|
||||
|
@ -317,6 +331,12 @@ int bts_main(int argc, char **argv)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
rc = phy_links_open();
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "unable ot open PHY link(s)\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.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>
|
||||
|
||||
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, "connectiong" },
|
||||
{ PHY_LINK_CONNECTED, "connected" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
|
||||
LOGP(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));
|
||||
|
||||
/* 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;
|
||||
|
||||
switch (state) {
|
||||
case PHY_LINK_CONNECTED:
|
||||
LOGP(DL1C, LOGL_INFO, "trx_set_avail(1)\n");
|
||||
trx_set_available(trx, 1);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1C, LOGL_INFO, "trx_set_avail(0)\n");
|
||||
trx_set_available(trx, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
plink->state = state;
|
||||
}
|
||||
|
||||
struct phy_instance *phy_instance_by_num(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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "phy%u.%u", pinst->phy_link->num,
|
||||
pinst->num);
|
||||
return buf;
|
||||
}
|
|
@ -134,11 +134,13 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
|||
* init / exit
|
||||
*/
|
||||
|
||||
int trx_sched_init(struct l1sched_trx *l1t)
|
||||
int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx)
|
||||
{
|
||||
uint8_t tn;
|
||||
int i;
|
||||
|
||||
l1t->trx = trx;
|
||||
|
||||
LOGP(DL1C, LOGL_NOTICE, "Init scheduler for trx=%u\n", l1t->trx->nr);
|
||||
|
||||
for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
|
||||
|
@ -191,7 +193,7 @@ void trx_sched_exit(struct l1sched_trx *l1t)
|
|||
void trx_sched_reset(struct l1sched_trx *l1t)
|
||||
{
|
||||
trx_sched_exit(l1t);
|
||||
trx_sched_init(l1t);
|
||||
trx_sched_init(l1t, l1t->trx);
|
||||
}
|
||||
|
||||
struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
|
||||
|
|
194
src/common/vty.c
194
src/common/vty.c
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
|
@ -53,6 +54,13 @@
|
|||
int bts_vty_go_parent(struct vty *vty)
|
||||
{
|
||||
switch (vty->node) {
|
||||
case PHY_INST_NODE:
|
||||
vty->node = PHY_NODE;
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
vty->index = pinst->phy_link;
|
||||
}
|
||||
break;
|
||||
case TRX_NODE:
|
||||
vty->node = BTS_NODE;
|
||||
{
|
||||
|
@ -60,6 +68,7 @@ int bts_vty_go_parent(struct vty *vty)
|
|||
vty->index = trx->bts;
|
||||
}
|
||||
break;
|
||||
case PHY_NODE:
|
||||
default:
|
||||
vty->node = CONFIG_NODE;
|
||||
}
|
||||
|
@ -71,6 +80,8 @@ int bts_vty_is_config_node(struct vty *vty, int node)
|
|||
switch (node) {
|
||||
case TRX_NODE:
|
||||
case BTS_NODE:
|
||||
case PHY_NODE:
|
||||
case PHY_INST_NODE:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -81,6 +92,17 @@ gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
|
|||
"Exit current node, go down to provious node")
|
||||
{
|
||||
switch (vty->node) {
|
||||
case PHY_INST_NODE:
|
||||
vty->node = PHY_NODE;
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
vty->index = pinst->phy_link;
|
||||
}
|
||||
break;
|
||||
case PHY_NODE:
|
||||
vty->node = CONFIG_NODE;
|
||||
vty->index = NULL;
|
||||
break;
|
||||
case TRX_NODE:
|
||||
vty->node = BTS_NODE;
|
||||
{
|
||||
|
@ -141,6 +163,7 @@ static struct cmd_node trx_node = {
|
|||
1,
|
||||
};
|
||||
|
||||
|
||||
DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
||||
"trx <0-254>",
|
||||
"Select a TRX to configure\n" "TRX number\n")
|
||||
|
@ -151,7 +174,7 @@ DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
|||
|
||||
trx = gsm_bts_trx_num(bts, trx_nr);
|
||||
if (!trx) {
|
||||
vty_out(vty, "Unknown TRX %u. Aavialable TRX are: 0..%d%s",
|
||||
vty_out(vty, "Unknown TRX %u. Aavialable TRX are: 0..%u%s",
|
||||
trx_nr, bts->num_trx - 1, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
@ -232,6 +255,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
struct trx_power_params *tpp = &trx->power_params;
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
|
||||
|
||||
if (trx->power_params.user_gain_mdB)
|
||||
|
@ -246,6 +270,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||
vty_out(vty, " ms-power-control %s%s",
|
||||
trx->ms_power_control == 0 ? "dsp" : "osmo",
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num,
|
||||
pinst->num, VTY_NEWLINE);
|
||||
|
||||
bts_model_config_write_trx(vty, trx);
|
||||
}
|
||||
|
@ -262,6 +288,35 @@ static int config_write_bts(struct vty *vty)
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void config_write_phy_single(struct vty *vty, struct phy_link *plink)
|
||||
{
|
||||
int i;
|
||||
|
||||
vty_out(vty, "phy %u%s", plink->num, VTY_NEWLINE);
|
||||
bts_model_config_write_phy(vty, plink);
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
struct phy_instance *pinst = phy_instance_by_num(plink, i);
|
||||
if (!pinst)
|
||||
break;
|
||||
vty_out(vty, " instance %u%s", pinst->num, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
static int config_write_phy(struct vty *vty)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
struct phy_link *plink = phy_link_by_num(i);
|
||||
if (!plink)
|
||||
break;
|
||||
config_write_phy_single(vty, plink);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_dummy(struct vty *vty)
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
|
@ -532,6 +587,33 @@ DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_phy, cfg_trx_phy_cmd,
|
||||
"phy <0-255> instance <0-255>",
|
||||
"Configure PHY Link+Instance for this TRX\n"
|
||||
"PHY Link number\n" "PHY instance\n" "PHY Instance number")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct phy_link *plink = phy_link_by_num(atoi(argv[0]));
|
||||
struct phy_instance *pinst;
|
||||
|
||||
if (!plink) {
|
||||
vty_out(vty, "phy%s does not exist%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst = phy_instance_by_num(plink, atoi(argv[1]));
|
||||
if (!pinst) {
|
||||
vty_out(vty, "phy%s instance %s does not exit%s",
|
||||
argv[0], argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
trx->role_bts.l1h = pinst;
|
||||
pinst->trx = trx;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* SHOW
|
||||
|
@ -702,6 +784,106 @@ DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static struct cmd_node phy_node = {
|
||||
PHY_NODE,
|
||||
"%s(phy)#",
|
||||
1,
|
||||
};
|
||||
|
||||
static struct cmd_node phy_inst_node = {
|
||||
PHY_INST_NODE,
|
||||
"%s(phy-inst)#",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_phy, cfg_phy_cmd,
|
||||
"phy <0-255>",
|
||||
"Select a PHY to configure\n" "PHY number\n")
|
||||
{
|
||||
int phy_nr = atoi(argv[0]);
|
||||
struct phy_link *plink;
|
||||
|
||||
plink = phy_link_by_num(phy_nr);
|
||||
if (!plink)
|
||||
plink = phy_link_create(tall_bts_ctx, phy_nr);
|
||||
if (!plink)
|
||||
return CMD_WARNING;
|
||||
|
||||
vty->index = plink;
|
||||
vty->index_sub = &plink->description;
|
||||
vty->node = PHY_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_inst, cfg_phy_inst_cmd,
|
||||
"instance <0-255>",
|
||||
"Select a PHY instance to configure\n" "PHY Instance number\n")
|
||||
{
|
||||
int inst_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = vty->index;
|
||||
struct phy_instance *pinst;
|
||||
|
||||
pinst = phy_instance_by_num(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
pinst = phy_instance_create(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
vty_out(vty, "Unable to create phy%u instance %u%s",
|
||||
plink->num, inst_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
vty->index = pinst;
|
||||
vty->index_sub = &pinst->description;
|
||||
vty->node = PHY_INST_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_no_inst, cfg_phy_no_inst_cmd,
|
||||
"no instance <0-255>"
|
||||
NO_STR "Select a PHY instance to remove\n", "PHY Instance number\n")
|
||||
{
|
||||
int inst_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = vty->index;
|
||||
struct phy_instance *pinst;
|
||||
|
||||
pinst = phy_instance_by_num(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
vty_out(vty, "No such instance %u%s", inst_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
phy_instance_destroy(pinst);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
DEFUN(cfg_phy_type, cfg_phy_type_cmd,
|
||||
"type (sysmobts|osmo-trx|virtual)",
|
||||
"configure the type of the PHY\n"
|
||||
"sysmocom sysmoBTS PHY\n"
|
||||
"OsmoTRX based PHY\n"
|
||||
"Virtual PHY (GSMTAP based)\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Cannot change type of active PHY%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "sysmobts"))
|
||||
plink->type = PHY_LINK_T_SYSMOBTS;
|
||||
else if (!strcmp(argv[0], "osmo-trx"))
|
||||
plink->type = PHY_LINK_T_OSMOTRX;
|
||||
else if (!strcmp(argv[0], "virtual"))
|
||||
plink->type = PHY_LINK_T_VIRTUAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFUN(bts_t_t_l_jitter_buf,
|
||||
bts_t_t_l_jitter_buf_cmd,
|
||||
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>",
|
||||
|
@ -813,10 +995,20 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
|||
install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_ms_power_control_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_phy_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd);
|
||||
install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_phy_cmd);
|
||||
install_node(&phy_node, config_write_phy);
|
||||
install_default(PHY_NODE);
|
||||
install_element(PHY_NODE, &cfg_phy_inst_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_no_inst_cmd);
|
||||
|
||||
install_node(&phy_inst_node, config_write_dummy);
|
||||
install_default(PHY_INST_NODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <osmocom/core/socket.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
|
@ -109,6 +110,17 @@ osmocom_to_octphy_band(enum gsm_band osmo_band, unsigned int arfcn)
|
|||
}
|
||||
};
|
||||
|
||||
struct gsm_bts_trx *trx_by_l1h(struct octphy_hdl *fl1h, unsigned int trx_id)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
|
||||
pinst = phy_instance_by_num(fl1h->phy_link, trx_id);
|
||||
if (!pinst)
|
||||
return NULL;
|
||||
|
||||
return pinst->trx;
|
||||
}
|
||||
|
||||
struct gsm_lchan *get_lchan_by_lchid(struct gsm_bts_trx *trx,
|
||||
tOCTVC1_GSM_LOGICAL_CHANNEL_ID *lch_id)
|
||||
{
|
||||
|
@ -282,10 +294,9 @@ int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
|
|||
}
|
||||
|
||||
/* For OctPHY, this only about sending state changes to BSC */
|
||||
int l1if_activate_rf(struct octphy_hdl *fl1h, int on)
|
||||
int l1if_activate_rf(struct gsm_bts_trx *trx, int on)
|
||||
{
|
||||
int i;
|
||||
struct gsm_bts_trx *trx = fl1h->priv;
|
||||
if (on) {
|
||||
/* signal availability */
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
|
||||
|
@ -422,7 +433,8 @@ static void empty_req_from_rts_ind(tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_E
|
|||
static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
|
||||
struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *l1msg = l1p_msgb_alloc();
|
||||
uint32_t u32Fn;
|
||||
uint8_t u8Tn, subCh, sapi = 0;
|
||||
|
@ -489,7 +501,7 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
|
|||
l1if_fill_msg_hdr(&data_req->Header, l1msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID);
|
||||
|
||||
data_req->TrxId.byTrxId = trx->nr;
|
||||
data_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
data_req->LchId.byTimeslotNb = u8Tn;
|
||||
data_req->LchId.bySAPI = sapi;
|
||||
data_req->LchId.bySubChannelNb = subCh;
|
||||
|
@ -508,7 +520,7 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
|
|||
l1if_fill_msg_hdr(&empty_frame_req->Header, l1msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CID);
|
||||
|
||||
empty_frame_req->TrxId.byTrxId = trx->nr;
|
||||
empty_frame_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
empty_frame_req->LchId.byTimeslotNb = u8Tn;
|
||||
empty_frame_req->LchId.bySAPI = sapi;
|
||||
empty_frame_req->LchId.bySubChannelNb = subCh;
|
||||
|
@ -527,7 +539,8 @@ done:
|
|||
static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
|
||||
struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct gsm_lchan *lchan;
|
||||
uint32_t u32Fn;
|
||||
uint8_t u8Tn, subCh, sapi, ss;
|
||||
|
@ -565,7 +578,7 @@ static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
|
|||
l1if_fill_msg_hdr(&data_req->Header, nmsg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID);
|
||||
|
||||
data_req->TrxId.byTrxId = trx->nr;
|
||||
data_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
data_req->LchId.byTimeslotNb = u8Tn;
|
||||
data_req->LchId.bySAPI = sapi;
|
||||
data_req->LchId.bySubChannelNb = subCh;
|
||||
|
@ -590,7 +603,7 @@ static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
|
|||
l1if_fill_msg_hdr(&empty_frame_req->Header, nmsg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CID);
|
||||
|
||||
empty_frame_req->TrxId.byTrxId = trx->nr;
|
||||
empty_frame_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
empty_frame_req->LchId.byTimeslotNb = u8Tn;
|
||||
empty_frame_req->LchId.bySAPI = sapi;
|
||||
empty_frame_req->LchId.bySubChannelNb = subCh;
|
||||
|
@ -686,32 +699,78 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int trx_close_all_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *car =
|
||||
(tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *) resp->l2h;
|
||||
|
||||
/* in a completion call-back, we take msgb ownership and must
|
||||
* release it before returning */
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP_SWAP(car);
|
||||
|
||||
/* we now know that the PHY link is connected */
|
||||
phy_link_state_set(fl1->phy_link, PHY_LINK_CONNECTED);
|
||||
|
||||
msgb_free(resp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int phy_link_trx_close_all(struct phy_link *plink)
|
||||
{
|
||||
struct octphy_hdl *fl1h = plink->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *cac;
|
||||
|
||||
cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *)
|
||||
msgb_put(msg, sizeof(*cac));
|
||||
l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CID);
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD_SWAP(cac);
|
||||
|
||||
return l1if_req_compl(fl1h, msg, trx_close_all_cb, NULL);
|
||||
}
|
||||
|
||||
int bts_model_phy_link_open(struct phy_link *plink)
|
||||
{
|
||||
if (plink->u.octphy.hdl)
|
||||
l1if_close(plink->u.octphy.hdl);
|
||||
|
||||
phy_link_state_set(plink, PHY_LINK_CONNECTING);
|
||||
|
||||
plink->u.octphy.hdl = l1if_open(plink);
|
||||
if (!plink->u.octphy.hdl) {
|
||||
phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* do we need to iterate over the list of instances and do some
|
||||
* instance-specific initialization? */
|
||||
|
||||
/* close all TRXs that might still exist in this link from
|
||||
* previous execitions / sessions */
|
||||
phy_link_trx_close_all(plink);
|
||||
|
||||
/* in the call-back to the above we will set the link state to
|
||||
* connected */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb;
|
||||
struct octphy_hdl *fl1h;
|
||||
|
||||
LOGP(DL1C, LOGL_NOTICE, "model_init()\n");
|
||||
|
||||
btsb = bts_role_bts(bts);
|
||||
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
|
||||
|
||||
fl1h = talloc_zero(bts, struct octphy_hdl);
|
||||
if (!fl1h)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LLIST_HEAD(&fl1h->wlc_list);
|
||||
INIT_LLIST_HEAD(&fl1h->wlc_postponed);
|
||||
fl1h->priv = bts->c0;
|
||||
bts->c0->role_bts.l1h = fl1h;
|
||||
/* FIXME: what is the nominal transmit power of the PHY/board? */
|
||||
bts->c0->nominal_power = 15;
|
||||
|
||||
/* configure some reasonable defaults, to be overridden by VTY */
|
||||
fl1h->config.rf_port_index = 0;
|
||||
fl1h->config.rx_gain_db = 70;
|
||||
fl1h->config.tx_atten_db = 0;
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
return 0;
|
||||
|
@ -750,24 +809,16 @@ static void dump_meas_res(int ll, tOCTVC1_GSM_MEASUREMENT_INFO * m)
|
|||
|
||||
static int handle_mph_time_ind(struct octphy_hdl *fl1, uint8_t trx_id, uint32_t fn)
|
||||
{
|
||||
struct gsm_bts_trx *trx = fl1->priv;
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct gsm_bts_trx *trx = trx_by_l1h(fl1, trx_id);
|
||||
struct osmo_phsap_prim l1sap;
|
||||
|
||||
/* increment the primitive count for the alive timer */
|
||||
fl1->alive_prim_cnt++;
|
||||
|
||||
/* ignore every time indication, except for c0 */
|
||||
if (trx != bts->c0)
|
||||
if (trx != trx->bts->c0)
|
||||
return 0;
|
||||
|
||||
if (trx_id != trx->nr) {
|
||||
LOGP(DL1C, LOGL_FATAL,
|
||||
"TRX id %d from response does not match the L1 context trx %d\n",
|
||||
trx_id, trx->nr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&l1sap, 0, sizeof(l1sap));
|
||||
osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO,
|
||||
PRIM_OP_INDICATION, NULL);
|
||||
|
@ -783,7 +834,7 @@ static int handle_ph_readytosend_ind(struct octphy_hdl *fl1,
|
|||
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *evt,
|
||||
struct msgb *l1p_msg)
|
||||
{
|
||||
struct gsm_bts_trx *trx = fl1->priv;
|
||||
struct gsm_bts_trx *trx = trx_by_l1h(fl1, evt->TrxId.byTrxId);
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
struct gsm_time g_time;
|
||||
|
@ -908,7 +959,7 @@ static int handle_ph_data_ind(struct octphy_hdl *fl1,
|
|||
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *data_ind,
|
||||
struct msgb *l1p_msg)
|
||||
{
|
||||
struct gsm_bts_trx *trx = fl1->priv;
|
||||
struct gsm_bts_trx *trx = trx_by_l1h(fl1, data_ind->TrxId.byTrxId);
|
||||
uint8_t chan_nr, link_id;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
uint32_t fn;
|
||||
|
@ -992,7 +1043,7 @@ static int handle_ph_rach_ind(struct octphy_hdl *fl1,
|
|||
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EVT *ra_ind,
|
||||
struct msgb *l1p_msg)
|
||||
{
|
||||
struct gsm_bts_trx *trx = fl1->priv;
|
||||
struct gsm_bts_trx *trx = trx_by_l1h(fl1, ra_ind->TrxId.byTrxId);
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct gsm_lchan *lchan;
|
||||
|
@ -1131,7 +1182,7 @@ static int rx_octvc1_resp(struct msgb *msg, uint32_t msg_id, uint32_t trans_id)
|
|||
if (wlc->cb) {
|
||||
/* call-back function must take msgb
|
||||
* ownership. */
|
||||
rc = wlc->cb(fl1h->priv, msg, wlc->cb_data);
|
||||
rc = wlc->cb(fl1h, msg, wlc->cb_data);
|
||||
} else {
|
||||
rc = 0;
|
||||
msgb_free(msg);
|
||||
|
@ -1485,6 +1536,18 @@ static int rx_octphy_msg(struct msgb *msg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void bts_model_phy_link_set_defaults(struct phy_link *plink)
|
||||
{
|
||||
/* configure some reasonable defaults, to be overridden by VTY */
|
||||
plink->u.octphy.rf_port_index = 0;
|
||||
plink->u.octphy.rx_gain_db = 70;
|
||||
plink->u.octphy.tx_atten_db = 0;
|
||||
}
|
||||
|
||||
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
|
||||
{
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* octphy socket / main loop integration
|
||||
***********************************************************************/
|
||||
|
@ -1534,15 +1597,25 @@ static int octphy_write_cb(struct osmo_fd *fd, struct msgb *msg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int l1if_open(struct octphy_hdl *fl1h)
|
||||
struct octphy_hdl *l1if_open(struct phy_link *plink)
|
||||
{
|
||||
struct octphy_hdl *fl1h;
|
||||
struct ifreq ifr;
|
||||
int sfd, rc;
|
||||
char *phy_dev = fl1h->netdev_name;
|
||||
char *phy_dev = plink->u.octphy.netdev_name;
|
||||
|
||||
fl1h = talloc_zero(plink, struct octphy_hdl);
|
||||
if (!fl1h)
|
||||
return NULL;
|
||||
|
||||
INIT_LLIST_HEAD(&fl1h->wlc_list);
|
||||
INIT_LLIST_HEAD(&fl1h->wlc_postponed);
|
||||
fl1h->phy_link = plink;
|
||||
|
||||
if (!phy_dev) {
|
||||
LOGP(DL1C, LOGL_ERROR, "You have to specify a phy-netdev\n");
|
||||
return -EINVAL;
|
||||
talloc_free(fl1h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOGP(DL1C, LOGL_NOTICE, "Opening L1 interface for OctPHY (%s)\n",
|
||||
|
@ -1553,7 +1626,8 @@ int l1if_open(struct octphy_hdl *fl1h)
|
|||
if (sfd < 0) {
|
||||
LOGP(DL1C, LOGL_FATAL, "Error opening PHY socket: %s\n",
|
||||
strerror(errno));
|
||||
return -EIO;
|
||||
talloc_free(fl1h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* resolve the string device name to an ifindex */
|
||||
|
@ -1564,18 +1638,21 @@ int l1if_open(struct octphy_hdl *fl1h)
|
|||
LOGP(DL1C, LOGL_FATAL, "Error using network device %s: %s\n",
|
||||
phy_dev, strerror(errno));
|
||||
close(sfd);
|
||||
return -EIO;
|
||||
talloc_free(fl1h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fl1h->session_id = rand();
|
||||
|
||||
/* set fl1h->phy_addr, which we use as sendto() destionation */
|
||||
/* set fl1h->phy_addr, which we use as sendto() destination */
|
||||
fl1h->phy_addr.sll_family = AF_PACKET;
|
||||
fl1h->phy_addr.sll_protocol = htons(cOCTPKT_HDR_ETHERTYPE);
|
||||
fl1h->phy_addr.sll_ifindex = ifr.ifr_ifindex;
|
||||
fl1h->phy_addr.sll_hatype = ARPHRD_ETHER;
|
||||
fl1h->phy_addr.sll_halen = 6;
|
||||
/* sll_addr is filled by bts_model_vty code */
|
||||
fl1h->phy_addr.sll_halen = ETH_ALEN;
|
||||
/* plink->phy_addr.sll_addr is filled by bts_model_vty code */
|
||||
memcpy(fl1h->phy_addr.sll_addr, plink->u.octphy.phy_addr.sll_addr,
|
||||
ETH_ALEN);
|
||||
|
||||
/* Write queue / osmo_fd registration */
|
||||
osmo_wqueue_init(&fl1h->phy_wq, 10);
|
||||
|
@ -1588,10 +1665,11 @@ int l1if_open(struct octphy_hdl *fl1h)
|
|||
rc = osmo_fd_register(&fl1h->phy_wq.bfd);
|
||||
if (rc < 0) {
|
||||
close(sfd);
|
||||
return -EIO;
|
||||
talloc_free(fl1h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return fl1h;
|
||||
}
|
||||
|
||||
int l1if_close(struct octphy_hdl *fl1h)
|
||||
|
|
|
@ -13,16 +13,16 @@
|
|||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
|
||||
#include <octphy/octvc1/gsm/octvc1_gsm_api.h>
|
||||
|
||||
struct octphy_hdl {
|
||||
/* MAC address of the PHY */
|
||||
struct sockaddr_ll phy_addr;
|
||||
|
||||
/* packet socket to talk with PHY */
|
||||
struct osmo_wqueue phy_wq;
|
||||
/* MAC address of th PHY */
|
||||
struct sockaddr_ll phy_addr;
|
||||
/* Network device name */
|
||||
char *netdev_name;
|
||||
|
||||
/* address parameters of the PHY */
|
||||
uint32_t session_id;
|
||||
|
@ -32,12 +32,6 @@ struct octphy_hdl {
|
|||
/* clock manager state */
|
||||
uint32_t clkmgr_state;
|
||||
|
||||
struct {
|
||||
uint32_t rf_port_index;
|
||||
uint32_t rx_gain_db;
|
||||
uint32_t tx_atten_db;
|
||||
} config;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
char *name;
|
||||
|
@ -72,8 +66,8 @@ struct octphy_hdl {
|
|||
struct llist_head wlc_postponed;
|
||||
int wlc_postponed_len;
|
||||
|
||||
/* private pointer, points back to TRX */
|
||||
void *priv;
|
||||
/* back pointer to the PHY link */
|
||||
struct phy_link *phy_link;
|
||||
|
||||
struct osmo_timer_list alive_timer;
|
||||
uint32_t alive_prim_cnt;
|
||||
|
@ -82,15 +76,10 @@ struct octphy_hdl {
|
|||
int opened;
|
||||
};
|
||||
|
||||
static inline struct octphy_hdl *trx_octphy_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
void l1if_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, struct msgb *msg,
|
||||
struct octphy_hdl *fl1h, uint32_t msg_type, uint32_t api_cmd);
|
||||
|
||||
typedef int l1if_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, void *data);
|
||||
typedef int l1if_compl_cb(struct octphy_hdl *fl1, struct msgb *l1_msg, void *data);
|
||||
|
||||
/* send a request primitive to the L1 and schedule completion call-back */
|
||||
int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
|
||||
|
@ -100,19 +89,21 @@ int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
|
|||
struct gsm_lchan *get_lchan_by_lchid(struct gsm_bts_trx *trx,
|
||||
tOCTVC1_GSM_LOGICAL_CHANNEL_ID *lch_id);
|
||||
|
||||
int l1if_open(struct octphy_hdl *fl1h);
|
||||
struct octphy_hdl *l1if_open(struct phy_link *plink);
|
||||
int l1if_close(struct octphy_hdl *hdl);
|
||||
|
||||
int l1if_trx_open(struct gsm_bts_trx *trx);
|
||||
int l1if_trx_close_all(struct gsm_bts *bts);
|
||||
int l1if_enable_events(struct gsm_bts_trx *trx);
|
||||
|
||||
int l1if_activate_rf(struct octphy_hdl *fl1h, int on);
|
||||
int l1if_activate_rf(struct gsm_bts_trx *trx, int on);
|
||||
|
||||
int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *
|
||||
data_ind);
|
||||
|
||||
struct gsm_bts_trx *trx_by_l1h(struct octphy_hdl *fl1h, unsigned int trx_id);
|
||||
|
||||
struct msgb *l1p_msgb_alloc(void);
|
||||
|
||||
/* tch.c */
|
||||
|
|
|
@ -348,10 +348,11 @@ static void sapi_clear_queue(struct llist_head *queue)
|
|||
}
|
||||
}
|
||||
|
||||
static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int lchan_act_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP *ar =
|
||||
(tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP *) resp->l2h;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_lchan *lchan;
|
||||
uint8_t sapi;
|
||||
uint8_t direction;
|
||||
|
@ -361,7 +362,7 @@ static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *
|
|||
* release it before returning */
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP_SWAP(ar);
|
||||
OSMO_ASSERT(ar->TrxId.byTrxId == trx->nr);
|
||||
trx = trx_by_l1h(fl1, ar->TrxId.byTrxId);
|
||||
|
||||
lchan = get_lchan_by_lchid(trx, &ar->LchId);
|
||||
sapi = ar->LchId.bySAPI;
|
||||
|
@ -411,7 +412,8 @@ err:
|
|||
|
||||
static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CMD *lac;
|
||||
|
||||
|
@ -420,7 +422,7 @@ static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
|
|||
l1if_fill_msg_hdr(&lac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CID);
|
||||
|
||||
lac->TrxId.byTrxId = lchan->ts->trx->nr;
|
||||
lac->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
lac->LchId.byTimeslotNb = lchan->ts->nr;
|
||||
lac->LchId.bySubChannelNb = lchan_to_GsmL1_SubCh_t(lchan);
|
||||
lac->LchId.bySAPI = cmd->sapi;
|
||||
|
@ -451,10 +453,11 @@ static tOCTVC1_GSM_CIPHERING_ID_ENUM rsl2l1_ciph[] = {
|
|||
[4] = cOCTVC1_GSM_CIPHERING_ID_ENUM_A5_3
|
||||
};
|
||||
|
||||
static int set_ciph_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int set_ciph_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP *pcr =
|
||||
(tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP *) resp->l2h;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
|
@ -470,6 +473,7 @@ static int set_ciph_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
trx = trx_by_l1h(fl1, pcr->TrxId.byTrxId);
|
||||
OSMO_ASSERT(pcr->TrxId.byTrxId == trx->nr);
|
||||
ts = &trx->ts[pcr->PchId.byTimeslotNb];
|
||||
/* for some strange reason the response does not tell which
|
||||
|
@ -508,8 +512,8 @@ err:
|
|||
|
||||
static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
|
||||
{
|
||||
struct gsm_bts_trx *trx = lchan->ts->trx;
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CMD *pcc;
|
||||
|
||||
|
@ -518,6 +522,7 @@ static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *c
|
|||
l1if_fill_msg_hdr(&pcc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CID);
|
||||
|
||||
pcc->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
pcc->PchId.byTimeslotNb = lchan->ts->nr;
|
||||
pcc->ulSubchannelNb = lchan_to_GsmL1_SubCh_t(lchan);
|
||||
pcc->ulDirection = cmd->dir;
|
||||
|
@ -627,7 +632,8 @@ static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir)
|
|||
|
||||
static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
|
||||
int i, res;
|
||||
|
||||
|
@ -654,10 +660,11 @@ static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int lchan_deact_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP *ldr =
|
||||
(tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP *) resp->l2h;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_lchan *lchan;
|
||||
struct sapi_cmd *cmd;
|
||||
uint8_t status;
|
||||
|
@ -666,7 +673,7 @@ static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void
|
|||
* release it before returning */
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP_SWAP(ldr);
|
||||
OSMO_ASSERT(ldr->TrxId.byTrxId == trx->nr);
|
||||
trx = trx_by_l1h(fl1, ldr->TrxId.byTrxId);
|
||||
|
||||
lchan = get_lchan_by_lchid(trx, &ldr->LchId);
|
||||
|
||||
|
@ -725,7 +732,8 @@ err:
|
|||
|
||||
static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CMD *ldc;
|
||||
|
||||
|
@ -734,6 +742,7 @@ static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd
|
|||
l1if_fill_msg_hdr(&ldc->Header, msg, fl1h,cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CID);
|
||||
|
||||
ldc->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
ldc->LchId.byTimeslotNb = lchan->ts->nr;
|
||||
ldc->LchId.bySubChannelNb = lchan_to_GsmL1_SubCh_t(lchan);
|
||||
ldc->LchId.byDirection = cmd->dir;
|
||||
|
@ -1031,7 +1040,8 @@ static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir)
|
|||
|
||||
int lchan_activate(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
|
||||
unsigned int i;
|
||||
|
||||
|
@ -1069,7 +1079,7 @@ int l1if_rsl_chan_act(struct gsm_lchan *lchan)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int enable_events_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int enable_events_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_MAIN_MSG_API_SYSTEM_MODIFY_SESSION_EVT_RSP *mser =
|
||||
(tOCTVC1_MAIN_MSG_API_SYSTEM_MODIFY_SESSION_EVT_RSP *) resp->l2h;
|
||||
|
@ -1088,7 +1098,8 @@ static int enable_events_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, vo
|
|||
|
||||
int l1if_enable_events(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_MAIN_MSG_API_SYSTEM_MODIFY_SESSION_EVT_CMD *mse;
|
||||
|
||||
|
@ -1112,9 +1123,8 @@ int l1if_enable_events(struct gsm_bts_trx *trx)
|
|||
dst = talloc_strdup(ctx, (const char *) src); \
|
||||
} while (0)
|
||||
|
||||
static int app_info_sys_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int app_info_sys_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data)
|
||||
{
|
||||
struct octphy_hdl *fl1h = resp->dst;
|
||||
tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP *aisr =
|
||||
(tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP *) resp->l2h;
|
||||
|
||||
|
@ -1136,7 +1146,8 @@ static int app_info_sys_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, voi
|
|||
|
||||
int l1if_check_app_sys_version(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CMD *ais;
|
||||
|
||||
|
@ -1152,9 +1163,8 @@ int l1if_check_app_sys_version(struct gsm_bts_trx *trx)
|
|||
return l1if_req_compl(fl1h, msg, app_info_sys_compl_cb, 0);
|
||||
}
|
||||
|
||||
static int app_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int app_info_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data)
|
||||
{
|
||||
struct octphy_hdl *fl1h = resp->dst;
|
||||
tOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP *air =
|
||||
(tOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP *) resp->l2h;
|
||||
|
||||
|
@ -1178,7 +1188,8 @@ static int app_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
|
|||
|
||||
int l1if_check_app_version(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_MAIN_MSG_APPLICATION_INFO_CMD *ai;
|
||||
|
||||
|
@ -1193,9 +1204,50 @@ int l1if_check_app_version(struct gsm_bts_trx *trx)
|
|||
return l1if_req_compl(fl1h, msg, app_info_compl_cb, 0);
|
||||
}
|
||||
|
||||
/* call-back once the TRX_OPEN_CID response arrives */
|
||||
static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int trx_close_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_GSM_MSG_TRX_CLOSE_RSP *car =
|
||||
(tOCTVC1_GSM_MSG_TRX_CLOSE_RSP *) resp->l2h;
|
||||
|
||||
/* in a completion call-back, we take msgb ownership and must
|
||||
* release it before returning */
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_CLOSE_RSP_SWAP(car);
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "Rx TRX-CLOSE.conf(%u)\n", car->TrxId.byTrxId);
|
||||
|
||||
msgb_free(resp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trx_close(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
struct octphy_hdl *fl1h = plink->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_CLOSE_CMD *cac;
|
||||
|
||||
cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_CMD *)
|
||||
msgb_put(msg, sizeof(*cac));
|
||||
l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_CLOSE_CID);
|
||||
|
||||
cac->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "Tx TRX-CLOSE.req(%u)\n", cac->TrxId.byTrxId);
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_CLOSE_CMD_SWAP(cac);
|
||||
|
||||
return l1if_req_compl(fl1h, msg, trx_close_cb, NULL);
|
||||
}
|
||||
|
||||
/* call-back once the TRX_OPEN_CID response arrives */
|
||||
static int trx_open_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
tOCTVC1_GSM_MSG_TRX_OPEN_RSP *or =
|
||||
(tOCTVC1_GSM_MSG_TRX_OPEN_RSP *) resp->l2h;
|
||||
|
||||
|
@ -1203,8 +1255,7 @@ static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
|
|||
* release it before returning */
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_OPEN_RSP_SWAP(or);
|
||||
|
||||
OSMO_ASSERT(or->TrxId.byTrxId == trx->nr);
|
||||
trx = trx_by_l1h(fl1h, or->TrxId.byTrxId);
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "TRX-OPEN.resp(trx=%u) = %s\n",
|
||||
trx->nr, octvc1_rc2string(or->Header.ulReturnCode));
|
||||
|
@ -1221,7 +1272,6 @@ static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
|
|||
|
||||
opstart_compl(&trx->mo);
|
||||
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
octphy_hw_get_pcb_info(fl1h);
|
||||
octphy_hw_get_rf_port_info(fl1h, 0);
|
||||
octphy_hw_get_rf_ant_rx_config(fl1h, 0, 0);
|
||||
|
@ -1238,22 +1288,24 @@ static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
|
|||
int l1if_trx_open(struct gsm_bts_trx *trx)
|
||||
{
|
||||
/* putting it all together */
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_OPEN_CMD *oc;
|
||||
|
||||
oc = (tOCTVC1_GSM_MSG_TRX_OPEN_CMD *) msgb_put(msg, sizeof(*oc));
|
||||
l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_OPEN_CID);
|
||||
oc->ulRfPortIndex = fl1h->config.rf_port_index;
|
||||
oc->TrxId.byTrxId = trx->nr;
|
||||
oc->ulRfPortIndex = plink->u.octphy.rf_port_index;
|
||||
oc->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
oc->Config.ulBand = osmocom_to_octphy_band(trx->bts->band, trx->arfcn);
|
||||
oc->Config.usArfcn = trx->arfcn;
|
||||
oc->Config.usTsc = trx->bts->bsic & 0x7;
|
||||
oc->Config.usBcchArfcn = trx->bts->c0->arfcn;
|
||||
oc->RfConfig.ulRxGainDb = fl1h->config.rx_gain_db;
|
||||
oc->RfConfig.ulRxGainDb = plink->u.octphy.rx_gain_db;
|
||||
/* FIXME: compute this based on nominal transmit power, etc. */
|
||||
oc->RfConfig.ulTxAttndB = fl1h->config.tx_atten_db;
|
||||
oc->RfConfig.ulTxAttndB = plink->u.octphy.tx_atten_db;
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "Tx TRX-OPEN.req(trx=%u, rf_port=%u, arfcn=%u, "
|
||||
"tsc=%u, rx_gain=%u, tx_atten=%u)\n",
|
||||
|
@ -1266,38 +1318,6 @@ int l1if_trx_open(struct gsm_bts_trx *trx)
|
|||
return l1if_req_compl(fl1h, msg, trx_open_compl_cb, NULL);
|
||||
}
|
||||
|
||||
static int trx_close_all_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *car =
|
||||
(tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *) resp->l2h;
|
||||
|
||||
/* in a completion call-back, we take msgb ownership and must
|
||||
* release it before returning */
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP_SWAP(car);
|
||||
|
||||
msgb_free(resp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l1if_trx_close_all(struct gsm_bts *bts)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(bts->c0);
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *cac;
|
||||
|
||||
cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *)
|
||||
msgb_put(msg, sizeof(*cac));
|
||||
l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CID);
|
||||
|
||||
mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD_SWAP(cac);
|
||||
|
||||
return l1if_req_compl(fl1h, msg, trx_close_all_cb, NULL);
|
||||
}
|
||||
|
||||
|
||||
uint32_t trx_get_hlayer1(struct gsm_bts_trx * trx)
|
||||
{
|
||||
return 0;
|
||||
|
@ -1313,8 +1333,6 @@ static int trx_init(struct gsm_bts_trx *trx)
|
|||
/* return oml_mo_opstart_nack(&trx->mo, NM_NACK_CANT_PERFORM); */
|
||||
}
|
||||
|
||||
l1if_trx_close_all(trx->bts);
|
||||
|
||||
l1if_check_app_version(trx);
|
||||
l1if_check_app_sys_version(trx);
|
||||
|
||||
|
@ -1325,11 +1343,12 @@ static int trx_init(struct gsm_bts_trx *trx)
|
|||
* PHYSICAL CHANNE ACTIVATION
|
||||
***********************************************************************/
|
||||
|
||||
static int pchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int pchan_act_compl_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;
|
||||
struct gsm_abis_mo *mo;
|
||||
|
||||
|
@ -1337,9 +1356,8 @@ static int pchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *
|
|||
* 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(ar->TrxId.byTrxId == trx->nr);
|
||||
OSMO_ASSERT(ts_nr <= ARRAY_SIZE(trx->ts));
|
||||
|
||||
ts = &trx->ts[ts_nr];
|
||||
|
@ -1367,7 +1385,8 @@ static int pchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *
|
|||
|
||||
static int ts_connect(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(ts->trx);
|
||||
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;
|
||||
|
@ -1376,7 +1395,7 @@ static int ts_connect(struct gsm_bts_trx_ts *ts)
|
|||
l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
|
||||
cOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CID);
|
||||
|
||||
oc->TrxId.byTrxId = ts->trx->nr;
|
||||
oc->TrxId.byTrxId = pinst->u.octphy.trx_id;
|
||||
oc->PchId.byTimeslotNb = ts->nr;
|
||||
oc->ulChannelType = pchan_to_logChComb[ts->pchan];
|
||||
|
||||
|
@ -1430,8 +1449,7 @@ int bts_model_oml_estab(struct gsm_bts *bts)
|
|||
int i;
|
||||
for (i = 0; i < bts->num_trx; i++) {
|
||||
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, i);
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
l1if_activate_rf(fl1h, 1);
|
||||
l1if_activate_rf(trx, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1447,14 +1465,13 @@ int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
|||
|
||||
int bts_model_trx_deact_rf(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct octphy_hdl *fl1 = trx_octphy_hdl(trx);
|
||||
return l1if_activate_rf(fl1, 0);
|
||||
return l1if_activate_rf(trx, 0);
|
||||
}
|
||||
|
||||
int bts_model_trx_close(struct gsm_bts_trx *trx)
|
||||
{
|
||||
/* FIXME: close only one TRX */
|
||||
return l1if_trx_close_all(trx->bts);
|
||||
return trx_close(trx);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,10 +52,9 @@
|
|||
|
||||
extern int pcu_direct;
|
||||
|
||||
static struct gsm_bts *bts;
|
||||
|
||||
int bts_model_print_help()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_model_handle_options(int argc, char **argv)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <octphy/octvc1/hw/octvc1_hw_api_swap.h>
|
||||
|
||||
/* Chapter 12.1 */
|
||||
static int get_pcb_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
static int get_pcb_info_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_PCB_INFO_RSP *pir =
|
||||
(tOCTVC1_HW_MSG_PCB_INFO_RSP *) resp->l2h;
|
||||
|
@ -69,7 +69,7 @@ int octphy_hw_get_pcb_info(struct octphy_hdl *fl1h)
|
|||
}
|
||||
|
||||
/* Chapter 12.9 */
|
||||
static int rf_port_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
static int rf_port_info_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
|
||||
void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_RF_PORT_INFO_RSP *pir =
|
||||
|
@ -114,7 +114,7 @@ static const struct value_string radio_std_vals[] = {
|
|||
};
|
||||
|
||||
/* Chapter 12.10 */
|
||||
static int rf_port_stats_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
static int rf_port_stats_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
|
||||
void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_RF_PORT_STATS_RSP *psr =
|
||||
|
@ -167,7 +167,7 @@ static const struct value_string rx_gain_mode_vals[] = {
|
|||
};
|
||||
|
||||
/* Chapter 12.13 */
|
||||
static int rf_ant_rx_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
static int rf_ant_rx_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
|
||||
void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP *arc =
|
||||
|
@ -209,7 +209,7 @@ int octphy_hw_get_rf_ant_rx_config(struct octphy_hdl *fl1h, uint32_t port_idx,
|
|||
}
|
||||
|
||||
/* Chapter 12.14 */
|
||||
static int rf_ant_tx_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
static int rf_ant_tx_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
|
||||
void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP *atc =
|
||||
|
@ -292,7 +292,7 @@ static const struct value_string clocksync_state_vals[] = {
|
|||
};
|
||||
|
||||
/* Chapter 12.15 */
|
||||
static int get_clock_sync_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
static int get_clock_sync_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
|
||||
void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP *cir =
|
||||
|
@ -326,7 +326,7 @@ int octphy_hw_get_clock_sync_info(struct octphy_hdl *fl1h)
|
|||
}
|
||||
|
||||
/* Chapter 12.16 */
|
||||
static int get_clock_sync_stats_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
static int get_clock_sync_stats_cb(struct octphy_hdl *fl1, struct msgb *resp,
|
||||
void *data)
|
||||
{
|
||||
tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP *csr =
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <osmocom/vty/misc.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/vty.h>
|
||||
|
||||
|
@ -51,149 +52,189 @@
|
|||
SHOW_STR \
|
||||
TRX_STR
|
||||
|
||||
#define OCT_STR "OCTPHY Um interface\n"
|
||||
|
||||
static struct gsm_bts *vty_bts;
|
||||
|
||||
/* configuration */
|
||||
|
||||
DEFUN(cfg_bts_phy_hwaddr, cfg_bts_phy_hwaddr_cmd,
|
||||
"phy-hw-addr HWADDR",
|
||||
"Configure the hardware addess of the OCTPHY\n"
|
||||
DEFUN(cfg_phy_hwaddr, cfg_phy_hwaddr_cmd,
|
||||
"octphy hw-addr HWADDR",
|
||||
OCT_STR "Configure the hardware addess of the OCTPHY\n"
|
||||
"hardware address in aa:bb:cc:dd:ee:ff format\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_trx *trx = bts->c0;
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
int rc;
|
||||
|
||||
rc = osmo_macaddr_parse(fl1h->phy_addr.sll_addr, argv[0]);
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Can only reconfigure a PHY link that is down%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
rc = osmo_macaddr_parse(plink->u.octphy.phy_addr.sll_addr, argv[0]);
|
||||
if (rc < 0)
|
||||
return CMD_WARNING;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_phy_netdev, cfg_bts_phy_netdev_cmd,
|
||||
"phy-netdev NAME",
|
||||
"Configure the hardware device towards the OCTPHY\n"
|
||||
DEFUN(cfg_phy_netdev, cfg_phy_netdev_cmd,
|
||||
"octphy net-device NAME",
|
||||
OCT_STR "Configure the hardware device towards the OCTPHY\n"
|
||||
"Ethernet device name\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_trx *trx = bts->c0;
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
if (fl1h->netdev_name)
|
||||
talloc_free(fl1h->netdev_name);
|
||||
fl1h->netdev_name = talloc_strdup(fl1h, argv[0]);
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Can only reconfigure a PHY link that is down%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (plink->u.octphy.netdev_name)
|
||||
talloc_free(plink->u.octphy.netdev_name);
|
||||
plink->u.octphy.netdev_name = talloc_strdup(plink, argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_rf_port_idx, cfg_trx_rf_port_idx_cmd,
|
||||
"rf-port-index <0-255>",
|
||||
"Configure the RF Port for this TRX\n"
|
||||
DEFUN(cfg_phy_rf_port_idx, cfg_phy_rf_port_idx_cmd,
|
||||
"octphy rf-port-index <0-255>",
|
||||
OCT_STR "Configure the RF Port for this TRX\n"
|
||||
"RF Port Index\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
fl1h->config.rf_port_index = atoi(argv[0]);
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Can only reconfigure a PHY link that is down%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
plink->u.octphy.rf_port_index = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_rx_gain_db, cfg_trx_rx_gain_db_cmd,
|
||||
"rx-gain <0-73>",
|
||||
"Configure the Rx Gain in dB\n"
|
||||
DEFUN(cfg_phy_rx_gain_db, cfg_phy_rx_gain_db_cmd,
|
||||
"octphy rx-gain <0-73>",
|
||||
OCT_STR "Configure the Rx Gain in dB\n"
|
||||
"Rx gain in dB\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
fl1h->config.rx_gain_db = atoi(argv[0]);
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Can only reconfigure a PHY link that is down%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
plink->u.octphy.rx_gain_db = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_tx_atten_db, cfg_trx_tx_atten_db_cmd,
|
||||
"tx-attenuation <0-359>",
|
||||
"Configure the Tx Attenuation in quarter-dB\n"
|
||||
DEFUN(cfg_phy_tx_atten_db, cfg_phy_tx_atten_db_cmd,
|
||||
"octphy tx-attenuation <0-359>",
|
||||
OCT_STR "Configure the Tx Attenuation in quarter-dB\n"
|
||||
"Tx attenuation in quarter-dB\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
fl1h->config.tx_atten_db = atoi(argv[0]);
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Can only reconfigure a PHY link that is down%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
plink->u.octphy.tx_atten_db = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(get_rf_port_stats, get_rf_port_stats_cmd,
|
||||
"get-rf-port-stats <0-1>",
|
||||
"Obtain statistics for the RF Port\n"
|
||||
DEFUN(show_rf_port_stats, show_rf_port_stats_cmd,
|
||||
"show phy <0-255> rf-port-stats <0-1>",
|
||||
"Show statistics for the RF Port\n"
|
||||
"RF Port Number\n")
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(vty_bts->c0);
|
||||
int phy_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = phy_link_by_num(phy_nr);
|
||||
|
||||
octphy_hw_get_rf_port_stats(fl1h, atoi(argv[0]));
|
||||
octphy_hw_get_rf_port_stats(plink->u.octphy.hdl, atoi(argv[1]));
|
||||
|
||||
/* FIXME: Actually print to VTY, not just log */
|
||||
vty_out(vty, "Please check the log file for the response%s",
|
||||
VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(get_clk_sync_stats, get_clk_sync_stats_cmd,
|
||||
"get-clk-sync-stats",
|
||||
DEFUN(show_clk_sync_stats, show_clk_sync_stats_cmd,
|
||||
"show phy <0-255> clk-sync-stats",
|
||||
"Obtain statistics for the Clock Sync Manager\n")
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(vty_bts->c0);
|
||||
int phy_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = phy_link_by_num(phy_nr);
|
||||
|
||||
octphy_hw_get_clock_sync_stats(fl1h);
|
||||
octphy_hw_get_clock_sync_stats(plink->u.octphy.hdl);
|
||||
|
||||
/* FIXME: Actually print to VTY, not just log */
|
||||
vty_out(vty, "Please check the log file for the response%s",
|
||||
VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink)
|
||||
{
|
||||
if (plink->u.octphy.netdev_name)
|
||||
vty_out(vty, " netdev %s%s", plink->u.octphy.netdev_name,
|
||||
VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " hw-addr %02x:%02x:%02x:%02x:%02x:%02x%s",
|
||||
plink->u.octphy.phy_addr.sll_addr[0],
|
||||
plink->u.octphy.phy_addr.sll_addr[1],
|
||||
plink->u.octphy.phy_addr.sll_addr[2],
|
||||
plink->u.octphy.phy_addr.sll_addr[3],
|
||||
plink->u.octphy.phy_addr.sll_addr[4],
|
||||
plink->u.octphy.phy_addr.sll_addr[5],
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " rx-gain %u%s", plink->u.octphy.rx_gain_db,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " tx-attenuation %u%s", plink->u.octphy.tx_atten_db,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " rf-port-index %u%s", plink->u.octphy.rf_port_index,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(bts->c0);
|
||||
|
||||
if (fl1h->netdev_name)
|
||||
vty_out(vty, " phy-netdev %s%s", fl1h->netdev_name,
|
||||
VTY_NEWLINE);
|
||||
|
||||
if (btsb->auto_band)
|
||||
vty_out(vty, " auto-band%s", VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " phy-hw-addr %02x:%02x:%02x:%02x:%02x:%02x%s",
|
||||
fl1h->phy_addr.sll_addr[0], fl1h->phy_addr.sll_addr[1],
|
||||
fl1h->phy_addr.sll_addr[2], fl1h->phy_addr.sll_addr[3],
|
||||
fl1h->phy_addr.sll_addr[4], fl1h->phy_addr.sll_addr[5],
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
|
||||
|
||||
vty_out(vty, " rx-gain %u%s", fl1h->config.rx_gain_db,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " tx-attenuation %u%s", fl1h->config.tx_atten_db,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
DEFUN(show_sys_info, show_sys_info_cmd,
|
||||
"show trx <0-255> system-information",
|
||||
"show phy <0-255> system-information",
|
||||
SHOW_TRX_STR "Display information about system\n")
|
||||
{
|
||||
int trx_nr = atoi(argv[0]);
|
||||
struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
|
||||
int phy_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = phy_link_by_num(phy_nr);
|
||||
struct octphy_hdl *fl1h;
|
||||
int i;
|
||||
|
||||
if (!trx) {
|
||||
vty_out(vty, "Cannot find TRX number %u%s",
|
||||
trx_nr, VTY_NEWLINE);
|
||||
if (!plink) {
|
||||
vty_out(vty, "Cannot find PHY number %u%s",
|
||||
phy_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
fl1h = trx_octphy_hdl(trx);
|
||||
fl1h = plink->u.octphy.hdl;
|
||||
|
||||
vty_out(vty, "System Platform: '%s', Version: '%s'%s",
|
||||
fl1h->info.system.platform, fl1h->info.system.version,
|
||||
|
@ -210,15 +251,14 @@ int bts_model_vty_init(struct gsm_bts *bts)
|
|||
{
|
||||
vty_bts = bts;
|
||||
|
||||
install_element(BTS_NODE, &cfg_bts_phy_hwaddr_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_phy_netdev_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_hwaddr_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_netdev_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_rf_port_idx_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_rx_gain_db_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_tx_atten_db_cmd);
|
||||
|
||||
install_element(TRX_NODE, &cfg_trx_rf_port_idx_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_rx_gain_db_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_tx_atten_db_cmd);
|
||||
|
||||
install_element_ve(&get_rf_port_stats_cmd);
|
||||
install_element_ve(&get_clk_sync_stats_cmd);
|
||||
install_element_ve(&show_rf_port_stats_cmd);
|
||||
install_element_ve(&show_clk_sync_stats_cmd);
|
||||
install_element_ve(&show_sys_info_cmd);
|
||||
|
||||
return 0;
|
||||
|
@ -226,13 +266,5 @@ int bts_model_vty_init(struct gsm_bts *bts)
|
|||
|
||||
int bts_model_ctrl_cmds_install(struct gsm_bts *bts)
|
||||
{
|
||||
/* FIXME: really ugly hack: We can only initialize the L1 intrface
|
||||
* after reading the config file, and this is the only call-back after
|
||||
* vty_read_config_fioe() at this point. Will be cleaned up with the
|
||||
* phy interface generalization patches coming up soon as part of the
|
||||
* multi-trx work */
|
||||
struct octphy_hdl *fl1h = bts->c0->role_bts.l1h;
|
||||
l1if_open(fl1h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ static const uint8_t transceiver_chan_types[_GSM_PCHAN_MAX] = {
|
|||
* create/destroy trx l1 instance
|
||||
*/
|
||||
|
||||
struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
|
||||
struct trx_l1h *l1if_open(struct phy_instance *pinst)
|
||||
{
|
||||
struct trx_l1h *l1h;
|
||||
int rc;
|
||||
|
@ -67,11 +67,9 @@ struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
|
|||
l1h = talloc_zero(tall_bts_ctx, struct trx_l1h);
|
||||
if (!l1h)
|
||||
return NULL;
|
||||
l1h->trx = trx;
|
||||
l1h->l1s.trx = trx;
|
||||
trx->role_bts.l1h = l1h;
|
||||
l1h->phy_inst = pinst;
|
||||
|
||||
trx_sched_init(&l1h->l1s);
|
||||
trx_sched_init(&l1h->l1s, pinst->trx);
|
||||
|
||||
rc = trx_if_open(l1h);
|
||||
if (rc < 0) {
|
||||
|
@ -83,7 +81,6 @@ struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
|
|||
|
||||
err:
|
||||
l1if_close(l1h);
|
||||
trx->role_bts.l1h = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -100,7 +97,8 @@ void l1if_reset(struct trx_l1h *l1h)
|
|||
|
||||
static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail)
|
||||
{
|
||||
struct gsm_bts_trx *trx = l1h->trx;
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
struct gsm_bts_trx *trx = pinst->trx;
|
||||
uint8_t tn;
|
||||
|
||||
/* HACK, we should change state when we receive first clock from
|
||||
|
@ -132,10 +130,10 @@ static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail)
|
|||
int check_transceiver_availability(struct gsm_bts *bts, int avail)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct trx_l1h *l1h;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
check_transceiver_availability_trx(l1h, avail);
|
||||
}
|
||||
return 0;
|
||||
|
@ -147,6 +145,7 @@ int check_transceiver_availability(struct gsm_bts *bts, int avail)
|
|||
*/
|
||||
int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
|
||||
{
|
||||
struct phy_link *plink = l1h->phy_inst->phy_link;
|
||||
uint8_t tn;
|
||||
|
||||
if (!transceiver_available)
|
||||
|
@ -177,18 +176,23 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
|
|||
}
|
||||
|
||||
/* after power on */
|
||||
if (l1h->config.rxgain_valid && !l1h->config.rxgain_sent) {
|
||||
trx_if_cmd_setrxgain(l1h, l1h->config.rxgain);
|
||||
l1h->config.rxgain_sent = 1;
|
||||
}
|
||||
if (l1h->config.power_valid && !l1h->config.power_sent) {
|
||||
trx_if_cmd_setpower(l1h, l1h->config.power);
|
||||
l1h->config.power_sent = 1;
|
||||
if (l1h->phy_inst->num == 0) {
|
||||
if (plink->u.osmotrx.rxgain_valid &&
|
||||
!plink->u.osmotrx.rxgain_sent) {
|
||||
trx_if_cmd_setrxgain(l1h, plink->u.osmotrx.rxgain);
|
||||
plink->u.osmotrx.rxgain_sent = 1;
|
||||
}
|
||||
if (plink->u.osmotrx.power_valid &&
|
||||
!plink->u.osmotrx.power_sent) {
|
||||
trx_if_cmd_setpower(l1h, plink->u.osmotrx.power);
|
||||
plink->u.osmotrx.power_sent = 1;
|
||||
}
|
||||
}
|
||||
if (l1h->config.maxdly_valid && !l1h->config.maxdly_sent) {
|
||||
trx_if_cmd_setmaxdly(l1h, l1h->config.maxdly);
|
||||
l1h->config.maxdly_sent = 1;
|
||||
}
|
||||
|
||||
for (tn = 0; tn < TRX_NR_TS; tn++) {
|
||||
if (l1h->config.slottype_valid[tn]
|
||||
&& !l1h->config.slottype_sent[tn]) {
|
||||
|
@ -203,8 +207,10 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
|
|||
if (!l1h->config.poweron && !l1h->config.poweron_sent) {
|
||||
trx_if_cmd_poweroff(l1h);
|
||||
l1h->config.poweron_sent = 1;
|
||||
l1h->config.rxgain_sent = 0;
|
||||
l1h->config.power_sent = 0;
|
||||
if (l1h->phy_inst->num == 0) {
|
||||
plink->u.osmotrx.rxgain_sent = 0;
|
||||
plink->u.osmotrx.power_sent = 0;
|
||||
}
|
||||
l1h->config.maxdly_sent = 0;
|
||||
for (tn = 0; tn < TRX_NR_TS; tn++)
|
||||
l1h->config.slottype_sent[tn] = 0;
|
||||
|
@ -216,17 +222,20 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
|
|||
int l1if_provision_transceiver(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct trx_l1h *l1h;
|
||||
uint8_t tn;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
l1h->config.arfcn_sent = 0;
|
||||
l1h->config.tsc_sent = 0;
|
||||
l1h->config.bsic_sent = 0;
|
||||
l1h->config.poweron_sent = 0;
|
||||
l1h->config.rxgain_sent = 0;
|
||||
l1h->config.power_sent = 0;
|
||||
if (l1h->phy_inst->num == 0) {
|
||||
plink->u.osmotrx.rxgain_sent = 0;
|
||||
plink->u.osmotrx.power_sent = 0;
|
||||
}
|
||||
l1h->config.maxdly_sent = 0;
|
||||
for (tn = 0; tn < TRX_NR_TS; tn++)
|
||||
l1h->config.slottype_sent[tn] = 0;
|
||||
|
@ -242,7 +251,8 @@ int l1if_provision_transceiver(struct gsm_bts *bts)
|
|||
/* initialize the layer1 */
|
||||
static int trx_init(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
|
||||
/* power on transceiver, if not already */
|
||||
if (!l1h->config.poweron) {
|
||||
|
@ -264,7 +274,8 @@ static int trx_init(struct gsm_bts_trx *trx)
|
|||
/* deactivate transceiver */
|
||||
int bts_model_trx_close(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
enum gsm_phys_chan_config pchan = trx->ts[0].pchan;
|
||||
|
||||
/* close all logical channels and reset timeslots */
|
||||
|
@ -308,7 +319,6 @@ int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan)
|
|||
static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct trx_l1h *l1h;
|
||||
uint8_t bsic = bts->bsic;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
|
@ -318,7 +328,8 @@ static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr)
|
|||
}
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
if (l1h->config.bsic != bsic || !l1h->config.bsic_valid) {
|
||||
l1h->config.bsic = bsic;
|
||||
l1h->config.bsic_valid = 1;
|
||||
|
@ -335,7 +346,9 @@ static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr)
|
|||
/* set trx attributes */
|
||||
static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
uint16_t arfcn = trx->arfcn;
|
||||
|
||||
if (l1h->config.arfcn != arfcn || !l1h->config.arfcn_valid) {
|
||||
|
@ -345,10 +358,10 @@ static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
|
|||
l1if_provision_transceiver_trx(l1h);
|
||||
}
|
||||
|
||||
if (l1h->config.power_oml) {
|
||||
l1h->config.power = trx->max_power_red;
|
||||
l1h->config.power_valid = 1;
|
||||
l1h->config.power_sent = 0;
|
||||
if (plink->u.osmotrx.power_oml && pinst->num == 0) {
|
||||
plink->u.osmotrx.power = trx->max_power_red;
|
||||
plink->u.osmotrx.power_valid = 1;
|
||||
plink->u.osmotrx.power_sent = 0;
|
||||
l1if_provision_transceiver_trx(l1h);
|
||||
}
|
||||
|
||||
|
@ -358,7 +371,8 @@ static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
|
|||
/* set ts attributes */
|
||||
static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(ts->trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(ts->trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
uint8_t tn = ts->nr;
|
||||
uint16_t tsc = ts->tsc;
|
||||
enum gsm_phys_chan_config pchan = ts->pchan;
|
||||
|
@ -439,6 +453,7 @@ static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
enum osmo_mph_info_type type, uint8_t cause)
|
||||
{
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
struct osmo_phsap_prim l1sap;
|
||||
|
||||
memset(&l1sap, 0, sizeof(l1sap));
|
||||
|
@ -448,7 +463,7 @@ static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr,
|
|||
l1sap.u.info.u.act_cnf.chan_nr = chan_nr;
|
||||
l1sap.u.info.u.act_cnf.cause = cause;
|
||||
|
||||
return l1sap_up(l1h->trx, &l1sap);
|
||||
return l1sap_up(pinst->trx, &l1sap);
|
||||
}
|
||||
|
||||
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn)
|
||||
|
@ -503,7 +518,8 @@ int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint
|
|||
/* primitive from common part */
|
||||
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
struct msgb *msg = l1sap->oph.msg;
|
||||
uint8_t chan_nr;
|
||||
uint8_t tn, ss;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define L1_IF_H_TRX
|
||||
|
||||
#include <osmo-bts/scheduler.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
|
||||
struct trx_config {
|
||||
uint8_t poweron; /* poweron(1) or poweroff(0) */
|
||||
|
@ -19,15 +20,6 @@ struct trx_config {
|
|||
uint8_t bsic;
|
||||
int bsic_sent;
|
||||
|
||||
int rxgain_valid;
|
||||
int rxgain;
|
||||
int rxgain_sent;
|
||||
|
||||
int power_valid;
|
||||
int power;
|
||||
int power_oml;
|
||||
int power_sent;
|
||||
|
||||
int maxdly_valid;
|
||||
int maxdly;
|
||||
int maxdly_sent;
|
||||
|
@ -42,7 +34,8 @@ struct trx_config {
|
|||
struct trx_l1h {
|
||||
struct llist_head trx_ctrl_list;
|
||||
|
||||
struct gsm_bts_trx *trx;
|
||||
//struct gsm_bts_trx *trx;
|
||||
struct phy_instance *phy_inst;
|
||||
|
||||
struct osmo_fd trx_ofd_ctrl;
|
||||
struct osmo_timer_list trx_ctrl_timer;
|
||||
|
@ -55,7 +48,7 @@ struct trx_l1h {
|
|||
struct l1sched_trx l1s;
|
||||
};
|
||||
|
||||
struct trx_l1h *l1if_open(struct gsm_bts_trx *trx);
|
||||
struct trx_l1h *l1if_open(struct phy_instance *pinst);
|
||||
void l1if_close(struct trx_l1h *l1h);
|
||||
void l1if_reset(struct trx_l1h *l1h);
|
||||
int check_transceiver_availability(struct gsm_bts *bts, int avail);
|
||||
|
@ -69,7 +62,8 @@ int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint
|
|||
|
||||
static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx->role_bts.l1h;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
return &l1h->l1s;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <osmocom/core/bits.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
@ -58,43 +59,6 @@
|
|||
#include "l1_if.h"
|
||||
#include "trx_if.h"
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts)
|
||||
{
|
||||
void *l1h;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2);
|
||||
if (!settsc_enabled && !setbsic_enabled)
|
||||
settsc_enabled = setbsic_enabled = 1;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
l1h = l1if_open(trx);
|
||||
if (!l1h) {
|
||||
LOGP(DL1C, LOGL_FATAL, "Cannot open L1 Interface\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
trx->role_bts.l1h = l1h;
|
||||
trx->nominal_power = 23;
|
||||
|
||||
l1if_reset(l1h);
|
||||
}
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
l1h = trx->role_bts.l1h;
|
||||
if (l1h)
|
||||
l1if_close(l1h);
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* dummy, since no direct dsp support */
|
||||
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
|
||||
{
|
||||
|
@ -103,10 +67,6 @@ uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
|
|||
|
||||
void bts_model_print_help()
|
||||
{
|
||||
printf(
|
||||
" -I --local-trx-ip Local IP for transceiver to connect (default=%s)\n"
|
||||
, transceiver_ip
|
||||
);
|
||||
}
|
||||
|
||||
int bts_model_handle_options(int argc, char **argv)
|
||||
|
@ -116,21 +76,16 @@ int bts_model_handle_options(int argc, char **argv)
|
|||
while (1) {
|
||||
int option_idx = 0, c;
|
||||
static const struct option long_options[] = {
|
||||
/* specific to this hardware */
|
||||
{ "local-trx-ip", 1, 0, 'I' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "I:",
|
||||
c = getopt_long(argc, argv, "",
|
||||
long_options, &option_idx);
|
||||
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'I':
|
||||
transceiver_ip = strdup(optarg);
|
||||
break;
|
||||
default:
|
||||
num_errors++;
|
||||
break;
|
||||
|
@ -140,6 +95,35 @@ int bts_model_handle_options(int argc, char **argv)
|
|||
return num_errors;
|
||||
}
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2);
|
||||
|
||||
/* FIXME: this needs to be overridden with the real hardrware
|
||||
* value */
|
||||
bts->c0->nominal_power = 23;
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bts_model_phy_link_set_defaults(struct phy_link *plink)
|
||||
{
|
||||
plink->u.osmotrx.transceiver_ip = talloc_strdup(plink, "127.0.0.1");
|
||||
plink->u.osmotrx.base_port_local = 5800;
|
||||
plink->u.osmotrx.base_port_remote = 5700;
|
||||
plink->u.osmotrx.clock_advance = 20;
|
||||
plink->u.osmotrx.rts_advance = 5;
|
||||
plink->u.osmotrx.power_oml = 1;
|
||||
}
|
||||
|
||||
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return bts_main(argc, argv);
|
||||
|
|
|
@ -55,12 +55,6 @@ uint32_t transceiver_last_fn;
|
|||
static struct timeval transceiver_clock_tv;
|
||||
static struct osmo_timer_list transceiver_clock_timer;
|
||||
|
||||
/* clock advance for the transceiver */
|
||||
uint32_t trx_clock_advance = 20;
|
||||
|
||||
/* advance RTS to give some time for data processing. (especially PCU) */
|
||||
uint32_t trx_rts_advance = 5; /* about 20ms */
|
||||
|
||||
/* Enable this to multiply TOA of RACH by 10.
|
||||
* This is usefull to check tenth of timing advances with RSSI test tool.
|
||||
* Note that regular phones will not work when using this test! */
|
||||
|
@ -1262,14 +1256,16 @@ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
|
|||
/* send time indication */
|
||||
l1if_mph_time_ind(bts, fn);
|
||||
|
||||
/* advance frame number, so the transceiver has more time until
|
||||
* it must be transmitted. */
|
||||
fn = (fn + trx_clock_advance) % GSM_HYPERFRAME;
|
||||
|
||||
/* process every TRX */
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct l1sched_trx *l1t = trx_l1sched_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
struct l1sched_trx *l1t = &l1h->l1s;
|
||||
|
||||
/* advance frame number, so the transceiver has more
|
||||
* time until it must be transmitted. */
|
||||
fn = (fn + plink->u.osmotrx.clock_advance) % GSM_HYPERFRAME;
|
||||
|
||||
/* we don't schedule, if power is off */
|
||||
if (!trx_if_powered(l1h))
|
||||
|
@ -1279,7 +1275,7 @@ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
|
|||
for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
|
||||
/* ready-to-send */
|
||||
_sched_rts(l1t, tn,
|
||||
(fn + trx_rts_advance) % GSM_HYPERFRAME);
|
||||
(fn + plink->u.osmotrx.rts_advance) % GSM_HYPERFRAME);
|
||||
/* get burst for FN */
|
||||
bits = _sched_dl_burst(l1t, tn, fn);
|
||||
if (!bits) {
|
||||
|
@ -1323,10 +1319,12 @@ no_clock:
|
|||
/* flush pending messages of transceiver */
|
||||
/* close all logical channels and reset timeslots */
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
trx_if_flush(trx_l1h_hdl(trx));
|
||||
trx_sched_reset(trx_l1sched_hdl(trx));
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
trx_if_flush(l1h);
|
||||
trx_sched_reset(&l1h->l1s);
|
||||
if (trx->nr == 0)
|
||||
trx_if_cmd_poweroff(trx_l1h_hdl(trx));
|
||||
trx_if_cmd_poweroff(l1h);
|
||||
}
|
||||
|
||||
/* tell BSC */
|
||||
|
@ -1461,7 +1459,8 @@ new_clock:
|
|||
|
||||
void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(l1t->trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(l1t->trx);
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
|
||||
if (activate)
|
||||
trx_if_cmd_handover(l1h, tn, ss);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* OpenBTS TRX interface handling
|
||||
*
|
||||
* Copyright (C) 2013 Andreas Eversberg <jolly@eversberg.eu>
|
||||
* Copyright (C) 2016 Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
|
@ -34,6 +35,7 @@
|
|||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/bits.h>
|
||||
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
@ -45,7 +47,6 @@
|
|||
//#define TOA_RSSI_DEBUG
|
||||
|
||||
int transceiver_available = 0;
|
||||
const char *transceiver_ip = "127.0.0.1";
|
||||
int settsc_enabled = 0;
|
||||
int setbsic_enabled = 0;
|
||||
|
||||
|
@ -53,11 +54,10 @@ int setbsic_enabled = 0;
|
|||
* socket
|
||||
*/
|
||||
|
||||
static uint16_t base_port_local = 5800;
|
||||
|
||||
/* open socket */
|
||||
static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
|
||||
int (*cb)(struct osmo_fd *fd, unsigned int what))
|
||||
static int trx_udp_open(void *priv, struct osmo_fd *ofd, const char *host,
|
||||
uint16_t port_local, uint16_t port_remote,
|
||||
int (*cb)(struct osmo_fd *fd, unsigned int what))
|
||||
{
|
||||
struct sockaddr_storage sas;
|
||||
struct sockaddr *sa = (struct sockaddr *)&sas;
|
||||
|
@ -71,8 +71,8 @@ static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
|
|||
ofd->data = priv;
|
||||
|
||||
/* Listen / Binds */
|
||||
rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, 0, transceiver_ip,
|
||||
port, OSMO_SOCK_F_BIND);
|
||||
rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, 0, host,
|
||||
port_local, OSMO_SOCK_F_BIND);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
|
@ -84,10 +84,10 @@ static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
|
|||
|
||||
if (sa->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
sin->sin_port = htons(ntohs(sin->sin_port) - 100);
|
||||
sin->sin_port = htons(port_remote);
|
||||
} else if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6->sin6_port = htons(ntohs(sin6->sin6_port) - 100);
|
||||
sin6->sin6_port = htons(port_remote);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -115,13 +114,11 @@ static void trx_udp_close(struct osmo_fd *ofd)
|
|||
* clock
|
||||
*/
|
||||
|
||||
static struct osmo_fd trx_ofd_clk;
|
||||
|
||||
|
||||
/* get clock from clock socket */
|
||||
static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
|
||||
{
|
||||
struct trx_l1h *l1h = ofd->data;
|
||||
struct phy_link *plink = ofd->data;
|
||||
struct phy_instance *pinst = phy_instance_by_num(plink, 0);
|
||||
char buf[1500];
|
||||
int len;
|
||||
uint32_t fn;
|
||||
|
@ -146,7 +143,7 @@ static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
|
|||
"correctly, correcting to fn=%u\n", fn);
|
||||
}
|
||||
|
||||
trx_sched_clock(l1h->trx->bts, fn);
|
||||
trx_sched_clock(pinst->trx->bts, fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -168,8 +165,8 @@ static void trx_ctrl_send(struct trx_l1h *l1h)
|
|||
return;
|
||||
tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, list);
|
||||
|
||||
LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to trx=%u\n", tcm->cmd,
|
||||
l1h->trx->nr);
|
||||
LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to %s\n", tcm->cmd,
|
||||
phy_instance_name(l1h->phy_inst));
|
||||
/* send command */
|
||||
send(l1h->trx_ofd_ctrl.fd, tcm->cmd, strlen(tcm->cmd)+1, 0);
|
||||
|
||||
|
@ -184,8 +181,8 @@ static void trx_ctrl_timer_cb(void *data)
|
|||
{
|
||||
struct trx_l1h *l1h = data;
|
||||
|
||||
LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for trx=%d\n",
|
||||
l1h->trx->nr);
|
||||
LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for %s\n",
|
||||
phy_instance_name(l1h->phy_inst));
|
||||
|
||||
trx_ctrl_send(l1h);
|
||||
}
|
||||
|
@ -232,7 +229,8 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
|
|||
|
||||
int trx_if_cmd_poweroff(struct trx_l1h *l1h)
|
||||
{
|
||||
if (l1h->trx->nr == 0)
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
if (pinst->num == 0)
|
||||
return trx_ctrl_cmd(l1h, 1, "POWEROFF", "");
|
||||
else
|
||||
return 0;
|
||||
|
@ -240,7 +238,8 @@ int trx_if_cmd_poweroff(struct trx_l1h *l1h)
|
|||
|
||||
int trx_if_cmd_poweron(struct trx_l1h *l1h)
|
||||
{
|
||||
if (l1h->trx->nr == 0)
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
if (pinst->num == 0)
|
||||
return trx_ctrl_cmd(l1h, 1, "POWERON", "");
|
||||
else
|
||||
return 0;
|
||||
|
@ -324,6 +323,7 @@ int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
|
|||
static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
|
||||
{
|
||||
struct trx_l1h *l1h = ofd->data;
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
char buf[1500];
|
||||
int len, resp;
|
||||
|
||||
|
@ -374,11 +374,12 @@ static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
|
|||
sscanf(p + 1, "%d", &resp);
|
||||
if (resp) {
|
||||
LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE,
|
||||
"transceiver (trx=%d) rejected TRX command "
|
||||
"with response: '%s'\n", l1h->trx->nr, buf);
|
||||
"transceiver (%s) rejected TRX command "
|
||||
"with response: '%s'\n",
|
||||
phy_instance_name(pinst), buf);
|
||||
rsp_error:
|
||||
if (tcm->critical) {
|
||||
bts_shutdown(l1h->trx->bts, "SIGINT");
|
||||
bts_shutdown(pinst->trx->bts, "SIGINT");
|
||||
/* keep tcm list, so process is stopped */
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -493,37 +494,91 @@ int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
|
|||
* open/close
|
||||
*/
|
||||
|
||||
int trx_if_open(struct trx_l1h *l1h)
|
||||
int bts_model_phy_link_open(struct phy_link *plink)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
int rc;
|
||||
|
||||
LOGP(DTRX, LOGL_NOTICE, "Open transceiver for trx=%u\n", l1h->trx->nr);
|
||||
phy_link_state_set(plink, PHY_LINK_CONNECTING);
|
||||
|
||||
/* open the shared/common clock socket */
|
||||
rc = trx_udp_open(plink, &plink->u.osmotrx.trx_ofd_clk,
|
||||
plink->u.osmotrx.transceiver_ip,
|
||||
plink->u.osmotrx.base_port_local,
|
||||
plink->u.osmotrx.base_port_remote,
|
||||
trx_clk_read_cb);
|
||||
if (rc < 0) {
|
||||
phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* open the individual instances with their ctrl+data sockets */
|
||||
llist_for_each_entry(pinst, &plink->instances, list) {
|
||||
pinst->u.osmotrx.hdl = l1if_open(pinst);
|
||||
if (!pinst->u.osmotrx.hdl)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
|
||||
llist_for_each_entry(pinst, &plink->instances, list) {
|
||||
if (pinst->u.osmotrx.hdl) {
|
||||
trx_if_close(pinst->u.osmotrx.hdl);
|
||||
pinst->u.osmotrx.hdl = NULL;
|
||||
}
|
||||
}
|
||||
trx_udp_close(&plink->u.osmotrx.trx_ofd_clk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint16_t compute_port(struct phy_instance *pinst, int remote, int is_data)
|
||||
{
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
uint16_t inc = 1;
|
||||
|
||||
if (is_data)
|
||||
inc = 2;
|
||||
|
||||
if (remote)
|
||||
return plink->u.osmotrx.base_port_remote + (pinst->num << 1) + inc;
|
||||
else
|
||||
return plink->u.osmotrx.base_port_local + (pinst->num << 1) + inc;
|
||||
}
|
||||
|
||||
int trx_if_open(struct trx_l1h *l1h)
|
||||
{
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
struct phy_link *plink = pinst->phy_link;
|
||||
int rc;
|
||||
|
||||
LOGP(DTRX, LOGL_NOTICE, "Open transceiver for %s\n",
|
||||
phy_instance_name(pinst));
|
||||
|
||||
/* initialize ctrl queue */
|
||||
INIT_LLIST_HEAD(&l1h->trx_ctrl_list);
|
||||
|
||||
/* open sockets */
|
||||
if (l1h->trx->nr == 0) {
|
||||
rc = trx_udp_open(l1h, &trx_ofd_clk, base_port_local,
|
||||
trx_clk_read_cb);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
LOGP(DTRX, LOGL_NOTICE, "Waiting for transceiver send clock\n");
|
||||
}
|
||||
rc = trx_udp_open(l1h, &l1h->trx_ofd_ctrl,
|
||||
base_port_local + (l1h->trx->nr << 1) + 1, trx_ctrl_read_cb);
|
||||
plink->u.osmotrx.transceiver_ip,
|
||||
compute_port(pinst, 0, 0),
|
||||
compute_port(pinst, 1, 0), trx_ctrl_read_cb);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
rc = trx_udp_open(l1h, &l1h->trx_ofd_data,
|
||||
base_port_local + (l1h->trx->nr << 1) + 2, trx_data_read_cb);
|
||||
plink->u.osmotrx.transceiver_ip,
|
||||
compute_port(pinst, 0, 1),
|
||||
compute_port(pinst, 1, 1), trx_data_read_cb);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
/* enable all slots */
|
||||
l1h->config.slotmask = 0xff;
|
||||
|
||||
if (l1h->trx->nr == 0)
|
||||
trx_if_cmd_poweroff(l1h);
|
||||
/* FIXME: why was this only for TRX0 ? */
|
||||
//if (l1h->trx->nr == 0)
|
||||
trx_if_cmd_poweroff(l1h);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -548,13 +603,13 @@ void trx_if_flush(struct trx_l1h *l1h)
|
|||
|
||||
void trx_if_close(struct trx_l1h *l1h)
|
||||
{
|
||||
LOGP(DTRX, LOGL_NOTICE, "Close transceiver for trx=%u\n", l1h->trx->nr);
|
||||
struct phy_instance *pinst = l1h->phy_inst;
|
||||
LOGP(DTRX, LOGL_NOTICE, "Close transceiver for %s\n",
|
||||
phy_instance_name(pinst));
|
||||
|
||||
trx_if_flush(l1h);
|
||||
|
||||
/* close sockets */
|
||||
if (l1h->trx->nr == 0)
|
||||
trx_udp_close(&trx_ofd_clk);
|
||||
trx_udp_close(&l1h->trx_ofd_ctrl);
|
||||
trx_udp_close(&l1h->trx_ofd_data);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ extern const char *transceiver_ip;
|
|||
extern int settsc_enabled;
|
||||
extern int setbsic_enabled;
|
||||
|
||||
struct trx_l1h;
|
||||
|
||||
struct trx_ctrl_msg {
|
||||
struct llist_head list;
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "trx_if.h"
|
||||
#include "loops.h"
|
||||
|
||||
#define OSMOTRX_STR "OsmoTRX Transceiver configuration\n"
|
||||
|
||||
static struct gsm_bts *vty_bts;
|
||||
|
||||
DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
|
||||
|
@ -53,7 +55,6 @@ DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
|
|||
struct gsm_bts *bts = vty_bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct trx_l1h *l1h;
|
||||
uint8_t tn;
|
||||
|
||||
if (!transceiver_available) {
|
||||
vty_out(vty, "transceiver is not connected%s", VTY_NEWLINE);
|
||||
|
@ -63,7 +64,8 @@ DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
|
|||
}
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
l1h = pinst->u.osmotrx.hdl;
|
||||
vty_out(vty, "TRX %d%s", trx->nr, VTY_NEWLINE);
|
||||
vty_out(vty, " %s%s",
|
||||
(l1h->config.poweron) ? "poweron":"poweroff",
|
||||
|
@ -85,56 +87,70 @@ DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
|
|||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " bisc : undefined%s", VTY_NEWLINE);
|
||||
if (l1h->config.rxgain_valid)
|
||||
vty_out(vty, " rxgain : %d%s", l1h->config.rxgain,
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " rxgain : undefined%s", VTY_NEWLINE);
|
||||
if (l1h->config.power_valid)
|
||||
vty_out(vty, " power : %d%s", l1h->config.power,
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " power : undefined%s", VTY_NEWLINE);
|
||||
if (l1h->config.maxdly_valid)
|
||||
vty_out(vty, " maxdly : %d%s", l1h->config.maxdly,
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " maxdly : undefined%s", VTY_NEWLINE);
|
||||
for (tn = 0; tn < TRX_NR_TS; tn++) {
|
||||
if (!((1 << tn) & l1h->config.slotmask))
|
||||
vty_out(vty, " slot #%d: unsupported%s", tn,
|
||||
VTY_NEWLINE);
|
||||
else if (l1h->config.slottype_valid[tn])
|
||||
vty_out(vty, " slot #%d: type %d%s", tn,
|
||||
l1h->config.slottype[tn],
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " slot #%d: undefined%s", tn,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_fn_advance, cfg_bts_fn_advance_cmd,
|
||||
"fn-advance <0-30>",
|
||||
"Set the number of frames to be transmitted to transceiver in advance "
|
||||
"of current FN\n"
|
||||
"Advance in frames\n")
|
||||
{
|
||||
trx_clock_advance = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
static void show_phy_inst_single(struct vty *vty, struct phy_instance *pinst)
|
||||
{
|
||||
uint8_t tn;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
|
||||
vty_out(vty, "PHY Instance %s%s",
|
||||
phy_instance_name(pinst), VTY_NEWLINE);
|
||||
if (l1h->config.maxdly_valid)
|
||||
vty_out(vty, " maxdly : %d%s", l1h->config.maxdly,
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " maxdly : undefined%s", VTY_NEWLINE);
|
||||
for (tn = 0; tn < TRX_NR_TS; tn++) {
|
||||
if (!((1 << tn) & l1h->config.slotmask))
|
||||
vty_out(vty, " slot #%d: unsupported%s", tn,
|
||||
VTY_NEWLINE);
|
||||
else if (l1h->config.slottype_valid[tn])
|
||||
vty_out(vty, " slot #%d: type %d%s", tn,
|
||||
l1h->config.slottype[tn],
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " slot #%d: undefined%s", tn,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_rts_advance, cfg_bts_rts_advance_cmd,
|
||||
"rts-advance <0-30>",
|
||||
"Set the number of frames to be requested (PCU) in advance of current "
|
||||
"FN. Do not change this, unless you have a good reason!\n"
|
||||
"Advance in frames\n")
|
||||
static void show_phy_single(struct vty *vty, struct phy_link *plink)
|
||||
{
|
||||
trx_rts_advance = atoi(argv[0]);
|
||||
struct phy_instance *pinst;
|
||||
|
||||
vty_out(vty, "PHY %u%s", plink->num, VTY_NEWLINE);
|
||||
|
||||
if (plink->u.osmotrx.rxgain_valid)
|
||||
vty_out(vty, " rx-gain : %d dB%s",
|
||||
plink->u.osmotrx.rxgain, VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " rx-gain : undefined%s", VTY_NEWLINE);
|
||||
if (plink->u.osmotrx.power_valid)
|
||||
vty_out(vty, " tx-attenuation : %d dB%s",
|
||||
plink->u.osmotrx.power, VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " tx-attenuation : undefined%s", VTY_NEWLINE);
|
||||
|
||||
llist_for_each_entry(pinst, &plink->instances, list)
|
||||
show_phy_inst_single(vty, pinst);
|
||||
}
|
||||
|
||||
DEFUN(show_phy, show_phy_cmd, "show phy",
|
||||
SHOW_STR "Display information about the available PHYs")
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
struct phy_link *plink = phy_link_by_num(i);
|
||||
if (!plink)
|
||||
break;
|
||||
show_phy_single(vty, plink);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
@ -220,63 +236,14 @@ DEFUN(cfg_bts_no_setbsic, cfg_bts_no_setbsic_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_rxgain, cfg_trx_rxgain_cmd,
|
||||
"rxgain <0-50>",
|
||||
"Set the receiver gain in dB\n"
|
||||
"Gain in dB\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
|
||||
l1h->config.rxgain = atoi(argv[0]);
|
||||
l1h->config.rxgain_valid = 1;
|
||||
l1h->config.rxgain_sent = 0;
|
||||
l1if_provision_transceiver_trx(l1h);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_power, cfg_trx_power_cmd,
|
||||
"power <0-50>",
|
||||
"Set the transmitter power dampening\n"
|
||||
"Power dampening in dB\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
|
||||
l1h->config.power = atoi(argv[0]);
|
||||
l1h->config.power_oml = 0;
|
||||
l1h->config.power_valid = 1;
|
||||
l1h->config.power_sent = 0;
|
||||
l1if_provision_transceiver_trx(l1h);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_poweroml_, cfg_trx_power_oml_cmd,
|
||||
"power oml",
|
||||
"Set the transmitter power dampening\n"
|
||||
"Given by NM_ATT_RF_MAXPOWR_R (max power reduction) via OML\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
|
||||
l1h->config.power = trx->max_power_red;
|
||||
l1h->config.power_oml = 1;
|
||||
l1h->config.power_valid = 1;
|
||||
l1h->config.power_sent = 0;
|
||||
l1if_provision_transceiver_trx(l1h);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_maxdly, cfg_trx_maxdly_cmd,
|
||||
"maxdly <0-31>",
|
||||
DEFUN(cfg_phyinst_maxdly, cfg_phyinst_maxdly_cmd,
|
||||
"osmotrx maxdly <0-31>",
|
||||
"Set the maximum delay of GSM symbols\n"
|
||||
"GSM symbols (approx. 1.1km per symbol)\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = vty->index;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
|
||||
l1h->config.maxdly = atoi(argv[0]);
|
||||
l1h->config.maxdly_valid = 1;
|
||||
|
@ -286,7 +253,7 @@ DEFUN(cfg_trx_maxdly, cfg_trx_maxdly_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_slotmask, cfg_trx_slotmask_cmd,
|
||||
DEFUN(cfg_phyinst_slotmask, cfg_phyinst_slotmask_cmd,
|
||||
"slotmask (1|0) (1|0) (1|0) (1|0) (1|0) (1|0) (1|0) (1|0)",
|
||||
"Set the supported slots\n"
|
||||
"TS0 supported\nTS0 unsupported\nTS1 supported\nTS1 unsupported\n"
|
||||
|
@ -294,8 +261,8 @@ DEFUN(cfg_trx_slotmask, cfg_trx_slotmask_cmd,
|
|||
"TS4 supported\nTS4 unsupported\nTS5 supported\nTS5 unsupported\n"
|
||||
"TS6 supported\nTS6 unsupported\nTS7 supported\nTS7 unsupported\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_instance *pinst = vty->index;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
uint8_t tn;
|
||||
|
||||
l1h->config.slotmask = 0;
|
||||
|
@ -306,76 +273,171 @@ DEFUN(cfg_trx_slotmask, cfg_trx_slotmask_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_no_rxgain, cfg_trx_no_rxgain_cmd,
|
||||
"no rxgain <0-50>",
|
||||
NO_STR "Unset the receiver gain in dB\n"
|
||||
|
||||
DEFUN(cfg_phy_fn_advance, cfg_phy_fn_advance_cmd,
|
||||
"osmotrx fn-advance <0-30>",
|
||||
OSMOTRX_STR
|
||||
"Set the number of frames to be transmitted to transceiver in advance "
|
||||
"of current FN\n"
|
||||
"Advance in frames\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.clock_advance = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_rts_advance, cfg_phy_rts_advance_cmd,
|
||||
"osmotrx rts-advance <0-30>",
|
||||
OSMOTRX_STR
|
||||
"Set the number of frames to be requested (PCU) in advance of current "
|
||||
"FN. Do not change this, unless you have a good reason!\n"
|
||||
"Advance in frames\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.rts_advance = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_rxgain, cfg_phy_rxgain_cmd,
|
||||
"osmotrx rx-gain <0-50>",
|
||||
OSMOTRX_STR
|
||||
"Set the receiver gain in dB\n"
|
||||
"Gain in dB\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
l1h->config.rxgain_valid = 0;
|
||||
plink->u.osmotrx.rxgain = atoi(argv[0]);
|
||||
plink->u.osmotrx.rxgain_valid = 1;
|
||||
plink->u.osmotrx.rxgain_sent = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_no_power, cfg_trx_no_power_cmd,
|
||||
"no power <0-50>",
|
||||
NO_STR "Unset the transmitter power dampening\n"
|
||||
"Power dampening in dB\n")
|
||||
DEFUN(cfg_phy_tx_atten, cfg_phy_tx_atten_cmd,
|
||||
"osmotrx tx-attenuation <0-50>",
|
||||
OSMOTRX_STR
|
||||
"Set the transmitter attenuation\n"
|
||||
"Fixed attenuation in dB, overriding OML\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
l1h->config.power_valid = 0;
|
||||
plink->u.osmotrx.power = atoi(argv[0]);
|
||||
plink->u.osmotrx.power_oml = 0;
|
||||
plink->u.osmotrx.power_valid = 1;
|
||||
plink->u.osmotrx.power_sent = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_no_maxdly, cfg_trx_no_maxdly_cmd,
|
||||
"no maxdly <0-31>",
|
||||
NO_STR "Unset the maximum delay of GSM symbols\n"
|
||||
"GSM symbols (approx. 1.1km per symbol)\n")
|
||||
DEFUN(cfg_phy_tx_atten_oml, cfg_phy_tx_atten_oml_cmd,
|
||||
"osmotrx tx-attenuation oml",
|
||||
OSMOTRX_STR
|
||||
"Set the transmitter attenuation\n"
|
||||
"Use NM_ATT_RF_MAXPOWR_R (max power reduction) from BSC via OML\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.power_oml = 1;
|
||||
plink->u.osmotrx.power_valid = 1;
|
||||
plink->u.osmotrx.power_sent = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_no_rxgain, cfg_phy_no_rxgain_cmd,
|
||||
"no osmotrx rx-gain",
|
||||
NO_STR OSMOTRX_STR "Unset the receiver gain in dB\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.rxgain_valid = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_no_tx_atten, cfg_phy_no_tx_atten_cmd,
|
||||
"no osmotrx tx-attenuation",
|
||||
NO_STR OSMOTRX_STR "Unset the transmitter attenuation\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.power_valid = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phyinst_no_maxdly, cfg_phyinst_no_maxdly_cmd,
|
||||
"no osmotrx maxdly",
|
||||
NO_STR "Unset the maximum delay of GSM symbols\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
|
||||
l1h->config.maxdly_valid = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
DEFUN(cfg_phy_transc_ip, cfg_phy_transc_ip_cmd,
|
||||
"osmotrx ip HOST",
|
||||
OSMOTRX_STR
|
||||
"Set remote IP address\n"
|
||||
"IP address of OsmoTRX\n")
|
||||
{
|
||||
vty_out(vty, " fn-advance %d%s", trx_clock_advance, VTY_NEWLINE);
|
||||
vty_out(vty, " rts-advance %d%s", trx_rts_advance, VTY_NEWLINE);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
if (trx_ms_power_loop)
|
||||
vty_out(vty, " ms-power-loop %d%s", trx_target_rssi,
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " no ms-power-loop%s", VTY_NEWLINE);
|
||||
vty_out(vty, " %stiming-advance-loop%s", (trx_ta_loop) ? "":"no ",
|
||||
VTY_NEWLINE);
|
||||
if (settsc_enabled)
|
||||
vty_out(vty, " settsc%s", VTY_NEWLINE);
|
||||
if (setbsic_enabled)
|
||||
vty_out(vty, " setbsic%s", VTY_NEWLINE);
|
||||
if (plink->u.osmotrx.transceiver_ip)
|
||||
talloc_free(plink->u.osmotrx.transceiver_ip);
|
||||
plink->u.osmotrx.transceiver_ip = talloc_strdup(plink, argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
DEFUN(cfg_phy_base_port, cfg_phy_base_port_cmd,
|
||||
"osmotrx base-port (local|remote) <0-65535>",
|
||||
OSMOTRX_STR "Set base UDP port number\n" "Local UDP port\n"
|
||||
"Remote UDP port\n" "UDP base port number\n")
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
if (l1h->config.rxgain_valid)
|
||||
vty_out(vty, " rxgain %d%s", l1h->config.rxgain, VTY_NEWLINE);
|
||||
if (l1h->config.power_valid) {
|
||||
if (l1h->config.power_oml)
|
||||
vty_out(vty, " power oml%s", VTY_NEWLINE);
|
||||
if (!strcmp(argv[0], "local"))
|
||||
plink->u.osmotrx.base_port_local = atoi(argv[1]);
|
||||
else
|
||||
plink->u.osmotrx.base_port_remote = atoi(argv[1]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink)
|
||||
{
|
||||
if (plink->u.osmotrx.transceiver_ip)
|
||||
vty_out(vty, " osmotrx ip %s%s",
|
||||
plink->u.osmotrx.transceiver_ip, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " osmotrx fn-advance %d%s",
|
||||
plink->u.osmotrx.clock_advance, VTY_NEWLINE);
|
||||
vty_out(vty, " osmotrx rts-advance %d%s",
|
||||
plink->u.osmotrx.rts_advance, VTY_NEWLINE);
|
||||
if (plink->u.osmotrx.rxgain_valid)
|
||||
vty_out(vty, " osmotrx rx-gain %d%s",
|
||||
plink->u.osmotrx.rxgain, VTY_NEWLINE);
|
||||
if (plink->u.osmotrx.power_valid) {
|
||||
if (plink->u.osmotrx.power_oml)
|
||||
vty_out(vty, " osmotrx tx-attenuation oml%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " power %d%s", l1h->config.power,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " osmotrx tx-attenuation %d%s",
|
||||
plink->u.osmotrx.power, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst)
|
||||
{
|
||||
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
|
||||
|
||||
if (l1h->config.maxdly_valid)
|
||||
vty_out(vty, " maxdly %d%s", l1h->config.maxdly, VTY_NEWLINE);
|
||||
if (l1h->config.slotmask != 0xff)
|
||||
|
@ -391,14 +453,32 @@ void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
|
|||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
if (trx_ms_power_loop)
|
||||
vty_out(vty, " ms-power-loop %d%s", trx_target_rssi,
|
||||
VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " no ms-power-loop%s", VTY_NEWLINE);
|
||||
vty_out(vty, " %stiming-advance-loop%s", (trx_ta_loop) ? "":"no ",
|
||||
VTY_NEWLINE);
|
||||
if (settsc_enabled)
|
||||
vty_out(vty, " settsc%s", VTY_NEWLINE);
|
||||
if (setbsic_enabled)
|
||||
vty_out(vty, " setbsic%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
{
|
||||
}
|
||||
|
||||
int bts_model_vty_init(struct gsm_bts *bts)
|
||||
{
|
||||
vty_bts = bts;
|
||||
|
||||
install_element_ve(&show_transceiver_cmd);
|
||||
install_element_ve(&show_phy_cmd);
|
||||
|
||||
install_element(BTS_NODE, &cfg_bts_fn_advance_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rts_advance_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_ms_power_loop_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_ms_power_loop_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_timing_advance_loop_cmd);
|
||||
|
@ -408,14 +488,19 @@ int bts_model_vty_init(struct gsm_bts *bts)
|
|||
install_element(BTS_NODE, &cfg_bts_no_settsc_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_setbsic_cmd);
|
||||
|
||||
install_element(TRX_NODE, &cfg_trx_rxgain_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_power_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_power_oml_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_maxdly_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_slotmask_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_no_rxgain_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_no_power_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_no_maxdly_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_base_port_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_fn_advance_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_rts_advance_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_transc_ip_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_rxgain_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_tx_atten_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_tx_atten_oml_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_no_rxgain_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_no_tx_atten_cmd);
|
||||
|
||||
install_element(PHY_INST_NODE, &cfg_phyinst_slotmask_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phyinst_maxdly_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phyinst_no_maxdly_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue