1#!/bin/bash
2
3export PATH=$PATH:/usr/sbin:/usr/libexec
4
5# shellcheck source=meta-facebook/meta-bletchley/recipes-bletchley/plat-tools/files/bletchley-common-functions
6source /usr/libexec/bletchley-common-functions
7
8MDIO_TOOL="/usr/sbin/mdio"
9SWITCH_MDIO_BUS="1e650000.mdio-1"
10
11declare -a HOST_PREVIOUS_STATE=("" "" "" "" "" "" "")
12declare -a HOST_NEW_STATE_TEMP=("" "" "" "" "" "" "")
13declare -a HOST_STATE_CHANGE_CHECK=(0 0 0 0 0 0 0)
14HOST_STATE_CHANGE_CHECH_CNT=8
15
16declare -A HOST_ACPI_ST_MAP
17HOST_ACPI_ST_MAP["UNKNOW"]="Unknow"
18HOST_ACPI_ST_MAP["NOT_PRESENT"]="G3"
19HOST_ACPI_ST_MAP["AC_OFF"]="G3"
20HOST_ACPI_ST_MAP["OFF"]="G3"
21HOST_ACPI_ST_MAP["SLEEP"]="SLEEP"
22HOST_ACPI_ST_MAP["ON"]="S0_G0_D0"
23
24declare -A HOST_STATE_MAP
25HOST_STATE_MAP["UNKNOW"]="Quiesced"
26HOST_STATE_MAP["NOT_PRESENT"]="Off"
27HOST_STATE_MAP["AC_OFF"]="Off"
28HOST_STATE_MAP["OFF"]="Off"
29HOST_STATE_MAP["SLEEP"]="Standby"
30HOST_STATE_MAP["ON"]="Running"
31
32declare -A CHASSIS_PWR_STATE_MAP
33CHASSIS_PWR_STATE_MAP["UNKNOW"]="On"
34CHASSIS_PWR_STATE_MAP["NOT_PRESENT"]="Off"
35CHASSIS_PWR_STATE_MAP["AC_OFF"]="Off"
36CHASSIS_PWR_STATE_MAP["OFF"]="On"
37CHASSIS_PWR_STATE_MAP["SLEEP"]="On"
38CHASSIS_PWR_STATE_MAP["ON"]="On"
39
40is_host_ac_on()
41{
42    local I2C_BUS
43    I2C_BUS=$(get_bus_num "$1")
44    local P1_OUTPUT_REG
45    local P1_CONFIG_REG
46    local HOST_PWR
47    local IS_OUTPUT
48
49    P1_OUTPUT_REG=$(i2cget -f -y "$I2C_BUS" 0x76 0x03)
50    P1_CONFIG_REG=$(i2cget -f -y "$I2C_BUS" 0x76 0x07)
51    HOST_PWR="$(( (P1_OUTPUT_REG & 0x80)>>7 ))"
52    IS_OUTPUT="$(( (~P1_CONFIG_REG & 0x80)>>7 ))"
53
54    if [ "$((HOST_PWR & IS_OUTPUT))" -eq 1 ];then
55        return 0
56    fi
57
58    return 1
59}
60
61update_host_acpi_power_state()
62{
63    local BUS_NAME="xyz.openbmc_project.Settings"
64    local OBJ_PATH="/xyz/openbmc_project/control/host$1/acpi_power_state"
65    local DBUS_PROPERTIES_INTF_NAME="org.freedesktop.DBus.Properties"
66    local INTF_NAME="xyz.openbmc_project.Control.Power.ACPIPowerState"
67    local PROPERTY_NAME="SysACPIStatus"
68    local PROPERTY_VAL="xyz.openbmc_project.Control.Power.ACPIPowerState.ACPI.$2"
69    busctl call "$BUS_NAME" "$OBJ_PATH" "$DBUS_PROPERTIES_INTF_NAME" Set ssv "$INTF_NAME" "$PROPERTY_NAME" s "$PROPERTY_VAL"
70}
71
72update_host_state()
73{
74    local BUS_NAME="xyz.openbmc_project.State.Host$1"
75    local OBJ_PATH="/xyz/openbmc_project/state/host$1"
76    local DBUS_PROPERTIES_INTF_NAME="org.freedesktop.DBus.Properties"
77    local INTF_NAME="xyz.openbmc_project.State.Host"
78    local PROPERTY_NAME="CurrentHostState"
79    local PROPERTY_VAL="xyz.openbmc_project.State.Host.HostState.$2"
80    busctl call "$BUS_NAME" "$OBJ_PATH" "$DBUS_PROPERTIES_INTF_NAME" Set ssv "$INTF_NAME" "$PROPERTY_NAME" s "$PROPERTY_VAL"
81}
82
83update_chassis_power_state()
84{
85    local BUS_NAME="xyz.openbmc_project.State.Chassis$1"
86    local OBJ_PATH="/xyz/openbmc_project/state/chassis$1"
87    local DBUS_PROPERTIES_INTF_NAME="org.freedesktop.DBus.Properties"
88    local INTF_NAME="xyz.openbmc_project.State.Chassis"
89    local PROPERTY_NAME="CurrentPowerState"
90    local PROPERTY_VAL="xyz.openbmc_project.State.Chassis.PowerState.$2"
91    busctl call "$BUS_NAME" "$OBJ_PATH" "$DBUS_PROPERTIES_INTF_NAME" Set ssv "$INTF_NAME" "$PROPERTY_NAME" s "$PROPERTY_VAL"
92}
93
94update_sled_led_state()
95{
96    local HOST_ID=$1
97    local HOST_STATE=$2
98    case "$HOST_STATE" in
99        ON|SLEEP)
100            systemctl start obmc-led-group-start@sled"$HOST_ID"_good.service
101            ;;
102        AC_OFF|OFF)
103            systemctl start obmc-led-group-stop@sled"$HOST_ID"_good.service
104            ;;
105        *)
106            ;;
107    esac
108}
109
110check_host_state()
111{
112    if ! PORT_ST_VAL=$("$MDIO_TOOL" "$SWITCH_MDIO_BUS" phy "${PORT_NUM_MAP[$1]}" 0x00); then
113        # failed to get port status via mdio
114        echo "UNKNOW"
115        return 1
116    fi
117
118    if [ $((PORT_ST_VAL&16#0800)) -eq $((16#0000)) ]; then
119        echo "OFF"
120    elif [ $((PORT_ST_VAL&16#0A00)) -eq $((16#0A00)) ]; then
121        echo "ON"
122    elif [ $((PORT_ST_VAL&16#0900)) -eq $((16#0900)) ]; then
123        echo "SLEEP"
124    else
125        echo "UNKNOW"
126    fi
127    return 0
128}
129
130update_chassis_power_state "0" "On"
131
132while true
133do
134    for i in $(seq 1 "$MAX_SLED_NUM")
135    do
136        HOST_STATE=""
137        if ! is_sled_present "$i"; then
138            HOST_STATE="NOT_PRESENT"
139        elif ! is_host_ac_on "$i"; then
140            HOST_STATE="AC_OFF"
141        else
142            HOST_STATE=$(check_host_state "$i")
143        fi
144
145        if [ "$HOST_STATE" = "${HOST_PREVIOUS_STATE[$i]}" ]; then
146            if [ "${HOST_STATE_CHANGE_CHECK[$i]}" -lt "$HOST_STATE_CHANGE_CHECH_CNT" ]; then
147                echo "SLED$i: detected state recover (previous:${HOST_PREVIOUS_STATE[$i]}, current:$HOST_STATE)"
148            fi
149            HOST_STATE_CHANGE_CHECK[i]="$HOST_STATE_CHANGE_CHECH_CNT"
150            HOST_NEW_STATE_TEMP[i]="$HOST_STATE"
151        else
152            if [ "$HOST_STATE" != "${HOST_NEW_STATE_TEMP[$i]}" ]; then
153                HOST_STATE_CHANGE_CHECK[i]="$HOST_STATE_CHANGE_CHECH_CNT"
154            fi
155
156            if [ "${HOST_STATE_CHANGE_CHECK[$i]}" -gt "0" ]; then
157                echo "SLED$i: detected state changed (previous:${HOST_PREVIOUS_STATE[$i]}, current:$HOST_STATE), check count: ${HOST_STATE_CHANGE_CHECK[$i]}"
158                HOST_STATE_CHANGE_CHECK[i]=$((HOST_STATE_CHANGE_CHECK[i]-1))
159            else
160                echo "SLED$i: detected state changed, update host state to $HOST_STATE"
161                update_host_acpi_power_state "$i" "${HOST_ACPI_ST_MAP[$HOST_STATE]}"
162                update_host_state "$i" "${HOST_STATE_MAP[$HOST_STATE]}"
163                update_chassis_power_state "$i" "${CHASSIS_PWR_STATE_MAP[$HOST_STATE]}"
164                update_sled_led_state "$i" "$HOST_STATE"
165                HOST_STATE_CHANGE_CHECK[i]="$HOST_STATE_CHANGE_CHECH_CNT"
166                HOST_PREVIOUS_STATE[i]="$HOST_STATE"
167            fi
168            HOST_NEW_STATE_TEMP[i]="$HOST_STATE"
169        fi
170    done
171    sleep 1
172done