#!/bin/sh # script Version 1.1 20240912 # 支持测试的传感器芯片 emc1413 ina3221 adc128 # 支持通过 chip 参数直接做I2C命令透传来访问芯片寄存器 # 支持通过 fru 参数读取FRU十六进制内容 # --------------------------------------------------------- # Project Feature Varible (按照项目需要修改) # --------------------------------------------------------- # ADC128 分压系数 (Ravel) votage_division_factor_0="1" votage_division_factor_1="1" votage_division_factor_2="1" votage_division_factor_3="0.8" votage_division_factor_4="0.6" votage_division_factor_5="0.6" votage_division_factor_6="0.2326" votage_division_factor_7="1" # ADC128 channel名称定制(可更换为对应的 电压/电流/温度 的名称) ADC128_Channel0_name="Channel 0" ADC128_Channel1_name="Channel 1" ADC128_Channel2_name="Channel 2" ADC128_Channel3_name="Channel 3" ADC128_Channel4_name="Channel 4" ADC128_Channel5_name="Channel 5" ADC128_Channel6_name="Channel 6" ADC128_Channel7_name="Channel 7" # INA3221 分流电阻, 单位(毫欧姆)(Ravel) shunt_resistor_0="2" shunt_resistor_1="2" shunt_resistor_2="5" # EMC1413 channel名称定制(可更换为对应的 电压/电流/温度 的名称) EMC1413_Channel0_name="Channel 0" EMC1413_Channel1_name="Channel 1" EMC1413_Channel2_name="Channel 2" # fru 烧录的起始地址 fru_offset="0x00 0x00" # 应用的服务器产品,根据服务器产品手动修改这个变量 # 当前适配的服务器产品 5280m7 5468m7 donghu yichun server_type="5280m7" # --------------------------------------------------------- # Common Varible (请勿随意修改) # --------------------------------------------------------- # Input Param # Introduction of pcie_slot # 1.脚本即将访问的网卡位于服务器上的PCIe插槽位置 pcie_slot=$1 # Introduction of sensor_type # 1.脚本即将读取和处理的传感器名称 sensor_type=$2 # Introduction of chip_slave # 1.chip i2c slave address(7bit) chip_slave=$3 # Introduction of option_data # 1.在FRU的处理过程中,使用option_data来区分是读操作还是写操作,将值设置为 # "read"或者"write" # 2.在chip的处理过程中,使用option_data来代表一条完整的i2c命令,这条命令会 # 被发到chip上,一个例子:"i2ctransfer -y 12 w2@0x10 0x90 0x00 r9" option_data=$4 # Introduction of option_data2 # 1.仅用于fru write操作,代表即将写入的fru文件名 option_data2=$5 # CHIP REGISTER REG_pca9641_controll="0x01" REG_adc128_config="0x00" REG_adc128_advance="0x0b" REG_adc128_status="0x0c" REG_adc128_ch0="0x20" REG_adc128_ch1="0x21" REG_adc128_ch2="0x22" REG_adc128_ch3="0x23" REG_adc128_ch4="0x24" REG_adc128_ch5="0x25" REG_adc128_ch6="0x26" REG_adc128_ch7="0x27" REG_emc1413_TD1_H="0x00" REG_emc1413_TD1_L="0x29" REG_emc1413_TD2_H="0x01" REG_emc1413_TD2_L="0x10" REG_emc1413_TD3_H="0x23" REG_emc1413_TD3_L="0x24" REG_ina3221_ch1="0x01" REG_ina3221_ch2="0x03" REG_ina3221_ch3="0x05" REG_ina3221_bus1="0x02" REG_ina3221_bus2="0x04" REG_ina3221_bus3="0x06" # --------------------------------------------------------- # Global Varible (请勿随意修改) # --------------------------------------------------------- # DEBUG MODE=0 : Disable debug mode # =1 : Enable debug mode # 启用debug模式后需要手动配置 i2c_bus DEBUG_MODE=0 # 选通网卡I2C通路的关键变量 i2c_bus=12 pca9641_slave=0x41 pca9548_channel=0x04 pca9548_slave=0x72 # 硬件上是否有PCA9641? is_have_pca9641=1 log="/tmp/nicsensor_debug.log" INA3221_SHUNT_VOLT=0 INA3221_BUS_VOLT=1 INA3221_POWER=2 INFO="Info" WARNING="Warning" ERROR="Error" ina3221_ch0_volt="0" ina3221_ch1_volt="0" ina3221_ch2_volt="0" ina3221_ch0_current="0" ina3221_ch1_current="0" ina3221_ch2_current="0" SCRIPT_VRESION="1.2 InTest Rev3" fru_file_name=$option_data2 fru_write_size=0 fru_write_data="" # --------------------------------------------------------- # Script Function Defination # --------------------------------------------------------- # script usage print_usage(){ echo "" echo "================>>> nicsensor script usage <<<=================" echo " Command Format : ./nicsensor.sh [slot] [sensor tpye] [slave]" echo " Option Detail" echo " [slot] : 0 1 2 3 4 5 ..." echo " [sensor type] : emc1413, adc128, ina3221" echo " [slave] : chip slave address , please provide 7 bit address" echo " E.G. : ./nicsensor.sh 0 adc128 0x1f" echo "" echo " To Auto detect i2c slave on server, please use:" echo " ./nicsensor.sh detect" echo " This function now only support on server 5280m7, 5468m7, donghu" echo "" echo " If want to read/write chip register, use the below format" echo " ./nicsensor.sh [slot] chip [slave] [i2c_command]" echo " i2c_command : such as [i2ctransfer -y 13 w1@0x10 0x00 r2]" echo "" echo " If want to use debug mode, please modify the DEBUG_MODE to 1" echo " now status : DEBUG_MODE = $DEBUG_MODE" echo "" } print_chip_command_format(){ echo "Command Format : ./nicsensor.sh [slot] chip [slave] [i2c_command]" } print_fru_command_format(){ echo "Command Format : ./nicsensor.sh [slot] fru [slave] write [fru_file]" } # 格式化输出信息 # @Param1 信息等级 [Info/Warning/Error] # @Param2 信息内容 format_print(){ echo ">>> [$1] $2" } # 格式化输出信息到日志文件 # @Param1 信息等级 [Info/Warning/Error] # @Param2 信息内容 format_log_print(){ echo "[$1] $2" >> $log } # 自查一些脚本中的属性配置 conf_pre_check(){ # 校验debug mode的值 if [ $DEBUG_MODE -ne 0 && $DEBUG_MODE -ne 1 ];then format_print $ERROR "Invalid conf value, DEBUG_MODE: $DEBUG_MODE" exit 1 fi } # 根据5280m7 pcie slot 和 i2c 对对应关系调整变量 set_configuration_5280m7(){ is_have_pca9641=1 # set pca9641 address && I2C BUS if [ $pcie_slot -le 2 ];then pca9641_slave="0x41" i2c_bus=12 else pca9641_slave="0x42" i2c_bus=13 fi # set pca9548 switch channel if [ $pcie_slot -eq 0 ];then pca9548_channel="0x02" elif [ $pcie_slot -eq 1 ];then pca9548_channel="0x04" elif [ $pcie_slot -eq 2 ];then pca9548_channel="0x08" elif [ $pcie_slot -eq 3 ];then pca9548_channel="0x02" elif [ $pcie_slot -eq 4 ];then pca9548_channel="0x04" elif [ $pcie_slot -eq 5 ];then pca9548_channel="0x08" fi } # 根据5468m7 pcie slot 和 i2c 对对应关系调整变量 set_configuration_5468m7(){ is_have_pca9641=1 # set pca9641 address && I2C BUS if [ $pcie_slot -le 4 ];then pca9641_slave="0x31" pca9548_slave="0x70" i2c_bus=13 else pca9641_slave="0x42" pca9548_slave="0x71" i2c_bus=14 fi # set pca9548 switch channel if [ $pcie_slot -eq 0 ];then pca9548_channel="0x01" elif [ $pcie_slot -eq 1 ];then pca9548_channel="0x02" elif [ $pcie_slot -eq 2 ];then pca9548_channel="0x04" elif [ $pcie_slot -eq 3 ];then pca9548_channel="0x08" elif [ $pcie_slot -eq 4 ];then pca9548_channel="0x10" elif [ $pcie_slot -eq 5 ];then pca9548_channel="0x01" elif [ $pcie_slot -eq 6 ];then pca9548_channel="0x02" elif [ $pcie_slot -eq 7 ];then pca9548_channel="0x04" elif [ $pcie_slot -eq 8 ];then pca9548_channel="0x08" elif [ $pcie_slot -eq 9 ];then pca9548_channel="0x10" elif [ $pcie_slot -eq 10 ];then pca9548_channel="0x20" fi } # 根据donghu pcie slot 和 i2c 对对应关系调整变量 set_configuration_donghu(){ is_have_pca9641=0 i2c_bus=3 # set pca9548 switch channel if [ $pcie_slot -eq 0 ];then pca9548_channel="0x80" elif [ $pcie_slot -eq 1 ];then pca9548_channel="0x40" elif [ $pcie_slot -eq 2 ];then pca9548_channel="0x20" elif [ $pcie_slot -eq 3 ];then pca9548_channel="0x10" elif [ $pcie_slot -eq 4 ];then pca9548_channel="0x08" elif [ $pcie_slot -eq 5 ];then pca9548_channel="0x04" elif [ $pcie_slot -eq 6 ];then pca9548_channel="0x02" elif [ $pcie_slot -eq 7 ];then pca9548_channel="0x01" fi } # 根据yichun pcie slot 和 i2c 对对应关系调整变量 set_configuration_yichun(){ is_have_pca9641=0 pca9548_slave="0x74" # set pca9548 switch channel if [ $pcie_slot -eq 0 ];then i2c_bus=12 pca9548_channel="0x02" elif [ $pcie_slot -eq 1 ];then i2c_bus=13 pca9548_channel="0x02" elif [ $pcie_slot -eq 2 ];then i2c_bus=14 pca9548_channel="0x02" fi } # 根据输入信息调整选通芯片的配置(PCA9641 PCA9548) # 20240912 - 更新脚本:支持通过服务器型号进行配置 set_configuration(){ format_log_print $INFO "Server Type : $server_type" # 根据服务器型号执行对应的配置策略 if [ $server_type == "5280m7" ];then set_configuration_5280m7 elif [ $server_type == "5468m7" ];then set_configuration_5468m7 elif [ $server_type == "donghu" ];then set_configuration_donghu elif [ $server_type == "yichun" ];then set_configuration_yichun else format_print $ERROR "Error: Unsupport Server Type !!! - $server_type" exit 1 fi } # 初始化调试日志 init_debuglog(){ # 只保留一次日志读取记录 if [ -e $log ];then rm $log fi # print time header res_date=`date` format_log_print $INFO "=========================== $res_date" format_log_print $INFO "Script Version : $SCRIPT_VERSION" if [ $DEBUG_MODE -ne 0 ];then format_log_print $WARNING "Enable debug mode : $DEBUG_MODE" fi } # 记录配置信息日志 prepare_start_info(){ # 记录单次配置信息到调试日志中去 format_log_print $INFO "PCIE slot : $pcie_slot" format_log_print $INFO "I2C Bus: $i2c_bus" format_log_print $INFO "PCA9641 slave: $pca9641_slave" format_log_print $INFO "PCA9548 slave: $pca9548_slave" format_log_print $INFO "PCA9548 channel: $pca9548_channel" # Record i2c device info to log res_info=`i2cdetect -y $i2c_bus` echo $res_info >> $log } # 获取PCA9641的控制权 get_pca9641_controll(){ # Request 9641 lock res_lock=`i2ctransfer -y $i2c_bus w2@$pca9641_slave $REG_pca9641_controll 0x81 r1` format_log_print $INFO "After request 9641 lock, The REG value is $res_lock" # Build 9641 Connection res_build=`i2ctransfer -y $i2c_bus w2@$pca9641_slave $REG_pca9641_controll 0x85 r1` format_log_print $INFO "After Build 9641 connection, The REG value is $res_build" # After get 9641 controll, Record i2c device info to log res_after=`i2cdetect -y $i2c_bus` echo $res_after >> $log if [ "$res_build" != "0x87" ];then format_print $ERROR "Cannot establish connection with pca9641 !!!" exit 1 fi } # 选通PCA9548的channel switch_pca9548_channel(){ # set 9548 channel res_setchannel=`i2ctransfer -y $i2c_bus w1@$pca9548_slave $pca9548_channel` format_log_print $INFO "After switch channel" # After set 9548 channel , record i2c device info res_after=`i2cdetect -y $i2c_bus` echo $res_after >> $log } # --------------------------------------------------------- # Chip EMC1413 # --------------------------------------------------------- # 处理EMC1413读到的数据并输出结果 # @Param1 emc1413读取数据高位 # @Param2 emc1413读取数据低位 # @Param3 channel号/定制化名称 convert_emc1413_data(){ # 将读取到的两位数据去掉 0x 前缀 hex_value1=$(echo "$1" | awk '{sub(/^0x/,""); print}') hex_value2=$(echo "$2" | awk '{sub(/^0x/,""); print}') # 由于 bc 计算器只能识别大写的 十六进制数据,将小写的十六进制数据全部转化为大写的数据 upper_hex_value1=$(echo "$hex_value1" | awk '{ for(i=1; i<=length($0); i++){ if(tolower(substr($0,i,1)) ~ /^[a-f]$/) printf toupper(substr($0,i,1)); else printf substr($0,i,1); } print "" }') upper_hex_value2=$(echo "$hex_value2" | awk '{ for(i=1; i<=length($0); i++){ if(tolower(substr($0,i,1)) ~ /^[a-f]$/) printf toupper(substr($0,i,1)); else printf substr($0,i,1); } print "" }') # 转化为10进制数据 dec_value1=$(echo "ibase=16; $upper_hex_value1" | bc) dec_value2=$(echo "ibase=16; $upper_hex_value2" | bc) # 计算温度值 temp=$(echo "scale=4; $dec_value1 + ($dec_value2 / 32 * 0.125 )" | bc) # 格式化输出数据 format_temp=$(echo "$temp" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') echo "$3 : $format_temp C, hex value : $hex_value1 $hex_value2" } # 读取EMC1413芯片每个通道的数据,随后调用数据处理函数进行数据解析并输出 read_emc1413_channel_value(){ echo "Start EMC1413 channel data ..." >> $log res_td1_h=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD1_H r1` res_td1_l=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD1_L r1` res_td2_h=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD2_H r1` res_td2_l=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD2_L r1` res_td3_h=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD3_H r1` res_td3_l=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD3_L r1` # 将 I2C 读取的 raw 数据记录到调试日志中 echo "channel 1 : $res_td1_h $res_td1_l" >> $log echo "channel 2 : $res_td2_h $res_td2_l" >> $log echo "channel 3 : $res_td3_h $res_td3_l" >> $log # start parse raw data echo ">>> The emc1413 value is:" convert_emc1413_data $res_td1_h $res_td1_l $EMC1413_Channel0_name convert_emc1413_data $res_td2_h $res_td2_l $EMC1413_Channel1_name convert_emc1413_data $res_td3_h $res_td3_l $EMC1413_Channel2_name } # EMC1413处理逻辑 process_emc1413(){ # emc1413 no need to init # get chip emc1413 value read_emc1413_channel_value } # --------------------------------------------------------- # Chip ADC128 # --------------------------------------------------------- # 进行ADC128芯片的初始化 check_adc128_init(){ # Get Reg 0x00 status res_adc128_status=`i2cget -y $i2c_bus $chip_slave $REG_adc128_config` echo "REG adc128 STATUS : $res_adc128_status" >> $log # if stauts is not 0x01 (Start Monitor) ,then do init if [ "$res_adc128_status" != "0x01" ];then echo "Start Init ADC128 Chip" >> $log # Init ADC128 work as mode 1 (0x02) res_adc128_advance=`i2ctransfer -y $i2c_bus w2@$chip_slave $REG_adc128_advance 0x02` # Set ADC128 on start (0x01) res_adc128_setstart=`i2ctransfer -y $i2c_bus w2@$chip_slave $REG_adc128_config 0x01 r1` echo "After Set status, the REG 0x00 value is $res_adc128_setstart" >> $log fi } # 处理ADC128读到的数据并输出结果 # @Param 1 ADC128读取数据高位 # @Param 2 ADC128读取数据低位 # @Param 3 channel号/定制化名称 # @Param 4 分压系数 convert_adc128_data(){ # 将读取到的两位数据拼接起来 hex_value1=$(echo "$1" | awk '{sub(/^0x/,""); print}') hex_value2=$(echo "$2" | awk '{sub(/^0x/,""); print}') merge_value="${hex_value1}${hex_value2}" # 由于 bc 计算器只能识别大写的 十六进制数据,这里将小写的十六进制数据全部转化为大写的数据 upper_hex_value=$(echo "$merge_value" | awk '{ for(i=1; i<=length($0); i++){ if(tolower(substr($0,i,1)) ~ /^[a-f]$/) printf toupper(substr($0,i,1)); else printf substr($0,i,1); } print "" }') # 利用bc计算器进行运算,并将返回值格式化后输出 dec_val=$(echo "ibase=16; $upper_hex_value" | bc) volt=$(echo "scale=4; $dec_val / 16 / 4096 * 2.65 / $4" | bc) format_volt=$(echo "$volt" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') echo "$3 : $format_volt v, hex value: $upper_hex_value" } # 读取ADC128芯片每个通道的数据,随后调用数据处理函数进行数据解析并输出 read_adc128_channel_value(){ echo "Start Read ADC128 channel data ..." >> $log res_ch0=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch0 r2` res_ch1=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch1 r2` res_ch2=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch2 r2` res_ch3=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch3 r2` res_ch4=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch4 r2` res_ch5=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch5 r2` res_ch6=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch6 r2` res_ch7=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch7 r2` # 将 I2C 读取的 raw 数据记录到调试日志中 echo "channel0 : $res_ch0" >> $log echo "channel1 : $res_ch1" >> $log echo "channel2 : $res_ch2" >> $log echo "channel3 : $res_ch3" >> $log echo "channel4 : $res_ch4" >> $log echo "channel5 : $res_ch5" >> $log echo "channel6 : $res_ch6" >> $log echo "channel7 : $res_ch7" >> $log # start parse raw data echo ">>> The ADC128 value is :" convert_adc128_data $res_ch0 $ADC128_Channel0_name $votage_division_factor_0 convert_adc128_data $res_ch1 $ADC128_Channel1_name $votage_division_factor_1 convert_adc128_data $res_ch2 $ADC128_Channel2_name $votage_division_factor_2 convert_adc128_data $res_ch3 $ADC128_Channel3_name $votage_division_factor_3 convert_adc128_data $res_ch4 $ADC128_Channel4_name $votage_division_factor_4 convert_adc128_data $res_ch5 $ADC128_Channel5_name $votage_division_factor_5 convert_adc128_data $res_ch6 $ADC128_Channel6_name $votage_division_factor_6 convert_adc128_data $res_ch7 $ADC128_Channel7_name $votage_division_factor_7 } # ADC128处理逻辑 process_adc128(){ # check if chip adc128 need init check_adc128_init # get chip adc128 value read_adc128_channel_value } # --------------------------------------------------------- # Chip INA3221 # --------------------------------------------------------- # 处理INA3221读到的电流数据并输出结果 # @Param1 ina3221读取数据高位 # @Param2 ina3221读取数据低位 # @Param3 channel号 # @Param4 0代表数据是shunt volt # 1代表数据是bus volt # @Param5 分流电阻 (仅在 Param4 是 shunt volt时有用) convert_ina3221_data(){ # 将读取到的两位数据拼接起来 hex_value1=$(echo "$1" | awk '{sub(/^0x/,""); print}') hex_value2=$(echo "$2" | awk '{sub(/^0x/,""); print}') merge_value="${hex_value1}${hex_value2}" # 由于 bc 计算器只能识别大写的 十六进制数据,这里将小写的十六进制数据全部转化为大写的数据 upper_hex_value=$(echo "$merge_value" | awk '{ for(i=1; i<=length($0); i++){ if(tolower(substr($0,i,1)) ~ /^[a-f]$/) printf toupper(substr($0,i,1)); else printf substr($0,i,1); } print "" }') # 将16进制数据转化为10进制 dec_val=$(echo "ibase=16; $upper_hex_value" | bc) # todo 检查这个数据的最高位是否为1 # max_unsigned_32bit_half=$(echo "scale=0; 2^31 / 2" | bc) # if [ $(echo "$dec_val >= $max_unsigned_32bit_half" | bc) -eq 1 ];then # echo "" # else # echo "" # fi if [ $4 -eq $INA3221_BUS_VOLT ];then # 计算每个通道上的电压 volt=$(echo "scale=4; $dec_val / 8 * 40 / 10000 * 2" | bc) # 格式化输出数据 format_volt=$(echo "$volt" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') echo "channel $3 : $format_volt V, hex value: $upper_hex_value" if [ $3 -eq 0 ];then ina3221_ch0_volt=$format_volt elif [ $3 -eq 1 ];then ina3221_ch1_volt=$format_volt else ina3221_ch2_volt=$format_volt fi elif [ $4 -eq $INA3221_SHUNT_VOLT ];then # 计算每个分流电阻上的电压,同时计算出电流 current_mv=$(echo "scale=4; $dec_val / 8 * 40 / 1000" | bc) current=$(echo "scale=4; $current_mv / $5" | bc) # 格式化输出数据 format_current=$(echo "$current" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') format_current_mv=$(echo "$current_mv" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') echo "channel $3 : $format_current A, shunt volt: $format_current_mv mV, shunt resistor: $5 mOhm, hex value: $upper_hex_value" if [ $3 -eq 0 ];then ina3221_ch0_current=$format_current elif [ $3 -eq 1 ];then ina3221_ch1_current=$format_current else ina3221_ch2_current=$format_current fi elif [ $4 -eq $INA3221_POWER ];then # 计算每个通道上的功耗,并算总和 power_ch0=$(echo "scale=4; $ina3221_ch0_volt * $ina3221_ch0_current" | bc) power_ch1=$(echo "scale=4; $ina3221_ch1_volt * $ina3221_ch1_current" | bc) power_ch2=$(echo "scale=4; $ina3221_ch2_volt * $ina3221_ch2_current" | bc) # 格式化输出数据 format_power_ch0=$(echo "$power_ch0" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') format_power_ch1=$(echo "$power_ch1" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') format_power_ch2=$(echo "$power_ch2" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }') total_power=$(echo "scale=4; $power_ch0 + $power_ch1 + $power_ch2" | bc) echo "channel 0 : $format_power_ch0 W" echo "channel 1 : $format_power_ch1 W" echo "channel 2 : $format_power_ch2 W" echo "total power: $total_power W" fi } # 读取INA3221芯片每个通道的数据,随后调用数据处理函数进行数据解析并输出 read_ina3221_channel_value(){ echo "Start Read INA3221 channel data ..." >> $log res_ch0=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_ch1 r2` res_ch1=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_ch2 r2` res_ch2=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_ch3 r2` res_bus0=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_bus1 r2` res_bus1=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_bus2 r2` res_bus2=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_bus3 r2` # 将 I2C 读取的 raw 数据记录到调试日志中 echo "channel 0 shunt volt: $res_ch0" >> $log echo "channel 1 shunt volt: $res_ch1" >> $log echo "channel 2 shunt volt: $res_ch2" >> $log echo "Channel 0 bus volt : $res_bus0" >> $log echo "Channel 1 bus volt : $res_bus1" >> $log echo "Channel 2 bus volt : $res_bus2" >> $log # start parse raw data echo ">>> The INA3221 shunt value is :" convert_ina3221_data $res_ch0 0 $INA3221_SHUNT_VOLT $shunt_resistor_0 convert_ina3221_data $res_ch1 1 $INA3221_SHUNT_VOLT $shunt_resistor_1 convert_ina3221_data $res_ch2 2 $INA3221_SHUNT_VOLT $shunt_resistor_2 echo ">>> The INA3221 bus value is :" convert_ina3221_data $res_bus0 0 $INA3221_BUS_VOLT convert_ina3221_data $res_bus1 1 $INA3221_BUS_VOLT convert_ina3221_data $res_bus2 2 $INA3221_BUS_VOLT echo ">>> The INA3221 bus power is :" convert_ina3221_data 0 0 0 $INA3221_POWER } # INA3221处理逻辑 process_ina3221(){ # ina3221 no need to init first # get chip ina3221 value read_ina3221_channel_value } # --------------------------------------------------------- # CHIP # --------------------------------------------------------- # 临时支持CHIP读取寄存器 write_read_chip(){ # Modify i2c cmd which write to cpld if need cmd_wr=$option_data res_wr=`$cmd_wr` echo ">>> Chip Command: $cmd_wr" echo ">>> The Result : $res_wr" } # chip处理逻辑 process_chip(){ # cpld no need to init first # write and read cpld write_read_chip } # --------------------------------------------------------- # FRU # --------------------------------------------------------- # 将传入的fru文件解析为可被i2cransfer直接写入的数据 parse_fru_write_data(){ # 判断fru文件是否存在于当前目录 if [ -e $fru_file_name ];then echo "Fru file exist!" >> $log else echo "Fru file not exist!" >> $log echo "Fru file not exist in current directory!" echo "Error: Operation Failed!" exit 1 fi # 计算需要写入的fru文件大小 fru_write_size=`ls -lht | grep $fru_file_name | awk '{print $5}'` echo "Fru File [$fru_file_name] size = $fru_write_size Bytes" echo "Fru File [$fru_file_name] size = $fru_write_size Bytes" >> $log # 获取fru文件的 raw data fru_raw_data=`hexdump -C $fru_file_name | awk '{ for(i=2;i<18;i++){ print $i } }'` echo "Fru Raw Data: $fru_raw_data" >> $log # 将raw data解析为可被 i2ctransfer 写入的数据 fru_write_data=`echo $fru_raw_data | awk -v size=$fru_write_size '{ for(i=1;i<=size;i++){ printf "0x%s ",$i } }'` } # 支持FRU读取 read_fru(){ res_fru=`i2ctransfer -y $i2c_bus w2@$chip_slave $fru_offset r256` # 将FRU数据按照每行16个字符输出 echo "The Fru Data :" echo "$res_fru" | \ awk '{ line=""; count=0; for(i=1; i<=NF; i++){ hex=substr($i, 3); if(line != ""){ line = line " "; } line = line hex; count++; if (count == 16){ print line; line = ""; count = 0; } } if(line != ""){ print line; } }' } # 20240926 支持写板卡FRU write_fru(){ i2c_write_byte=$(($fru_write_size+2)) # 组装command并发送 write_command="i2ctransfer -y $i2c_bus w$i2c_write_byte@$chip_slave $fru_offset $fru_write_data" write_res=`$write_command` echo "Exec Command: $write_command" >> $log } # fru 处理逻辑 process_fru(){ # fru no need to init first # write and read fru if [ "$option_data" == "write" ];then write_fru else # 默认为读取操作 read_fru fi } # --------------------------------------------------------- # END of CHIP Function # --------------------------------------------------------- # 读取sensor流程的起点 start_get_sensor(){ # 首先选通 PCA9641 和 PCA9548,构建I2C通路 # 如果使用了debug模式,那么将不执行选通9641和9548的操作 if [ $DEBUG_MODE -eq 0 ];then # set global varible by server type set_configuration # 记录开始执行脚本前的I2C配置信息 prepare_start_info # 从9641获取I2C控制权 if [ $is_have_pca9641 -eq 1 ];then get_pca9641_controll fi # 选择9548 channel switch_pca9548_channel fi # get sensor detail value if [ "$sensor_type" == "emc1413" ];then process_emc1413 elif [ "$sensor_type" == "adc128" ];then process_adc128 elif [ "$sensor_type" == "ina3221" ];then process_ina3221 elif [ "$sensor_type" == "chip" ];then process_chip elif [ "$sensor_type" == "fru" ];then process_fru else echo "Error: Unsupport Sensor Type !!!" print_usage fi } # 在 5280m7 上扫描每个pcie slot下的I2C设备 # 详细对应关系参阅 readme.txt 第二节 detect_on_5280m7(){ # 从9641获取I2C控制权 i2c_bus=12 pca9641_slave="0x41" get_pca9641_controll echo ">>> PCIe slot 0 : bus12 9548channel 1" i2ctransfer -y $i2c_bus w1@0x72 0x02 i2cdetect -y $i2c_bus echo ">>> PCIe slot 1 : bus12 9548channel 2" i2ctransfer -y $i2c_bus w1@0x72 0x04 i2cdetect -y $i2c_bus echo ">>> PCIe slot 2 : bus12 9548channel 3" i2ctransfer -y $i2c_bus w1@0x72 0x08 i2cdetect -y $i2c_bus i2c_bus=13 pca9641_slave="0x42" get_pca9641_controll echo ">>> PCIe slot 3 : bus13 9548channel 1" i2ctransfer -y $i2c_bus w1@0x72 0x02 i2cdetect -y $i2c_bus echo ">>> PCIe slot 4 : bus13 9548channel 2" i2ctransfer -y $i2c_bus w1@0x72 0x04 i2cdetect -y $i2c_bus echo ">>> PCIe slot 5 : bus13 9548channel 3" i2ctransfer -y $i2c_bus w1@0x72 0x08 i2cdetect -y $i2c_bus } # 在 5468m7 上扫描每个pcie slot下的I2C设备 # 详细对应关系参阅 readme.txt 第二节 detect_on_5468m7(){ # 从9641获取I2C控制权 i2c_bus=13 pca9641_slave="0x31" get_pca9641_controll echo ">>> PCIe slot 0 : bus13 9548channel 0" i2ctransfer -y $i2c_bus w1@0x70 0x01 i2cdetect -y $i2c_bus echo ">>> PCIe slot 1 : bus13 9548channel 1" i2ctransfer -y $i2c_bus w1@0x70 0x02 i2cdetect -y $i2c_bus echo ">>> PCIe slot 2 : bus13 9548channel 2" i2ctransfer -y $i2c_bus w1@0x70 0x04 i2cdetect -y $i2c_bus echo ">>> PCIe slot 3 : bus13 9548channel 3" i2ctransfer -y $i2c_bus w1@0x70 0x08 i2cdetect -y $i2c_bus echo ">>> PCIe slot 4 : bus13 9548channel 4" i2ctransfer -y $i2c_bus w1@0x70 0x10 i2cdetect -y $i2c_bus i2c_bus=14 pca9641_slave="0x42" get_pca9641_controll echo ">>> PCIe slot 5 : bus14 9548channel 0" i2ctransfer -y $i2c_bus w1@0x71 0x01 i2cdetect -y $i2c_bus echo ">>> PCIe slot 6 : bus14 9548channel 1" i2ctransfer -y $i2c_bus w1@0x71 0x02 i2cdetect -y $i2c_bus echo ">>> PCIe slot 7 : bus14 9548channel 2" i2ctransfer -y $i2c_bus w1@0x71 0x04 i2cdetect -y $i2c_bus echo ">>> PCIe slot 8 : bus14 9548channel 3" i2ctransfer -y $i2c_bus w1@0x71 0x08 i2cdetect -y $i2c_bus echo ">>> PCIe slot 9 : bus14 9548channel 4" i2ctransfer -y $i2c_bus w1@0x71 0x10 i2cdetect -y $i2c_bus echo ">>> PCIe slot 10 : bus14 9548channel 5" i2ctransfer -y $i2c_bus w1@0x71 0x20 i2cdetect -y $i2c_bus } # 在 donghu 上扫描每个pcie slot下的I2C设备 detect_on_donghu(){ i2c_bus=3 echo ">>> PCIe slot 0 : bus3 9548channel 7" i2ctransfer -y $i2c_bus w1@0x70 0x80 i2cdetect -y $i2c_bus echo ">>> PCIe slot 1 : bus3 9548channel 6" i2ctransfer -y $i2c_bus w1@0x70 0x40 i2cdetect -y $i2c_bus echo ">>> PCIe slot 2 : bus3 9548channel 5" i2ctransfer -y $i2c_bus w1@0x70 0x20 i2cdetect -y $i2c_bus echo ">>> PCIe slot 3 : bus3 9548channel 4" i2ctransfer -y $i2c_bus w1@0x70 0x10 i2cdetect -y $i2c_bus echo ">>> PCIe slot 4 : bus3 9548channel 3" i2ctransfer -y $i2c_bus w1@0x70 0x08 i2cdetect -y $i2c_bus echo ">>> PCIe slot 5 : bus3 9548channel 2" i2ctransfer -y $i2c_bus w1@0x70 0x04 i2cdetect -y $i2c_bus echo ">>> PCIe slot 6 : bus3 9548channel 1" i2ctransfer -y $i2c_bus w1@0x70 0x02 i2cdetect -y $i2c_bus echo ">>> PCIe slot 7 : bus3 9548channel 0" i2ctransfer -y $i2c_bus w1@0x70 0x01 i2cdetect -y $i2c_bus } # 在 yichun 上扫描每个pcie slot下的I2C设备 detect_on_yichun(){ i2c_bus=12 echo ">>> PCIe slot 0 : bus12 9546channel 2" i2ctransfer -y $i2c_bus w1@0x74 0x02 i2cdetect -y $i2c_bus i2c_bus=13 echo ">>> PCIe slot 1 : bus13 9546channel 2" i2ctransfer -y $i2c_bus w1@0x74 0x02 i2cdetect -y $i2c_bus i2c_bus=14 echo ">>> PCIe slot 2 : bus14 9546channel 2" i2ctransfer -y $i2c_bus w1@0x74 0x02 i2cdetect -y $i2c_bus } # 搜索服务器所有PCIE插槽的I2C设备信息,当前仅支持特定Riser卡上的设备 # change list : 20240912-支持服务器器型号5280m7,5468m7 start_detect_device(){ # debug mode下进行detect操作仅对当前链路进行detect if [ $DEBUG_MODE -ne 0 ];then echo "In debug mode now, only detect i2c_bus$i2c_bus:" i2cdetect -y $i2c_bus exit 0 fi echo ">>>>>> Detect on server : $server_type" if [ $server_type == "5280m7" ];then detect_on_5280m7 elif [ $server_type == "5468m7" ];then detect_on_5468m7 elif [ $server_type == "donghu" ];then detect_on_donghu elif [ $server_type == "yichun" ];then detect_on_yichun else echo "Error: Unsupport Server Type !!!" fi } # --------------------------------------------------------- # Start Execute Script # --------------------------------------------------------- # 配置校验 conf_pre_check # 参数合法校验 if [ "$sensor_type" == "chip" ];then if [ $# -le 3 ];then format_print $ERROR "Command Format illegal" print_chip_command_format exit 1 fi fi if [ "$1" == "detect" ];then start_detect_device exit 0 fi # 在正式执行脚本之前初始化调试日志 init_debuglog # 如果是fru write操作, 需要对即将写入的bin文件进行数据预处理 if [ "$sensor_type" == "fru" ];then if [ "$option_data" == "write" ];then format_log_print $INFO "Opreation FRU Write" # 在fru write操作下要求必须有 option_data2, 做参数检查 if [ "$option_data2" == "" ];then format_print $ERROR "Please provide fru file name" print_fru_command_format exit 1 fi # 解析fru bin文件 parse_fru_write_data fi fi if [ $# -le 2 ];then print_usage else start_get_sensor fi