#!/bin/bash

ECFM_SESSION_BLOCK_SIZE=0x0150
#Offset within the block
ECFM_FRAME_GEN_MEMORY=0x0000
ECFM_STAT_BIN_MEMORY=0x0080
ECFM_SESSION_GEN=0x00B0
ECFM_RX_CLASS_MEMORY=0x00C0
ECFM_TX_RX_COUNTER=0x00E0
ECFM_RX_FRAME_CHK_MEMORY=0x00F0
ECFM_RX_STAT=0x0100

get_ecfm_base_addr () 
{
   if [ -z ${ecfm_base_addr+x} ]; 
   then
       ecfm_base_addr=$(cat /proc/iomem | grep -i ecfm | sed 's/-.*$//g') 
   fi
   echo "0x$ecfm_base_addr";
}


ecfm_table_modify ()
{
    local field="$1"
    local value="$2"
    local table_id="$3"
    shift 3

    ecfm_table_dump "$table_id" "$@" | sed "/$field/s/:.*/: $value/" | ecfm_table_fill "$table_id"
}

ecfm_table_clear ()
{
    local table_id="$1"
    shift 1

    ecfm_table_dump "$table_id" "$@" | grep ^0 | ecfm_table_fill "$table_id"
}



ecfm_init()
{
    cfmreg ECFM_REG_CNTRL.CLEAR_TLV_OFFSET_RAM 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_ZBT 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_EHG_HDR_TEMPLATE_TABLE 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_TX_SEQUENCE_NUM_GENERATOR 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_GPORT_BITMAP_TABLE 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_SESSION_SCAN_RAM 0x1
    ecfmreg ECFM_REG_CNTRL.GLOBAL_DROP_CCM_EN 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_MEP_ID_RAM 0x1
    ecfmreg ECFM_REG_CNTRL.CLEAR_EHG_HDR_TYPE_TABLE 0x1
    sleep 1 

    ecfmreg ECFM_REG_PRT_BMP_CTRL.CLEAR_TABLE 1
    ecfmreg ECFM_REG_CLASS_CTRL.CLEAR_CLASSIFIER_TABLE 1

    ecfmreg ECFM_REG_DEBUG 0x0
    ecfmreg ECFM_REG_DEBUG.RESET_SPFL_INTR_FIFO 0x1
    ecfmreg ECFM_REG_DEBUG.RESET_RXFC_INTR_FIFO 0x1
    ecfmreg ECFM_REG_DEBUG 0x0

    
}




ecfm_dump_ECFM_GPORT2BMP_RAM()
{

    if [ "$#" -ne 1 ]
    then
    echo "Usage: <gport>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Gport to Port-Bitmap Mapping table "
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_GPORT2BMP_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 4)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 2 2 
}





ecfm_dump_ECFM_EHG_HDR_TEMPLATE_RAM()
{
    local id="$1"
    shift 1

    echo "Encapsulation header(14) + E-HG header (16) "
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_EHG_HDR_TEMPLATE_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA ))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 15 2 
  
}


ecfm_dump_ECFM_CAPTURE_BUFFER_RAM()
{
    local id="$1"
    shift 1

    echo "Frame capture buffer..."
    echo "In continuous mode, this is a wrapping circular buffer." 
    echo "In one-shot mode, the frame starts at offset 0x0."
    echo "See CAPTURE_BUFFER_CTRL for control bits."
    echo "Frames start with SFD (0xD5)"
    echo "bits: [15:0] contain byte(n+1),byte(n)"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_CAPTURE_BUFFER_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 1022 1 

}

ECFM_COUNTERS_DROPPED=0
ECFM_COUNTERS_REFLECTED=1*256
ECFM_COUNTERS_TERMINATED=2*256
ECFM_COUNTERS_PASSED=3*256
ECFM_COUNTERS_PASSED_DUE_TO_CLASS_MISS=4*256
ECFM_COUNTERS_UNUSED1=5*256
ECFM_COUNTERS_UNUSED2=6*256
ECFM_COUNTERS_UNUSED3=7*256

ecfm_dump_ECFM_COUNTERS_GLOBAL_DEBUG()
{
    local id="$1"
    shift 1

    echo "Debug counter block, each counter is 32 bits wide"
    echo "Adrs[10:8] = Action[3:0] = Action taken on Frame"
    echo "    0 = Dropped"
    echo "    1 = Reflected"
    echo "    2 = Terminated"
    echo "    3 = Passed"
    echo "    4 = Passed due to classifier miss"
    echo "Adrs[7:2] = Frame_type[5:0] = Frame type:"
    echo "    1 = CCM Frames"
    echo "    2 = LBR Frames"
    echo "    3 = LBM Frames"
    echo "    42 = LMR Frames"
    echo "    43 = LMM Frames"
    echo "    45 = DM1 Frames"
    echo "    46 = DMR Frames"
    echo "    47 = DMM Frames"
    echo "    54 = SLR Frames"
    echo "    55 = SLM Frames"
    echo "    other = unknown frame type"

    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_COUNTERS_RAM  | sed 's/ .*$//g' | sed 's/^0*//')

    printf "\n **** DROPPED ****\n"
    local addr=$(($base+$regA + $ECFM_COUNTERS_DROPPED))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 
  
    printf "\n **** REFLECTED ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_REFLECTED))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 

    printf "\n **** TERMINATED ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_TERMINATED))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 

    printf "\n **** PASSED ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_PASSED))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 

    printf "\n **** PASSED DUE TO CLASS MISS ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_PASSED_DUE_TO_CLASS_MISS))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 

    printf "\n **** UNUSED1 ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_UNUSED1))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 

    printf "\n **** UNUSED2 ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_UNUSED2))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 

    printf "\n **** UNUSED3 ****\n"
    addr=$(($base+$regA + $ECFM_COUNTERS_UNUSED3))
    temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 64 4 


}



