#!/bin/bash
####################################################################
#
#      File: S40klmfabric
#      Name: Rajesh Ranga
#
#      Description:
#      broadcom klm for fabric on FC card
#
# Copyright (c) 2015-2018, 2020 by cisco Systems, Inc.
# All rights reserved.
#
#####################################################################

. /etc/init.d/mod_ins/module-load-functions
. /etc/init.d/spirit_pd.sh

boot_debug "Executing $0 [S44klmfabric]"

BRCM_KBDE_DEV_NAME=/dev/linux-kernel-bde
BRCM_UBDE_DEV_NAME=/dev/linux-user-bde

IS_RAMON_BASED_BOARD=0
num_devices=0
num_duplicate_devices=0
# Init BOARDTYPE and IOFPGA base address
get_board_type
init_iofpga_base_addr

# Log message in /var/log/kern.log so they can be cached in /mnt/pstore
# that can be debugged later as everything in /var/log will be lost after
# reload in memboot cards.
function log_klmfabric_msg () {
    echo "klmfabric: $@" > /dev/kmsg
}

# Check if DM2 state if enabled or not
IOFPGA_FC_PWR_DM2_GOOD_BIT=0x80000
function check_dm2_enable_state () {
    local board_ctrl=$(iofpga_reg_read $IOFPGA_BOARD_STATUS_REG_ADDR)
    local dm2_enabled=$(($board_ctrl & $IOFPGA_FC_PWR_DM2_GOOD_BIT))

    if [ $dm2_enabled -eq $(($IOFPGA_FC_PWR_DM2_GOOD_BIT)) ]; then
        echo "on"
    else
        echo "off"
    fi
}

# Take all the FE3200 devices out of reset
IOFPGA_FC_RESET_CTRL_REG_ADDR=0x84
#IOFPGA_FC16_FE3200_RESET_MASK=0x104f0000
IOFPGA_FC16_FE3200_RESET_MASK=0xffffffff
IOFPGA_FC8_FE3200_RESET_MASK=0x30000
# PCIE reset register for RAMON
#Ramon 32bit register, FE0=>bit0, FE1=>bit11, FE2=>bit17
IOFPGA_FE_CHIP_OUT_OF_RESET_REG_ADDR=0x31c
IOFPGA_FC16_RAMON_PCI_RESET_MASK=0x20801
IOFPGA_FC16_RAMON_RESET_MASK=0xffffffff
IOFPGA_REG_ID=0x4
IOFPGA_ID_FC_AUGUSTUS16=11596586
function take_fe_out_of_reset () {
     # 27042 Augustus8
     # 27037 Augustus16
     # 27004 Uluru16
     # 27003 Uluru8
	 # 27043 Augustus4
     local reset_ctrl=0
     if [ "$CARDINDEX" == "27042" ] || [ "$CARDINDEX" == "27037" ]; then
         log_klmfabric_msg "Power domain 2 successfully enabled, CARDINDEX is : $CARDINDEX"
         IS_RAMON_BASED_BOARD=1
         sleep 1
         local fe_io_ctrl=$(iofpga_reg_read $IOFPGA_FE_CHIP_OUT_OF_RESET_REG_ADDR)
         fe_io_ctrl=$(($fe_io_ctrl | $IOFPGA_FC16_RAMON_PCI_RESET_MASK))
         log_klmfabric_msg "fe_io_ctrl is : ${fe_io_ctrl} $(printf 0x%08X $fe_io_ctrl)"
         iofpga_reg_write $IOFPGA_FE_CHIP_OUT_OF_RESET_REG_ADDR $(printf 0x%08X $fe_io_ctrl)
         sleep 1
         local reset_ctrl=$(iofpga_reg_read $IOFPGA_FC_RESET_CTRL_REG_ADDR)
         reset_ctrl=$(($reset_ctrl & ~$IOFPGA_FC16_RAMON_RESET_MASK))
         iofpga_reg_write $IOFPGA_FC_RESET_CTRL_REG_ADDR $(printf 0x%08X $reset_ctrl)
         sleep 0.4
    elif [ "$CARDINDEX" == "27043" ]; then
        local reset_ctrl=$(iofpga_reg_read $IOFPGA_FC_RESET_CTRL_REG_ADDR)
        reset_ctrl=$(($reset_ctrl & ~$IOFPGA_FC16_RAMON_RESET_MASK))
        iofpga_reg_write $IOFPGA_FC_RESET_CTRL_REG_ADDR $(printf 0x%08X $reset_ctrl)  # SYS-RST

        sleep 0.2  # Wait for 200msec
        local fe_io_ctrl=$(iofpga_reg_read $IOFPGA_FE_CHIP_OUT_OF_RESET_REG_ADDR)
        fe_io_ctrl=$(($fe_io_ctrl | $IOFPGA_FC16_RAMON_PCI_RESET_MASK))
        iofpga_reg_write $IOFPGA_FE_CHIP_OUT_OF_RESET_REG_ADDR $(printf 0x%08X $fe_io_ctrl)  # PCI-e unreset
        sleep 1
        IS_RAMON_BASED_BOARD=1
        log_klmfabric_msg "Power domain 2 successfully enabled, CARDINDEX is : $CARDINDEX"

     elif [ "$CARDINDEX" == "27004" ]; then
         log_klmfabric_msg "Power domain 2 successfully enabled, CARDINDEX is : $CARDINDEX"
         reset_ctrl=$(iofpga_reg_read $IOFPGA_FC_RESET_CTRL_REG_ADDR)
         reset_ctrl=$(($reset_ctrl & ~$IOFPGA_FC16_FE3200_RESET_MASK))
         iofpga_reg_write $IOFPGA_FC_RESET_CTRL_REG_ADDR $(printf 0x%08X $reset_ctrl)
     else
        log_klmfabric_msg "Power domain 2 successfully enabled, CARDINDEX is : $CARDINDEX"
        reset_ctrl=$(iofpga_reg_read $IOFPGA_FC_RESET_CTRL_REG_ADDR)
        reset_ctrl=$(($reset_ctrl & ~$IOFPGA_FC8_FE3200_RESET_MASK))
        iofpga_reg_write $IOFPGA_FC_RESET_CTRL_REG_ADDR $(printf 0x%08X $reset_ctrl)
     fi
}

