fboss/qsfp_service/module/cmis/CmisModule.cpp
/*
 * setModuleRxEqualizerLocked
 *
 * Customize the optics for Rx pre-cursor, Rx post cursor, Rx main amplitude
 * 1. Check P11h, B223-234 to compare current and desired pre/post/main
 * 2. Write P10h, B162-165 for Pre
 * 3. Write P10h, B166-169 for Post
 * 4. Write P10h, B170-173 for Main
 * 5. Write P10h, B145-152 bit 0 = 1 to use Staged Set 0 values
 * 6. Write P10h, B144 = 0xFF to apply stage 0 control value immediately
 */
setModuleRxEqualizerLocked
Customize the optics for Rx pre-cursor, Rx post cursor, Rx main amplitude
1. Check P11h, B223-234 to compare current and desired pre/post/main
2.
setModuleRxEqualizerLocked Customize the optics for Rx pre - cursor Rx post cursor Rx main amplitude 1 . Check P11h B223 - 234 to compare current and desired pre / post / main 2 .
void CmisModule::setModuleRxEqualizerLocked(RxEqualizerSettings rxEqualizer) {
  uint8_t currPre[4], currPost[4], currMain[4];
  uint8_t desiredPre[4], desiredPost[4], desiredMain[4];
  bool changePre = false, changePost = false, changeMain = false;
  int offset, length, dataAddress;
  XLOG(INFO) << folly::sformat(
      "setModuleRxEqualizerLocked called for {:s}", qsfpImpl_->getName());
  for (int i = 0; i < 4; i++) {
    desiredPre[i] = ((*rxEqualizer.preCursor_ref() & 0xf) << 4) |
        (*rxEqualizer.preCursor_ref() & 0xf);
    desiredPost[i] = ((*rxEqualizer.postCursor_ref() & 0xf) << 4) |
        (*rxEqualizer.postCursor_ref() & 0xf);
    desiredMain[i] = ((*rxEqualizer.mainAmplitude_ref() & 0xf) << 4) |
        (*rxEqualizer.mainAmplitude_ref() & 0xf);
  }
  uint8_t page = 0x11;
  qsfpImpl_->writeTransceiver(
      TransceiverI2CApi::ADDR_QSFP, 127, sizeof(page), &page);
  auto compareSettings = [&](uint8_t currSettings[],
                             uint8_t desiredSettings[],
                             int length,
                             bool& changeNeeded) {
    for (auto i = 0; i < length; i++) {
      if (currSettings[i] != desiredSettings[i]) {
        changeNeeded = true;
        return;
      }
    }
  };
  getQsfpFieldAddress(
      CmisField::RX_OUT_PRE_CURSOR, dataAddress, offset, length);
  qsfpImpl_->readTransceiver(
      TransceiverI2CApi::ADDR_QSFP, offset, length, currPre);
  compareSettings(currPre, desiredPre, length, changePre);
  getQsfpFieldAddress(
      CmisField::RX_OUT_POST_CURSOR, dataAddress, offset, length);
  qsfpImpl_->readTransceiver(
      TransceiverI2CApi::ADDR_QSFP, offset, length, currPost);
  compareSettings(currPost, desiredPost, length, changePost);
  getQsfpFieldAddress(CmisField::RX_OUT_MAIN, dataAddress, offset, length);
  qsfpImpl_->readTransceiver(
      TransceiverI2CApi::ADDR_QSFP, offset, length, currMain);
  compareSettings(currMain, desiredMain, length, changeMain);
  if (changePre || changePost || changeMain) {
    page = 0x10;
    qsfpImpl_->writeTransceiver(
        TransceiverI2CApi::ADDR_QSFP, 127, sizeof(page), &page);
    if (changePre) {
      getQsfpFieldAddress(
          CmisField::RX_CONTROL_PRE_CURSOR, dataAddress, offset, length);
      qsfpImpl_->writeTransceiver(
          TransceiverI2CApi::ADDR_QSFP, offset, length, desiredPre);
    }
    if (changePost) {
      getQsfpFieldAddress(
          CmisField::RX_CONTROL_POST_CURSOR, dataAddress, offset, length);
      qsfpImpl_->writeTransceiver(
          TransceiverI2CApi::ADDR_QSFP, offset, length, desiredPost);
    }
    if (changeMain) {
      getQsfpFieldAddress(
          CmisField::RX_CONTROL_MAIN, dataAddress, offset, length);
      qsfpImpl_->writeTransceiver(
          TransceiverI2CApi::ADDR_QSFP, offset, length, desiredMain);
    }
    getQsfpFieldAddress(CmisField::APP_SEL_LANE_1, dataAddress, offset, length);
    uint8_t stage0Control[8];
    uint8_t numLanes = numHostLanes();
    qsfpImpl_->readTransceiver(
        TransceiverI2CApi::ADDR_QSFP, offset, 8, stage0Control);
    for (int i = 0; i < numLanes; i++) {
      stage0Control[i] |= 1;
    }
    qsfpImpl_->writeTransceiver(
        TransceiverI2CApi::ADDR_QSFP, offset, numLanes, stage0Control);
    getQsfpFieldAddress(
        CmisField::STAGE_CTRL_SET0_IMMEDIATE, dataAddress, offset, length);
    uint8_t stage0ControlTrigger = (1 << numLanes) - 1;
    qsfpImpl_->writeTransceiver(
        TransceiverI2CApi::ADDR_QSFP, offset, length, &stage0ControlTrigger);
    XLOG(INFO) << folly::sformat(
        "Module {:s} customized for {:s} {:s} {:s}",
        qsfpImpl_->getName(),
        changePre ? "Pre-cursor" : "",
        changePost ? "Post-cursor" : "",
        changeMain ? "Rx-out-main" : "");
    if (!checkLaneConfigError()) {
      XLOG(ERR) << folly::sformat(
          "Module {:s} customization config rejected", qsfpImpl_->getName());
    }
  }
}
void CmisModule :: setModuleRxEqualizerLocked ( RxEqualizerSettings rxEqualizer ) { uint8_t currPre [ 4 ] , currPost [ 4 ] , currMain [ 4 ] ; uint8_t desiredPre [ 4 ] , desiredPost [ 4 ] , desiredMain [ 4 ] ; bool changePre = false , changePost = false , changeMain = false ; int offset , length , dataAddress ; XLOG ( INFO ) << folly :: sformat ( " " , qsfpImpl_ -> getName ( ) ) ; for ( int i = 0 ; i < 4 ; i ++ ) { desiredPre [ i ] = ( ( * rxEqualizer . preCursor_ref ( ) & 0xf ) << 4 ) | ( * rxEqualizer . preCursor_ref ( ) & 0xf ) ; desiredPost [ i ] = ( ( * rxEqualizer . postCursor_ref ( ) & 0xf ) << 4 ) | ( * rxEqualizer . postCursor_ref ( ) & 0xf ) ; desiredMain [ i ] = ( ( * rxEqualizer . mainAmplitude_ref ( ) & 0xf ) << 4 ) | ( * rxEqualizer . mainAmplitude_ref ( ) & 0xf ) ; } uint8_t page = 0x11 ; qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , 127 , sizeof ( page ) , & page ) ; auto compareSettings = [ & ] ( uint8_t currSettings [ ] , uint8_t desiredSettings [ ] , int length , bool & changeNeeded ) { for ( auto i = 0 ; i < length ; i ++ ) { if ( currSettings [ i ] != desiredSettings [ i ] ) { changeNeeded = true ; return ; } } } ; getQsfpFieldAddress ( CmisField :: RX_OUT_PRE_CURSOR , dataAddress , offset , length ) ; qsfpImpl_ -> readTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , currPre ) ; compareSettings ( currPre , desiredPre , length , changePre ) ; getQsfpFieldAddress ( CmisField :: RX_OUT_POST_CURSOR , dataAddress , offset , length ) ; qsfpImpl_ -> readTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , currPost ) ; compareSettings ( currPost , desiredPost , length , changePost ) ; getQsfpFieldAddress ( CmisField :: RX_OUT_MAIN , dataAddress , offset , length ) ; qsfpImpl_ -> readTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , currMain ) ; compareSettings ( currMain , desiredMain , length , changeMain ) ; if ( changePre || changePost || changeMain ) { page = 0x10 ; qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , 127 , sizeof ( page ) , & page ) ; if ( changePre ) { getQsfpFieldAddress ( CmisField :: RX_CONTROL_PRE_CURSOR , dataAddress , offset , length ) ; qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , desiredPre ) ; } if ( changePost ) { getQsfpFieldAddress ( CmisField :: RX_CONTROL_POST_CURSOR , dataAddress , offset , length ) ; qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , desiredPost ) ; } if ( changeMain ) { getQsfpFieldAddress ( CmisField :: RX_CONTROL_MAIN , dataAddress , offset , length ) ; qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , desiredMain ) ; } getQsfpFieldAddress ( CmisField :: APP_SEL_LANE_1 , dataAddress , offset , length ) ; uint8_t stage0Control [ 8 ] ; uint8_t numLanes = numHostLanes ( ) ; qsfpImpl_ -> readTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , 8 , stage0Control ) ; for ( int i = 0 ; i < numLanes ; i ++ ) { stage0Control [ i ] |= 1 ; } qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , numLanes , stage0Control ) ; getQsfpFieldAddress ( CmisField :: STAGE_CTRL_SET0_IMMEDIATE , dataAddress , offset , length ) ; uint8_t stage0ControlTrigger = ( 1 << numLanes ) - 1 ; qsfpImpl_ -> writeTransceiver ( TransceiverI2CApi :: ADDR_QSFP , offset , length , & stage0ControlTrigger ) ; XLOG ( INFO ) << folly :: sformat ( " " , qsfpImpl_ -> getName ( ) , changePre ? " " : " " , changePost ? " " : " " , changeMain ? " " : " " ) ; if ( ! checkLaneConfigError ( ) ) { XLOG ( ERR ) << folly :: sformat ( " " , qsfpImpl_ -> getName ( ) ) ; } } }
setModuleRxEqualizerLocked
 Customize the optics for Rx pre-cursor, Rx post cursor, Rx main amplitude
 1.
setModuleRxEqualizerLocked Customize the optics for Rx pre - cursor Rx post cursor Rx main amplitude 1 .
// Flip to page 0x11 to read current values // Some of the pre-cursor value needs to be changed so break from // here // Compare current Pre cursor value to see if the change is needed // Compare current Post cursor value to see if the change is needed // Compare current Rx Main value to see if the change is needed // If anything is changed then apply the change and trigger it // Flip to page 0x10 to change the values // Apply the change for pre/post/main if needed // Apply the change using stage 0 control // Trigger the stage 0 control values to be operational in optics // Check if the config has been applied correctly or not