ecfm_dump_ECFM_EHG_HDR_TYPE_RAM()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <index>"
    return  
    fi

    local id="$1"
    shift 1

    echo "The header type bits are [27:0], stored across two locations"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_EHG_HDR_TYPE_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 4)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 1 4
    echo "------------------------------------------" 
    dmem  $temp 2 2 
 
  
}

ecfm_dump_ECFM_MEP_ID_RAM()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "MEP ID"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_MEP_ID_RAM  | sed 's/ .*$//g' | sed 's/^0*//') 
    local addr=$(($base+$regA + ($id * 2)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 1 2 
  
}


ecfm_dump_ECFM_SEQUENCE_RAM()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "TX editor flow sequence number generator"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_SEQUENCE_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 4)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 1 4
    echo "------------------------------------------" 
    dmem  $temp 4 2 
  
}

ecfm_dump_ECFM_PFL_SS_RAM()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Profile: Session Scan Table"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_PFL_SS_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 4)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 1 4
    echo "------------------------------------------" 
    dmem  $temp 2 2 
  
}





ecfm_dump_ECFM_ZBT_RX_CHK()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "CFM Receive Frame Check Table"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_ZBT_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * $ECFM_SESSION_BLOCK_SIZE) + $ECFM_RX_FRAME_CHK_MEMORY))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 8 2  
}




ecfm_dump_ECFM_ZBT_RX_STATS()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Rx Processing Stats"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_ZBT_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * $ECFM_SESSION_BLOCK_SIZE) + $ECFM_RX_STAT))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 12 8
    echo "------------------------------------------" 
    dmem  $temp 48 2  
}


ecfm_dump_ECFM_ZBT_SESSION_GEN()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Sessions Generation Table"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_ZBT_RAM  | sed 's/ .*$//g' |  sed 's/^0*//')
    local addr=$(($base+$regA + ($id * $ECFM_SESSION_BLOCK_SIZE) + $ECFM_SESSION_GEN))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 1 8
    echo "------------------------------------------" 
    dmem  $temp 4 2 

}

ecfm_dump_ECFM_COUNTERS2()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Frame counter RAM - CLEAR on READ ENABLED"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_COUNTERS2_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 16)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 2 8

}

ecfm_dump_ECFM_COUNTERS2_NC()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Frame counter RAM - CLEAR on READ DISABLED"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_COUNTERS2_NC_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 16)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 2 8

}


ecfm_dump_ECFM_COUNTERS()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Frame Tx/Rx counter"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_ZBT_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * $ECFM_SESSION_BLOCK_SIZE) + $ECFM_TX_RX_COUNTER))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 2 8

}


ecfm_dump_ECFM_ZBT_GEN_RAM()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Frame Generation RAM"
    echo "Each session has 128 bytes of frame generation memory. Offset 0x00 is the first two bytes of payload"
#    echo "offset 0x00: Session 0, Frame payload byte 1, 0"
#    echo "offset 0x02: Session 0, Frame payload byte 3, 2"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_ZBT_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * $ECFM_SESSION_BLOCK_SIZE) + $ECFM_FRAME_GEN_MEMORY))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 128 1
#    dmem  $temp 128 1 > /tmp/ttt
#    cat /tmp/ttt

#    echo "------------------------------------------" 
#    echo "On the wire:"
#    echo "------------------------------------------" 
#    awk '{  t = $2; $2 = $3; $3 = t;  
#            t = $4; $4 = $5; $5 = t;
#            t = $6; $6 = $7; $7 = t;
#            t = $8; $8 = $9; $9 = t;
#            t = $10; $10 = $11; $11 = t;
#            t = $12; $12 = $13; $13 = t;
#            t = $14; $14 = $15; $15 = t;
#            t = $16; $16 = $17; $17 = t;  print; }' /tmp/ttt 

#    rm /tmp/ttt
}

ecfm_dump_ECFM_TLV_OFFSETS_RAM()
{
    if [ "$#" -ne 1 ]
    then
    echo "Usage: <sessionId>"
    return  
    fi

    local id="$1"
    shift 1

    echo "Locations for TLV offsets inside CCM frames"
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_TLV_OFFSETS_RAM  | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA + ($id * 2)))
    local temp=`printf "0x%x\n" ${addr}`
    dmem  $temp 2 1 


}

ecfm_dump_ECFM_RX_PROC_TS_DATA()
{
    local base=$(get_ecfm_base_addr)
    local regA=0x$(ecfmreg ECFM_RX_PROC_TS_DATA | sed 's/ .*$//g' | sed 's/^0*//')
    local addr=$(($base+$regA))
    local temp=$(printf "0x%x\n" ${addr})

    local fifo_level=$(ecfmreg ECFM_RX_PROC_TS_FIFO_FILL_LEVEL.FILL_LEVEL | awk '{ print $5 }')
    fifo_level=$(printf "%d\n" $fifo_level)

    echo "FIFO Fill Level:$fifo_level" 
    local counter=0
    while [ $counter -lt $fifo_level ]; do
       echo "counter:$counter"
       dmem  $temp 9 4
       counter=$(($counter+1))
    done
 
}







