nsmd: FPGA link and optical module telemetry Add the C2C and Ethernet link group to the LP30 map: eight C2C per-lane pcs-ready rules (lane l of a connection is channel 3-l of its bank) and, per Ethernet MAC, pcs-ready, local fault, remote fault and high-BER. Each reads one status word on the link's AVMM station and decodes one active-high bit; fault rules first gate on the fault reporting enable word. Add the five optical module cages as table rows: a group per module whose setup rows read the mux mask, select the presence expander and read its pins and its reset latch and direction, end the round as Absent, NotPowered or Standby (reset still held) from those bytes, select the module channel, read the CMIS header, bank and page bytes, select page 1 and read the bank count and monitor capability bytes into the group buffer; group cleanup gives the bank, page and mux mask back. Every module shares one item row set: presence, power good and module state decode from the group buffer without rows, inventory reads page 0 bytes 129 to 181 once (manufacturer, part number, revision, serial number), temperature reads bytes 14 and 15 each round, and the Tx_Fault, Rx_Los, Tx_Power and Rx_Power lane vectors read page 0x11 of every bank the module has while the module is ready, each gated on its capability bit. The lane items publish on the module object through the shared PortOpticalModuleMetrics and OpticalLaneStatus interfaces. The engine is unchanged; this is two part files of the map with their table test. Change-Id: I9bc6a97cb631aba6858c544a0cb99b78533b5e2a
diff --git a/libnsm/fpga/fpga-rules-lp30-links.c b/libnsm/fpga/fpga-rules-lp30-links.c new file mode 100644 index 0000000..f68ed0a --- /dev/null +++ b/libnsm/fpga/fpga-rules-lp30-links.c
@@ -0,0 +1,205 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright OpenBMC Authors +/* clang-format off */ +/* Generated from fpga-rules-lp30-links.rows by gen-fpga-rules.py, do not edit. */ +#include "fpga-tables.h" + +#include <math.h> + +static const struct nsm_fpga_command rows_C2C_0_Lane_0_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 9, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_state_entry states_C2C_0_Lane_0_Pcs_Ready[] = { + {8, 8, NSM_FPGA_STATE_ENABLED, NSM_FPGA_HEALTH_OK}, + {0, 0, NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, NSM_FPGA_HEALTH_WARNING}, +}; + +static const struct nsm_fpga_command rows_C2C_0_Lane_1_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 7, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_C2C_0_Lane_2_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 5, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_C2C_0_Lane_3_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 3, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_C2C_1_Lane_0_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 17, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_C2C_1_Lane_1_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 15, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_C2C_1_Lane_2_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 13, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_C2C_1_Lane_3_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 11, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_Ethernet_0_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 19, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_Ethernet_0_Local_Fault[] = { + {.op = NSM_FPGA_OP_READ32, .station = 19, .u = {.csr = {0x100, 0}}, .expect = {.mask = 0xe0, .value = 0xa0}}, + {.op = NSM_FPGA_OP_READ32, .station = 19, .u = {.csr = {0x4200, 0}}, .expect = {.mask = 1, .value = 1}}, + {.op = NSM_FPGA_OP_READ32, .station = 19, .u = {.csr = {0x120, 0}}}, +}; + +static const struct nsm_fpga_state_entry states_Ethernet_0_Local_Fault[] = { + {1, 1, NSM_FPGA_STATE_FAULT, NSM_FPGA_HEALTH_CRITICAL}, + {0, 0, NSM_FPGA_STATE_ENABLED, NSM_FPGA_HEALTH_OK}, +}; + +static const struct nsm_fpga_state_entry states_Ethernet_0_Remote_Fault[] = { + {2, 2, NSM_FPGA_STATE_FAULT, NSM_FPGA_HEALTH_CRITICAL}, + {0, 0, NSM_FPGA_STATE_ENABLED, NSM_FPGA_HEALTH_OK}, +}; + +static const struct nsm_fpga_command rows_Ethernet_0_High_Ber[] = { + {.op = NSM_FPGA_OP_READ32, .station = 19, .u = {.csr = {0x100, 0}}, .expect = {.mask = 0xe0, .value = 0xa0}}, + {.op = NSM_FPGA_OP_READ32, .station = 19, .u = {.csr = {0x4084, 0}}}, +}; + +static const struct nsm_fpga_command rows_Ethernet_1_Pcs_Ready[] = { + {.op = NSM_FPGA_OP_READ32, .station = 24, .u = {.csr = {0x118, 0}}}, +}; + +static const struct nsm_fpga_command rows_Ethernet_1_Local_Fault[] = { + {.op = NSM_FPGA_OP_READ32, .station = 24, .u = {.csr = {0x100, 0}}, .expect = {.mask = 0xe0, .value = 0xa0}}, + {.op = NSM_FPGA_OP_READ32, .station = 24, .u = {.csr = {0x4200, 0}}, .expect = {.mask = 1, .value = 1}}, + {.op = NSM_FPGA_OP_READ32, .station = 24, .u = {.csr = {0x120, 0}}}, +}; + +static const struct nsm_fpga_command rows_Ethernet_1_High_Ber[] = { + {.op = NSM_FPGA_OP_READ32, .station = 24, .u = {.csr = {0x100, 0}}, .expect = {.mask = 0xe0, .value = 0xa0}}, + {.op = NSM_FPGA_OP_READ32, .station = 24, .u = {.csr = {0x4084, 0}}}, +}; + +static const struct nsm_fpga_rule rules_links[] = { + {.name = "C2C_0_Lane_0_Pcs_Ready", + .commands = rows_C2C_0_Lane_0_Pcs_Ready, + .command_count = sizeof(rows_C2C_0_Lane_0_Pcs_Ready) / sizeof(rows_C2C_0_Lane_0_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_0_Lane_1_Pcs_Ready", + .commands = rows_C2C_0_Lane_1_Pcs_Ready, + .command_count = sizeof(rows_C2C_0_Lane_1_Pcs_Ready) / sizeof(rows_C2C_0_Lane_1_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_0_Lane_2_Pcs_Ready", + .commands = rows_C2C_0_Lane_2_Pcs_Ready, + .command_count = sizeof(rows_C2C_0_Lane_2_Pcs_Ready) / sizeof(rows_C2C_0_Lane_2_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_0_Lane_3_Pcs_Ready", + .commands = rows_C2C_0_Lane_3_Pcs_Ready, + .command_count = sizeof(rows_C2C_0_Lane_3_Pcs_Ready) / sizeof(rows_C2C_0_Lane_3_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_1_Lane_0_Pcs_Ready", + .commands = rows_C2C_1_Lane_0_Pcs_Ready, + .command_count = sizeof(rows_C2C_1_Lane_0_Pcs_Ready) / sizeof(rows_C2C_1_Lane_0_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_1_Lane_1_Pcs_Ready", + .commands = rows_C2C_1_Lane_1_Pcs_Ready, + .command_count = sizeof(rows_C2C_1_Lane_1_Pcs_Ready) / sizeof(rows_C2C_1_Lane_1_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_1_Lane_2_Pcs_Ready", + .commands = rows_C2C_1_Lane_2_Pcs_Ready, + .command_count = sizeof(rows_C2C_1_Lane_2_Pcs_Ready) / sizeof(rows_C2C_1_Lane_2_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "C2C_1_Lane_3_Pcs_Ready", + .commands = rows_C2C_1_Lane_3_Pcs_Ready, + .command_count = sizeof(rows_C2C_1_Lane_3_Pcs_Ready) / sizeof(rows_C2C_1_Lane_3_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "C2C_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "Ethernet_0_Pcs_Ready", + .commands = rows_Ethernet_0_Pcs_Ready, + .command_count = sizeof(rows_Ethernet_0_Pcs_Ready) / sizeof(rows_Ethernet_0_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "Ethernet_0_Local_Fault", + .commands = rows_Ethernet_0_Local_Fault, + .command_count = sizeof(rows_Ethernet_0_Local_Fault) / sizeof(rows_Ethernet_0_Local_Fault[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_Ethernet_0_Local_Fault, + .state_count = sizeof(states_Ethernet_0_Local_Fault) / sizeof(states_Ethernet_0_Local_Fault[0])}, + {.name = "Ethernet_0_Remote_Fault", + .commands = rows_Ethernet_0_Local_Fault, + .command_count = sizeof(rows_Ethernet_0_Local_Fault) / sizeof(rows_Ethernet_0_Local_Fault[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_Ethernet_0_Remote_Fault, + .state_count = sizeof(states_Ethernet_0_Remote_Fault) / sizeof(states_Ethernet_0_Remote_Fault[0])}, + {.name = "Ethernet_0_High_Ber", + .commands = rows_Ethernet_0_High_Ber, + .command_count = sizeof(rows_Ethernet_0_High_Ber) / sizeof(rows_Ethernet_0_High_Ber[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_Ethernet_0_Remote_Fault, + .state_count = sizeof(states_Ethernet_0_Remote_Fault) / sizeof(states_Ethernet_0_Remote_Fault[0])}, + {.name = "Ethernet_1_Pcs_Ready", + .commands = rows_Ethernet_1_Pcs_Ready, + .command_count = sizeof(rows_Ethernet_1_Pcs_Ready) / sizeof(rows_Ethernet_1_Pcs_Ready[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_C2C_0_Lane_0_Pcs_Ready, + .state_count = sizeof(states_C2C_0_Lane_0_Pcs_Ready) / sizeof(states_C2C_0_Lane_0_Pcs_Ready[0])}, + {.name = "Ethernet_1_Local_Fault", + .commands = rows_Ethernet_1_Local_Fault, + .command_count = sizeof(rows_Ethernet_1_Local_Fault) / sizeof(rows_Ethernet_1_Local_Fault[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_Ethernet_0_Local_Fault, + .state_count = sizeof(states_Ethernet_0_Local_Fault) / sizeof(states_Ethernet_0_Local_Fault[0])}, + {.name = "Ethernet_1_Remote_Fault", + .commands = rows_Ethernet_1_Local_Fault, + .command_count = sizeof(rows_Ethernet_1_Local_Fault) / sizeof(rows_Ethernet_1_Local_Fault[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_Ethernet_0_Remote_Fault, + .state_count = sizeof(states_Ethernet_0_Remote_Fault) / sizeof(states_Ethernet_0_Remote_Fault[0])}, + {.name = "Ethernet_1_High_Ber", + .commands = rows_Ethernet_1_High_Ber, + .command_count = sizeof(rows_Ethernet_1_High_Ber) / sizeof(rows_Ethernet_1_High_Ber[0]), + .kind = NSM_FPGA_RULE_STATE, + .group = "Ethernet_Link", + .states = states_Ethernet_0_Remote_Fault, + .state_count = sizeof(states_Ethernet_0_Remote_Fault) / sizeof(states_Ethernet_0_Remote_Fault[0])}, +}; + +extern const struct nsm_fpga_part nsm_fpga_part_links; +const struct nsm_fpga_part nsm_fpga_part_links = { + .rules = rules_links, + .rule_count = sizeof(rules_links) / sizeof(rules_links[0]), +};
diff --git a/libnsm/fpga/fpga-rules-lp30-links.rows b/libnsm/fpga/fpga-rules-lp30-links.rows new file mode 100644 index 0000000..2159c6a --- /dev/null +++ b/libnsm/fpga/fpga-rules-lp30-links.rows
@@ -0,0 +1,98 @@ +# LP30 C2C and Ethernet link telemetry: pcs ready, faults and high BER +# from the link AVMM stations. +# gen-fpga-rules.py turns this file into fpga-rules-lp30-links.c. + +part links +include fpga-rules-lp30.rows + +# C2C and Ethernet links: pcs status 0x118 and link fault 0x120 are station +# relative; rx-pcs status 0x84 and fault enable 0x200 sit in the window the +# rate field of gui-option 0x100 (bits 5 to 7) selects, 0x4000 for 200GE +const LINK_PCS_READY_BIT 0x8 +const LINK_LOCAL_FAULT_BIT 0x1 +const LINK_REMOTE_FAULT_BIT 0x2 +const LINK_HIGH_BER_BIT 0x2 +const LINK_FAULT_ENABLE_BIT 0x1 +const LINK_RATE_MASK 0xe0 +const LINK_RATE_200GE 0xa0 +const ETH_RATE_BASE 0x4000 + +# C2C connection c is bank 13A (c 0) or 13C (c 1); its lane l is channel 3-l +seq link_ready st grp + kind state + group $grp + state LINK_PCS_READY_BIT LINK_PCS_READY_BIT enabled ok + state default unavailable warning + read32 $st 0x118 +end +# Rows in the rate window first confirm the rate, fault rows also that fault +# reporting is enabled; a disabled fault reports unavailable, never clear +seq link_rate st + read32 $st 0x100 expect & LINK_RATE_MASK == LINK_RATE_200GE +end +seq link_fault st bit + kind state + group Ethernet_Link + state $bit $bit fault critical + state default enabled ok + use link_rate $st + read32 $st ETH_RATE_BASE+0x200 expect & LINK_FAULT_ENABLE_BIT == LINK_FAULT_ENABLE_BIT + read32 $st 0x120 +end +seq link_high_ber st + kind state + group Ethernet_Link + state LINK_HIGH_BER_BIT LINK_HIGH_BER_BIT fault critical + state default enabled ok + use link_rate $st + read32 $st ETH_RATE_BASE+0x84 +end + +rule C2C_0_Lane_0_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth3_mm_B13A_C2C_LOWER_QSFP_3 C2C_Link +end +rule C2C_0_Lane_1_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth2_mm_B13A_C2C_LOWER_QSFP_2 C2C_Link +end +rule C2C_0_Lane_2_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth1_mm_B13A_C2C_LOWER_QSFP_1 C2C_Link +end +rule C2C_0_Lane_3_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth0_mm_B13A_C2C_LOWER_QSFP_0 C2C_Link +end +rule C2C_1_Lane_0_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth3_mm_B13C_C2C_LOWER_QSFP_3 C2C_Link +end +rule C2C_1_Lane_1_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth2_mm_B13C_C2C_LOWER_QSFP_2 C2C_Link +end +rule C2C_1_Lane_2_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth1_mm_B13C_C2C_LOWER_QSFP_1 C2C_Link +end +rule C2C_1_Lane_3_Pcs_Ready + use link_ready GroqNetV2_reconfig_eth0_mm_B13C_C2C_LOWER_QSFP_0 C2C_Link +end +rule Ethernet_0_Pcs_Ready + use link_ready Network_reconfig_eth0_mm_B12A_Q2_LOWER_QSFP_200G_LOWER_QSFP Ethernet_Link +end +rule Ethernet_0_Local_Fault + use link_fault Network_reconfig_eth0_mm_B12A_Q2_LOWER_QSFP_200G_LOWER_QSFP LINK_LOCAL_FAULT_BIT +end +rule Ethernet_0_Remote_Fault + use link_fault Network_reconfig_eth0_mm_B12A_Q2_LOWER_QSFP_200G_LOWER_QSFP LINK_REMOTE_FAULT_BIT +end +rule Ethernet_0_High_Ber + use link_high_ber Network_reconfig_eth0_mm_B12A_Q2_LOWER_QSFP_200G_LOWER_QSFP +end +rule Ethernet_1_Pcs_Ready + use link_ready Network_reconfig_eth0_mm_B12A_Q3_LOWER_QSFP_200G_LOWER_QSFP Ethernet_Link +end +rule Ethernet_1_Local_Fault + use link_fault Network_reconfig_eth0_mm_B12A_Q3_LOWER_QSFP_200G_LOWER_QSFP LINK_LOCAL_FAULT_BIT +end +rule Ethernet_1_Remote_Fault + use link_fault Network_reconfig_eth0_mm_B12A_Q3_LOWER_QSFP_200G_LOWER_QSFP LINK_REMOTE_FAULT_BIT +end +rule Ethernet_1_High_Ber + use link_high_ber Network_reconfig_eth0_mm_B12A_Q3_LOWER_QSFP_200G_LOWER_QSFP +end
diff --git a/libnsm/fpga/fpga-rules-lp30-optics.c b/libnsm/fpga/fpga-rules-lp30-optics.c new file mode 100644 index 0000000..dff7e29 --- /dev/null +++ b/libnsm/fpga/fpga-rules-lp30-optics.c
@@ -0,0 +1,639 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright OpenBMC Authors +/* clang-format off */ +/* Generated from fpga-rules-lp30-optics.rows by gen-fpga-rules.py, do not edit. */ +#include "fpga-tables.h" + +#include <math.h> + +static const struct nsm_fpga_state_entry states_Optics_0[] = { + {0x10, 0, NSM_FPGA_STATE_ENABLED, NSM_FPGA_HEALTH_OK}, + {0, 0, NSM_FPGA_STATE_ABSENT, NSM_FPGA_HEALTH_OK}, +}; + +static const struct nsm_fpga_state_entry states_Optics_0_Power_Good[] = { + {2, 2, NSM_FPGA_STATE_ENABLED, NSM_FPGA_HEALTH_OK}, + {0, 0, NSM_FPGA_STATE_FAULT, NSM_FPGA_HEALTH_CRITICAL}, +}; + +static const struct nsm_fpga_state_entry states_Optics_0_Module_State[] = { + {0xe, 6, NSM_FPGA_STATE_ENABLED, NSM_FPGA_HEALTH_OK}, + {0xe, 4, NSM_FPGA_STATE_STARTING, NSM_FPGA_HEALTH_OK}, + {0xe, 2, NSM_FPGA_STATE_STANDBY_OFFLINE, NSM_FPGA_HEALTH_OK}, + {0xe, 8, NSM_FPGA_STATE_STANDBY_OFFLINE, NSM_FPGA_HEALTH_OK}, + {0xe, 0xa, NSM_FPGA_STATE_FAULT, NSM_FPGA_HEALTH_CRITICAL}, + {0, 0, NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, NSM_FPGA_HEALTH_WARNING}, +}; + +static const struct nsm_fpga_command rows_Optics_0_Inventory[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x81, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x85, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x89, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x8d, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x91, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x95, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x99, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9d, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa1, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa5, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa9, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xad, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xb1, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xb5, 0, 0}, 1, 1, 0, 0}}}, +}; + +static const struct nsm_fpga_identity_field fields_Optics_0_Inventory[] = { + {.asset = NSM_FPGA_ASSET_MANUFACTURER, .format = NSM_FPGA_IDENTITY_ASCII, .buffer = NSM_FPGA_BUF_ITEM, .offset = 0, .length = 16}, + {.asset = NSM_FPGA_ASSET_PART, .format = NSM_FPGA_IDENTITY_ASCII, .buffer = NSM_FPGA_BUF_ITEM, .offset = 19, .length = 16}, + {.asset = NSM_FPGA_ASSET_REVISION, .format = NSM_FPGA_IDENTITY_ASCII, .buffer = NSM_FPGA_BUF_ITEM, .offset = 35, .length = 2}, + {.asset = NSM_FPGA_ASSET_SERIAL, .format = NSM_FPGA_IDENTITY_ASCII, .buffer = NSM_FPGA_BUF_ITEM, .offset = 37, .length = 16}, +}; + +static const struct nsm_fpga_command rows_Optics_0_Temp_0[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xe, 0, 0}, 1, 2, 0, 0}}}, +}; + +static const struct nsm_fpga_command rows_Optics_0_Tx_Fault[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0x11}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x87, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 1, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1101}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x87, 0, 0}, 1, 1, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 2, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1102}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x87, 0, 0}, 1, 1, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 3, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1103}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x87, 0, 0}, 1, 1, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, +}; + +static const struct nsm_fpga_command rows_Optics_0_Rx_Los[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0x11}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x93, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 1, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1101}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x93, 0, 0}, 1, 1, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 2, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1102}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x93, 0, 0}, 1, 1, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 3, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1103}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x93, 0, 0}, 1, 1, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, +}; + +static const struct nsm_fpga_command rows_Optics_0_Tx_Power[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0x11}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9a, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9e, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa2, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa6, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 1, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1101}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9a, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9e, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa2, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa6, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 2, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1102}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9a, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9e, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa2, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa6, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 3, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1103}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9a, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0x9e, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa2, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xa6, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, +}; + +static const struct nsm_fpga_command rows_Optics_0_Rx_Power[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0x11}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xba, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xbe, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc2, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc6, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 1, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1101}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xba, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xbe, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc2, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc6, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 8, .mask = 3, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 2, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1102}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xba, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xbe, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc2, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc6, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 3, 0x11}, 3, 0, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x1103}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xba, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xbe, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc2, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_ITEM, .u = {.xfer = {0x50, {0xc6, 0, 0}, 1, 4, 0, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 8, .mask = 3, .value = 2}}, +}; + +static const struct nsm_fpga_rule rules_optics[] = { + {.name = "Optics_0", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_0", + .states = states_Optics_0, + .state_count = sizeof(states_Optics_0) / sizeof(states_Optics_0[0])}, + {.name = "Optics_0_Power_Good", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_0", + .states = states_Optics_0_Power_Good, + .state_count = sizeof(states_Optics_0_Power_Good) / sizeof(states_Optics_0_Power_Good[0])}, + {.name = "Optics_0_Module_State", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 5}, + .group = "Optics_0", + .states = states_Optics_0_Module_State, + .state_count = sizeof(states_Optics_0_Module_State) / sizeof(states_Optics_0_Module_State[0])}, + {.name = "Optics_0_Inventory", + .commands = rows_Optics_0_Inventory, + .command_count = sizeof(rows_Optics_0_Inventory) / sizeof(rows_Optics_0_Inventory[0]), + .kind = NSM_FPGA_RULE_IDENTITY, + .group = "Optics_0", + .identity = fields_Optics_0_Inventory, + .identity_count = sizeof(fields_Optics_0_Inventory) / sizeof(fields_Optics_0_Inventory[0])}, + {.name = "Optics_0_Temp_0", + .commands = rows_Optics_0_Temp_0, + .command_count = sizeof(rows_Optics_0_Temp_0) / sizeof(rows_Optics_0_Temp_0[0]), + .kind = NSM_FPGA_RULE_NUMERIC, + .numeric = {.sensor_type = "temperature", .format = NSM_FPGA_FORMAT_S16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.00390625, .min_value = -40.0, .max_value = 125.0}, + .group = "Optics_0", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 11, .mask = 1, .value = 1}}, + {.name = "Optics_0_Tx_Fault", + .commands = rows_Optics_0_Tx_Fault, + .command_count = sizeof(rows_Optics_0_Tx_Fault) / sizeof(rows_Optics_0_Tx_Fault[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_TX_FAULT}, + .group = "Optics_0_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 9, .mask = 1, .value = 1}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_0_Rx_Los", + .commands = rows_Optics_0_Rx_Los, + .command_count = sizeof(rows_Optics_0_Rx_Los) / sizeof(rows_Optics_0_Rx_Los[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_RX_LOS}, + .group = "Optics_0_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 10, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_0_Tx_Power", + .commands = rows_Optics_0_Tx_Power, + .command_count = sizeof(rows_Optics_0_Tx_Power) / sizeof(rows_Optics_0_Tx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_TX_POWER}, + .group = "Optics_0_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_0_Rx_Power", + .commands = rows_Optics_0_Rx_Power, + .command_count = sizeof(rows_Optics_0_Rx_Power) / sizeof(rows_Optics_0_Rx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_RX_POWER}, + .group = "Optics_0_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 4, .value = 4}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_1", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_1", + .states = states_Optics_0, + .state_count = sizeof(states_Optics_0) / sizeof(states_Optics_0[0])}, + {.name = "Optics_1_Power_Good", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_1", + .states = states_Optics_0_Power_Good, + .state_count = sizeof(states_Optics_0_Power_Good) / sizeof(states_Optics_0_Power_Good[0])}, + {.name = "Optics_1_Module_State", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 5}, + .group = "Optics_1", + .states = states_Optics_0_Module_State, + .state_count = sizeof(states_Optics_0_Module_State) / sizeof(states_Optics_0_Module_State[0])}, + {.name = "Optics_1_Inventory", + .commands = rows_Optics_0_Inventory, + .command_count = sizeof(rows_Optics_0_Inventory) / sizeof(rows_Optics_0_Inventory[0]), + .kind = NSM_FPGA_RULE_IDENTITY, + .group = "Optics_1", + .identity = fields_Optics_0_Inventory, + .identity_count = sizeof(fields_Optics_0_Inventory) / sizeof(fields_Optics_0_Inventory[0])}, + {.name = "Optics_1_Temp_0", + .commands = rows_Optics_0_Temp_0, + .command_count = sizeof(rows_Optics_0_Temp_0) / sizeof(rows_Optics_0_Temp_0[0]), + .kind = NSM_FPGA_RULE_NUMERIC, + .numeric = {.sensor_type = "temperature", .format = NSM_FPGA_FORMAT_S16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.00390625, .min_value = -40.0, .max_value = 125.0}, + .group = "Optics_1", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 11, .mask = 1, .value = 1}}, + {.name = "Optics_1_Tx_Fault", + .commands = rows_Optics_0_Tx_Fault, + .command_count = sizeof(rows_Optics_0_Tx_Fault) / sizeof(rows_Optics_0_Tx_Fault[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_TX_FAULT}, + .group = "Optics_1_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 9, .mask = 1, .value = 1}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_1_Rx_Los", + .commands = rows_Optics_0_Rx_Los, + .command_count = sizeof(rows_Optics_0_Rx_Los) / sizeof(rows_Optics_0_Rx_Los[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_RX_LOS}, + .group = "Optics_1_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 10, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_1_Tx_Power", + .commands = rows_Optics_0_Tx_Power, + .command_count = sizeof(rows_Optics_0_Tx_Power) / sizeof(rows_Optics_0_Tx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_TX_POWER}, + .group = "Optics_1_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_1_Rx_Power", + .commands = rows_Optics_0_Rx_Power, + .command_count = sizeof(rows_Optics_0_Rx_Power) / sizeof(rows_Optics_0_Rx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_RX_POWER}, + .group = "Optics_1_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 4, .value = 4}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_2", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_2", + .states = states_Optics_0, + .state_count = sizeof(states_Optics_0) / sizeof(states_Optics_0[0])}, + {.name = "Optics_2_Power_Good", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_2", + .states = states_Optics_0_Power_Good, + .state_count = sizeof(states_Optics_0_Power_Good) / sizeof(states_Optics_0_Power_Good[0])}, + {.name = "Optics_2_Module_State", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 5}, + .group = "Optics_2", + .states = states_Optics_0_Module_State, + .state_count = sizeof(states_Optics_0_Module_State) / sizeof(states_Optics_0_Module_State[0])}, + {.name = "Optics_2_Inventory", + .commands = rows_Optics_0_Inventory, + .command_count = sizeof(rows_Optics_0_Inventory) / sizeof(rows_Optics_0_Inventory[0]), + .kind = NSM_FPGA_RULE_IDENTITY, + .group = "Optics_2", + .identity = fields_Optics_0_Inventory, + .identity_count = sizeof(fields_Optics_0_Inventory) / sizeof(fields_Optics_0_Inventory[0])}, + {.name = "Optics_2_Temp_0", + .commands = rows_Optics_0_Temp_0, + .command_count = sizeof(rows_Optics_0_Temp_0) / sizeof(rows_Optics_0_Temp_0[0]), + .kind = NSM_FPGA_RULE_NUMERIC, + .numeric = {.sensor_type = "temperature", .format = NSM_FPGA_FORMAT_S16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.00390625, .min_value = -40.0, .max_value = 125.0}, + .group = "Optics_2", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 11, .mask = 1, .value = 1}}, + {.name = "Optics_2_Tx_Fault", + .commands = rows_Optics_0_Tx_Fault, + .command_count = sizeof(rows_Optics_0_Tx_Fault) / sizeof(rows_Optics_0_Tx_Fault[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_TX_FAULT}, + .group = "Optics_2_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 9, .mask = 1, .value = 1}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_2_Rx_Los", + .commands = rows_Optics_0_Rx_Los, + .command_count = sizeof(rows_Optics_0_Rx_Los) / sizeof(rows_Optics_0_Rx_Los[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_RX_LOS}, + .group = "Optics_2_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 10, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_2_Tx_Power", + .commands = rows_Optics_0_Tx_Power, + .command_count = sizeof(rows_Optics_0_Tx_Power) / sizeof(rows_Optics_0_Tx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_TX_POWER}, + .group = "Optics_2_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_2_Rx_Power", + .commands = rows_Optics_0_Rx_Power, + .command_count = sizeof(rows_Optics_0_Rx_Power) / sizeof(rows_Optics_0_Rx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_RX_POWER}, + .group = "Optics_2_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 4, .value = 4}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_3", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_3", + .states = states_Optics_0, + .state_count = sizeof(states_Optics_0) / sizeof(states_Optics_0[0])}, + {.name = "Optics_3_Power_Good", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_3", + .states = states_Optics_0_Power_Good, + .state_count = sizeof(states_Optics_0_Power_Good) / sizeof(states_Optics_0_Power_Good[0])}, + {.name = "Optics_3_Module_State", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 5}, + .group = "Optics_3", + .states = states_Optics_0_Module_State, + .state_count = sizeof(states_Optics_0_Module_State) / sizeof(states_Optics_0_Module_State[0])}, + {.name = "Optics_3_Inventory", + .commands = rows_Optics_0_Inventory, + .command_count = sizeof(rows_Optics_0_Inventory) / sizeof(rows_Optics_0_Inventory[0]), + .kind = NSM_FPGA_RULE_IDENTITY, + .group = "Optics_3", + .identity = fields_Optics_0_Inventory, + .identity_count = sizeof(fields_Optics_0_Inventory) / sizeof(fields_Optics_0_Inventory[0])}, + {.name = "Optics_3_Temp_0", + .commands = rows_Optics_0_Temp_0, + .command_count = sizeof(rows_Optics_0_Temp_0) / sizeof(rows_Optics_0_Temp_0[0]), + .kind = NSM_FPGA_RULE_NUMERIC, + .numeric = {.sensor_type = "temperature", .format = NSM_FPGA_FORMAT_S16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.00390625, .min_value = -40.0, .max_value = 125.0}, + .group = "Optics_3", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 11, .mask = 1, .value = 1}}, + {.name = "Optics_3_Tx_Fault", + .commands = rows_Optics_0_Tx_Fault, + .command_count = sizeof(rows_Optics_0_Tx_Fault) / sizeof(rows_Optics_0_Tx_Fault[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_TX_FAULT}, + .group = "Optics_3_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 9, .mask = 1, .value = 1}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_3_Rx_Los", + .commands = rows_Optics_0_Rx_Los, + .command_count = sizeof(rows_Optics_0_Rx_Los) / sizeof(rows_Optics_0_Rx_Los[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_RX_LOS}, + .group = "Optics_3_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 10, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_3_Tx_Power", + .commands = rows_Optics_0_Tx_Power, + .command_count = sizeof(rows_Optics_0_Tx_Power) / sizeof(rows_Optics_0_Tx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_TX_POWER}, + .group = "Optics_3_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_3_Rx_Power", + .commands = rows_Optics_0_Rx_Power, + .command_count = sizeof(rows_Optics_0_Rx_Power) / sizeof(rows_Optics_0_Rx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_RX_POWER}, + .group = "Optics_3_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 4, .value = 4}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_4", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_4", + .states = states_Optics_0, + .state_count = sizeof(states_Optics_0) / sizeof(states_Optics_0[0])}, + {.name = "Optics_4_Power_Good", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 1}, + .group = "Optics_4", + .states = states_Optics_0_Power_Good, + .state_count = sizeof(states_Optics_0_Power_Good) / sizeof(states_Optics_0_Power_Good[0])}, + {.name = "Optics_4_Module_State", + .kind = NSM_FPGA_RULE_STATE, + .numeric = {.buffer = NSM_FPGA_BUF_GROUP, .offset = 5}, + .group = "Optics_4", + .states = states_Optics_0_Module_State, + .state_count = sizeof(states_Optics_0_Module_State) / sizeof(states_Optics_0_Module_State[0])}, + {.name = "Optics_4_Inventory", + .commands = rows_Optics_0_Inventory, + .command_count = sizeof(rows_Optics_0_Inventory) / sizeof(rows_Optics_0_Inventory[0]), + .kind = NSM_FPGA_RULE_IDENTITY, + .group = "Optics_4", + .identity = fields_Optics_0_Inventory, + .identity_count = sizeof(fields_Optics_0_Inventory) / sizeof(fields_Optics_0_Inventory[0])}, + {.name = "Optics_4_Temp_0", + .commands = rows_Optics_0_Temp_0, + .command_count = sizeof(rows_Optics_0_Temp_0) / sizeof(rows_Optics_0_Temp_0[0]), + .kind = NSM_FPGA_RULE_NUMERIC, + .numeric = {.sensor_type = "temperature", .format = NSM_FPGA_FORMAT_S16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.00390625, .min_value = -40.0, .max_value = 125.0}, + .group = "Optics_4", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 11, .mask = 1, .value = 1}}, + {.name = "Optics_4_Tx_Fault", + .commands = rows_Optics_0_Tx_Fault, + .command_count = sizeof(rows_Optics_0_Tx_Fault) / sizeof(rows_Optics_0_Tx_Fault[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_TX_FAULT}, + .group = "Optics_4_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 9, .mask = 1, .value = 1}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_4_Rx_Los", + .commands = rows_Optics_0_Rx_Los, + .command_count = sizeof(rows_Optics_0_Rx_Los) / sizeof(rows_Optics_0_Rx_Los[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_FIXED, .buffer = NSM_FPGA_BUF_ITEM, .bit_width = 1, .scale = 1.0, .min_value = 0.0, .max_value = 1.0, .element_count = 32, .stride_bits = 1, .vector = NSM_FPGA_VECTOR_RX_LOS}, + .group = "Optics_4_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 10, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_4_Tx_Power", + .commands = rows_Optics_0_Tx_Power, + .command_count = sizeof(rows_Optics_0_Tx_Power) / sizeof(rows_Optics_0_Tx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_TX_POWER}, + .group = "Optics_4_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 2, .value = 2}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, + {.name = "Optics_4_Rx_Power", + .commands = rows_Optics_0_Rx_Power, + .command_count = sizeof(rows_Optics_0_Rx_Power) / sizeof(rows_Optics_0_Rx_Power[0]), + .kind = NSM_FPGA_RULE_ARRAY, + .numeric = {.format = NSM_FPGA_FORMAT_U16BE, .buffer = NSM_FPGA_BUF_ITEM, .scale = 0.0001, .min_value = 0.0, .max_value = 6.6, .element_count = 32, .stride_bits = 16, .vector = NSM_FPGA_VECTOR_RX_POWER}, + .group = "Optics_4_Lanes", + .valid_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 12, .mask = 4, .value = 4}, + .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 5, .mask = 0xe, .value = 6}}, +}; + +static const struct nsm_fpga_command setup_Optics_0[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 0}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x74, {0, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 0x10, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_ABSENT, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 2, .value = 2}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_WARNING}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {2, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 8}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {6, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {1, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 1}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x40}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_LE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x5f}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 4, .mask = 0x80, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 1}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x8e, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x9d, 0, 0}, 1, 4, 0, 0}}}, +}; + +static const struct nsm_fpga_command cleanup_Optics_0[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 3, 0, 6, 6}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 7, .mask = 0, .value = 0}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 1, 0, 1, 0}}, .run_if = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .mask = 0, .value = 0}}, +}; + +static const struct nsm_fpga_command setup_Optics_1[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 0}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x74, {1, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 0x10, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_ABSENT, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 2, .value = 2}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_WARNING}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {3, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 8}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {7, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {2, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 2}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x40}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_LE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x5f}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 4, .mask = 0x80, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 1}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x8e, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x9d, 0, 0}, 1, 4, 0, 0}}}, +}; + +static const struct nsm_fpga_command setup_Optics_2[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 0}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x74, {0, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 0x10, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_ABSENT, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 2, .value = 2}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_WARNING}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {2, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 8}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {6, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {8, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 8}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x40}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_LE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x5f}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 4, .mask = 0x80, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 1}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x8e, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x9d, 0, 0}, 1, 4, 0, 0}}}, +}; + +static const struct nsm_fpga_command setup_Optics_3[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 0}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x74, {1, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 0x10, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_ABSENT, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 2, .value = 2}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_WARNING}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {3, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 8}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x74, {7, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0x10, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 0x10}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x40}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_LE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x5f}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 4, .mask = 0x80, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 1}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x8e, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x9d, 0, 0}, 1, 4, 0, 0}}}, +}; + +static const struct nsm_fpga_command setup_Optics_4[] = { + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {4, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 4}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x70, {0, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 0x10, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_ABSENT, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 1, .mask = 2, .value = 2}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_WARNING}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x70, {1, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 8}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x70, {3, 0, 0}, 1, 1, 0, 0}}, .expect = {.mask = 8, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_STANDBY_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {4, 0, 0}, 1, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x71, {0, 0, 0}, 0, 1, 0, 0}}, .expect = {.mask = 0xff, .value = 4}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0, 0, 0}, 1, 4, 0, 0}}}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_GE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x40}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .op = NSM_FPGA_CMP_LE, .width = 1, .offset = 3, .mask = 0xff, .value = 0x5f}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_CHECK, .station = 1, .expect = {.buffer = NSM_FPGA_BUF_GROUP, .width = 1, .offset = 4, .mask = 0x80, .value = 0}, .on_expect_fail = NSM_FPGA_END_GROUP, .group_state = NSM_FPGA_STATE_UNAVAILABLE_OFFLINE, .group_health = NSM_FPGA_HEALTH_OK}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 1}, 3, 0, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .u = {.xfer = {0x50, {0x7e, 0, 0}, 1, 2, 0, 0}}, .expect = {.mask = 0xffff, .value = 0x100}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x8e, 0, 0}, 1, 1, 0, 0}}}, + {.op = NSM_FPGA_OP_I2C_XFER, .station = 1, .capture = NSM_FPGA_BUF_GROUP, .u = {.xfer = {0x50, {0x9d, 0, 0}, 1, 4, 0, 0}}}, +}; + +static const struct nsm_fpga_group groups_optics[] = { + {.name = "Optics_0", + .setup = setup_Optics_0, + .setup_count = sizeof(setup_Optics_0) / sizeof(setup_Optics_0[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_1", + .setup = setup_Optics_1, + .setup_count = sizeof(setup_Optics_1) / sizeof(setup_Optics_1[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_2", + .setup = setup_Optics_2, + .setup_count = sizeof(setup_Optics_2) / sizeof(setup_Optics_2[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_3", + .setup = setup_Optics_3, + .setup_count = sizeof(setup_Optics_3) / sizeof(setup_Optics_3[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_4", + .setup = setup_Optics_4, + .setup_count = sizeof(setup_Optics_4) / sizeof(setup_Optics_4[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_0_Lanes", + .setup = setup_Optics_0, + .setup_count = sizeof(setup_Optics_0) / sizeof(setup_Optics_0[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_1_Lanes", + .setup = setup_Optics_1, + .setup_count = sizeof(setup_Optics_1) / sizeof(setup_Optics_1[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_2_Lanes", + .setup = setup_Optics_2, + .setup_count = sizeof(setup_Optics_2) / sizeof(setup_Optics_2[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_3_Lanes", + .setup = setup_Optics_3, + .setup_count = sizeof(setup_Optics_3) / sizeof(setup_Optics_3[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, + {.name = "Optics_4_Lanes", + .setup = setup_Optics_4, + .setup_count = sizeof(setup_Optics_4) / sizeof(setup_Optics_4[0]), + .cleanup = cleanup_Optics_0, + .cleanup_count = sizeof(cleanup_Optics_0) / sizeof(cleanup_Optics_0[0])}, +}; + +extern const struct nsm_fpga_part nsm_fpga_part_optics; +const struct nsm_fpga_part nsm_fpga_part_optics = { + .rules = rules_optics, + .rule_count = sizeof(rules_optics) / sizeof(rules_optics[0]), + .groups = groups_optics, + .group_count = sizeof(groups_optics) / sizeof(groups_optics[0]), +};
diff --git a/libnsm/fpga/fpga-rules-lp30-optics.rows b/libnsm/fpga/fpga-rules-lp30-optics.rows new file mode 100644 index 0000000..020453b --- /dev/null +++ b/libnsm/fpga/fpga-rules-lp30-optics.rows
@@ -0,0 +1,340 @@ +# LP30 optical module telemetry: presence, power good, state, inventory, +# temperature and lane vectors of the five CMIS cages on the osfp I2C master. +# gen-fpga-rules.py turns this file into fpga-rules-lp30-optics.c. + +part optics +include fpga-rules-lp30.rows + +# Optical modules on the osfp I2C master, read with bounded transactions. Each +# module has two groups with the same setup: the module group carries +# presence, power good, state, inventory and temperature at the temperature +# rate; the lane group carries the four lane vectors at their own rate. A +# pointerless mux at 0x71 selects +# the module or the presence expander; the expander input register carries +# the present pin (bit 4, active low) and power good (bit 1), its output latch +# and direction register carry the module reset on bit 3, released when the +# latch bit is high and the pin is an output; the CMIS module answers at 0x50. Group buffer: 0 mux mask found, 1 expander pins, 2 to 5 +# CMIS bytes 0 to 3, 6 and 7 bank and page found, 8 page 1 byte 142 (bank +# count code), 9 to 12 page 1 bytes 157 to 160 (monitor capabilities). +const OPTICS_MUX 0x71 +const OPTICS_MODULE 0x50 +const CMIS_PAGE_REGISTER 126 + +# Select a mux channel mask and confirm it +seq mux_select mask + xfer i2c_master_osfp OPTICS_MUX w $mask + xfer i2c_master_osfp OPTICS_MUX r 1 expect & 0xff == $mask +end +# Select a module bank and page and confirm both +seq page_select bank page + xfer i2c_master_osfp OPTICS_MODULE w CMIS_PAGE_REGISTER $bank $page + xfer i2c_master_osfp OPTICS_MODULE w CMIS_PAGE_REGISTER r 2 expect & 0xffff == $bank|($page<<8) +end +# Read count bytes from a module register +seq module_read reg count + xfer i2c_master_osfp OPTICS_MODULE w $reg r $count capture item +end + +seq optics_setup chan exp_mask exp_addr exp_reg exp_out exp_dir + xfer i2c_master_osfp OPTICS_MUX r 1 capture group + use mux_select $exp_mask + xfer i2c_master_osfp $exp_addr w $exp_reg r 1 capture group + check i2c_master_osfp group 1 & 0x10 == 0 else end_group absent ok + check i2c_master_osfp group 1 & 0x02 == 0x02 else end_group unavailable warning + xfer i2c_master_osfp $exp_addr w $exp_out r 1 expect & 0x08 == 0x08 else end_group standby ok + xfer i2c_master_osfp $exp_addr w $exp_dir r 1 expect & 0x08 == 0 else end_group standby ok + use mux_select $chan + xfer i2c_master_osfp OPTICS_MODULE w 0 r 4 capture group + check i2c_master_osfp group 3 & 0xff >= 0x40 else end_group unavailable ok + check i2c_master_osfp group 3 & 0xff <= 0x5f else end_group unavailable ok + check i2c_master_osfp group 4 & 0x80 == 0 else end_group unavailable ok + xfer i2c_master_osfp OPTICS_MODULE w CMIS_PAGE_REGISTER r 2 capture group + use page_select 0 1 + xfer i2c_master_osfp OPTICS_MODULE w 142 r 1 capture group + xfer i2c_master_osfp OPTICS_MODULE w 157 r 4 capture group +end +# Give back the bank and page found, then the mux mask found +seq optics_cleanup + xfer i2c_master_osfp OPTICS_MODULE w CMIS_PAGE_REGISTER wc 6 wc 7 if group 7 & 0 == 0 + xfer i2c_master_osfp OPTICS_MUX wc 0 if group 0 & 0 == 0 +end + +# Presence from the expander pin, module state from CMIS byte 3 bits 1 to 3 +seq optics_present grp + kind state + group $grp + word group 1 + state 0x10 0 enabled ok + state default absent ok +end +# Power good from the expander pin (bit 1), whatever the module state +seq optics_power_good grp + kind state + group $grp + word group 1 + state 0x02 0x02 enabled ok + state default fault critical +end +seq optics_module_state grp + kind state + group $grp + word group 5 + state 0x0e 0x06 enabled ok + state 0x0e 0x04 starting ok + state 0x0e 0x02 standby ok + state 0x0e 0x08 standby ok + state 0x0e 0x0a fault critical + state default unavailable warning +end +# Inventory: page 0 bytes 129 to 181, vendor, part, revision and serial +seq optics_inventory grp + kind identity + group $grp + field manufacturer ascii item 0 16 + field part ascii item 19 16 + field revision ascii item 35 2 + field serial ascii item 37 16 + use page_select 0 0 + use module_read 129 53 +end +# Module temperature: lower memory bytes 14 and 15, signed 1/256 degrees +seq optics_temp grp + kind numeric temperature + group $grp + decode s16be item 0 scale 1/256 range -40 125 + valid_if group 11 & 0x01 == 0x01 + use module_read 14 2 +end +# Per-lane items read page 0x11 of every bank the module has: the bank count +# code (group byte 8) is 0 for one bank, 1 for two, 2 for four; lanes are read +# only while the module state is ready +seq bank_read bank reg count + use page_select $bank 0x11 + use module_read $reg $count +end +seq lane_rows reg count + use bank_read 0 $reg $count + use bank_read 1 $reg $count if group 8 & 0x3 >= 1 + use bank_read 2 $reg $count if group 8 & 0x3 == 2 + use bank_read 3 $reg $count if group 8 & 0x3 == 2 +end +# Flags: one byte per bank, bit i is lane i; valid when the capability is set +seq lane_flags grp vector reg cap_off cap_bit + kind array $vector + group $grp + decode fixed item 0 width 1 scale 1 range 0 1 count 32 stride 1 + valid_if group $cap_off & $cap_bit == $cap_bit + run_if group 5 & 0x0e == 0x06 + use lane_rows $reg 1 +end +# Power: eight big-endian words per bank, 0.1 uW per count +seq lane_power grp vector reg cap_bit + kind array $vector + group $grp + decode u16be item 0 scale 0.0001 range 0 6.6 count 32 stride 16 + valid_if group 12 & $cap_bit == $cap_bit + run_if group 5 & 0x0e == 0x06 + use lane_rows $reg 16 +end + +rule Optics_0 + use optics_present Optics_0 +end +rule Optics_0_Power_Good + use optics_power_good Optics_0 +end +rule Optics_0_Module_State + use optics_module_state Optics_0 +end +rule Optics_0_Inventory + use optics_inventory Optics_0 +end +rule Optics_0_Temp_0 + use optics_temp Optics_0 +end +rule Optics_0_Tx_Fault + use lane_flags Optics_0_Lanes tx_fault 135 9 0x01 +end +rule Optics_0_Rx_Los + use lane_flags Optics_0_Lanes rx_los 147 10 0x02 +end +rule Optics_0_Tx_Power + use lane_power Optics_0_Lanes tx_power 154 0x02 +end +rule Optics_0_Rx_Power + use lane_power Optics_0_Lanes rx_power 186 0x04 +end + +rule Optics_1 + use optics_present Optics_1 +end +rule Optics_1_Power_Good + use optics_power_good Optics_1 +end +rule Optics_1_Module_State + use optics_module_state Optics_1 +end +rule Optics_1_Inventory + use optics_inventory Optics_1 +end +rule Optics_1_Temp_0 + use optics_temp Optics_1 +end +rule Optics_1_Tx_Fault + use lane_flags Optics_1_Lanes tx_fault 135 9 0x01 +end +rule Optics_1_Rx_Los + use lane_flags Optics_1_Lanes rx_los 147 10 0x02 +end +rule Optics_1_Tx_Power + use lane_power Optics_1_Lanes tx_power 154 0x02 +end +rule Optics_1_Rx_Power + use lane_power Optics_1_Lanes rx_power 186 0x04 +end + +rule Optics_2 + use optics_present Optics_2 +end +rule Optics_2_Power_Good + use optics_power_good Optics_2 +end +rule Optics_2_Module_State + use optics_module_state Optics_2 +end +rule Optics_2_Inventory + use optics_inventory Optics_2 +end +rule Optics_2_Temp_0 + use optics_temp Optics_2 +end +rule Optics_2_Tx_Fault + use lane_flags Optics_2_Lanes tx_fault 135 9 0x01 +end +rule Optics_2_Rx_Los + use lane_flags Optics_2_Lanes rx_los 147 10 0x02 +end +rule Optics_2_Tx_Power + use lane_power Optics_2_Lanes tx_power 154 0x02 +end +rule Optics_2_Rx_Power + use lane_power Optics_2_Lanes rx_power 186 0x04 +end + +rule Optics_3 + use optics_present Optics_3 +end +rule Optics_3_Power_Good + use optics_power_good Optics_3 +end +rule Optics_3_Module_State + use optics_module_state Optics_3 +end +rule Optics_3_Inventory + use optics_inventory Optics_3 +end +rule Optics_3_Temp_0 + use optics_temp Optics_3 +end +rule Optics_3_Tx_Fault + use lane_flags Optics_3_Lanes tx_fault 135 9 0x01 +end +rule Optics_3_Rx_Los + use lane_flags Optics_3_Lanes rx_los 147 10 0x02 +end +rule Optics_3_Tx_Power + use lane_power Optics_3_Lanes tx_power 154 0x02 +end +rule Optics_3_Rx_Power + use lane_power Optics_3_Lanes rx_power 186 0x04 +end + +rule Optics_4 + use optics_present Optics_4 +end +rule Optics_4_Power_Good + use optics_power_good Optics_4 +end +rule Optics_4_Module_State + use optics_module_state Optics_4 +end +rule Optics_4_Inventory + use optics_inventory Optics_4 +end +rule Optics_4_Temp_0 + use optics_temp Optics_4 +end +rule Optics_4_Tx_Fault + use lane_flags Optics_4_Lanes tx_fault 135 9 0x01 +end +rule Optics_4_Rx_Los + use lane_flags Optics_4_Lanes rx_los 147 10 0x02 +end +rule Optics_4_Tx_Power + use lane_power Optics_4_Lanes tx_power 154 0x02 +end +rule Optics_4_Rx_Power + use lane_power Optics_4_Lanes rx_power 186 0x04 +end + +# Module paths: mux channel mask, expander address, input, output and direction registers +group Optics_0 + setup + use optics_setup 0x01 0x00 0x74 0 2 6 + cleanup + use optics_cleanup +end +group Optics_1 + setup + use optics_setup 0x02 0x00 0x74 1 3 7 + cleanup + use optics_cleanup +end +group Optics_2 + setup + use optics_setup 0x08 0x00 0x74 0 2 6 + cleanup + use optics_cleanup +end +group Optics_3 + setup + use optics_setup 0x10 0x00 0x74 1 3 7 + cleanup + use optics_cleanup +end +group Optics_4 + setup + use optics_setup 0x04 0x04 0x70 0 1 3 + cleanup + use optics_cleanup +end +group Optics_0_Lanes + setup + use optics_setup 0x01 0x00 0x74 0 2 6 + cleanup + use optics_cleanup +end +group Optics_1_Lanes + setup + use optics_setup 0x02 0x00 0x74 1 3 7 + cleanup + use optics_cleanup +end +group Optics_2_Lanes + setup + use optics_setup 0x08 0x00 0x74 0 2 6 + cleanup + use optics_cleanup +end +group Optics_3_Lanes + setup + use optics_setup 0x10 0x00 0x74 1 3 7 + cleanup + use optics_cleanup +end +group Optics_4_Lanes + setup + use optics_setup 0x04 0x04 0x70 0 1 3 + cleanup + use optics_cleanup +end
diff --git a/libnsm/fpga/fpga-rules-lp30.c b/libnsm/fpga/fpga-rules-lp30.c index 8f28df9..dfe53a5 100644 --- a/libnsm/fpga/fpga-rules-lp30.c +++ b/libnsm/fpga/fpga-rules-lp30.c
@@ -50,11 +50,15 @@ extern const struct nsm_fpga_part nsm_fpga_part_pdb; extern const struct nsm_fpga_part nsm_fpga_part_sdm; extern const struct nsm_fpga_part nsm_fpga_part_dimm; +extern const struct nsm_fpga_part nsm_fpga_part_links; +extern const struct nsm_fpga_part nsm_fpga_part_optics; static const struct nsm_fpga_part *const parts_p0[] = { &nsm_fpga_part_pdb, &nsm_fpga_part_sdm, &nsm_fpga_part_dimm, + &nsm_fpga_part_links, + &nsm_fpga_part_optics, }; static const struct nsm_fpga_map map_p0 = {
diff --git a/libnsm/fpga/fpga-rules-lp30.rows b/libnsm/fpga/fpga-rules-lp30.rows index 9b4322f..09d5296 100644 --- a/libnsm/fpga/fpga-rules-lp30.rows +++ b/libnsm/fpga/fpga-rules-lp30.rows
@@ -6,6 +6,8 @@ part pdb part sdm part dimm + part links + part optics end const ETH_WINDOW 0xffff
diff --git a/libnsm/meson.build b/libnsm/meson.build index e866038..855dc74 100644 --- a/libnsm/meson.build +++ b/libnsm/meson.build
@@ -26,6 +26,8 @@ if fs.exists('fpga/fpga-tables.h') libnsm_sources += files( 'fpga/fpga-rules-lp30-dimm.c', + 'fpga/fpga-rules-lp30-links.c', + 'fpga/fpga-rules-lp30-optics.c', 'fpga/fpga-rules-lp30-pdb.c', 'fpga/fpga-rules-lp30-sdm.c', )
diff --git a/libnsm/test/libnsm_fpga_rules_links_test.cpp b/libnsm/test/libnsm_fpga_rules_links_test.cpp new file mode 100644 index 0000000..d5f9fd6 --- /dev/null +++ b/libnsm/test/libnsm_fpga_rules_links_test.cpp
@@ -0,0 +1,153 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright OpenBMC Authors +#include "fpga/fpga-tables.h" + +#include <gtest/gtest.h> + +extern "C" const struct nsm_fpga_part nsm_fpga_part_links; +extern "C" const struct nsm_fpga_part nsm_fpga_part_optics; + +TEST(fpgaRulesLinks, partsHoldTheRules) +{ + EXPECT_EQ(nsm_fpga_part_links.rule_count, 16u); + EXPECT_EQ(nsm_fpga_part_links.group_count, 0u); + EXPECT_EQ(nsm_fpga_part_optics.rule_count, 45u); + EXPECT_EQ(nsm_fpga_part_optics.group_count, 10u); +} + +TEST(fpgaRulesLinks, linkRules) +{ + const auto *p0 = nsm_fpga_map_p0(); + const auto *ready = nsm_fpga_find_rule( + p0, "HGX_Chassis_0_FPGA_0_C2C_1_Lane_3_Pcs_Ready"); + ASSERT_NE(ready, nullptr); + EXPECT_EQ(ready->kind, NSM_FPGA_RULE_STATE); + /* lane 3 of connection 1 is channel 0 of bank 13C */ + EXPECT_EQ(ready->commands[0].station, 11); + EXPECT_TRUE(nsm_fpga_rule_valid(p0, ready)); + const auto *ber = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Ethernet_1_High_Ber"); + ASSERT_NE(ber, nullptr); + EXPECT_EQ(ber->kind, NSM_FPGA_RULE_STATE); + EXPECT_EQ(ber->commands[0].station, 24); + EXPECT_TRUE(nsm_fpga_rule_valid(p0, ber)); +} + +TEST(fpgaRulesLinks, opticsRules) +{ + const auto *p0 = nsm_fpga_map_p0(); + const auto *group = nsm_fpga_find_group(p0, "Optics_4"); + ASSERT_NE(group, nullptr); + ASSERT_EQ(group->setup_count, 19u); + ASSERT_EQ(group->cleanup_count, 2u); + /* the mux mask found is captured first, then the expander pins */ + EXPECT_EQ(group->setup[0].op, NSM_FPGA_OP_I2C_XFER); + EXPECT_EQ(group->setup[0].u.xfer.dev_addr, 0x71); + EXPECT_EQ(group->setup[0].u.xfer.read_count, 1); + EXPECT_EQ(group->setup[0].capture, NSM_FPGA_BUF_GROUP); + EXPECT_EQ(group->setup[1].u.xfer.write[0], 0x04); + EXPECT_EQ(group->setup[3].u.xfer.dev_addr, 0x70); + EXPECT_EQ(group->setup[3].u.xfer.write_count, 1); + EXPECT_EQ(group->setup[3].u.xfer.read_count, 1); + EXPECT_EQ(group->setup[4].op, NSM_FPGA_OP_CHECK); + EXPECT_EQ(group->setup[4].group_state, NSM_FPGA_STATE_ABSENT); + EXPECT_EQ(group->setup[5].group_state, + NSM_FPGA_STATE_UNAVAILABLE_OFFLINE); + EXPECT_EQ(group->setup[5].group_health, NSM_FPGA_HEALTH_WARNING); + /* the expander output latch and direction reads for power good */ + EXPECT_EQ(group->setup[6].u.xfer.write[0], 0x01); + EXPECT_EQ(group->setup[6].u.xfer.read_count, 1); + EXPECT_EQ(group->setup[7].u.xfer.write[0], 0x03); + EXPECT_EQ(group->setup[7].u.xfer.read_count, 1); + EXPECT_EQ(group->setup[8].u.xfer.write[0], 0x04); + /* the CMIS header: one pointer byte, four bytes read into the group */ + EXPECT_EQ(group->setup[10].u.xfer.dev_addr, 0x50); + EXPECT_EQ(group->setup[10].u.xfer.read_count, 4); + EXPECT_EQ(group->setup[10].capture, NSM_FPGA_BUF_GROUP); + /* cleanup gives the bank and page, then the mux, back from the buffer + */ + EXPECT_EQ(group->cleanup[0].u.xfer.write_count, 3); + EXPECT_EQ(group->cleanup[0].u.xfer.captured, 0x6); + EXPECT_EQ(group->cleanup[0].u.xfer.captured_offset, 6); + EXPECT_EQ(group->cleanup[1].u.xfer.dev_addr, 0x71); + EXPECT_EQ(group->cleanup[1].u.xfer.captured, 0x1); + EXPECT_EQ(group->cleanup[1].run_if.offset, 0); + /* the lane vectors read through a second group with the same setup */ + const auto *lanes = nsm_fpga_find_group(p0, "Optics_4_Lanes"); + ASSERT_NE(lanes, nullptr); + EXPECT_EQ(lanes->setup_count, group->setup_count); + EXPECT_EQ(lanes->cleanup_count, group->cleanup_count); + EXPECT_EQ(lanes->setup[1].u.xfer.write[0], 0x04); + const auto *txp = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_4_Tx_Power"); + ASSERT_NE(txp, nullptr); + EXPECT_STREQ(txp->group, "Optics_4_Lanes"); + const auto *presence = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_4"); + ASSERT_NE(presence, nullptr); + EXPECT_EQ(presence->command_count, 0u); + ASSERT_EQ(presence->state_count, 2u); + EXPECT_EQ(presence->states[0].mask, 0x10u); + EXPECT_EQ(presence->states[1].state, NSM_FPGA_STATE_ABSENT); + EXPECT_EQ(presence->numeric.offset, 1); + EXPECT_STREQ(presence->group, "Optics_4"); + /* power good: bit 1 of the same expander byte, no rows of its own */ + const auto *pgood = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_4_Power_Good"); + ASSERT_NE(pgood, nullptr); + EXPECT_EQ(pgood->command_count, 0u); + EXPECT_EQ(pgood->numeric.offset, 1); + ASSERT_EQ(pgood->state_count, 2u); + EXPECT_EQ(pgood->states[0].mask, 0x02u); + EXPECT_EQ(pgood->states[0].state, NSM_FPGA_STATE_ENABLED); + EXPECT_EQ(pgood->states[1].state, NSM_FPGA_STATE_FAULT); + EXPECT_EQ(pgood->states[1].health, NSM_FPGA_HEALTH_CRITICAL); + const auto *state = nsm_fpga_find_rule( + p0, "HGX_Chassis_0_FPGA_0_Optics_0_Module_State"); + ASSERT_NE(state, nullptr); + EXPECT_EQ(state->state_count, 6u); + EXPECT_EQ(state->states[0].mask, 0x0eu); + /* inventory: page select, confirm, then 53 bytes in four-byte steps */ + const auto *inventory = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_0_Inventory"); + ASSERT_NE(inventory, nullptr); + EXPECT_EQ(inventory->kind, NSM_FPGA_RULE_IDENTITY); + EXPECT_EQ(inventory->command_count, 16u); + EXPECT_EQ(inventory->commands[2].u.xfer.write[0], 129); + EXPECT_EQ(inventory->commands[2].u.xfer.read_count, 4); + EXPECT_EQ(inventory->commands[15].u.xfer.write[0], 181); + EXPECT_EQ(inventory->commands[15].u.xfer.read_count, 1); + ASSERT_EQ(inventory->identity_count, 4u); + EXPECT_EQ(inventory->identity[0].asset, NSM_FPGA_ASSET_MANUFACTURER); + EXPECT_EQ(inventory->identity[2].asset, NSM_FPGA_ASSET_REVISION); + EXPECT_EQ(inventory->identity[3].offset, 37); + const auto *temp = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_2_Temp_0"); + ASSERT_NE(temp, nullptr); + EXPECT_EQ(temp->command_count, 1u); + EXPECT_EQ(temp->numeric.format, NSM_FPGA_FORMAT_S16BE); + EXPECT_EQ(temp->valid_if.offset, 11); + const auto *power = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_1_Rx_Power"); + ASSERT_NE(power, nullptr); + EXPECT_EQ(power->kind, NSM_FPGA_RULE_ARRAY); + EXPECT_EQ(power->numeric.vector, NSM_FPGA_VECTOR_RX_POWER); + EXPECT_EQ(power->numeric.stride_bits, 16); + EXPECT_EQ(power->command_count, 24u); + /* banks 1 to 3 run only when the bank count code allows them */ + EXPECT_EQ(power->commands[0].run_if.buffer, NSM_FPGA_BUF_NONE); + EXPECT_EQ(power->commands[6].run_if.op, NSM_FPGA_CMP_GE); + EXPECT_EQ(power->commands[6].run_if.value, 1u); + EXPECT_EQ(power->commands[12].run_if.op, NSM_FPGA_CMP_EQ); + EXPECT_EQ(power->commands[12].run_if.value, 2u); + EXPECT_EQ(power->run_if.offset, 5); + EXPECT_EQ(power->run_if.value, 0x06u); + EXPECT_EQ(power->valid_if.mask, 0x04u); + const auto *fault = + nsm_fpga_find_rule(p0, "HGX_Chassis_0_FPGA_0_Optics_3_Tx_Fault"); + ASSERT_NE(fault, nullptr); + EXPECT_EQ(fault->numeric.vector, NSM_FPGA_VECTOR_TX_FAULT); + EXPECT_EQ(fault->numeric.stride_bits, 1); + EXPECT_EQ(fault->command_count, 12u); + EXPECT_EQ(fault->commands[2].u.xfer.write[0], 135); +}
diff --git a/libnsm/test/meson.build b/libnsm/test/meson.build index 226c32e..1caea25 100644 --- a/libnsm/test/meson.build +++ b/libnsm/test/meson.build
@@ -71,6 +71,7 @@ # Row tests build only when the FPGA tables header is present if fs.exists('../fpga/fpga-tables.h') tests += [ + 'libnsm_fpga_rules_links_test', 'libnsm_fpga_rules_pdb_test', 'libnsm_fpga_rules_dimm_test', 'libnsm_fpga_rules_sdm_test', @@ -101,6 +102,8 @@ # Every generated FPGA table must match its rows file fpga_rows = [ 'fpga-rules-lp30', + 'fpga-rules-lp30-links', + 'fpga-rules-lp30-optics', 'fpga-rules-lp30-pdb', 'fpga-rules-lp30-sdm', 'fpga-rules-lp30-dimm',
diff --git a/nsmd/nsmFpgaTelemetry/meson.build b/nsmd/nsmFpgaTelemetry/meson.build index c55a717..f0df868 100644 --- a/nsmd/nsmFpgaTelemetry/meson.build +++ b/nsmd/nsmFpgaTelemetry/meson.build
@@ -9,6 +9,8 @@ '../libnsm/fpga/fpga-tables.c', '../libnsm/fpga/fpga-run.c', '../libnsm/fpga/fpga-rules-lp30.c', + '../libnsm/fpga/fpga-rules-lp30-links.c', + '../libnsm/fpga/fpga-rules-lp30-optics.c', '../libnsm/fpga/fpga-rules-lp30-pdb.c', '../libnsm/fpga/fpga-rules-lp30-dimm.c', '../libnsm/fpga/fpga-rules-lp30-sdm.c',