function get_num_devices () {
    num_devices=`lspci -nn | grep "14e4:8" | cut -d " " -f 1 |wc -l`
    if [ $IS_RAMON_BASED_BOARD -eq 1 ]; then
        num_duplicate_devices=`lspci -nn | grep "14e4:84" | cut -d " " -f 1 |wc -l`
    else
        # Two entry from lspci per fabric device for FE3200
        num_duplicate_devices=$num_devices
    fi
    num_duplicate_devices=$(($num_duplicate_devices / 2))
    num_devices=$(($num_devices - $num_duplicate_devices))
}

case $1 in
    start)
        #
        # NOTE: We are doing powering up, take device out of reset and do PCI rescan
        #       here instead of having this done via fabric plugin in Calvados VM 
        #
        #
        # Power up Broadcom fe3200 [14e4:8950]] or fe3600 [14e4:8775] that
        # are located in power domain 2. Set bit 1 in register 0x300
        log_klmfabric_msg "Begin Power up Broadcom FE32/9600 device"
        iofpga_reg_write $IOFPGA_BOARD_CTRL_REG_ADDR 0x1

        # Wait for DM2 to power up by checking the DM2 status bit
        # Augustus-4 Ramon initialization sequence changed.
        # Enable Power DM2, check for DM2 power good after waiting min 60msec 
        # After DM2 good, perform ramon SYS-RST, wait for 200msec
        # and finally perform PCI-e reset
    
        get_card_index

        if [ "$CARDINDEX" == "27043" ]; then
            sleep 0.1
            local dm2_state=$(check_dm2_enable_state)
            if [ "$dm2_state" == "off" ]; then
                log_klmfabric_msg "Power domain 2 not yet enabled after 100 miliseconds, wait some more time ..."
                sleep 0.06
                dm2_state=$(check_dm2_enable_state)
                if [ "$dm2_state" == "off" ]; then
                    log_klmfabric_msg "Power domain 2 still not yet enabled after another 60msec, Exiting ..."
                    exit 1
                fi
            fi
        else
            sleep 0.2
            local dm2_state=$(check_dm2_enable_state)
            if [ "$dm2_state" == "off" ]; then
                log_klmfabric_msg "Power domain 2 not yet enabled after 0.2 seconds, wait some more time ..."
                sleep 0.5
                dm2_state=$(check_dm2_enable_state)
                if [ "$dm2_state" == "off" ]; then
                    log_klmfabric_msg "Power domain 2 still not yet enabled after another 0.5 seconds. Exiting ..."
                    exit 1
                fi
            fi
        fi

        # Take fabric devices out of reset
        take_fe_out_of_reset
        log_klmfabric_msg "IS_RAMON_BASED_BOARD $IS_RAMON_BASED_BOARD"
        sleep 0.6

        # Do PCI rescan to discover the fabric devices
        echo 1 > /sys/bus/pci/rescan
        #HACK mahessin: this is temp workaround put to avoid kernel panic
        #on augustus cards during disk-boot.
        if  pd_is_augustus_card ; then
            dmesg 
        fi
        sleep 0.6
        get_num_devices
        log_klmfabric_msg "num_devices:$num_devices"
        num_retry=0
        
        while [ $num_devices -eq 0 ]
        do
            # Re-try couple of (now 3) more time before giving up
            log_klmfabric_msg "Re-scan PCI bus again to discover fabric devices ..."
            echo 1 > /sys/bus/pci/rescan
            sleep 0.4
            get_num_devices
        
            if [ $num_devices -eq 0 ]; then
                log_klmfabric_msg "Failed to detect any fabric device from "\
                                  "PCI bus,retry count: ${num_retry}"
            fi
            num_retry=`expr $num_retry + 1` 
            if [ $num_retry -gt 2 ];
            then
                break
            fi
        done

        if [ $num_devices -gt 0 ]; then
            # Two entry from lspci per fabric device
            log_klmfabric_msg "Detected $num_devices fabric devices present in PCI bus"
        fi

        log_klmfabric_msg "Loading BCM KLMs ..."
        # FC card has a BCM switch requiring BCM KLMs
        # For Aug-4 cards having Intel processor, the broadcom klm names are different.
        # linux-kernel-bde.ko, linux-user-bde.ko
     get_card_index
     log_klmfabric_msg "CARDINDEX is : $CARDINDEX"
     if [ "$CARDINDEX" == "27043" ]; then

        #TODO: Update the bcm-klm-6.5.9-r1.0.x86_64.rpm to create sym link in 
        # /lib/modules/ to point to modules installed in below insmod command 
        insmod /lib/modules/`uname -r`/extra/linux-kernel-bde.ko reverse_enum_dev_total=0 dmasize=32M usemsi=1 debug=2
        insmod /lib/modules/`uname -r`/extra/linux-user-bde.ko

     else
        insmod /lib/modules/klm_fabric_kernel_bde.o reverse_enum_dev_total=0 dmasize=32M usemsi=1 debug=2
        insmod /lib/modules/klm_fabric_user_bde.o
	 fi
        BRCM_KBDE_MAJ_NUM=`cat /proc/devices | fgrep linux-kernel-bde | awk '{print $1}'`
        BRCM_UBDE_MAJ_NUM=`cat /proc/devices | fgrep linux-user-bde | awk '{print $1}'`
        mknod $BRCM_KBDE_DEV_NAME c $BRCM_KBDE_MAJ_NUM 0
        mknod $BRCM_UBDE_DEV_NAME c $BRCM_UBDE_MAJ_NUM 0
    ;;

    stop)
        boot_debug "Stopping klm_fabric"
        rmmod klm_eth_user_bde.o
        rmmod klm_eth_kernel_bde.o
    ;;
esac
