#!/bin/bash debug_flag=0 port_map=('00' '10' '11' '12' '13' '14' '15' '16' '17' '18' '19' '1a' '1b' '1c' '1d' '1e' '1f' '20' '21' '22' '23' '24' '25' '26' '27' '28' '29' '2a' '2b' '2c' '2d' '2e' '2f') port_1_8_presence=0 port_9_16_presence=0 port_17_24_presence=0 port_25_32_presence=0 port_1_8_reset=0 port_9_16_reset=0 port_17_24_reset=0 port_25_32_reset=0 result=0 pre_port_1_8_reset=256 pre_port_9_16_reset=256 pre_port_17_24_reset=256 pre_port_25_32_reset=256 pre_port_1_8_lpmode=256 pre_port_9_16_lpmode=256 pre_port_17_24_lpmode=256 pre_port_25_32_lpmode=256 pre_port_1_8_modsel=256 pre_port_9_16_modsel=256 pre_port_17_24_modsel=256 pre_port_25_32_modsel=256 byte_hex_test() { if ! [[ $1 =~ ^[0-9A-Fa-f]{2}$ ]] ; then return 0 else return 1 fi } #$1=mux $2=channel $3=dev_addr, $4=reg, $5=val bmc_write() { addr_8b=$(echo $(($3)) | awk '{printf $1}') addr_8b=`expr $addr_8b \\* 2` ipmitool raw 0x30 0x85 $1 $2 $addr_8b 2 $4 $5 1>>/dev/null 2>>/dev/null sleep 1 ipmitool raw 0x30 0x87 1>>/dev/null 2>>/dev/null } #$1=mux $2=channel $3=dev_addr, $4=reg, $5=len bmc_read() { addr_8b=$(echo $(($3)) | awk '{printf $1}') addr_8b=`expr $addr_8b \\* 2` ipmitool raw 0x30 0x86 $1 $2 $addr_8b $5 $4 1>>/dev/null 2>>/dev/null sleep 1 val=$(ipmitool raw 0x30 0x87 2>>/dev/null) if [ $? -eq 0 ];then result=$val return 1 else return 0 fi } bmc_qsfp_lpmode_write() { cpld_path="/sys/bus/i2c/devices/0-0006/" val=0 for i in $(seq 1 8); do lpmode_path=$cpld_path"port"$i"_lpmode" lpmode_input=$(cat $lpmode_path | awk '{printf $1}') val=$((val | (lpmode_input << ($i - 1)))) done if [ $val -ne $pre_port_1_8_lpmode ]; then ipmitool raw 0x30 0x25 0x00 0x0c 0x0 0x50 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_1_8_lpmode=$val fi val=0 for i in $(seq 9 16); do lpmode_path=$cpld_path"port"$i"_lpmode" lpmode_input=$(cat $lpmode_path | awk '{printf $1}') val=$((val | (lpmode_input << ($i - 9)))) done if [ $val -ne $pre_port_9_16_lpmode ]; then ipmitool raw 0x30 0x25 0x00 0x0c 0x0 0x51 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_9_16_lpmode=$val fi cpld_path="/sys/bus/i2c/devices/0-0007/" val=0 for i in $(seq 17 24); do lpmode_path=$cpld_path"port"$i"_lpmode" lpmode_input=$(cat $lpmode_path | awk '{printf $1}') val=$((val | (lpmode_input << ($i - 17)))) done if [ $val -ne $pre_port_17_24_lpmode ]; then ipmitool raw 0x30 0x25 0x00 0x0e 0x0 0x50 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_17_24_lpmode=$val fi val=0 for i in $(seq 25 32); do lpmode_path=$cpld_path"port"$i"_lpmode" lpmode_input=$(cat $lpmode_path | awk '{printf $1}') val=$((val | (lpmode_input << ($i - 25)))) done if [ $val -ne $pre_port_25_32_lpmode ]; then ipmitool raw 0x30 0x25 0x00 0x0e 0x0 0x51 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_25_32_lpmode=$val fi return 0 } bmc_qsfp_modsel_write() { cpld_path="/sys/bus/i2c/devices/0-0006/" val=0 for i in $(seq 1 8); do modsel_path=$cpld_path"port"$i"_modsel" modsel_input=$(cat $modsel_path | awk '{printf $1}') val=$((val | (modsel_input << ($i - 1)))) done val=$((0xff - val)) if [ $val -ne $pre_port_1_8_modsel ]; then ipmitool raw 0x30 0x25 0x00 0x0c 0x0 0x60 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_1_8_modsel=$val fi val=0 for i in $(seq 9 16); do modsel_path=$cpld_path"port"$i"_modsel" modsel_input=$(cat $modsel_path | awk '{printf $1}') val=$((val | (modsel_input << ($i - 9)))) done val=$((0xff - val)) if [ $val -ne $pre_port_9_16_modsel ]; then ipmitool raw 0x30 0x25 0x00 0x0c 0x0 0x61 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_9_16_modsel=$val fi cpld_path="/sys/bus/i2c/devices/0-0007/" val=0 for i in $(seq 17 24); do modsel_path=$cpld_path"port"$i"_modsel" modsel_input=$(cat $modsel_path | awk '{printf $1}') val=$((val | (modsel_input << ($i - 17)))) done val=$((0xff - val)) if [ $val -ne $pre_port_17_24_modsel ]; then ipmitool raw 0x30 0x25 0x00 0x0e 0x0 0x60 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_17_24_modsel=$val fi val=0 for i in $(seq 25 32); do modsel_path=$cpld_path"port"$i"_modsel" modsel_input=$(cat $modsel_path | awk '{printf $1}') val=$((val | (modsel_input << ($i - 25)))) done val=$((0xff - val)) if [ $val -ne $pre_port_25_32_modsel ]; then ipmitool raw 0x30 0x25 0x00 0x0e 0x0 0x61 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_25_32_modsel=$val fi return 0 } bmc_qsfp_presence_read() { a=0 tmp1=$(ipmitool raw 0x30 0x25 0x00 0x0c 0x1 0x30 2>>/dev/null) a=$((a+$?)) tmp1=$(echo $tmp1 | awk '{printf $1}') sleep 0.05 tmp2=$(ipmitool raw 0x30 0x25 0x00 0x0c 0x1 0x31 2>>/dev/null) a=$((a+$?)) tmp2=$(echo $tmp2 | awk '{printf $1}') sleep 0.05 tmp3=$(ipmitool raw 0x30 0x25 0x00 0x0e 0x1 0x30 2>>/dev/null) a=$((a+$?)) tmp3=$(echo $tmp3 | awk '{printf $1}') sleep 0.05 tmp4=$(ipmitool raw 0x30 0x25 0x00 0x0e 0x1 0x31 2>>/dev/null) a=$((a+$?)) tmp4=$(echo $tmp4 | awk '{printf $1}') sleep 0.05 if [ $a -eq 0 ];then byte_hex_test $tmp1 if [ $? -eq 0 ]; then return 0 fi port_1_8_presence=$( printf "%d" 0x$tmp1 ) byte_hex_test $tmp2 if [ $? -eq 0 ]; then return 0 fi port_9_16_presence=$( printf "%d" 0x$tmp2 ) byte_hex_test $tmp3 if [ $? -eq 0 ]; then return 0 fi port_17_24_presence=$( printf "%d" 0x$tmp3 ) byte_hex_test $tmp4 if [ $? -eq 0 ]; then return 0 fi port_25_32_presence=$( printf "%d" 0x$tmp4 ) return 1 fi return 0 } bmc_qsfp_reset_write() { cpld_path="/sys/bus/i2c/devices/0-0006/" val=0 for i in $(seq 1 8); do reset_path=$cpld_path"port"$i"_reset" reset_input=$(cat $reset_path | awk '{printf $1}') val=$((val | (reset_input << ($i - 1)))) done val=$((0xff - val)) if [ $val -ne $pre_port_1_8_reset ]; then ipmitool raw 0x30 0x25 0x00 0x0c 0x0 0x20 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_1_8_reset=$val fi val=0 for i in $(seq 9 16); do reset_path=$cpld_path"port"$i"_reset" reset_input=$(cat $reset_path | awk '{printf $1}') val=$((val | (reset_input << ($i - 9)))) done val=$((0xff - val)) if [ $val -ne $pre_port_9_16_reset ]; then ipmitool raw 0x30 0x25 0x00 0x0c 0x0 0x21 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_9_16_reset=$val fi cpld_path="/sys/bus/i2c/devices/0-0007/" val=0 for i in $(seq 17 24); do reset_path=$cpld_path"port"$i"_reset" reset_input=$(cat $reset_path | awk '{printf $1}') val=$((val | (reset_input << ($i - 17)))) done val=$((0xff - val)) if [ $val -ne $pre_port_17_24_reset ]; then ipmitool raw 0x30 0x25 0x00 0x0e 0x0 0x20 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_17_24_reset=$val fi val=0 for i in $(seq 25 32); do reset_path=$cpld_path"port"$i"_reset" reset_input=$(cat $reset_path | awk '{printf $1}') val=$((val | (reset_input << ($i - 25)))) done val=$((0xff - val)) if [ $val -ne $pre_port_25_32_reset ]; then ipmitool raw 0x30 0x25 0x00 0x0e 0x0 0x21 $val 1>>/dev/null 2>>/dev/null sleep 0.05 pre_port_25_32_reset=$val fi return 0 } #$1=port_no bmc_qsfp_eeprom_read() { local port=$1 local eeprom_part1 local eeprom_part2 local eeprom_part3 local eeprom_part4 local eeprom1_full local eeprom2_full port=`expr $port - 1` i2cmux_dev=0 i2cmux_dev=`expr $port / 8` i2cmux_dev=`expr $i2cmux_dev + 2` ch=`expr $port % 8` bmc_write $i2cmux_dev $ch 0x50 0x7f 0x00 bmc_read $i2cmux_dev $ch 0x50 0 128 if [ $? -eq 1 ];then eeprom_part1=$result else return 1 fi bmc_read $i2cmux_dev $ch 0x50 128 128 if [ $? -eq 1 ];then eeprom_part2=$result else return 1 fi #QSFP-DD page2 bmc_write $i2cmux_dev $ch 0x50 0x7f 0x02 bmc_read $i2cmux_dev $ch 0x50 128 128 if [ $? -eq 1 ];then eeprom_part3=$result else return 1 fi #QSFP-DD page11 bmc_write $i2cmux_dev $ch 0x50 0x7f 0x11 bmc_read $i2cmux_dev $ch 0x50 128 128 if [ $? -eq 1 ];then eeprom_part4=$result else return 1 fi sfp_type=$(echo $eeprom_part1 | awk '{printf $1}') byte_hex_test $sfp_type if [ $? -eq 0 ]; then return fi sfp_type=$( printf "%d" 0x$sfp_type ) #get temperature temp=$(echo $eeprom_part1 | awk '{printf $15}') if [ $temp != "" ];then temp=$( printf "%d" 0x$temp ) temp_path="/sys/bus/i2c/devices/0-00"${port_map[$1]}"/temp" echo $temp > $temp_path fi #get lp_mode lpmod_path="/sys/bus/i2c/devices/0-00"${port_map[$1]}"/lp_mode" if [ $sfp_type -eq 24 ];then lpmod=$(echo $eeprom_part1 | awk '{printf $27}') if [ $lpmod != "" ];then state=$((lpmod&0x10)) if [ $state -eq 16 ];then echo 1 > $lpmod_path else echo 0 > $lpmod_path fi fi elif [ $sfp_type -eq 17 ];then lpmod=$(echo $eeprom_part1 | awk '{printf $93}') if [ $lpmod != "" ];then state=$((lpmod&0x02)) if [ $state -eq 2 ];then echo 1 > $lpmod_path else echo 0 > $lpmod_path fi fi else lpmod="" fi eeprom1_full=$eeprom_part1$eeprom_part2 eeprom1_full=$(echo $eeprom1_full | sed 's/[[:space:]]//g') eeprom2_full=$eeprom_part3$eeprom_part4 eeprom2_full=$(echo $eeprom2_full | sed 's/[[:space:]]//g') if [ $debug_flag -eq 0 ];then eeprom1_path="/sys/bus/i2c/devices/0-00"${port_map[$1]}"/eeprom1" eeprom1_full=$(echo $eeprom1_full | sed -e 's/ //g') echo $eeprom1_full > $eeprom1_path eeprom2_path="/sys/bus/i2c/devices/0-00"${port_map[$1]}"/eeprom2" eeprom2_full=$(echo $eeprom2_full | sed -e 's/ //g') echo $eeprom2_full > $eeprom2_path else printf "\nPort %d EEPROM:" $1 printf "-----------------------------------------------\n" for i in $(seq 1 256); do printf "%s " ${eeprom1_full:0:2} eeprom1_full=$(echo $eeprom1_full | sed 's/^..//') val=`expr $i % 16` if [ $val -eq 0 ];then printf "\n" fi done printf "\n-----------------------------------------------\n" fi return 0 } #$1=port_no bmc_qsfp_eeprom_clear() { eeprom1_path="/sys/bus/i2c/devices/0-00"${port_map[$1]}"/eeprom1" echo "" > $eeprom1_path eeprom2_path="/sys/bus/i2c/devices/0-00"${port_map[$1]}"/eeprom2" echo "" > $eeprom2_path } QSFP_monitor() { while true do if [ -e /sys/bus/i2c/devices/0-0006/port1_present ] && [ -e /sys/bus/i2c/devices/0-0007/port32_present ] && [ -e /sys/bus/i2c/devices/0-002f/eeprom1 ];then bmc_qsfp_presence_read mod_presence=$((port_25_32_presence<<8)) mod_presence=`expr $mod_presence + $port_17_24_presence` mod_presence=$((mod_presence<<8)) mod_presence=`expr $mod_presence + $port_9_16_presence` mod_presence=$((mod_presence<<8)) mod_presence=`expr $mod_presence + $port_1_8_presence` bmc_qsfp_lpmode_write bmc_qsfp_modsel_write bmc_qsfp_reset_write for i in $(seq 1 32); do idx=`expr $i - 1` check_bit=$((1<<$idx)) is_presence=$(($mod_presence & $check_bit)) if [ $i -le 16 ];then cpld_path="/sys/bus/i2c/devices/0-0006/" else cpld_path="/sys/bus/i2c/devices/0-0007/" fi if [ $is_presence -eq 0 ];then echo 1 > $cpld_path"port"$i"_present" bmc_qsfp_eeprom_read $i else echo 0 > $cpld_path"port"$i"_present" bmc_qsfp_eeprom_clear $i fi done sleep 2 else sleep 1 fi done } QSFP_monitor