#!/bin/bash
####################################################################
#
#      File: S40klmfabric
#      Name: Rajesh Ranga
#
#      Description:
#      broadcom klm for fabric on FC card
#
# Copyright (c) 2015-2016 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

# 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
function take_fe3200_out_of_reset () {
     get_card_index
     local reset_ctrl=0
     if [ "$CARDINDEX" = "27004" ]; then
         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
        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
}

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
        iofpga_reg_write $IOFPGA_BOARD_CTRL_REG_ADDR 0x1

        # Wait for DM2 to power up by checking the DM2 status bit
        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
        log_klmfabric_msg "Power domain 2 successfully enabled"

        # Take fabric devices out of reset
        take_fe3200_out_of_reset
        sleep 0.6

        # Do PCI rescan to discover the fabric devices
        echo 1 > /sys/bus/pci/rescan
        sleep 0.6
        num_devices=`lspci -nn | grep "14e4:8" | cut -d " " -f 1 |wc -l`
        if [ $num_devices -eq 0 ]; then
            # Re-try one 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
            num_devices=`lspci -nn | grep "14e4:8" | cut -d " " -f 1 |wc -l`
            if [ $num_devices -eq 0 ]; then
                log_klmfabric_msg "Failed to detect any fabric device from PCI bus"
                # We will continue even with this failure, fabric plugin in Calvados VM
                # will do the correct reporting to the issue when it sees this issue.
            fi
        fi
        if [ $num_devices -gt 0 ]; then
            # Two entry from lspci per fabric device
            num_devices=$(($num_devices / 2))
            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
        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
    
        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
