| /* |
| <: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 */ |
| |