blob: f32ff7e27394b897e506ee1ed2f7c5d357882636 [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 <bcmos_system.h>
#include <bcmolt_api.h>
#include <bcmolt_model_types.h>
#include <bcm_dev_log.h>
#include <bcmolt_board.h>
#include "omon.h"
#include "bcmolt_utils.h"
/* These macros need to be defined before the following include. */
#define BCM_I2C_DEV_ADDR_START typedef enum {
#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
#include "bcmolt_i2c_devs_addr.h"
/* Fixed sample delay exceeds the sum of the maximum grant size and a worst case
retrieval time based on various optics modules' data sheets */
#define OMON_FIXED_SAMPLE_DELAY_US 12000
#define SFF_8472_IDENTIFIER_ADDR 0x00 /* SFP and XFP Identifier byte*/
#define SFF_8077i_IDENTIFIER_ADDR 128 /* XFP Identifier byte */
#define SFF_8472_RX_POWER_ADDR 104 /* SFP offeset into A2 */
#define SFF_8077i_RX_POWER_ADDR 104 /* XFP byte 104/105 into A0 (yes A0) */
#define SFF_8077i_VENDOR_NAME_ADDR 148 /* XFP bytes 163-148 into A0 */
#define SFF_8077i_VENDOR_NAME_LEN 16 /* XFP name length */
#define SFF_8077i_VENDOR_PN_ADDR 168 /* XFP bytes 183-168 into A0 */
#define SFF_8077i_VENDOR_PN_LEN 16 /* XFP part number length */
#define SFF_8077i_VENDOR_REV_ADDR 184 /* XFP bytes 185-184 into A0 */
#define SFF_8077i_VENDOR_REV_LEN 2 /* XFP revision len */
#define SFF_8077i_VENDOR_SN_ADDR 196 /* XFP bytes 211-196 into A0 */
#define SFF_8077i_VENDOR_SN_LEN 16 /* XFP serial number len */
#define OMON_TASK_MSG_Q_SIZE 16 /* allow one message per port */
#define SFF_PAGE_ADDR1 0 /* use SFP_I2C_ADDR1 for I2C read A0 */
#define SFF_PAGE_ADDR2 1 /* use SFP_I2C_ADDR2 for 12C read A2 */
#define SFF_8472_VENDOR_NAME_ADDR 20 /* SFP bytes 20-35 into A0 */
#define SFF_8472_VENDOR_NAME_LEN 16 /* SFP name length */
#define SFF_8472_VENDOR_OUI_ADDR 37 /* SFP bytes 37-39 into A0 */
#define SFF_8472_VENDOR_OUI_LEN 3 /* SFP oui length */
#define SFF_8472_VENDOR_PN_ADDR 40 /* SFP bytes 40-55 into A0 */
#define SFF_8472_VENDOR_PN_LEN 16 /* SFP part number length */
#define SFF_8472_VENDOR_REV_ADDR 56 /* SFP bytes 56-59 into A0 */
#define SFF_8472_VENDOR_REV_LEN 4 /* SFP revision len */
#define SFF_8472_VENDOR_SN_ADDR 68 /* SFP bytes 68-83 into A0 */
#define SFF_8472_VENDOR_SN_LEN 16 /* SFP serial number len */
#define SFF_8472_VENDOR_SFF_ADDR 94 /* SFP bytes 94 into A0 */
#define SFF_8472_VENDOR_SFF_LEN 1 /* SFP SFF-8472 Compliance revision len */
#define SFF_8472_DIAG_MON_ADDR 92 /* SFP bytes 92 into A0 */
#define SFF_8472_ENHANCED_OPT_ADDR 93 /* SFP bytes 93 into A0 */
#define SFF_8472_TEMPERATURE_ADDR 96 /* SFP bytes 96 into A0 */
#define SFF_8472_DIAG_MON_LEN 1 /* SFP SFF-8472 Diagnostic Monitoring Type len */
/* Table 32 5.2 Identifier values SFF8077i*/
#define SFF_IDENTIFIER_SFP 0x03
#define SFF_IDENTIFIER_XFP 0x06
typedef uint32_t omon_rssi_value;
/* Uniquely identifies specific EPON links under management by this
application */
typedef struct
{
bcmolt_devid device_id;
bcmolt_epon_ni epon_ni;
bcmos_mac_address mac_address;
} omon_link_key;
typedef struct
{
uint32_t caddr; /* I2C switch control address */
uint32_t sctrl; /* I2C switch control command value */
} i2c_coords;
typedef struct
{
bcmos_msg os_msg;
omon_link_key link_key;
uint16_t trigger_width_ns;
uint16_t trigger_delay_ns;
uint16_t sample_period_us;
bcmcli_session *session;
bcmolt_epon_llid llid;
uint8_t scan_mode;
} omon_task_msg;
static dev_log_id omon_log_id = DEV_LOG_INVALID_ID;
static bcmos_task omon_task;
static bcmos_bool is_running = BCMOS_FALSE;
/*******************************************************************************
* BCM968620 platform dependent I2C access
******************************************************************************/
uint8_t bcm968620_client_switchctrl_sfp[16][2] =
{
{ 0x72, 0x80, },
{ 0x72, 0x40, },
{ 0x72, 0x20, },
{ 0x72, 0x10, },
{ 0x72, 0x8, },
{ 0x72, 0x4, },
{ 0x72, 0x2, },
{ 0x72, 0x1, },
{ 0x73, 0x10, },
{ 0x73, 0x20, },
{ 0x73, 0x40, },
{ 0x73, 0x80, },
{ 0x73, 0x1, },
{ 0x73, 0x2, },
{ 0x73, 0x4, },
{ 0x73, 0x8, },
};
uint8_t bcm968620_client_switchctrl_xfp[8][2] =
{
/* caddr, sctrl */
{ 0x72, 0x8, },
{ 0x72, 0x4, },
{ 0x72, 0x2, },
{ 0x72, 0x1, },
{ 0x73, 0x10, },
{ 0x73, 0x20, },
{ 0x73, 0x40, },
{ 0x73, 0x80, },
};
static bcmos_bool omon_is_epon_ni_valid(bcmolt_epon_ni epon)
{
bcmolt_system_mode system_mode;
bcmolt_system_mode_get(current_device, &system_mode);
switch (system_mode)
{
case BCMOLT_SYSTEM_MODE_EPON__16_X:
return epon < 16;
case BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA:
case BCMOLT_SYSTEM_MODE_EPON__8_X_10_G:
case BCMOLT_SYSTEM_MODE_EPON__8_X:
return epon < 8;
case BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA:
case BCMOLT_SYSTEM_MODE_EPON__4_X_10_G:
case BCMOLT_SYSTEM_MODE_EPON__4_X:
return epon < 4;
case BCMOLT_SYSTEM_MODE_EPON__2_X_10_G:
return epon < 2;
default:
return BCMOS_FALSE;
}
}
static bcmos_bool trx_id_from_epon_ni(bcmolt_epon_ni epon, uint8_t *trx_id)
{
static const uint8_t epon_4x[4] = { 2, 3, 6, 7 };
static const uint8_t epon_2x_10g[2] = { 3, 4 };
bcmolt_system_mode system_mode;
bcmolt_system_mode_get(current_device, &system_mode);
switch (system_mode)
{
case BCMOLT_SYSTEM_MODE_EPON__16_X:
case BCMOLT_SYSTEM_MODE_EPON__8_X:
case BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA:
case BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA:
case BCMOLT_SYSTEM_MODE_EPON__8_X_10_G:
case BCMOLT_SYSTEM_MODE_EPON__4_X_10_G:
*trx_id = (uint8_t)epon;
return BCMOS_TRUE;
case BCMOLT_SYSTEM_MODE_EPON__4_X:
*trx_id = epon_4x[epon];
return BCMOS_TRUE;
case BCMOLT_SYSTEM_MODE_EPON__2_X_10_G:
*trx_id = epon_2x_10g[epon];
return BCMOS_TRUE;
default:
*trx_id = (uint8_t)-1;
return BCMOS_FALSE;
}
}
static char * bcmolt_get_scan_result(bcmolt_rogue_scan_status status)
{
switch (status)
{
case BCMOLT_ROGUE_SCAN_STATUS_COMPLETE:
return "OK: EPON ROGUE SCAN IS COMPLETE";
case BCMOLT_ROGUE_SCAN_STATUS_LLID_STATE_IS_BAD:
return "FAIL: REQUESTED LLID IS IN USE";
case BCMOLT_ROGUE_SCAN_STATUS_SCAN_ERR_INTERNAL:
return "FAIL: SCAN HAD AN INTERNAL SW ERROR";
case BCMOLT_ROGUE_SCAN_STATUS_SCAN_ERR_NORES:
return "FAIL: NO RESOURCES AVAILABLE";
case BCMOLT_ROGUE_SCAN_STATUS_LLID_IS_OOR:
return "FAIL: REQUESTED LLID IS OUT OF RANGE";
default:
return "OK: BCMOLT_ROGUE_SCAN_STATUS_COMPLETE";
}
}
/**
* \brief Get I2C address
*
* This function returns the I2C mux target address for the given link_key
* object.
*
* \param epon_ni EPON port index
* \param coords I2C mux target container
*
* \return
* None
*/
static
void omon_get_i2c_coords(uint8_t trx_id, i2c_coords* coords)
{
bcmolt_system_mode system_mode;
bcmolt_system_mode_get(0, &system_mode);
if (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA)
{
coords->caddr = bcm968620_client_switchctrl_xfp[trx_id][0];
coords->sctrl = bcm968620_client_switchctrl_xfp[trx_id][1];
}
else
{
coords->caddr = bcm968620_client_switchctrl_sfp[trx_id][0];
coords->sctrl = bcm968620_client_switchctrl_sfp[trx_id][1];
}
} /* omon_get_i2c_coords */
/**
* \brief Configure I2C mux
*
* This function configures the I2C mux to target the correct optics module for
* the currently executing RSSI measurement.
*
* \param epon_ni EPON port index
*
* \return
* BCM_ERR_OK if successful, error code if not
*/
static
bcmos_errno omon_platform_configure_i2c(uint8_t trx_id, uint8_t page)
{
i2c_coords coords;
bcmos_errno rc;
omon_get_i2c_coords(trx_id, &coords);
rc = bcm_board_dev_change(coords.caddr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(WARNING, omon_log_id,
"bcm_board_dev_change(%u) failed\n", coords.caddr);
}
else
{
rc = bcm_board_switch_write(coords.sctrl);
if (rc != BCM_ERR_OK)
{
BCM_LOG(WARNING, omon_log_id,
"bcm_board_switch_write(%u) failed\n", coords.sctrl);
}
else
{
if (page == SFF_PAGE_ADDR1)
{
rc = bcm_board_dev_change(SFP_I2C_ADDR1);
}
else
{ // SFF_PAGE_ADDR2
rc = bcm_board_dev_change(SFP_I2C_ADDR2);
}
if (rc != BCM_ERR_OK)
{
BCM_LOG(WARNING, omon_log_id,
"bcm_board_dev_change(%u) failed\n", (SFP_I2C_ADDR1+page));
}
}
}
return rc;
} /* omon_platform_configure_i2c */
/**
* \brief Read Manufacturing data from Optic Module
*
* This function reads the XFP Tranceiver Data (according to
* SFF8077i for an XFP) from an optics module. The result is
* displayed for this sample code.
*
* \param epon_ni EPON NI to take measurement
*
* \return
* BCM_ERR_OK if successful, error code if not
*/
static
bcmos_errno omon_trx_status_read(bcmolt_epon_ni epon_ni, bcmcli_session *session)
{
uint32_t sff_identifier = 1;
bcmos_errno rc = BCM_ERR_OK;
uint8_t i;
// 80771 XFP Specific stuff
uint32_t raw_vendorId_8077i;
uint8_t vendorId_8077i[SFF_8077i_VENDOR_NAME_LEN+1];
uint32_t raw_vendorPn_8077i;
uint8_t vendorPn_8077i[SFF_8077i_VENDOR_PN_LEN+1];
uint32_t raw_vendorSn_8077i;
uint8_t vendorSn_8077i[SFF_8077i_VENDOR_SN_LEN+1];
uint32_t raw_vendorRev_8077i;
uint8_t vendorRev_8077i[SFF_8077i_VENDOR_REV_LEN+1];
memset(&vendorId_8077i, 0, sizeof(vendorId_8077i));
memset(&vendorPn_8077i, 0, sizeof(vendorPn_8077i));
memset(&vendorSn_8077i, 0, sizeof(vendorSn_8077i));
memset(&vendorRev_8077i, 0, sizeof(vendorRev_8077i));
// 8472 SFP Specific stuff
uint32_t raw_vendorId_8472;
uint8_t vendorId_8472[SFF_8472_VENDOR_NAME_LEN+1];
uint32_t raw_vendorPn_8472;
uint8_t vendorPn_8472[SFF_8472_VENDOR_PN_LEN+1];
uint32_t raw_vendorSn_8472;
uint8_t vendorSn_8472[SFF_8472_VENDOR_SN_LEN+1];
uint32_t raw_vendorRev_8472;
uint8_t vendorRev_8472[SFF_8472_VENDOR_REV_LEN+1];
uint32_t raw_vendorSff_8472;
uint8_t vendorSff_8472[SFF_8472_VENDOR_SFF_LEN+1];
uint32_t raw_vendorOui_8472;
uint8_t vendorOui_8472[SFF_8472_VENDOR_OUI_LEN+1];
uint32_t raw_diagMon_8472;
uint8_t diagMon_8472 = 0;
uint32_t raw_enhancedOpt_8472;
uint8_t enhancedOpt_8472 = 0;
memset(&vendorId_8472, 0, sizeof(vendorId_8472));
memset(&vendorPn_8472, 0, sizeof(vendorPn_8472));
memset(&vendorSn_8472, 0, sizeof(vendorSn_8472));
memset(&vendorRev_8472, 0, sizeof(vendorRev_8472));
memset(&vendorSff_8472, 0, sizeof(vendorSff_8472));
memset(&vendorOui_8472, 0, sizeof(vendorOui_8472));
uint8_t* tmpresult;
int16_t temp_result = 0;
uint32_t raw_temp_result = 0;
uint8_t trx_id;
if ( ! trx_id_from_epon_ni(epon_ni, &trx_id) )
{
BCM_LOG(ERROR, omon_log_id,
"TRX Id is invalid for EPON NI %d \n", epon_ni);
return BCM_ERR_RANGE;
}
char *pSfpType;
pSfpType = "UNKN";
// Check for transevier presence
if ( (rc = omon_platform_configure_i2c(trx_id, SFF_PAGE_ADDR1)) == BCM_ERR_OK)
{
/* Read module identifier */
if ( (rc = bcm_board_dev_read(8, SFF_8472_IDENTIFIER_ADDR, &sff_identifier)) == BCM_ERR_OK)
{
switch (sff_identifier & 0x000F)
{
case SFF_IDENTIFIER_SFP:
pSfpType = "SFP\0";
// Read the vendor Id
for (i=0; i<SFF_8472_VENDOR_NAME_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8472_VENDOR_NAME_ADDR+i, &raw_vendorId_8472);
vendorId_8472[i] = (uint8_t)raw_vendorId_8472;
}
// Read the part Number, serial number, SFF revision, and Revision
for (i=0; i<SFF_8472_VENDOR_PN_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8472_VENDOR_PN_ADDR+i, &raw_vendorPn_8472);
vendorPn_8472[i] = (uint8_t)raw_vendorPn_8472;
}
for (i=0; i<SFF_8472_VENDOR_SN_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8472_VENDOR_SN_ADDR+i, &raw_vendorSn_8472);
vendorSn_8472[i] = (uint8_t)raw_vendorSn_8472;
}
for (i=0; i<SFF_8472_VENDOR_REV_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8472_VENDOR_REV_ADDR+i, &raw_vendorRev_8472);
vendorRev_8472[i] = (uint8_t)raw_vendorRev_8472;
}
for (i=0; i<SFF_8472_VENDOR_SFF_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8472_VENDOR_SFF_ADDR+i, &raw_vendorSff_8472);
vendorSff_8472[i] = (uint8_t)raw_vendorSff_8472;
}
for (i=0; i<SFF_8472_VENDOR_OUI_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8472_VENDOR_OUI_ADDR+i, &raw_vendorOui_8472);
vendorOui_8472[i] = (uint8_t)raw_vendorOui_8472;
}
rc = rc | bcm_board_dev_read(8, SFF_8472_DIAG_MON_ADDR, &raw_diagMon_8472);
diagMon_8472 = (uint8_t)raw_diagMon_8472;
rc = rc | bcm_board_dev_read(8, SFF_8472_ENHANCED_OPT_ADDR, &raw_enhancedOpt_8472);
enhancedOpt_8472 = (uint8_t)raw_enhancedOpt_8472;
// Shift to A2
rc = rc | omon_platform_configure_i2c(trx_id, SFF_PAGE_ADDR2);
rc = rc | bcm_board_dev_read(16, SFF_8472_TEMPERATURE_ADDR, &raw_temp_result);
tmpresult = (uint8_t*)(&raw_temp_result);
temp_result = tmpresult[3];
temp_result = (temp_result << 8) | tmpresult[2];
break;
case SFF_IDENTIFIER_XFP:
pSfpType = "XFP\0";
// Read the vendor Id
for (i=0; i<SFF_8077i_VENDOR_NAME_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8077i_VENDOR_NAME_ADDR+i, &raw_vendorId_8077i);
vendorId_8077i[i] = (uint8_t)raw_vendorId_8077i;
}
// Read the part Number, SN, and Revision
for (i=0; i<SFF_8077i_VENDOR_PN_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8077i_VENDOR_PN_ADDR+i, &raw_vendorPn_8077i);
vendorPn_8077i[i] = (uint8_t)raw_vendorPn_8077i;
}
for (i=0; i<SFF_8077i_VENDOR_SN_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8077i_VENDOR_SN_ADDR+i, &raw_vendorSn_8077i);
vendorSn_8077i[i] = (uint8_t)raw_vendorSn_8077i;
}
for (i=0; i<SFF_8077i_VENDOR_REV_LEN; i++)
{
rc = rc | bcm_board_dev_read(8, SFF_8077i_VENDOR_REV_ADDR+i, &raw_vendorRev_8077i);
vendorRev_8077i[i] = (uint8_t)raw_vendorRev_8077i;
}
break;
default:
rc = BCM_ERR_NODEV;
break;
}
}
else
{
BCM_LOG(ERROR, omon_log_id,
"TRX Could not read device : SFF_8472_IDENTIFIER_ADDR for PON %d rc %d (%s)\n",
epon_ni, rc, bcmos_strerror(rc));
}
}
else
{
BCM_LOG(ERROR, omon_log_id,
"TRX Could not configure platform : SFF_PAGE_ADDR1 for PON %d rc %d (%s)\n",
epon_ni, rc, bcmos_strerror(rc));
rc = BCM_ERR_NODEV;
}
if (rc == BCM_ERR_OK)
{
if ( (sff_identifier & 0x000F) == SFF_IDENTIFIER_XFP)
{
bcmcli_session_print(session,
"\n[OMON] %s Tranceiver is present on PON %d\r\n"
" [OMON] Trx Vendor Id is: %s\r\n "
" [OMON] Vendor Part Number: %s\r\n "
" [OMON] Vendor Serial Number: %s\r\n "
" [OMON] Vendor Revision: %s\r\n ",
pSfpType, epon_ni, vendorId_8077i,
vendorPn_8077i, vendorSn_8077i, vendorRev_8077i);
}
else
{
// SFP stuff
bcmcli_session_print(session,
"\n[OMON] %s Tranceiver is present on PON %d\r\n"
" [OMON] Trx Vendor Id is: %s\r\n "
" [OMON] Vendor Part Number: %s\r\n "
" [OMON] Vendor Serial Number: %s\r\n "
" [OMON] Vendor Revision: %s\r\n "
" [OMON] Vendor OUI: %s\r\n "
" [OMON] Transceiver Temperature: %dC\r\n "
" [OMON] Enhanced Options SFF-8472 Byte 93: %x\r\n "
" [OMON] Diagnostic Monitor Type SFF-8472 Byte 92: %x\r\n ",
pSfpType, epon_ni, vendorId_8472,
vendorPn_8472, vendorSn_8472, vendorRev_8472, vendorOui_8472,
temp_result/256, enhancedOpt_8472, diagMon_8472 );
}
}
return rc;
} /* omon_rssi_read */
/**
* \brief Read RSSI results from I2C
*
* This function reads the RX Power Measurement (SFF8472 for an
* SFP and SFF8077i for an XFP) from an optics module. The
* result is stored in the global omon_state.
*
* \param epon_ni EPON NI to take measurement
* \param rssi_value Returned RSSI value if successful
*
* \return
* BCM_ERR_OK if successful, error code if not
*/
static
bcmos_errno omon_rssi_read(bcmolt_epon_ni epon_ni, uint32_t *rssi_value)
{
uint32_t raw_rssi_result = 0;
uint32_t sff_identifier = 1;
uint8_t trx_id;
uint32_t rssi_result = 0;
bcmos_errno rc = BCM_ERR_OK;
uint8_t* result;
if ( ! trx_id_from_epon_ni(epon_ni, &trx_id) )
{
BCM_LOG(ERROR, omon_log_id,
"TRX Id is invalid for EPON NI %d \n", epon_ni);
return BCM_ERR_RANGE;
}
// Check for transevier presence
if (bcm_board_trx_present(trx_id) == BCM_ERR_OK)
{
rc = omon_platform_configure_i2c(trx_id, SFF_PAGE_ADDR1);
/* Read module identifier */
if (rc == BCM_ERR_OK)
{
/* Read module identifier */
rc = bcm_board_dev_read(8, SFF_8472_IDENTIFIER_ADDR, &sff_identifier);
if (rc == BCM_ERR_OK)
{
result = (uint8_t*)(&raw_rssi_result);
switch (sff_identifier & 0x000F)
{
case SFF_IDENTIFIER_SFP:
rc = omon_platform_configure_i2c(trx_id, SFF_PAGE_ADDR2);
if (rc == BCM_ERR_OK)
{
rc = bcm_board_dev_read(16, SFF_8472_RX_POWER_ADDR, &raw_rssi_result);
}
break;
case SFF_IDENTIFIER_XFP:
rc = bcm_board_dev_read(16, SFF_8077i_RX_POWER_ADDR, &raw_rssi_result);
break;
default:
rc = BCM_ERR_NODEV;
break;
}
if (rc == BCM_ERR_OK)
{
rssi_result = result[3];
rssi_result = (rssi_result << 8) | result[2];
*rssi_value = rssi_result;
}
}
else
{
BCM_LOG(ERROR, omon_log_id,
"TRX Could not read device : SFF_8472_IDENTIFIER_ADDR for PON %d rc %d (%s)\n",
epon_ni, rc, bcmos_strerror(rc));
rc = BCM_ERR_IO;
}
}
else
{
BCM_LOG(ERROR, omon_log_id,
"TRX Could not read platform : SFF_PAGE_ADDR1 for PON %d rc %d (%s)\n",
epon_ni, rc, bcmos_strerror(rc));
rc = BCM_ERR_IO;
}
}
else
{
rc = BCM_ERR_NODEV;
}
return rc;
} /* omon_rssi_read */
/*******************************************************************************
* Platform independent RSSI measurement
******************************************************************************/
/**
* \brief Read XFP/SFP Data from Transceiver Module1
*
* This function reads the manufacturing data from the SFP
* module via I2C.
*
* \param link_key EPON NI
*
* \return
* None
*/
static
void omon_trx_status_initiate(bcmcli_session *session,
omon_link_key *link_key)
{
bcmos_errno rc;
/* Perform the I2C operations specified in SFF-8472 (SFP)/SFF-8077i (XFP) to
retrieve the pmanufacturer data from the optics module. */
if (! omon_is_epon_ni_valid(link_key->epon_ni))
{
BCM_LOG(ERROR, omon_log_id,
"[OMON] TRX Status: epon_ni of (%d) is out of range for platform\n", link_key->epon_ni);
return ;
}
// Check for transceiver presence
uint8_t trx_id;
if ( ! trx_id_from_epon_ni(link_key->epon_ni, &trx_id) )
{
BCM_LOG(ERROR, omon_log_id,
"[OMON] TRX Id is invalid for EPON NI %d \n", link_key->epon_ni);
return;
}
rc = bcm_board_trx_present(trx_id);
if (rc == BCM_ERR_NODEV)
{
bcmcli_session_print(session,
"[OMON] TRX Status: Trx_id %d Not Present on PON %d\r\n ", trx_id, link_key->epon_ni);
return;
}
rc = omon_trx_status_read(trx_id, session);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, omon_log_id,
"[OMON] Issue TRX Status: Read operation failed with rc %d (%s)\n",
rc, bcmos_strerror(rc));
return;
}
/* Notify external host code of the outcome through an optional callback,
defaulting to output in the CLI session where the command was initiated
if no callback is supplied. */
bcmcli_session_print(session,
"\n[OMON] TRX Status: Data on PON %d Complete\r\n", link_key->epon_ni);
}
/**
* \brief Read RSSI Measurement Result from Transceiver Module
*
* This function reads the stored RSSI measurement from the
* XFP/SFP module via I2C.
*
* \param link_key EPON NI
*
* \return
* None
*/
static
void omon_rssi_read_initiate(bcmcli_session *session,
omon_link_key *link_key)
{
uint32_t rssi_value = 0;
bcmos_errno rc;
if (! omon_is_epon_ni_valid(link_key->epon_ni))
{
BCM_LOG(ERROR, omon_log_id,
"[OMON] Rssi Read: epon_ni of (%d) is out of range for platform\n", link_key->epon_ni);
return ;
}
/* Perform the I2C operations specified in SFF-8472 (SFP)/SFF-8077i (XFP) to
retrieve the power measurements from the optics module. */
rc = omon_rssi_read(link_key->epon_ni, &rssi_value);
if (rc == BCM_ERR_NODEV)
{
bcmcli_session_print(session,
"[OMON] Rssi Read: TRX Not Present on PON %d\r\n ", link_key->epon_ni);
return;
}
if (rc == BCM_ERR_IO)
{
bcmcli_session_print(session,
"[OMON] Rssi Read: Could not read device for PON %d \n",link_key->epon_ni);
return;
}
if (rc != BCM_ERR_OK)
{
bcmcli_session_print(session,
"Issue RSSI Read operation failed with rc %d (%s)\n",
rc, bcmos_strerror(rc));
return;
}
/* Notify external host code of the outcome through an optional callback,
defaulting to output in the CLI session where the command was initiated
if no callback is supplied. */
bcmcli_session_print(session,
"[OMON] RSSI Read RX Power: Pon_ni=%d rx power %d.%duW\r\n",
link_key->epon_ni,
rssi_value/10,
rssi_value%10);
bcmcli_session_print(session,
"\n[OMON] RSSI Read on PON %d Complete\r\n",
link_key->epon_ni);
}
/*omon_rssi_read_initiate*/
/**
* \brief Request Maple Firmware to run the Rogue ONU LLID scan.
*
* This function sends an API message to the OLT to run a scan
* on a specific EPON LLID or across all LLIDs in the PON.
* Results are returned upon completion. Rogue LLIDs are marked
* and quarentined for the host to examine.
*
* \param link_key EPON link information
* \param epopn_llid Specific LLID to scan
* \param scan_mode Specifies a single LLID or All.
*
* \return
* None
*/
static
void omon_run_rogue_llid_scan(bcmcli_session *session,
omon_link_key *link_key,
bcmolt_epon_llid llid,
uint8_t scan_mode)
{
const bcmolt_epon_ni_key ni_key = { .epon_ni = link_key->epon_ni };
bcmolt_epon_ni_rogue_llid_scan issue_llid_scan_op;
bcmos_errno rc = BCM_ERR_OK;
/* Perform an API operation directing the Maple firmware to issue an bcmolt_epon_ni_issue_rogue_rx_power
RSSI grant to the specified EPON link. BCMOLT_EPON_NI_OPER_ID_ISSUE_ROGUE_RX_POWER*/
BCMOLT_OPER_INIT(&issue_llid_scan_op, epon_ni, rogue_llid_scan , ni_key);
BCMOLT_OPER_PROP_SET(&issue_llid_scan_op, epon_ni, rogue_llid_scan, mode, scan_mode);
BCMOLT_OPER_PROP_SET(&issue_llid_scan_op, epon_ni, rogue_llid_scan, llid, llid);
BCM_LOG_CALLER_FMT(INFO, omon_log_id,
"Issue Rogue Scan Operation for LLID 0x%x, Pon_ni=%d\r\n", llid, link_key->epon_ni);
rc = bcmolt_oper_submit(link_key->device_id, &issue_llid_scan_op.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, omon_log_id,
"Rogue Scan Operation Failed with rc %d (%s)\n",
rc, bcmos_strerror(rc));
return;
}
}/*omon_run_rogue_llid_scan*/
/**
* \brief Execute RSSI measurement
*
* This function sends an API message to the OLT to issue an RSSI grant. It
* then reads back the results via I2C. Set grant_length_tq to 0 to retreive the
* RSSI value without issuing the strobe command to the OLT.
*
* \param link_key EPON RSSI link information
* \param grant_length_tq Size of the RSSI grant
* \param start_offset Strobe offset from start of the RSSI grant
* \param end_offset Strobe offset from the end of the RSSI grant
*
* \return
* None
*/
static
void omon_rssi_measurement_initiate(bcmcli_session *session,
omon_link_key *link_key,
uint16_t trigger_width_tq,
uint16_t trigger_delay_tq,
uint16_t sample_period)
{
const bcmolt_epon_ni_key ni_key = { .epon_ni = link_key->epon_ni };
bcmolt_epon_ni_issue_rssi_grant issue_rssi_grant_op;
bcmos_errno rc = BCM_ERR_OK;
if (! omon_is_epon_ni_valid(link_key->epon_ni))
{
BCM_LOG(ERROR, omon_log_id,
"[OMON] Rx Power: epon_ni of (%d) is out of range for platform\n", link_key->epon_ni);
return ;
}
uint8_t trx_id;
if ( ! trx_id_from_epon_ni(link_key->epon_ni, &trx_id) )
{
BCM_LOG(ERROR, omon_log_id,
"[OMON] Rx Power: TRX Id is invalid for EPON NI %d \n", link_key->epon_ni);
return;
}
// Check for transevier presence
rc = bcm_board_trx_present(trx_id);
if (rc == BCM_ERR_NODEV)
{
bcmcli_session_print(session,
"[OMON] Rx Power: TRX Not Present on PON %d\r\n ", link_key->epon_ni);
return;
}
/* Perform an API operation directing the Maple firmware to issue an bcmolt_epon_ni_issue_rogue_rx_power
RSSI grant to the specified EPON link. BCMOLT_EPON_NI_OPER_ID_ISSUE_ROGUE_RX_POWER*/
BCMOLT_OPER_INIT(&issue_rssi_grant_op, epon_ni, issue_rssi_grant , ni_key);
BCMOLT_OPER_PROP_SET(&issue_rssi_grant_op, epon_ni, issue_rssi_grant,
granted_link, link_key->mac_address);
BCMOLT_OPER_PROP_SET(&issue_rssi_grant_op, epon_ni, issue_rssi_grant,
trigger_width, trigger_width_tq);
BCMOLT_OPER_PROP_SET(&issue_rssi_grant_op, epon_ni, issue_rssi_grant,
trigger_delay, trigger_delay_tq);
BCMOLT_OPER_PROP_SET(&issue_rssi_grant_op, epon_ni, issue_rssi_grant,
sample_period, sample_period);
rc = bcmolt_oper_submit(link_key->device_id, &issue_rssi_grant_op.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, omon_log_id,
"issue RSSI grant operation failed with rc %d (%s)\n",
rc, bcmos_strerror(rc));
return;
}
}
/*omon_rssi_measurement_initiate*/
// rssi specific indication handler interface --
static bcmos_errno bcmolt_user_appl_rssi_handle_ind(bcmolt_devid device_id,
uint8_t instance,
bcmolt_auto *ind)
{
bcmolt_epon_ni_rssi_measurement_completed* omon_ind;
uint32_t rssi_value = 0;
bcmolt_epon_ni epon_ni;
bcmos_errno rc = BCM_ERR_OK;
char tBuf[40];
omon_ind = (bcmolt_epon_ni_rssi_measurement_completed *) ind;
epon_ni = omon_ind->key.epon_ni;
if (omon_ind->data.status == BCMOLT_RESULT_SUCCESS)
{
/* Perform the I2C operations specified in SFF-8472 (SFP)/SFF-8077i (XFP) to
retrieve the power measurements from the optics module. */
rc = omon_rssi_read(epon_ni, &rssi_value);
}
/* Notify external host code of the outcome through an optional callback,
defaulting to output in the CLI session where the command was initiated
if no callback is supplied. */
BCM_LOG_CALLER_FMT(INFO, omon_log_id,
" RSSI Indication Rcv: for Link Mac %s, LLID 0x%x, Dev=%01d, Pon_ni=%d\r\n",
bcmos_mac_2_str(&omon_ind->data.link_mac, tBuf),
omon_ind->data.llid,
device_id,
omon_ind->key.epon_ni);
if (rc == BCM_ERR_OK)
{
BCM_LOG(INFO, omon_log_id,
" %s measured rx power %d.%duW raw_data %d\n",
(omon_ind->data.status == BCMOLT_RESULT_SUCCESS ? "Succeeded" : "Failed"),
rssi_value/10, rssi_value%10, rssi_value);
}
else
{
BCM_LOG(INFO, omon_log_id,
"pon %d, failed with errno %d (%s)\n",
epon_ni, rc, bcmos_strerror(rc));
}
return rc;
}
// epon rogue onu specific indication handler interface --
static bcmos_errno bcmolt_user_appl_rogue_handle_ind(bcmolt_devid device_id,
uint8_t instance,
bcmolt_auto *ind)
{
(void)instance;
bcmolt_epon_denied_link_rogue_violation* rogue_ind;
char tBuf[40];
rogue_ind = (bcmolt_epon_denied_link_rogue_violation *) ind;
/* Notify external host code of the outcome through an optional callback,
defaulting to output in the CLI session where the command was initiated
if no callback is supplied. */
BCM_LOG_CALLER_FMT(INFO, omon_log_id,
"Rogue ONU Scan Violation: AlmState = %s, Link Mac %s, LLID 0x%x, Range=%0d, Pon_ni=%2d\r\n",
(rogue_ind->data.alarm_status.alarm_status == BCMOLT_STATUS_ON ? "ON" : "OFF"),
bcmos_mac_2_str(&rogue_ind->key.mac_address, tBuf),
rogue_ind->data.alarm_status.denied_llid,
rogue_ind->data.alarm_status.denied_range,
rogue_ind->key.epon_ni);
return BCM_ERR_OK;
}
// epon rogue scan complete specific indication handler interface --
static bcmos_errno bcmolt_user_appl_rogue_complete_handle_ind(bcmolt_devid device_id,
uint8_t instance,
bcmolt_auto *ind)
{
(void)instance;
bcmolt_epon_ni_rogue_scan_complete* rogue_ind;
rogue_ind = (bcmolt_epon_ni_rogue_scan_complete *) ind;
/* Notify external host code of the outcome through an optional callback,
defaulting to output in the CLI session where the command was initiated
if no callback is supplied. */
BCM_LOG_CALLER_FMT(INFO, omon_log_id,
"Rogue ONU scan complete for Pon %d, Status = %s\r\n",
rogue_ind->key.epon_ni,
bcmolt_get_scan_result(rogue_ind->data.return_ind_status));
return BCM_ERR_OK;
}
// public indication handler interface -- called in transport layer context
bcmos_errno bcmolt_user_appl_omon_handle_ind(bcmolt_devid device_id, uint8_t instance, bcmolt_auto *ind)
{
// Not an error, we just don't care about this indication.
bcmos_errno rc = BCM_ERR_OK;
// We look at message targetting epon ni.
if (ind->hdr.obj_type == BCMOLT_OBJ_ID_EPON_NI)
{
// We look at RSSI Completion event indications.
if (ind->hdr.subgroup == (uint16_t)BCMOLT_EPON_NI_AUTO_ID_RSSI_MEASUREMENT_COMPLETED)
{
rc = bcmolt_user_appl_rssi_handle_ind(device_id,instance,ind);
}
else
{
// We look for Rogue Scan Complete event indications.
if (ind->hdr.subgroup == (uint16_t)BCMOLT_EPON_NI_AUTO_ID_ROGUE_SCAN_COMPLETE)
{
rc = bcmolt_user_appl_rogue_complete_handle_ind(device_id, instance, ind);
}
}
if (rc != BCM_ERR_OK )
{
BCM_LOG_CALLER_FMT(INFO, omon_log_id,
"OMON Handle Indication Error: Pon %d, Type %d, Rc %d\r\n",
instance, ind->hdr.subgroup, rc);
}
// Not an error, we just don't care about this indication.
return BCM_ERR_OK;
}
// We look at message targetting epon denied links.
if (ind->hdr.obj_type == BCMOLT_OBJ_ID_EPON_DENIED_LINK)
{
// We look at Denied Link Events of this type.
if (ind->hdr.subgroup == BCMOLT_EPON_DENIED_LINK_AUTO_ID_ROGUE_VIOLATION)
{
rc = bcmolt_user_appl_rogue_handle_ind(device_id, instance, ind);
}
else
{
// Not an error, we just don't care about this object.
return BCM_ERR_OK;
}
}
return rc;
} /* bcmolt_user_appl_omon_handle_ind */
/**
* \brief Optical monitoring task message handler
*
* This function is the optical monitoring task handler. At this time the only
* message is BCMOS_MSG_ID_INITIATE_RSSI_SAMPLE which starts the RSSI
* measurement on the OLT.
*
* \param module_id BCMOS_MODULE_ID_USER_APPL_OMON
* \param os_msg Message contents
*/
static
void omon_os_msg_handle(bcmos_module_id module_id, bcmos_msg *os_msg)
{
omon_task_msg *msg = (omon_task_msg *)os_msg;
switch (msg->os_msg.type)
{
case BCMOS_MSG_ID_INITIATE_RX_POWER:
omon_rssi_measurement_initiate(msg->session,
&msg->link_key,
msg->trigger_width_ns ,
msg->trigger_delay_ns,
msg->sample_period_us);
break;
case BCMOS_MSG_ID_INITIATE_TRX_STATUS:
omon_trx_status_initiate(msg->session,
&msg->link_key);
break;
case BCMOS_MSG_ID_INITIATE_ROGUE_SCAN:
omon_run_rogue_llid_scan(msg->session,
&msg->link_key,
msg->llid,
msg->scan_mode);
break;
case BCMOS_MSG_ID_INITIATE_RSSI_READ:
omon_rssi_read_initiate(msg->session,
&msg->link_key);
break;
default:
break;
}
bcmos_free(os_msg);
} /* omon_os_msg_handle */
/**
* \brief Start the optical monitoring task
*
* This function starts the user level optical monitoring task and creates the
* optical monitoring module. It should only be called once at start up.
*
* \return
* None
*/
void bcmolt_epon_omon_appl_init(void)
{
bcmos_errno rc;
bcmos_task_parm task_params =
{
.name = "user_appl_omon",
.priority = TASK_PRIORITY_USER_APPL_OMON,
.core = BCMOS_CPU_CORE_ANY, /* No CPU affinity */
.init_handler = NULL
};
bcmos_module_parm module_params =
{
.qparm =
{
.name = "user_appl_omon",
.size = OMON_TASK_MSG_Q_SIZE
}
};
if (is_running)
{
return;
}
omon_log_id = bcm_dev_log_id_register("user_appl_omon",
DEV_LOG_LEVEL_INFO,
DEV_LOG_ID_TYPE_BOTH);
BUG_ON(DEV_LOG_INVALID_ID == omon_log_id);
rc = bcmos_task_create(&omon_task, &task_params);
BUG_ON(rc != BCM_ERR_OK);
rc = bcmos_module_create(BCMOS_MODULE_ID_USER_APPL_OMON, &omon_task,
&module_params);
BUG_ON(rc != BCM_ERR_OK);
is_running = BCMOS_TRUE;
} /* bcmolt_epon_omon_appl_init */
/*******************************************************************************
* CLI
******************************************************************************/
/**
* \brief RX power sample CLI command
*
* This function handles the "sample" CLI command. It processes the CLI
* parameters and dispatches a start sample message to the optical monitoring
* task.
*
* \param session CLI session ID
* \param parm Command parameters
* \param n_parms Number of parameters
*
* \return
* BCM_ERR_OK if successful, error code if not
*/
static
bcmos_errno omon_cmd_rx_power(bcmcli_session *session,
const bcmcli_cmd_parm parm[],
uint16_t n_parms)
{
omon_link_key link_key;
bcmos_errno rc;
bcmcli_cmd_parm *epon_ni;
bcmcli_cmd_parm *mac_addr;
bcmcli_cmd_parm *Twidth_ns;
bcmcli_cmd_parm *Tdelay_ns;
bcmcli_cmd_parm *Tsample_us;
omon_task_msg *msg;
/* Get the CLI parameters. */
epon_ni = bcmcli_find_named_parm(session, "epon_ni");
mac_addr = bcmcli_find_named_parm(session, "granted_link");
Twidth_ns = bcmcli_find_named_parm(session, "trigger_width"); // RSSI Twidth in ns
Tdelay_ns = bcmcli_find_named_parm(session, "trigger_delay"); // RSSI Tdelay in ns
Tsample_us = bcmcli_find_named_parm(session, "sample_period"); // RSSI Tsample in us
link_key.device_id = current_device;
link_key.epon_ni = (bcmolt_epon_ni)epon_ni->value.number;
link_key.mac_address = (bcmos_mac_address)mac_addr->value.mac;
/* Send an indication to the internal task's message queue to be
processed. */
msg = bcmos_calloc(sizeof(*msg));
BUG_ON(msg == NULL);
msg->os_msg.type = BCMOS_MSG_ID_INITIATE_RX_POWER;
msg->os_msg.handler = omon_os_msg_handle;
msg->link_key = link_key;
msg->trigger_width_ns = Twidth_ns->value.number;
msg->trigger_delay_ns = Tdelay_ns->value.number;
msg->sample_period_us = Tsample_us->value.number;
msg->session = session;
rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_OMON,
&msg->os_msg, 0);
BUG_ON(rc);
return rc;
} /* omon_cmd_sample */
static
bcmos_errno omon_cmd_trx_data(bcmcli_session *session,
const bcmcli_cmd_parm parm[],
uint16_t n_parms)
{
omon_link_key link_key;
bcmos_errno rc;
bcmcli_cmd_parm *epon_ni;
omon_task_msg *msg;
/* Get the CLI parameters. */
epon_ni = bcmcli_find_named_parm(session, "epon_ni");
link_key.device_id = current_device;
link_key.epon_ni = (bcmolt_epon_ni)epon_ni->value.number;
/* Send an indication to the internal task's message queue to be
processed. */
msg = bcmos_calloc(sizeof(*msg));
BUG_ON(msg == NULL);
msg->os_msg.type = BCMOS_MSG_ID_INITIATE_TRX_STATUS;
msg->os_msg.handler = omon_os_msg_handle;
msg->link_key = link_key;
msg->session = session;
rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_OMON,
&msg->os_msg, 0);
BUG_ON(rc);
return rc;
}
/* omon_cmd_trx_data */
static
bcmos_errno omon_cmd_read_rssi_result(bcmcli_session *session,
const bcmcli_cmd_parm parm[],
uint16_t n_parms)
{
omon_link_key link_key;
bcmos_errno rc;
bcmcli_cmd_parm *epon_ni;
omon_task_msg *msg;
/* Get the CLI parameters. */
epon_ni = bcmcli_find_named_parm(session, "epon_ni");
link_key.device_id = current_device;
link_key.epon_ni = (bcmolt_epon_ni)epon_ni->value.number;
/* Send an indication to the internal task's message queue to be
processed. */
msg = bcmos_calloc(sizeof(*msg));
BUG_ON(msg == NULL);
msg->os_msg.type = BCMOS_MSG_ID_INITIATE_RSSI_READ;
msg->os_msg.handler = omon_os_msg_handle;
msg->link_key = link_key;
msg->session = session;
rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_OMON,
&msg->os_msg, 0);
BUG_ON(rc);
return rc;
}
/* omon_cmd_read_rssi_result */
static
bcmos_errno omon_cmd_llid_scan(bcmcli_session *session,
const bcmcli_cmd_parm parm[],
uint16_t n_parms)
{
omon_link_key link_key;
bcmos_errno rc;
bcmcli_cmd_parm *epon_ni;
bcmcli_cmd_parm *epon_llid;
bcmcli_cmd_parm *epon_mode;
omon_task_msg *msg;
/* Get the CLI parameters. */
epon_ni = bcmcli_find_named_parm(session, "epon_ni");
epon_mode = bcmcli_find_named_parm(session, "scan_mode");
epon_llid = bcmcli_find_named_parm(session, "epon_llid");
link_key.device_id = current_device;
link_key.epon_ni = (bcmolt_epon_ni)epon_ni->value.number;
/* Send an indication to the internal task's message queue to be
processed. */
msg = bcmos_calloc(sizeof(*msg));
BUG_ON(msg == NULL);
msg->os_msg.type = BCMOS_MSG_ID_INITIATE_ROGUE_SCAN;
msg->os_msg.handler = omon_os_msg_handle;
msg->link_key = link_key;
msg->session = session;
msg->llid = epon_llid->value.number;
msg->scan_mode = epon_mode->value.number;
rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_OMON,
&msg->os_msg, 0);
BUG_ON(rc);
return rc;
}
/**
* \brief Install CLI commands
*
* This function creates and optical monitoring command directoy "omon" and
* installs optical monitoring CLI commands to this directory.
*
* \param top_dir Parent of "omon" directory
*
* \return
* BCM_ERR_OK if successful, error code if not
*/
void bcmolt_user_appl_epon_omon_cli_init(bcmcli_entry *top_dir)
{
static const char *dir_name = "omon";
if (bcmcli_dir_find(top_dir, dir_name))
{
return;
}
bcmcli_entry *dir = bcmcli_dir_add(top_dir,
dir_name,
"EPON optical monitoring commands",
BCMCLI_ACCESS_ADMIN, NULL);
BUG_ON(dir == NULL);
BCMCLI_MAKE_CMD(dir, "rx_power", "Issue RX Power Measurement", omon_cmd_rx_power,
BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0),
BCMCLI_MAKE_PARM("granted_link", "Link mac address, 000000000000 for Idle Power", BCMCLI_PARM_MAC, 0),
BCMCLI_MAKE_PARM("trigger_width",
"RSSI Trigger Width (Tw) in ns, Desired width of RSSI Trigger based on the Optical Module Specifications."
"This is a mandatory parameter used for all RX Power measurements ( including Idle power) and must not be 0."
"Note: The granularity of the device is 1 TQ (16ns) the input will be rounded up to the next TQ."
, BCMCLI_PARM_NUMBER, 0),
BCMCLI_MAKE_PARM("trigger_delay",
"RSSI Trigger Delay (Td) in ns, Desired delay to meet the trigger delay timing requirement of the Optical Module Specifications."
"The rssi trigger delay is measured from the start of sync_time and is adjusted as needed. "
"The trigger delay moves the assertion of the RSSI Trigger strobe into the grant window."
"Note: The granularity of the device is 1 TQ (16ns) the input will be rounded up to the next TQ."
, BCMCLI_PARM_NUMBER, 0),
BCMCLI_MAKE_PARM("sample_period",
"(Ti2c) Sample period in uS, internal I2C hold/prohibit time where access to device is not allowed."
"During this period the internal RSSI data is invalid and I2C opertions on this device must not be executed."
"A value of 500uS is recommended for most applications. "
, BCMCLI_PARM_NUMBER, 0));
BCMCLI_MAKE_CMD(dir, "trx_data", "Read Tranceiver Data", omon_cmd_trx_data,
BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0));
BCMCLI_MAKE_CMD(dir, "read_rssi", "Read RSSI Result from Tranceiver", omon_cmd_read_rssi_result,
BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0));
BCMCLI_MAKE_CMD(dir, "llid_scan", "Run Rogue ONU LLID Scan", omon_cmd_llid_scan,
BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0),
BCMCLI_MAKE_PARM("scan_mode", "LLID scan mode 1 for full pon scan, 0 for targeted (llid required for targeted)", BCMCLI_PARM_NUMBER, 0),
BCMCLI_MAKE_PARM("epon_llid", "EPON llid to scan when mode=0", BCMCLI_PARM_HEX, 0));
}
/* bcmolt_user_appl_epon_omon_cli_init */
/* End of file omon.c */