#!/bin/bash

# This script is called from slice_mgr to 
# detect the MS FPGA . this script will print 0 for success
# & error for other errors . this error will be passed to coherent
# process. Coherent FMEA should handle it.
#
# Copyright (c) 2016, 2020 by Cisco Systems, Inc.

. /etc/init.d/spirit_pd.sh

function set_plx_msfpga_port_link_enable_disable(){
    local link_disable=0x10
    if [ "$CARDINDEX" = 27012 ]; then
        if [ "$1" = 0 ]; then
            platform_log "Disabling the link"
            link_disable=0x10    
        else    
            platform_log "Enabling the link"
            link_disable=0x0    
        fi

        setpci -s 04:03.0 78.B="$link_disable"
        setpci -s 04:05.0 78.B="$link_disable"
        setpci -s 04:07.0 78.B="$link_disable"
        get_plx_msfpga_port_link_status
    fi
}

function get_plx_msfpga_port_link_status(){
    if [ "$CARDINDEX" = 27012 ]; then
		platform_log "Get Link Status 78H"
		platform_log "04:03.0 `setpci -s 04:03.0 78.L`"
		platform_log "04:05.0 `setpci -s 04:05.0 78.L`"
		platform_log "04:07.0 `setpci -s 04:07.0 78.L`"
    fi
}

function get_plx_msfpga_port_link_control_state(){
    if [ "$CARDINDEX" = 27012 ]; then
		platform_log "Get Link Target Speed 98H"
		platform_log "04:03.0 `setpci -s 04:03.0 98.L`"
		platform_log "04:05.0 `setpci -s 04:05.0 98.L`"
		platform_log "04:07.0 `setpci -s 04:07.0 98.L`"
    fi
}

function set_plx_msfpga_port_retrain(){
    if [ "$CARDINDEX" = 27012 ]; then
		platform_log "Retraining the link "
        setpci -s 04:03.0 78.B=20
        setpci -s 04:05.0 78.B=20
        setpci -s 04:07.0 78.B=20
    fi
}

function set_plx_msfpga_port_capability(){
    if [ "$CARDINDEX" = 27012 ]; then
        get_plx_msfpga_port_link_control_state
        get_plx_msfpga_port_link_status    
        if [ "$1" = 1 ]; then
            platform_log "Changing the link speed to 2.5G"
        else    
            platform_log "Changing the link speed to 5G"
        fi
        setpci -s 04:03.0 98.B=$1
        setpci -s 04:05.0 98.B=$1
        setpci -s 04:07.0 98.B=$1
		# Retrain the link 
		set_plx_msfpga_port_retrain 
        get_plx_msfpga_port_link_control_state
        get_plx_msfpga_port_link_status
    fi
}

function check_card_type () {
  init_iofpga_base_addr
  card_value=$(iofpga_reg_read 0x4)
  case "$card_value" in
   0x01505327)
     CARDINDEX="27013"
     ;;
   0x0011986C)
     CARDINDEX="27012"
     ;;
   esac
   platform_log "MSFPGA found $CARDINDEX"
}

