blob: 279c314ab2595ae1e3fbb30a7c6bc745241496cc [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
#include <bcmolt_host_api.h>
#include <bcmolt_board.h>
#include <bcmolt_board_cli.h>
#include <bcmolt_user_appl_cli.h>
#include <bcmolt_user_appl_ex_cli.h>
#include <bcmolt_user_appl_epon_oam.h>
#if defined(LINUX_KERNEL_SPACE)
#include <bcmolt_dev_log_linux.h>
#endif
#include <bcmolt_dev_selector.h>
#include <bcm_api_cli.h>
#include <bcmolt_api_proxy.h>
#include <bcmolt_remote_cli.h>
#include <bcmolt_image_transfer.h>
#ifdef SIMULATION_BUILD
static void using_inband_set(bcmos_bool using_inband){}
static bcmos_bool using_inband_get(void)
{
return BCMOS_FALSE;
}
extern uint32_t bcmtr_host_ip;
extern uint16_t bcmtr_host_udp_port;
extern uint32_t bcmtr_olt_ip[BCMTR_MAX_OLTS];
extern uint16_t bcmtr_olt_udp_port[BCMTR_MAX_OLTS];
#else
#include <bcmtr_plugin.h>
#endif
#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
static bcmcli_session *current_session;
//#if defined(SIMULATION_BUILD) && defined(LINUX_USER_SPACE)
//extern uint32_t bcmtr_host_ip;
//extern uint16_t bcmtr_host_udp_port;
//extern uint32_t bcmtr_olt_ip[BCMTR_MAX_OLTS];
//extern uint16_t bcmtr_olt_udp_port[BCMTR_MAX_OLTS];
//#endif
#ifdef ENABLE_LOG
static int nologger=0;
#endif
static int _cmd_using_inband(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
{
bcmcli_session_print(sess, "Maple management using %s\n", (using_inband_get())? "In-Band" : "PCIe");
return 0;
}
static int _cli_help(const char *cmd)
{
const char *p;
while ((p = strchr(cmd, '/')))
{
cmd = p + 1;
}
fprintf(stderr,
"%s [-l <level>]"
#if defined(SIMULATION_BUILD) && defined(LINUX_USER_SPACE)
" [-p udp_port_device1] [-p udp_port_device2] ...\n"
"OR\n"
" [-olt ip_device1:port_device1] [-olt ip_device2:port_device2] ...\n"
" [-listen ip:port]\n"
#endif
#ifdef ENABLE_LOG
" [-nl]\n"
#endif
" [-ne]\n"
" [-dev]\n"
" [-if_mask mask]\n"
" [-proxy proxy_port_device1] [-proxy proxy_port_device2] ...\n"
" [-ud]\n"
" [-on_ready cmd]\n", cmd);
fprintf(stderr,
"\t\t level == guest | admin | debug\n"
#ifdef ENABLE_LOG
"\t\t -nl - disable kernel logger integration\n"
#endif
"\t\t -ne - disable line editing\n"
"\t\t -dev - device ID to auto-register for indications and run proxy on (default 0)\n"
"\t\t -if_mask - PON NI mask to apply to auto-registration of indications\n"
"\t\t -proxy - run the API proxy listening on this UDP port\n"
"\t\t -ud - use a unix domain connection to a user space device control"
"\t\t -on_ready - command for API proxy to execute after receiving device ready indication\n");
return -EINVAL;
}
/* quit command handler */
static int _cmd_quit(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
{
bcmcli_stop(sess);
bcmcli_session_print(sess, "Maple CLI terminated by 'Quit' command\n");
return 0;
}
#if defined(SIMULATION_BUILD) && defined(LINUX_USER_SPACE)
/* parse ip:port */
static bcmos_errno _parse_ip_port(const char *s, uint32_t *ip, uint16_t *port)
{
int n;
uint32_t ip1, ip2, ip3, ip4, pp;
n = sscanf(s, "%u.%u.%u.%u:%u", &ip1, &ip2, &ip3, &ip4, &pp);
if (n != 5 || ip1 > 0xff || ip2 > 0xff || ip3 > 0xff || ip4 > 0xff || pp > 0xffff)
{
fprintf(stderr, "Can't parse %s. Must be ip_address:port\n", s);
return BCM_ERR_PARM;
}
*ip = (ip1 << 24) | (ip2 << 16) | (ip3 << 8) | ip4;
*port = pp;
return BCM_ERR_OK;
}
#endif
/* Try to learn system mode */
static bcmolt_system_mode _get_system_mode(bcmolt_devid dev)
{
bcmolt_device_key key = {};
bcmolt_device_cfg dev_cfg;
bcmos_errno rc;
BCMOLT_CFG_INIT(&dev_cfg, device, key);
BCMOLT_CFG_PROP_GET(&dev_cfg, device, system_mode);
rc = bcmolt_cfg_get(dev, &dev_cfg.hdr);
if (rc != BCM_ERR_OK)
{
bcmos_printf("Device %u: failed to read system mode (%s). Waiting for configuration\n",
(unsigned)dev, bcmos_strerror(rc));
return BCMOLT_SYSTEM_MODE__NUM_OF;
}
bcmos_printf("Device %u: System mode: %s\n",
(unsigned)dev, bcmolt_system_mode_name(dev_cfg.data.system_mode));
return dev_cfg.data.system_mode;
}
#ifdef ENABLE_LOG
static int dev_log_time_to_str_cb(uint32_t time_stamp, char *time_str, int time_str_size)
{
return snprintf(time_str, time_str_size, "%u", time_stamp / 1000); /* convert from usec to msec. */
}
static bcmos_errno bcm_init_logger(void)
{
#define DEV_LOG_SIZE1 1<<11
#define DEV_LOG_SIZE2 1<<13
#define DEV_LOG_QUEUE_SIZE 1000
static uint8_t logger_buf1[DEV_LOG_SIZE1];
static uint8_t logger_buf2[DEV_LOG_SIZE2];
bcmos_errno err;
void *addresses[DEV_LOG_MAX_FILES] = {logger_buf1, logger_buf2};
uint32_t sizes[DEV_LOG_MAX_FILES] = {sizeof(logger_buf1), sizeof(logger_buf2)};
uint32_t flags[DEV_LOG_MAX_FILES] = {BCM_DEV_LOG_FILE_FLAG_STOP_WHEN_FULL, BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND};
err = bcm_dev_log_init_default_logger(addresses, sizes, flags, BCM_SIZEOFARRAY(addresses), 0x4000, TASK_PRIORITY_DEV_LOG, DEV_LOG_QUEUE_SIZE);
BCMOS_TRACE_CHECK_RETURN(err, err, "bcm_dev_log_initialize_dev_logger_default()\n");
bcm_dev_log_level_set_style(DEV_LOG_LEVEL_FATAL, BCM_DEV_LOG_STYLE_BOLD);
bcm_dev_log_level_set_style(DEV_LOG_LEVEL_ERROR, BCM_DEV_LOG_STYLE_BOLD);
bcm_dev_log_set_time_to_str_cb(dev_log_time_to_str_cb);
#if defined(LINUX_KERNEL_SPACE)
if (!nologger)
{
err = bcm_dev_log_linux_init();
BCMOS_TRACE_CHECK_RETURN(err, err, "bcm_dev_log_linux_init()\n");
}
#endif
BCM_LOG(INFO, def_log_id, "Hello Logger\n");
return BCM_ERR_OK;
}
#endif
static void handle_system_mode_change(bcmolt_devid dev)
{
bcmcli_entry *cur_dir = bcmcli_dir_get(current_session);
char old_dir_name[32] = "";
bcmolt_system_mode system_mode;
bcmolt_system_mode_get(dev, &system_mode);
bcm_common_gpon_init(system_mode);
if (dev == current_device)
{
if (cur_dir)
strncpy(old_dir_name, bcmcli_token_name(cur_dir), sizeof(old_dir_name) - 1);
api_cli_set_commands(current_session);
/* Restore current CLI directory */
cur_dir = bcmcli_dir_find(NULL, old_dir_name);
if (cur_dir)
bcmcli_dir_set(current_session, cur_dir);
}
bcmolt_user_appl_cli_handle_system_mode_change(dev);
}
static void cli_get_prompt(bcmcli_session *session, char *buf, uint32_t max_len)
{
snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, current_device);
}
int main(int argc, char *argv[])
{
bcmcli_session_parm mon_session_parm;
#ifndef SIMULATION_BUILD
uint32_t fpga_version;
#endif
int noedit = 0;
int rc;
int i;
bcmolt_host_init_params params =
{
#ifdef ENABLE_LOG
.logger_init_cb = bcm_init_logger,
#endif
.run_dev_ctrl = BCMOS_FALSE
};
bcmolt_devid device = 0;
bcmos_bool specific_device = BCMOS_FALSE;
bcmos_bool run_proxy = BCMOS_FALSE;
bcmos_bool run_remote_cli = BCMOS_FALSE;
uint32_t proxy_port[BCMTR_MAX_OLTS] = {};
uint32_t remote_cli_port = 0;
int cur_proxy_dev = 0;
char *on_ready_cmd = NULL;
struct bcmolt_rx_cfg rx_cfg =
{
.obj_type = BCMOLT_OBJECT_ANY,
.flags = BCMOLT_AUTO_FLAGS_NONE,
};
#if defined(SIMULATION_BUILD) && defined(LINUX_USER_SPACE)
int cur_olt = 0;
#endif
(void)noedit; /* prevent warning */
memset(&mon_session_parm, 0, sizeof(mon_session_parm));
mon_session_parm.get_prompt = cli_get_prompt;
mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
for (i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-l"))
{
++i;
if (!strcmp(argv[i], "admin"))
mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
else if (!strcmp(argv[i], "guest"))
mon_session_parm.access_right = BCMCLI_ACCESS_GUEST;
else if (!strcmp(argv[i], "debug"))
mon_session_parm.access_right = BCMCLI_ACCESS_DEBUG;
else
return _cli_help(argv[0]);
}
else if (!strcmp(argv[i], "-ne"))
{
noedit = 1;
}
#ifdef ENABLE_LOG
else if (!strcmp(argv[i], "-nl"))
{
nologger = 1;
}
#endif
#if defined(SIMULATION_BUILD) && defined(LINUX_USER_SPACE)
else if (!strcmp(argv[i], "-p"))
{
if (cur_olt >= BCMTR_MAX_OLTS)
{
printf("Too many -p and/or -olt options\n");
return -1;
}
++i;
bcmtr_olt_udp_port[cur_olt] = strtol(argv[i], NULL, 0);
++cur_olt;
}
else if (!strcmp(argv[i], "-olt"))
{
if (cur_olt >= BCMTR_MAX_OLTS)
{
printf("Too many -p and/or -olt options\n");
return -1;
}
++i;
if (_parse_ip_port(argv[i], &bcmtr_olt_ip[cur_olt], &bcmtr_olt_udp_port[cur_olt]) != BCM_ERR_OK)
return -1;
++cur_olt;
}
else if (!strcmp(argv[i], "-listen"))
{
++i;
if (_parse_ip_port(argv[i], &bcmtr_host_ip, &bcmtr_host_udp_port) != BCM_ERR_OK)
return -1;
}
#endif
else if (!strcmp(argv[i], "-dev"))
{
++i;
device = (bcmolt_devid)strtoul(argv[i], NULL, 0);
if (device >= BCMTR_MAX_OLTS)
{
printf("Invalid device ID\n");
return -1;
}
current_device = device;
specific_device = BCMOS_TRUE;
}
else if (!strcmp(argv[i], "-if_mask"))
{
++i;
rx_cfg.pon_ni_mask = (uint32_t)strtoul(argv[i], NULL, 0);
}
else if (!strcmp(argv[i], "-proxy"))
{
if (cur_proxy_dev >= BCMTR_MAX_OLTS)
{
printf("Too many -proxy options\n");
return -1;
}
++i;
run_proxy = BCMOS_TRUE;
proxy_port[cur_proxy_dev] = (uint32_t)strtoul(argv[i], NULL, 0);
if (proxy_port[cur_proxy_dev] > 0xffff)
{
printf("Invalid proxy port %u\n", (unsigned)proxy_port[cur_proxy_dev]);
return -1;
}
++cur_proxy_dev;
}
else if (!strcmp(argv[i], "-remote"))
{
++i;
run_remote_cli = BCMOS_TRUE;
remote_cli_port = (uint32_t)strtoul(argv[i], NULL, 0);
}
else if (!strcmp(argv[i], "-ud"))
{
using_inband_set(BCMOS_TRUE);
}
else if (!strcmp(argv[i], "-on_ready"))
{
++i;
on_ready_cmd = argv[i];
}
else
{
return _cli_help(argv[0]);
}
}
rc = bcmolt_host_init(&params);
BUG_ON(rc);
bcmos_trace_level_set(BCMOS_TRACE_LEVEL_DEBUG);
if (noedit)
{
mon_session_parm.line_edit_mode = BCMCLI_LINE_EDIT_DISABLE;
}
if (bcmcli_session_open(&mon_session_parm, &current_session))
{
printf("Can't open CLI session\n");
return -EINVAL;
}
/* Try to learn system mode for all devices */
if (specific_device)
{
bcmolt_system_mode_set(current_device, _get_system_mode(current_device));
}
else
{
for (i = 0; i < BCMTR_MAX_OLTS; i++)
bcmolt_system_mode_set(i, _get_system_mode(i));
}
/* Init device selector */
rc = bcmolt_dev_sel_init(NULL);
/* Add Maple API commands */
rc = rc ? rc : api_cli_init(NULL, current_session);
/* (x)GPON init. Does nothing if system mode is not (x)GPON */
if (rc == BCM_ERR_OK)
{
bcmolt_system_mode system_mode = BCMOLT_SYSTEM_MODE__NUM_OF;
bcmolt_system_mode_get(current_device, &system_mode);
bcm_common_gpon_init(system_mode);
}
/* Add transport commands */
rc = rc ? rc : bcmtr_cli_init();
/* Add capture, log, debug commands */
rc = rc ? rc : bcmtr_cld_init(current_session);
/* Initialize embedded CLI module */
rc = rc ? rc : bcm_embedded_cli_init();
rc = rc ? rc : bcmos_cli_init(NULL);
rc = rc ? rc : bcmolt_user_appl_cli_init(NULL);
rc = rc ? rc : bcmolt_user_appl_ex_cli_init();
#if defined(LINUX_KERNEL_SPACE)
rc = rc ? rc : bcm_board_init();
rc = rc ? rc : bcm_board_cli_init(NULL);
#endif
#ifdef ENABLE_LOG
/* logger CLI directory */
bcm_dev_log_cli_init(NULL);
#endif
if (run_proxy)
{
/* If executing for specific device, run only 1 proxy instance.
* Otherwise, create as many instances as requested
*/
if (specific_device)
rc = rc ? rc : bcmolt_api_proxy_init(NULL, device, proxy_port[0], on_ready_cmd);
else
{
for (i = 0; i < cur_proxy_dev; i++)
{
rc = rc ? rc : bcmolt_api_proxy_init(NULL, i, proxy_port[i], on_ready_cmd);
}
}
}
if (run_remote_cli)
{
rc = rc ? rc : bcmolt_remote_cli_init(NULL, device, remote_cli_port);
}
/* Add other commands, e.g., access to embedded CLI */
if (rc)
return rc;
rx_cfg.rx_cb = bcmolt_user_appl_indication_cb;
rc = bcmolt_auto_rx_cb_set(device, &rx_cfg);
BUG_ON(BCM_ERR_OK != rc);
rx_cfg.rx_cb = bcmolt_user_appl_proxy_rx_cb;
rc = bcmolt_proxy_rx_cb_set(device, &rx_cfg);
BUG_ON(BCM_ERR_OK != rc);
bcmolt_user_mftp_init();
sm_change_cb = handle_system_mode_change;
BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", _cmd_quit);
BCMCLI_MAKE_CMD_NOPARM(NULL, "using_inband", "Using In Band", _cmd_using_inband);
#ifndef SIMULATION_BUILD
bcm_board_fpga_version_get(&fpga_version);
bcmcli_session_print(current_session, "FPGA version: %d\n", fpga_version);
#endif
/* Process user input until EOF or quit command */
bcmcli_driver(current_session);
#if defined(LINUX_KERNEL_SPACE)
bcm_board_uninit();
#endif
bcmtr_exit();
bcmcli_session_close(current_session);
bcmcli_token_destroy(NULL);
if (run_proxy)
{
bcmolt_api_proxy_stop();
}
if (run_remote_cli)
{
bcmolt_remote_cli_stop();
}
return 0;
}