function lxc_xr_lc_enable_msfpga()
{
    local num_msfpga=0
    local detected_msfpga=""    
    local count=0
    local total_msfpga=2
    local fpga_version="10ee:8021"

    check_card_type

    # On 18 port MACSEC LC the power OFF and ON of DM2 during XR LXC reload 
    # causes the MSFPGA image loss we need to always check the status of 
    # MSFPGA using MIFPGA 0x40C status. If its not
    # 3ff then we need to reload MSFPGA using 0x408 writing 0x1 on it.
    if [ "$CARDINDEX" = "27013" ]; then
       fpga_version="1137:01c5";
       let total_msfpga=4
       local msfpga_conf=`/usr/sbin/pcimemread 0xd340040C 4 | grep ":" | grep 3ff | wc -l`
       if [ $msfpga_conf -le 0 ]; then
          # relaod MSFPGA and wait till it becomes stable
          /usr/sbin/pcimemwrite 0xd3400408  4  0x1 > /dev/null 2>&1
       fi 

       until [ $msfpga_conf -gt 0 ]; do
           msfpga_conf=`/usr/sbin/pcimemread 0xd340040C 4 | grep ":" | grep 3ff | wc -l`
           sleep 0.5
           let count=count+1
           if [ $count -gt 30 ]; then
             break
           fi
       done

       if [ $msfpga_conf -le 0 ]; then
          # MSFPGA NOT IN GOOD STATUS
          echo 2  
       fi 
    fi
 
    #  We start by rescanning with the PEX8619 switch link speed at  5G (default)
    #  We give a time of max 1 minute to see if all FPGA are found. 
    #  If not found, we change link speed to 2.5G and retrain the link and 
    #  do rescan again. This is done to handle errata#5 for PEX switch
    #  see DDTS CSCuz65801.
    #  We also try putting FPGA in reset and bring it out of reset too
    #  Once the devices are rescanned successfully, we change the link speed
    #  back to 5G speed.
    #      

    let count=0
    num_msfpga=`lspci -nn | grep "$fpga_version" | cut -d " " -f 1 |wc -l`
    until [ $num_msfpga -gt $total_msfpga ]; do
        if [ "$CARDINDEX" = 27012 ]; then
            echo 1 > /sys/class/pci_bus/0000:07/rescan
            echo 1 > /sys/class/pci_bus/0000:08/rescan
            echo 1 > /sys/class/pci_bus/0000:09/rescan
        else
            echo 1 > /sys/class/pci_bus/0000:05/rescan
            echo 1 > /sys/class/pci_bus/0000:08/rescan 
            echo 1 > /sys/class/pci_bus/0000:09/rescan 
            echo 1 > /sys/class/pci_bus/0000:0a/rescan
            echo 1 > /sys/class/pci_bus/0000:0f/rescan
        fi

        num_msfpga=`lspci -nn | grep "$fpga_version" | cut -d " " -f 1 |wc -l`
        if [ $num_msfpga -le $total_msfpga ]; then
            if [ $count -eq 180 ]; then # Step2: First 1.5 minute elapsed 
                # We might be running into Erratta#5 where PHY Polling state 
                # machine can get stuck under noisy link in 5G speed
                # So reducing the speed to 2.5G and retrain before next rescan
                set_plx_msfpga_port_capability 1
            elif [ $count -eq 240 ]; then # Step3: Next 1 minute elapsed
                # Disable the Link
                set_plx_msfpga_port_link_enable_disable 0
                # Let's try reset of MSFPGA and bring out of reset
                init_iofpga_base_addr
                # Put all FPGA in reset
                platform_log "MSFPGA in Reset"
                iofpga_reg_write 0x274 0x707 
                sleep 0.1
                # Bring out of reset
                platform_log "MSFPGA out of Reset"
                iofpga_reg_write 0x274 0x700 
                sleep 0.2
                # Enable the link
                set_plx_msfpga_port_link_enable_disable 1
                set_plx_msfpga_port_capability 1
            elif [ $count -eq 360 ]; then # Step4: Another 1 minute elapsed
                # Still we haven't seen the FPGA, Lets retrain the link 
			    # at 5G speed to recover any link down
                set_plx_msfpga_port_capability 2
            elif [ $count -eq 420 ]; then # Step5: Another 30 sec elapsed
                # Still we haven't seen the FPGA, Lets set the link 
                # at 2.5G speed again and try
                set_plx_msfpga_port_capability 1
            fi    
            sleep 0.5
        fi
        let count=count+1
        #Step6: Total Timeout of 240 second (480 * 0.5 second sleep)  and we bail out.
        if [ $count -gt 480 ]; then
            if [ $num_msfpga -gt 0 ]; then    
                detected_msfpga=`lspci -nn | grep "$fpga_version" | cut -d " " -f 1`
                platform_log "FOUND MSFPGA only at $detected_msfpga"    
            fi    
            break
        fi
    done

    if [ $num_msfpga -le 0 ]; then
       platform_log "NOT FOUND..MSFPGA"
       echo 1
       return 0
    fi
    platform_log "FOUND..$num_msfpga  MSFPGA"

    #Forced Switching back to 5G speed
    set_plx_msfpga_port_capability 2

    ssh 10.0.2.16 '/etc/init.d/dev-allow default-sdr--1' > /dev/null 2>&1  
    echo 0
    return 0
}

lxc_xr_lc_enable_msfpga
