#include #include #include #include #include #include #include #include #include #include "lux_json_api.h" #include "lux_system_api.h" #include "dimm_fsc.h" #include #include #include #include #include SFscInfo psFscInfo; INT8U g_u8FSCPresent = FALSE; INT8U g_u8FSCEnable = 0; INT8U g_u8DIMMHighTempProtect = 0; #if 0 SFscFanReg sSFscFanReg[MAX_DIMM_SLOT] = { {0, 0x0069}, {1, 0x0068}, {2, 0x0067}, {3, 0x0066}, {4, 0x0065}, {5, 0x0064}, {6, 0x005e}, {7, 0x005f}, {8, 0x0060}, {9, 0x0061}, {10, 0x0062}, {11, 0x0063}, {12, 0x005d}, {13, 0x005c}, {14, 0x005b}, {15, 0x005a}, {16, 0x0059}, {17, 0x0058}, {18, 0x0052}, {19, 0x0053}, {20, 0x0054}, {21, 0x0055}, {22, 0x0056}, {23, 0x0057}, }; #endif SFscFanReg sSFscFanReg[MAX_DIMM_SLOT] = { {0, 0x0064}, {1, 0x0065}, {2, 0x0066}, {3, 0x0067}, {4, 0x0068}, {5, 0x0069}, {6, 0x005e}, {7, 0x005f}, {8, 0x0060}, {9, 0x0061}, {10, 0x0062}, {11, 0x0063}, {12, 0x0058}, {13, 0x0059}, {14, 0x005a}, {15, 0x005b}, {16, 0x005c}, {17, 0x005d}, {18, 0x0052}, {19, 0x0053}, {20, 0x0054}, {21, 0x0055}, {22, 0x0056}, {23, 0x0057}, }; SFscHeatReg sSFscHeatReg[MAX_DIMM_SLOT] = { {0, 0x008d}, {1, 0x008c}, {2, 0x008b}, {3, 0x008a}, {4, 0x0089}, {5, 0x0088}, {6, 0x0082}, {7, 0x0083}, {8, 0x0084}, {9, 0x0085}, {10, 0x0086}, {11, 0x0087}, {12, 0x0081}, {13, 0x0080}, {14, 0x007f}, {15, 0x007e}, {16, 0x007d}, {17, 0x007c}, {18, 0x0076}, {19, 0x0077}, {20, 0x0078}, {21, 0x0079}, {22, 0x007a}, {23, 0x007b}, }; #if 0 SFsc6056FanReg sFsc6056FanReg[FCB_6056_FAN_NUM] = { {0, 0x008f}, {1, 0x0090}, {2, 0x0091}, {3, 0x0092}, }; #endif SFsc6056FanReg sFsc6056FanReg[FCB_6056_FAN_NUM] = { {0, 0x0092}, {1, 0x0091}, {2, 0x0090}, {3, 0x008f}, }; SDIMMDbus sSDIMMDbus[MAX_DIMM_SLOT] = { {0, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_A_Temp"}, {1, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_B_Temp"}, {2, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_C_Temp"}, {3, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_D_Temp"}, {4, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_E_Temp"}, {5, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_F_Temp"}, {6, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_G_Temp"}, {7, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_H_Temp"}, {8, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_I_Temp"}, {9, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_J_Temp"}, {10, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_K_Temp"}, {11, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU0_L_Temp"}, {12, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_A_Temp"}, {13, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_B_Temp"}, {14, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_C_Temp"}, {15, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_D_Temp"}, {16, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_E_Temp"}, {17, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_F_Temp"}, {18, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_G_Temp"}, {19, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_H_Temp"}, {20, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_I_Temp"}, {21, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_J_Temp"}, {22, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_K_Temp"}, {23, "/xyz/openbmc_project/sensors/temperature/DIMM_CPU1_L_Temp"}, }; SDIMMPowerDbus sSDIMMPowerDbus[MAX_DIMM_POWER_SLOT] = { {0, "/xyz/openbmc_project/sensors/power/DDR0_Power"}, {1, "/xyz/openbmc_project/sensors/power/DDR1_Power"}, {2, "/xyz/openbmc_project/sensors/power/DDR2_Power"}, {3, "/xyz/openbmc_project/sensors/power/DDR3_Power"}, }; SCPUDbus sSCPUDbus[2] = { {0, "/xyz/openbmc_project/sensors/temperature/CPU0_Temp"}, {1, "/xyz/openbmc_project/sensors/temperature/CPU1_Temp"}, }; EFuncRetCode check_dbus_error(DBusError *error) { if (dbus_error_is_set(error)) { //LuxPrintf("D-Bus Error: %s\n", error->message); dbus_error_free(error); return FUNC_FAILED; } } EFuncRetCode i2cReadWrite(INT8U bus, INT8U slaveAddr, INT8U* writeData, INT8U writelen, INT8U* readData, INT8U readlen) { char busPath[32] = {0}; struct i2c_msg messages[2]; struct i2c_rdwr_ioctl_data ioctl_data; LuxSprintf(busPath, "/dev/i2c-%d", bus); int fd = open(busPath, O_RDWR); if (fd < 0) { return FUNC_FAILED; } if (writelen > 0) { messages[0].addr = slaveAddr; messages[0].flags = 0; messages[0].len = writelen; messages[0].buf = writeData; } if (readlen > 0) { messages[1].addr = slaveAddr; messages[1].flags = I2C_M_RD; messages[1].len = readlen; messages[1].buf = readData; } ioctl_data.msgs = messages; ioctl_data.nmsgs = (writelen == 0 ? 0 : 1) + (readlen > 0 ? 1 : 0); if (ioctl(fd, I2C_RDWR, &ioctl_data) < 0) { close(fd); return FUNC_FAILED; } close(fd); return FUNC_OK; } EFuncRetCode LuxFSCDbusGetDIMMValue(char* pcDbusPatch, double* pdValue, INT8U* pu8Present, INT8U* pu8Status) { const char *bus_name = "xyz.openbmc_project.DIMMTempSensor"; const char *path = pcDbusPatch; const char *iface = "org.freedesktop.DBus.Properties"; const char *method = "Get"; const char *intf = "xyz.openbmc_project.Sensor.Value"; const char *prop = "Value"; DBusConnection *conn; DBusError err; DBusMessage *msg, *reply; DBusMessageIter args; dbus_error_init(&err); conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); check_dbus_error(&err); if (!conn) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } msg = dbus_message_new_method_call(bus_name, path, iface, method); if (!msg) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } dbus_message_iter_init_append(msg, &args); if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &intf)) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &prop)) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); check_dbus_error(&err); if (!reply) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } if (!dbus_message_iter_init(reply, &args)) { //LuxPrintf("Message has no arguments!\n"); } else if (DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&args)) { } else if (DBUS_TYPE_VARIANT == dbus_message_iter_get_arg_type(&args)) { DBusMessageIter variant_iter; dbus_message_iter_recurse(&args, &variant_iter); int type = dbus_message_iter_get_arg_type(&variant_iter); switch (type) { case DBUS_TYPE_STRING: { const char *str_value; dbus_message_iter_get_basic(&variant_iter, &str_value); //printf("Parsed string value from variant: %s\n", str_value); break; } case DBUS_TYPE_DOUBLE: { double double_value; dbus_message_iter_get_basic(&variant_iter, &double_value); //printf("Parsed double value from variant: %f\n", double_value); *pdValue = double_value; *pu8Present = FSC_SENSOR_PRESENT; *pu8Status = FSC_SENSOR_NORMAL; break; } case DBUS_TYPE_BOOLEAN: { dbus_bool_t bool_value; dbus_message_iter_get_basic(&variant_iter, &bool_value); //printf("Parsed boolean value from variant: %d\n", bool_value); break; } default: break; } } dbus_message_unref(reply); dbus_message_unref(msg); dbus_connection_unref(conn); return FUNC_OK; } EFuncRetCode LuxFSCDbusGetCPUValue(char* pcDbusPatch, double* pdValue, INT8U* pu8Present, INT8U* pu8Status) { const char *bus_name = "xyz.openbmc_project.IntelCPUSensor"; const char *path = pcDbusPatch; const char *iface = "org.freedesktop.DBus.Properties"; const char *method = "Get"; const char *intf = "xyz.openbmc_project.Sensor.Value"; const char *prop = "Value"; DBusConnection *conn; DBusError err; DBusMessage *msg, *reply; DBusMessageIter args; dbus_error_init(&err); conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); check_dbus_error(&err); if (!conn) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } msg = dbus_message_new_method_call(bus_name, path, iface, method); if (!msg) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } dbus_message_iter_init_append(msg, &args); if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &intf)) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &prop)) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); check_dbus_error(&err); if (!reply) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } if (!dbus_message_iter_init(reply, &args)) LuxPrintf("Message has no arguments!\n"); else if (DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&args)) { } else if (DBUS_TYPE_VARIANT == dbus_message_iter_get_arg_type(&args)) { DBusMessageIter variant_iter; dbus_message_iter_recurse(&args, &variant_iter); int type = dbus_message_iter_get_arg_type(&variant_iter); switch (type) { case DBUS_TYPE_STRING: { const char *str_value; dbus_message_iter_get_basic(&variant_iter, &str_value); //printf("Parsed string value from variant: %s\n", str_value); break; } case DBUS_TYPE_DOUBLE: { double double_value; dbus_message_iter_get_basic(&variant_iter, &double_value); //printf("Parsed double value from variant: %f\n", double_value); *pdValue = double_value; *pu8Present = FSC_SENSOR_PRESENT; *pu8Status = FSC_SENSOR_NORMAL; break; } case DBUS_TYPE_BOOLEAN: { dbus_bool_t bool_value; dbus_message_iter_get_basic(&variant_iter, &bool_value); //printf("Parsed boolean value from variant: %d\n", bool_value); break; } default: break; } } dbus_message_unref(reply); dbus_message_unref(msg); dbus_connection_unref(conn); return FUNC_OK; } EFuncRetCode LuxFSCDbusGetDIMMPowerValue(char* pcDbusPatch, double* pdValue, INT8U* pu8Present, INT8U* pu8Status) { const char *bus_name = "xyz.openbmc_project.PSUSensor"; const char *path = pcDbusPatch; const char *iface = "org.freedesktop.DBus.Properties"; const char *method = "Get"; const char *intf = "xyz.openbmc_project.Sensor.Value"; const char *prop = "Value"; DBusConnection *conn; DBusError err; DBusMessage *msg, *reply; DBusMessageIter args; dbus_error_init(&err); conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); check_dbus_error(&err); if (!conn) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } msg = dbus_message_new_method_call(bus_name, path, iface, method); if (!msg) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } dbus_message_iter_init_append(msg, &args); if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &intf)) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &prop)) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); check_dbus_error(&err); if (!reply) { if(reply) dbus_message_unref(reply); if(msg) dbus_message_unref(msg); if(conn) dbus_connection_unref(conn); return FUNC_FAILED; } if (!dbus_message_iter_init(reply, &args)) { //LuxPrintf("Message has no arguments!\n"); } else if (DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&args)) { } else if (DBUS_TYPE_VARIANT == dbus_message_iter_get_arg_type(&args)) { DBusMessageIter variant_iter; dbus_message_iter_recurse(&args, &variant_iter); int type = dbus_message_iter_get_arg_type(&variant_iter); switch (type) { case DBUS_TYPE_STRING: { const char *str_value; dbus_message_iter_get_basic(&variant_iter, &str_value); //printf("Parsed string value from variant: %s\n", str_value); break; } case DBUS_TYPE_DOUBLE: { double double_value; dbus_message_iter_get_basic(&variant_iter, &double_value); //printf("Parsed double value from variant: %f\n", double_value); *pdValue = double_value; *pu8Present = FSC_SENSOR_PRESENT; *pu8Status = FSC_SENSOR_NORMAL; break; } case DBUS_TYPE_BOOLEAN: { dbus_bool_t bool_value; dbus_message_iter_get_basic(&variant_iter, &bool_value); //printf("Parsed boolean value from variant: %d\n", bool_value); break; } default: break; } } dbus_message_unref(reply); dbus_message_unref(msg); dbus_connection_unref(conn); return FUNC_OK; } EFuncRetCode LuxFSCCheckFanTableExist(char* pcName) { /*check fan table file exist */ if(LuxAccess(pcName,F_OK) != 0) { LuxPrintf("Fan table file %s is not exist!!!\n",pcName); return FUNC_FAILED; } return FUNC_OK; } EFuncRetCode LuxFSCLoadHeader(cJSON* psCJSONRoot, SFscHeader* psFSCHeader) { char acTemp[MAX_JSON_CHARACTER_SIZE] = {0}; LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONRoot, "Project", acTemp))) { LuxPrintf("Parse fan table Project fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("Project value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFSCHeader->acProject, acTemp, LuxStrlen(acTemp)); } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONRoot, "Customer", psFSCHeader->acCustomer))) { LuxPrintf("Parse fan table Customer fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("Customer value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFSCHeader->acCustomer, acTemp, LuxStrlen(acTemp)); } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONRoot, "Version", psFSCHeader->acVersion))) { LuxPrintf("Parse fan table Version fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("Version value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFSCHeader->acVersion, acTemp, LuxStrlen(acTemp)); } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONRoot, "platform", psFSCHeader->acPlatform))) { LuxPrintf("Parse fan table platform fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("platform value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFSCHeader->acPlatform, acTemp, LuxStrlen(acTemp)); } } return FUNC_OK; } EFuncRetCode LuxFSCLoadGlobalConfig(cJSON* psCJSONRoot, SFscGlobalConfig* psFscGlobalConfig) { cJSON* psCJSONGlobalConfigRoot = NULL; int iTemp = 0; char acTemp[MAX_JSON_CHARACTER_SIZE] = {0}; psCJSONGlobalConfigRoot = LuxcJSONGetObjectItem(psCJSONRoot, "GlobalConfig"); if(NULL == psCJSONGlobalConfigRoot) { LuxPrintf("Can't get GlobalConfig cJSONRoot\n"); return FUNC_FAILED; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONGlobalConfigRoot, "MaxSensorReadingCache", &iTemp))) { LuxPrintf("Parse fan table MaxSensorReadingCache fail\n"); return FUNC_FAILED; } else { psFscGlobalConfig->u8MaxReadingCache = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONGlobalConfigRoot, "Elevation", &iTemp))) { LuxPrintf("Parse fan table Elevation fail\n"); return FUNC_FAILED; } else { psFscGlobalConfig->u16Elevation = iTemp; } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONGlobalConfigRoot, "FanType", acTemp))) { LuxPrintf("Parse fan table FanType fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("FanType value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFscGlobalConfig->acFanType, acTemp, LuxStrlen(acTemp)); } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONGlobalConfigRoot, "WorkDCOff", acTemp))) { LuxPrintf("Parse fan table WorkDCOff fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("WorkDCOff value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFscGlobalConfig->acWorkDCOff, acTemp, LuxStrlen(acTemp)); } } return FUNC_OK; } EFuncRetCode LuxFSCLoadFanConfig(cJSON* psCJSONRoot, SFscFanConfig* psFscFanConfig) { cJSON* psCJSONFanConfigRoot = NULL; int aiTemp[MAX_JSON_CHARACTER_SIZE] = {0}; int iArraySize = 0; int iTemp = 0; INT8U u8Index = 0; psCJSONFanConfigRoot = LuxcJSONGetObjectItem(psCJSONRoot, "FanConfig"); if(NULL == psCJSONFanConfigRoot) { LuxPrintf("Can't get FanConfig cJSONRoot\n"); return FUNC_FAILED; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONFanConfigRoot, "MaxPWMNumber", &iTemp))) { LuxPrintf("Parse fan table MaxPWMNumber fail\n"); return FUNC_FAILED; } else { psFscFanConfig->u8MaxPwmNum = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONFanConfigRoot, "MaxFanNumber", &iTemp))) { LuxPrintf("Parse fan table MaxFanNumber fail\n"); return FUNC_FAILED; } else { psFscFanConfig->u8MaxFanNum = (INT8U)iTemp; } LuxMemset(aiTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectIntArray(psCJSONFanConfigRoot, "FanSensorNumPWMMatch", aiTemp, &iArraySize))) { LuxPrintf("Parse fan table FanSensorNumPWMMatch fail\n"); return FUNC_FAILED; } else { if(iArraySize > MAX_FAN_COUNT) { LuxPrintf("FanSensorNumPWMMatch value error %s\n",aiTemp); return FUNC_FAILED; } else { for(u8Index = 0; u8Index < iArraySize; u8Index++) { psFscFanConfig->u8FanSensorNumPWMMatch[u8Index] = (INT8U)aiTemp[u8Index]; } } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONFanConfigRoot, "MaxFanDuty", &iTemp))) { LuxPrintf("Parse fan table MaxFanDuty fail\n"); return FUNC_FAILED; } else { psFscFanConfig->u8MaxFanDuty = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONFanConfigRoot, "MinFanDuty", &iTemp))) { LuxPrintf("Parse fan table MinFanDuty fail\n"); return FUNC_FAILED; } else { psFscFanConfig->u8MinFanDuty = (INT8U)iTemp; } return FUNC_OK; } EFuncRetCode LuxFSCLoadCloseloopSensor(cJSON* psCJSONRoot, SFscCLSensor* psFscCLSensor) { INT8U u8CLSensorCount = 0; INT8U u8SensorIndex = 0; SFscCLSensorInfo sFscCLSensorInfo; cJSON* psCJSONCloseloopRoot = NULL; cJSON* psCJSONCloseloopSensorRoot = NULL; char acKeyName[MAX_KEY_LENGTH] = {0}; int iArraySize = 0; int iRow = 0; int iColumn = 0; int iTemp = 0; char acTemp[MAX_JSON_CHARACTER_SIZE] = {0}; int aiTemp[MAX_JSON_CHARACTER_SIZE] = {0}; char asTemp[MAX_SETPOINT_CASE][MAX_JSON_CHARACTER_SIZE] = {0}; double adTemp[MAX_JSON_CHARACTER_SIZE][MAX_JSON_CHARACTER_SIZE] = {0}; INT8U u8RowIndex = 0; INT8U u8ColumnIndex =0; INT8U u8Index = 0; psCJSONCloseloopRoot = LuxcJSONGetObjectItem(psCJSONRoot, "CloseLoop"); if(NULL == psCJSONCloseloopRoot) { LuxPrintf("Can't get CloseLoop cJSONRoot\n"); return FUNC_FAILED; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopRoot, "MaxCloseloopSensor", &iTemp))) { LuxPrintf("Parse fan table MaxCloseloopSensor fail\n"); return FUNC_FAILED; } else { psFscCLSensor->u8MaxCLSensor = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopRoot, "TotalCloseloopSensor", &iTemp))) { LuxPrintf("Parse fan table TotalCloseloopSensor fail\n"); return FUNC_FAILED; } else { psFscCLSensor->u8TotalCLSensor = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONCloseloopRoot, "PidAdjustMethod", acTemp))) { LuxPrintf("Parse fan table PidAdjustMethod fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("PidAdjustMethod value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFscCLSensor->acPIDAdjustMethod, acTemp, LuxStrlen(acTemp)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopRoot, "ESection", &iTemp))) { LuxPrintf("Parse fan table ESection fail\n"); return FUNC_FAILED; } else { psFscCLSensor->u8CLSensorESection = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopRoot, "ECSection", &iTemp))) { LuxPrintf("Parse fan table ECSection fail\n"); return FUNC_FAILED; } else { psFscCLSensor->u8CLSensorECSection = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopRoot, "SensorSetpointMaxCase", &iTemp))) { LuxPrintf("Parse fan table SensorSetpointMaxCase fail\n"); return FUNC_FAILED; } else { psFscCLSensor->u8CLSensorSetpointMaxCase = (INT8U)iTemp; } u8CLSensorCount = psFscCLSensor->u8TotalCLSensor; if(u8CLSensorCount > psFscCLSensor->u8MaxCLSensor) { LuxPrintf("Wrong closeloop sensor count %d\n",u8CLSensorCount); } for(u8SensorIndex = 0; u8SensorIndex < u8CLSensorCount; u8SensorIndex++) { LuxMemset(&sFscCLSensorInfo, 0 ,sizeof(SFscCLSensorInfo)); LuxMemset(acKeyName, 0, MAX_KEY_LENGTH); LuxSprintf(acKeyName, "CLSensor%d", u8SensorIndex+1); /*In fsc json file, the sensor index count from 1 */ psCJSONCloseloopSensorRoot = LuxcJSONGetObjectItem(psCJSONCloseloopRoot, acKeyName); if(NULL == psCJSONCloseloopSensorRoot) { LuxPrintf("Can't get CLSensor%d cJSONRoot\n",u8SensorIndex); return FUNC_FAILED; } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONCloseloopSensorRoot, "SensorType", acTemp))) { LuxPrintf("Parse fan table fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("SensorType value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscCLSensorInfo.acCLSensorType, acTemp, LuxStrlen(acTemp)); } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONCloseloopSensorRoot, "SensorStatus", acTemp))) { LuxPrintf("Parse fan table SensorStatusfail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("SensorStatus value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscCLSensorInfo.acCLSensorStatus, acTemp, LuxStrlen(acTemp)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopSensorRoot, "DT", &iTemp))) { LuxPrintf("Parse fan table DT fail\n"); return FUNC_FAILED; } else { sFscCLSensorInfo.u8DT = (INT8U)iTemp; } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONCloseloopSensorRoot, "SensorName", acTemp))) { LuxPrintf("Parse fan table SensorName fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_SENSOR_NAME_LENGTH) { LuxPrintf("SensorName value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscCLSensorInfo.acSensorName, acTemp, LuxStrlen(acTemp)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopSensorRoot, "VendorSpec", &iTemp))) { LuxPrintf("Parse fan table VendorSpec fail\n"); return FUNC_FAILED; } else { sFscCLSensorInfo.s8VendorSpec = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopSensorRoot, "CustomerSpec", &iTemp))) { LuxPrintf("Parse fan table CustomerSpec fail\n"); return FUNC_FAILED; } else { sFscCLSensorInfo.s8CustomerSpec = (INT8U)iTemp; } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONCloseloopSensorRoot, "SetpointType", acTemp))) { LuxPrintf("Parse fan table SetpointType fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_SENSOR_NAME_LENGTH) { LuxPrintf("SetpointType value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscCLSensorInfo.acSetpointType, acTemp, LuxStrlen(acTemp)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopSensorRoot, "SetpointDefault", &iTemp))) { LuxPrintf("Parse fan table SetpointDefault fail\n"); return FUNC_FAILED; } else { sFscCLSensorInfo.s8SetpointDefault = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectStringArray(psCJSONCloseloopSensorRoot, "SetpointCase", asTemp, &iArraySize))) { LuxPrintf("Parse fan table SetpointCase fail\n"); return FUNC_FAILED; } else { if(iArraySize > MAX_SETPOINT_CASE) { LuxPrintf("SetpointCase value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscCLSensorInfo.acSetpointCase, (char**)asTemp, sizeof(sFscCLSensorInfo.acSetpointCase)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntArray(psCJSONCloseloopSensorRoot, "SetpointValue", aiTemp, &iArraySize))) { LuxPrintf("Parse fan table SetpointValue fail\n"); return FUNC_FAILED; } else { if(iArraySize > MAX_OL_SENSOR_STEPS) { LuxPrintf("SetpointValue value error %s\n",acTemp); return FUNC_FAILED; } else { for(u8Index = 0; u8Index < iArraySize; u8Index++) { sFscCLSensorInfo.as8SetpointValue[u8Index] = (INT8S)aiTemp[u8Index]; } } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONCloseloopSensorRoot, "SetpointCaseUse", acTemp))) { LuxPrintf("Parse fan table SetpointCaseUse fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_SENSOR_NAME_LENGTH) { LuxPrintf("SetpointCaseUse value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscCLSensorInfo.acSetpointCaseUse, acTemp, LuxStrlen(acTemp)); } } LuxMemset(aiTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectIntArray(psCJSONCloseloopSensorRoot, "FanWeighting", aiTemp, &iArraySize))) { LuxPrintf("Parse fan table FanWeighting fail\n"); return FUNC_FAILED; } else { if(iArraySize > MAX_FSC_PWM_CHANNEL) { LuxPrintf("FanWeighting value error %s\n",acTemp); return FUNC_FAILED; } else { for(u8Index = 0; u8Index < iArraySize; u8Index++) { sFscCLSensorInfo.au8FanWeight[u8Index] = (INT8U)aiTemp[u8Index]; } } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONCloseloopSensorRoot, "Hysteresis", &iTemp))) { LuxPrintf("Parse fan table Hysteresis fail\n"); return FUNC_FAILED; } else { sFscCLSensorInfo.u8Hysteresis = (INT8U)iTemp; } LuxMemset(aiTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectIntArray(psCJSONCloseloopSensorRoot, "E", aiTemp, &iArraySize))) { LuxPrintf("Parse fan table E fail\n"); return FUNC_FAILED; } else { if(iArraySize > MAX_SENSOR_E_SECTION-1) { LuxPrintf("E value error %s\n",acTemp); return FUNC_FAILED; } else { for(u8Index = 0; u8Index < iArraySize; u8Index++) { sFscCLSensorInfo.as8EValue[u8Index] = (INT8S)aiTemp[u8Index]; } } } LuxMemset(aiTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectIntArray(psCJSONCloseloopSensorRoot, "EC", aiTemp, &iArraySize))) { LuxPrintf("Parse fan table EC fail\n"); return FUNC_FAILED; } else { if(iArraySize > MAX_SENSOR_EC_SECTION-1) { LuxPrintf("EC value error %s\n",acTemp); return FUNC_FAILED; } else { for(u8Index = 0; u8Index < iArraySize; u8Index++) { sFscCLSensorInfo.as8ECValue[u8Index] = (INT8S)aiTemp[u8Index]; } } } LuxMemset(adTemp, 0, sizeof(adTemp)); if(FUNC_FAILED == (LuxcJSONGetObjectDoubleArray2(psCJSONCloseloopSensorRoot, "P", adTemp, &iRow, &iColumn))) { LuxPrintf("Parse fan table P fail\n"); return FUNC_FAILED; } else { if((iRow > MAX_SENSOR_EC_SECTION) || (iColumn > MAX_SENSOR_E_SECTION)) { LuxPrintf("P value error \n"); return FUNC_FAILED; } else { for(u8RowIndex = 0; u8RowIndex < MAX_SENSOR_EC_SECTION; u8RowIndex++) { for(u8ColumnIndex = 0; u8ColumnIndex < MAX_SENSOR_E_SECTION; u8ColumnIndex++) { sFscCLSensorInfo.afPValue[u8RowIndex][u8ColumnIndex] = adTemp[u8RowIndex][u8ColumnIndex]; } } } } LuxMemset(adTemp, 0, sizeof(adTemp)); if(FUNC_FAILED == (LuxcJSONGetObjectDoubleArray2(psCJSONCloseloopSensorRoot, "I", adTemp, &iRow, &iColumn))) { LuxPrintf("Parse fan table I fail\n"); return FUNC_FAILED; } else { if((iRow > MAX_SENSOR_EC_SECTION) || (iColumn > MAX_SENSOR_E_SECTION)) { LuxPrintf("I value error \n"); return FUNC_FAILED; } else { for(u8RowIndex = 0; u8RowIndex < MAX_SENSOR_EC_SECTION; u8RowIndex++) { for(u8ColumnIndex = 0; u8ColumnIndex < MAX_SENSOR_E_SECTION; u8ColumnIndex++) { sFscCLSensorInfo.afIValue[u8RowIndex][u8ColumnIndex] = adTemp[u8RowIndex][u8ColumnIndex]; } } } } LuxMemset(adTemp, 0, sizeof(adTemp)); if(FUNC_FAILED == (LuxcJSONGetObjectDoubleArray2(psCJSONCloseloopSensorRoot, "D", adTemp, &iRow, &iColumn))) { LuxPrintf("Parse fan table D fail\n"); return FUNC_FAILED; } else { if((iRow > MAX_SENSOR_EC_SECTION) || (iColumn > MAX_SENSOR_E_SECTION)) { LuxPrintf("D value error \n"); return FUNC_FAILED; } else { for(u8RowIndex = 0; u8RowIndex < MAX_SENSOR_EC_SECTION; u8RowIndex++) { for(u8ColumnIndex = 0; u8ColumnIndex < MAX_SENSOR_E_SECTION; u8ColumnIndex++) { sFscCLSensorInfo.afDValue[u8RowIndex][u8ColumnIndex] = adTemp[u8RowIndex][u8ColumnIndex]; } } } } LuxMemcpy(&psFscCLSensor->asFscCLSensorInfo[u8SensorIndex], &sFscCLSensorInfo, sizeof(SFscCLSensorInfo)); } return FUNC_OK; } EFuncRetCode LuxFSCLoadAbnormalConfig(cJSON* psCJSONRoot, SFscAbnormalEvent* psFscAbnormalEvent) { INT8U u8AbnormalSensorCount = 0; INT8U u8SensorIndex = 0; SFscSensorFailInfo sFscSensorFailInfo; cJSON* psCJSONAbnormalEventRoot = NULL; cJSON* psCJSONAbnormalSensorRoot = NULL; char acKeyName[MAX_KEY_LENGTH] = {0}; int iTemp = 0; char acTemp[MAX_JSON_CHARACTER_SIZE] = {0}; psCJSONAbnormalEventRoot = LuxcJSONGetObjectItem(psCJSONRoot, "AbnormalEvent"); if(NULL == psCJSONAbnormalEventRoot) { LuxPrintf("Can't get AbnormalEvent cJSONRoot\n"); return FUNC_FAILED; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONAbnormalEventRoot, "MaxFailSensor", &iTemp))) { LuxPrintf("Parse fan table MaxFailSensor fail\n"); return FUNC_FAILED; } else { psFscAbnormalEvent->u8MaxAbnormalSensor = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONAbnormalEventRoot, "TotalFailSensor", &iTemp))) { LuxPrintf("Parse fan table TotalFailSensor fail\n"); return FUNC_FAILED; } else { psFscAbnormalEvent->u8TotalAbnormalSensor = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONAbnormalEventRoot, "FanSensorNumberStart", &iTemp))) { LuxPrintf("Parse fan table FanSensorNumberStart fail\n"); return FUNC_FAILED; } else { psFscAbnormalEvent->sFscFanFail.u8FanSensorNumberStart = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONAbnormalEventRoot, "FanFailSingle", acTemp))) { LuxPrintf("Parse fan table FanFailSingle fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("FanFailSingle value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFscAbnormalEvent->sFscFanFail.acFanFailSingle, acTemp, LuxStrlen(acTemp)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONAbnormalEventRoot, "FanFailTwin_1", &iTemp))) { LuxPrintf("Parse fan table FanFailTwin_1 fail\n"); return FUNC_FAILED; } else { psFscAbnormalEvent->sFscFanFail.u8FanFailTwin1 = (INT8U)iTemp; } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONAbnormalEventRoot, "FanFailTwin_2_Diff", &iTemp))) { LuxPrintf("Parse fan table FanFailTwin_2_Diff fail\n"); return FUNC_FAILED; } else { psFscAbnormalEvent->sFscFanFail.u8FanFailTwin2Diff = (INT8U)iTemp; } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONAbnormalEventRoot, "FanFailTwin_2_Same", acTemp))) { LuxPrintf("Parse fan table FanFailTwin_2_Same fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("FanFailTwin_2_Same value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(psFscAbnormalEvent->sFscFanFail.acFanFailTwin2Same, acTemp, LuxStrlen(acTemp)); } } u8AbnormalSensorCount = psFscAbnormalEvent->u8TotalAbnormalSensor; if(u8AbnormalSensorCount > psFscAbnormalEvent->u8MaxAbnormalSensor) { LuxPrintf("Wrong abnormal sensor count %d\n",u8AbnormalSensorCount); } for(u8SensorIndex = 0; u8SensorIndex < u8AbnormalSensorCount; u8SensorIndex++) { LuxMemset(&sFscSensorFailInfo, 0 ,sizeof(SFscSensorFailInfo)); LuxMemset(acKeyName, 0, MAX_KEY_LENGTH); LuxSprintf(acKeyName, "AbnormalSensor%d", u8SensorIndex+1); /*In fsc json file, the sensor index count from 1 */ psCJSONAbnormalSensorRoot = LuxcJSONGetObjectItem(psCJSONAbnormalEventRoot, acKeyName); if(NULL == psCJSONAbnormalSensorRoot) { LuxPrintf("Can't get AbnormalSensor%d cJSONRoot\n",u8SensorIndex); return FUNC_FAILED; } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONAbnormalSensorRoot, "SensorName", acTemp))) { LuxPrintf("Parse fan table SensorName fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("SensorName value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscSensorFailInfo.acSensorName, acTemp, LuxStrlen(acTemp)); } } LuxMemset(acTemp, 0, MAX_JSON_CHARACTER_SIZE); if(FUNC_FAILED == (LuxcJSONGetObjectStringValue(psCJSONAbnormalSensorRoot, "Policy", acTemp))) { LuxPrintf("Parse fan table Policy fail\n"); return FUNC_FAILED; } else { if(LuxStrlen(acTemp) > MAX_KEY_LENGTH) { LuxPrintf("Policy value error %s\n",acTemp); return FUNC_FAILED; } else { LuxMemcpy(sFscSensorFailInfo.acFailPolicy, acTemp, LuxStrlen(acTemp)); } } if(FUNC_FAILED == (LuxcJSONGetObjectIntValue(psCJSONAbnormalSensorRoot, "FailValue", &iTemp))) { LuxPrintf("Parse fan table FailValue fail\n"); return FUNC_FAILED; } else { sFscSensorFailInfo.u8FailValue = (INT8U)iTemp; } LuxMemcpy(&psFscAbnormalEvent->asFscSensorFailInfo[u8SensorIndex], &sFscSensorFailInfo, sizeof(SFscSensorFailInfo)); } return FUNC_OK; } EFuncRetCode LuxFSCGetSetpointFromFile(INT8S* ps8Setpoint) { FILE* fp = NULL; char acCmdbuff[512] = {0}; char acCmdstr[1024] = {0}; INT8U u8Value = 0; if(0 != LuxAccess(DIMM_SETPOINT_PATH, F_OK)) { return FUNC_FAILED; } LuxSprintf(acCmdstr, "cat %s",DIMM_SETPOINT_PATH); if ((fp = LuxPopen(acCmdstr, "r")) != NULL) { fgets(acCmdbuff, sizeof(acCmdbuff), fp); u8Value = strtoul(acCmdbuff, NULL, 10); LuxPclose(fp); if (u8Value > 120) { return FUNC_FAILED; } else { *ps8Setpoint = (INT8S)u8Value; return FUNC_OK; } } else { return FUNC_FAILED; } return FUNC_OK; } EFuncRetCode LuxFSCSetSetpointToFile(INT8S s8Setpoint) { FILE *fp = NULL; char buffer[32] = {0}; fp = LuxFopen(DIMM_SETPOINT_PATH, "wb"); if(NULL == fp) { LuxPrintf("Error: LuxFopen %s Failed\n",DIMM_SETPOINT_PATH); return FUNC_FAILED; } snprintf(buffer, sizeof(buffer), "%d", s8Setpoint); if (fputs(buffer, fp) == EOF) { LuxPrintf("Error: fputs Failed\n"); LuxFclose(fp); return FUNC_FAILED; } LuxFclose(fp); return FUNC_OK; } EFuncRetCode LuxFSCGetFSCControlMode(SFscInfo* psFscInfo) { SFscControlMode sFscControlMode; FILE* fp = NULL; char acCmdbuff[512] = {0}; char acCmdstr[1024] = {0}; INT8U u8Value = 0; if(0 != LuxAccess(FSC_CONTROL_MODE, F_OK)) { psFscInfo->sFscRunningInfo.u8ControlMode = FSC_FAN_TABLE_AUTO; return FUNC_FAILED; } /*Read FSC configuration*/ fp = LuxFopen(FSC_CONTROL_MODE, "rb"); if(NULL == fp) { LuxPrintf("Error: LuxFopen %s Failed\n", FSC_CONTROL_MODE); return FUNC_FAILED; } if(1 != LuxFread(&sFscControlMode, sizeof(SFscControlMode), 1, fp)) { LuxPrintf("Error: LuxFread Failed\n"); LuxFclose(fp); return FUNC_FAILED; } psFscInfo->sFscRunningInfo.u8ControlMode = sFscControlMode.u8ControlMode; LuxMemcpy(psFscInfo->sFscRunningInfo.au8ManualPwmOut, sFscControlMode.u8PWM, MAX_FSC_PWM_CHANNEL); return FUNC_OK; } EFuncRetCode LuxFSCLoadFanTable(cJSON* psCJSONRoot, SFscInfo* psFscInfo) { EFuncRetCode eRetn = FUNC_FAILED; /*Load fan table header */ eRetn = LuxFSCLoadHeader(psCJSONRoot, &psFscInfo->sFSCHeader); if(FUNC_FAILED == eRetn) { LuxPrintf("Load fan table header fail !!!\n"); return FUNC_FAILED; } /*Load fan table global configuration */ eRetn = LuxFSCLoadGlobalConfig(psCJSONRoot, &psFscInfo->sFscGlobalConfig); if(FUNC_FAILED == eRetn) { LuxPrintf("Load fan table global config fail !!!\n"); return FUNC_FAILED; } /*Load fan table fan configuration */ eRetn = LuxFSCLoadFanConfig(psCJSONRoot, &psFscInfo->sFscFanConfig); if(FUNC_FAILED == eRetn) { LuxPrintf("Load fan table fan config fail !!!\n"); return FUNC_FAILED; } /*Load fan table closeloop sensor information */ eRetn = LuxFSCLoadCloseloopSensor(psCJSONRoot, &psFscInfo->sFscCLSensor); if(FUNC_FAILED == eRetn) { LuxPrintf("Load fan table fan config fail !!!\n"); return FUNC_FAILED; } return FUNC_OK; } EFuncRetCode LuxFSCInit() { char acFscFileName[64] = {0}; cJSON* psCJSONRoot = NULL; LuxMemset(&psFscInfo, 0, sizeof(SFscInfo)); LuxSprintf(acFscFileName,"%s",FAN_TABLE_PATH); LuxPrintf("Load fan table %s\n",acFscFileName); /*Check fan table exist*/ if(FUNC_FAILED == LuxFSCCheckFanTableExist(acFscFileName)) { LuxPrintf("Fan table is not exist !!!\n"); return FUNC_FAILED; } /* Load fan table */ psCJSONRoot = LuxcJSONParseJsonFile(acFscFileName); if(NULL == psCJSONRoot) { LuxPrintf("Can't open fan table file %s !!!\n",acFscFileName); return FUNC_FAILED; } if(LuxFSCLoadFanTable(psCJSONRoot, &psFscInfo) != FUNC_OK) { psFscInfo.sFscRunningInfo.u8FanTableLoadStatus = FSC_FAN_TABLE_LOAD_FAIL; } else { psFscInfo.sFscRunningInfo.u8FanTableLoadStatus = FSC_FAN_TABLE_LOAD_SUCCESS; LuxFSCSetSetpointToFile(psFscInfo.sFscCLSensor.asFscCLSensorInfo[0].s8SetpointDefault); LuxFSCSetSetpointToFile(psFscInfo.sFscCLSensor.asFscCLSensorInfo[0].s8SetpointDefault); } if(NULL != psCJSONRoot) { LuxcJSONDelete(psCJSONRoot); } return FUNC_OK; } EFuncRetCode LuxFSCFanTableUpdate(SFscInfo* psFscInfo) { if(FSC_FAN_TABLE_UPDATE == psFscInfo->sFscRunningInfo.u8UpdateFlag) { LuxPrintf("Fan table need update. re-load fan table.\n"); if(FUNC_OK != LuxFSCInit()) { LuxPrintf("Reload fan table fail!!!\n"); if(psFscInfo->sFscRunningInfo.u8LoadTableTries < 3) { LuxPrintf("Retry !!!\n"); psFscInfo->sFscRunningInfo.u8LoadTableTries ++; return FUNC_OK; } else { psFscInfo->sFscRunningInfo.u8UpdateFlag = FSC_FAN_TABLE_NORMAL; psFscInfo->sFscRunningInfo.u8FanTableLoadStatus = FSC_FAN_TABLE_LOAD_FAIL; psFscInfo->sFscRunningInfo.u8LoadTableTries = 0; return FUNC_FAILED; } } else { psFscInfo->sFscRunningInfo.u8UpdateFlag = FSC_FAN_TABLE_NORMAL; psFscInfo->sFscRunningInfo.u8FanTableLoadStatus = FSC_FAN_TABLE_LOAD_SUCCESS; return FUNC_OK; } } return FUNC_OK; } EFuncRetCode LuxPDKGetPSGood() { FILE* fp = NULL; char acCmdbuff[512] = {0}; char acCmdstr[1024] = {0}; unsigned long value = 0; LuxSprintf(acCmdstr, "devmem 0x1e780088"); if ((fp = LuxPopen(acCmdstr, "r")) != NULL) { fgets(acCmdbuff, sizeof(acCmdbuff), fp); value = strtoul(acCmdbuff, NULL, 16); LuxPclose(fp); if ((value & 0x2000) > 0) { return PS_GOOD_OK; } else { return PS_GOOD_FAIL; } } else { return FUNC_FAILED; } } EFuncRetCode LuxFSCGetDIMMValue(INT8U u8CPUIndex, INT8U u8DIMMIndex, INT8S* ps8Value, INT8U* pu8Present, INT8U* pu8Status) { FILE* fp = NULL; char acCmdbuff[512] = {0}; char acCmdstr[1024] = {0}; INT8U u8DIMMValue = 0; LuxSprintf(acCmdstr, "peci_cmds raw 0x%x 0x05 0x05 0xa1 0x00 0x0e 0x%x 0x00",(0x30 + u8CPUIndex), u8DIMMIndex); if ((fp = LuxPopen(acCmdstr, "r")) != NULL) { fgets(acCmdbuff, sizeof(acCmdbuff), fp); LuxPclose(fp); unsigned int byteValue = 0; int count = 0; char *token = strtok(acCmdbuff, " "); while (token != NULL) { if (count == 0) { sscanf(token, "%x", &byteValue); *pu8Status = (INT8U)byteValue; } if (count == 2) { sscanf(token, "%x", &byteValue); u8DIMMValue = (INT8U)byteValue; if(u8DIMMValue != 0) { *pu8Present = FSC_SENSOR_PRESENT; } else { *pu8Present = FSC_SENSOR_NOT_PRESENT; } break; } count++; token = strtok(NULL, " "); } *ps8Value = u8DIMMValue; } else { return FUNC_FAILED; } } EFuncRetCode LuxFSCGetCPUValue(INT8U u8CPUIndex, INT8S* ps8Value, INT8U* pu8Present, INT8U* pu8Status) { FILE *fp = NULL; char command[256]; char output[256]; float temperature = 0; char tempStr[255] = {0}; sprintf(command, "peci_cmds -a 0x%x GetTemp", (0x30 + u8CPUIndex)); if ((fp = popen(command, "r")) != NULL) { if (fgets(output, sizeof(output), fp) != NULL) { if (sscanf(output, "%*s (%fC)", &temperature) == 1) { // change temperature to int if (temperature < -128 || temperature > 127) { LuxPrintf("Temperature out of range for INT8U.\n"); pclose(fp); return FUNC_FAILED; } pclose(fp); *ps8Value = (INT8S)temperature; *pu8Present = FSC_SENSOR_PRESENT; return FUNC_OK; } else { LuxPrintf("Failed to parse temperature.\n"); pclose(fp); return FUNC_FAILED; } } else { pclose(fp); return FUNC_FAILED; } } else { LuxPrintf("Failed to execute command.\n"); return FUNC_FAILED; } } EFuncRetCode LuxFSCGetSensorStatus(SFscInfo* psFscInfo) { INT8U u8SensorIndex = 0; INT8U u8SensorNumber = 0; INT8U u8ReadingIndex = 0; double dSensorReading = 0; INT8U u8Status = 0; INT8U u8Present = 0; double dGroupAMaxTemp = 0; double dGroupAMinTemp = 0; double dGroupBMaxTemp = 0; double dGroupBMinTemp = 0; double dGroupCMaxTemp = 0; double dGroupCMinTemp = 0; double dGroupDMaxTemp = 0; double dGroupDMinTemp = 0; /*Get closeloop sensor status and reading */ for(u8SensorIndex = 0; u8SensorIndex < psFscInfo->sFscCLSensor.u8TotalCLSensor ; u8SensorIndex++) { /*CPU0 DIMM temperature */ dSensorReading = 0; u8Present = FSC_SENSOR_NOT_PRESENT; u8Status = FSC_SENSOR_NORMAL; if(u8SensorIndex < 24) { LuxFSCDbusGetDIMMValue(sSDIMMDbus[u8SensorIndex].acDbusPath, &dSensorReading, &u8Present, &u8Status); if(u8SensorIndex < 6) { if(dSensorReading != 0) { if(dGroupAMaxTemp < dSensorReading) { dGroupAMaxTemp = dSensorReading; psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[0] = dGroupAMaxTemp; } } } else if(u8SensorIndex < 12) { if(dSensorReading != 0) { if(dGroupBMaxTemp < dSensorReading) { dGroupBMaxTemp = dSensorReading; psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[1] = dGroupBMaxTemp; } } } else if(u8SensorIndex < 18) { if(dSensorReading != 0) { if(dGroupCMaxTemp < dSensorReading) { dGroupCMaxTemp = dSensorReading; psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[2] = dGroupCMaxTemp; } } } else if(u8SensorIndex < 24) { if(dSensorReading != 0) { if(dGroupDMaxTemp < dSensorReading) { dGroupDMaxTemp = dSensorReading; psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[3] = dGroupDMaxTemp; } } } } else { LuxFSCDbusGetCPUValue(sSCPUDbus[u8SensorIndex - MAX_DIMM_SLOT].acDbusPath, &dSensorReading, &u8Present, &u8Status); } /*Closeloop sensor need save the all real value. */ for(u8ReadingIndex = 0; u8ReadingIndex < MAX_READING_CACHE; u8ReadingIndex++) { if(SENSOR_REAL_VALUE_INITIAL == psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[u8ReadingIndex]) { psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[u8ReadingIndex] = dSensorReading; break; } } if(MAX_READING_CACHE == u8ReadingIndex) { for(u8ReadingIndex = 0; u8ReadingIndex < MAX_READING_CACHE; u8ReadingIndex++) { if(u8ReadingIndex < (MAX_READING_CACHE - 1)) { psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[u8ReadingIndex] = psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[u8ReadingIndex + 1]; } else { psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[MAX_READING_CACHE-1] = dSensorReading; } } } //psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8SensorStatus = psVolatileSensorZone->asLuxSensorInfo[u8SensorNumber].SensorInfo.EventFlags; //psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8Health = psVolatileSensorZone->asLuxSensorInfo[u8SensorNumber].SensorInfo.HealthLevel; psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8Present = u8Present; } return FUNC_OK; } EFuncRetCode LuxFSCGetTruePID(SFscCLSensorInfo* psFscCLSensorInfo, INT8U u8CLSensorESection, INT8U u8CLSensorECSection) { INT8U u8EIndex = 0; INT8U u8ECIndex = 0; INT8S s8E = 0; INT8S s8EC = 0; /*E = current_reading - setpoint */ s8E = psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE-1] - psFscCLSensorInfo->s8Setpoint; /*EC = current_reading - last_reading */ s8EC = psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE-1] - psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE-2]; /*get true pid parameter by query e and ec value */ for(u8ECIndex = 0; u8ECIndex < (u8CLSensorECSection - 1); u8ECIndex++) { if(psFscCLSensorInfo->as8ECValue[u8ECIndex] < s8EC) { continue; } else { /*LuxPrintf("find the EC section, u8ECIndex = %d\n",u8ECIndex);*/ break; } } if((u8CLSensorECSection - 1) == u8ECIndex) { /*LuxPrintf("EC chose the max\n");*/ u8ECIndex = (u8CLSensorECSection - 1); } for(u8EIndex = 0; u8EIndex < (u8CLSensorESection - 1); u8EIndex++) { if(psFscCLSensorInfo->as8EValue[u8EIndex] < s8E) { continue; } else { /*LuxPrintf("find the E section, u8EIndex = %d\n",u8EIndex);*/ break; } } if((u8CLSensorESection - 1) == u8EIndex) { /*LuxPrintf("E chose the max\n");*/ u8EIndex = (u8CLSensorESection - 1); } psFscCLSensorInfo->fP = psFscCLSensorInfo->afPValue[u8ECIndex][u8EIndex]; psFscCLSensorInfo->fI = psFscCLSensorInfo->afIValue[u8ECIndex][u8EIndex]; psFscCLSensorInfo->fI = 5; psFscCLSensorInfo->fD = psFscCLSensorInfo->afDValue[u8ECIndex][u8EIndex]; return FUNC_OK; } EFuncRetCode LuxFSCGetSetpointCase(SFscCLSensorInfo* psFscCLSensorInfo) { /*TBD */ if(0) { psFscCLSensorInfo = psFscCLSensorInfo; } return FUNC_OK; } EFuncRetCode LuxFSCGetTureSetpoint(SFscCLSensorInfo* psFscCLSensorInfo, INT8U u8SensorIndex) { INT8U u8SetpointCase = 0; INT8S s8Setpoint = 0; /* Search setpoint */ if(0 == LuxStrncmp(psFscCLSensorInfo->acSetpointType, SETPOINT_CONSTANT, LuxStrlen(SETPOINT_CONSTANT))) { if(u8SensorIndex < MAX_DIMM_SLOT) { if(FUNC_FAILED == LuxFSCGetSetpointFromFile(&s8Setpoint)) { psFscCLSensorInfo->s8Setpoint = psFscCLSensorInfo->s8SetpointDefault; } else { psFscCLSensorInfo->s8Setpoint = s8Setpoint; } } else { psFscCLSensorInfo->s8Setpoint = psFscCLSensorInfo->s8SetpointDefault; } } else if(0 == LuxStrncmp(psFscCLSensorInfo->acSetpointType, SETPOINT_VARIABLE, LuxStrlen(SETPOINT_VARIABLE))) { /*get variable setpoint sensor's case use*/ LuxFSCGetSetpointCase(psFscCLSensorInfo); for(u8SetpointCase = 0; u8SetpointCase < MAX_SETPOINT_CASE; u8SetpointCase++) { if(0 == LuxStrncmp(psFscCLSensorInfo->acSetpointCaseUse, psFscCLSensorInfo->acSetpointCase[u8SetpointCase], LuxStrlen(psFscCLSensorInfo->acSetpointCaseUse))) { /*find the setpoint define*/ psFscCLSensorInfo->s8Setpoint = psFscCLSensorInfo->as8SetpointValue[u8SetpointCase]; break; } } if(u8SetpointCase == MAX_SETPOINT_CASE) { /*Can't find setpoint define, use default setpoint*/ psFscCLSensorInfo->s8Setpoint = psFscCLSensorInfo->s8SetpointDefault; } } else { /*setpoint type is not correct, use default setpoint*/ psFscCLSensorInfo->s8Setpoint = psFscCLSensorInfo->s8SetpointDefault; } return FUNC_OK; } EFuncRetCode LuxFSCCloseloopCalculateDuty(SFscCLSensorInfo* psFscCLSensorInfo, INT8U u8MaxPwm, INT8U u8MinPwm) { double dReadingT = 0; double dReadingT1 = 0; double dReadingT2 = 0; double dPIncrement = 0; double fIIncrement = 0; double fDIncrement = 0; INT8U u8Pwm = 0; INT8U u8FanIndex=0; INT8U u8HysteresisIndex = 0; INT16S s16PwmSum = 0; float fPWMIncrease = 0; /*get last three sensor readings */ dReadingT = psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE - 3]; dReadingT1 = psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE - 2]; dReadingT2 = psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE - 1]; /*calculate pwm by PID formula */ dPIncrement = (float)(psFscCLSensorInfo->fP * (dReadingT2 - dReadingT1)); fIIncrement = (float)(psFscCLSensorInfo->fI * (dReadingT2 - psFscCLSensorInfo->s8Setpoint)); fDIncrement = (float)(psFscCLSensorInfo->fD * (dReadingT2 + dReadingT - 2*dReadingT1)); fPWMIncrease = dPIncrement + fIIncrement + fDIncrement; if((psFscCLSensorInfo->s16LastPwmPIDCalculate + fPWMIncrease) < 0) { u8Pwm = 0; } else if((psFscCLSensorInfo->s16LastPwmPIDCalculate + fPWMIncrease) > 100) { u8Pwm = 100; } else { u8Pwm = (INT8U)(psFscCLSensorInfo->s16LastPwmPIDCalculate + fPWMIncrease + 0.5); } psFscCLSensorInfo->dPIncrement = dPIncrement; psFscCLSensorInfo->dIIncrement = fIIncrement; psFscCLSensorInfo->dDIncrement = fDIncrement; /*judge if greater than max pwm */ if(u8Pwm >= u8MaxPwm) { u8Pwm = u8MaxPwm; } /*judge if less than max pwm */ if(u8Pwm <= u8MinPwm) { u8Pwm = u8MinPwm; } psFscCLSensorInfo->u8PwmPIDCalculate = u8Pwm; psFscCLSensorInfo->s16LastPwmPIDCalculate = (INT16S)u8Pwm; /*Calculate pwm after weighting*/ for(u8FanIndex = 0; u8FanIndex < MAX_FSC_PWM_CHANNEL; u8FanIndex++) { psFscCLSensorInfo->u8PwmAfterWeighting[u8FanIndex] = (INT8U)((float)u8Pwm * ((float)psFscCLSensorInfo->au8FanWeight[u8FanIndex] / 100)); } /*Calculate pwm after hysteresis*/ for(u8FanIndex = 0; u8FanIndex < MAX_FSC_PWM_CHANNEL; u8FanIndex++) { if(psFscCLSensorInfo->u32CalculateTick < (MAX_FAN_AVERAGE_COUNT-1)) { psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][psFscCLSensorInfo->u32CalculateTick] = psFscCLSensorInfo->u8PwmAfterWeighting[u8FanIndex]; } else { if(MAX_FAN_AVERAGE_COUNT == psFscCLSensorInfo->u32CalculateTick) { psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][MAX_FAN_AVERAGE_COUNT-1] = psFscCLSensorInfo->u8PwmAfterWeighting[u8FanIndex]; } else { for(u8HysteresisIndex = 0; u8HysteresisIndex < (MAX_FAN_AVERAGE_COUNT - 1); u8HysteresisIndex++) { psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][u8HysteresisIndex] = psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][u8HysteresisIndex+1]; } psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][MAX_FAN_AVERAGE_COUNT-1] = psFscCLSensorInfo->u8PwmAfterWeighting[u8FanIndex]; } s16PwmSum = 0; if(psFscCLSensorInfo->u8Hysteresis != 0) { for(u8HysteresisIndex = 0; u8HysteresisIndex < psFscCLSensorInfo->u8Hysteresis; u8HysteresisIndex++) { s16PwmSum += psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][MAX_FAN_AVERAGE_COUNT-1-u8HysteresisIndex]; } psFscCLSensorInfo->u8PwmAfterHysteresis[u8FanIndex] = s16PwmSum / psFscCLSensorInfo->u8Hysteresis; } else { psFscCLSensorInfo->u8PwmAfterHysteresis[u8FanIndex] = psFscCLSensorInfo->u8PwmAfterWeightingCache[u8FanIndex][(MAX_FAN_AVERAGE_COUNT - 1)]; } } } psFscCLSensorInfo->u32CalculateTick ++; return FUNC_OK; } EFuncRetCode LuxFSCHandleCloseloop(SFscInfo* psFscInfo) { INT8U u8SensorIndex = 0; SFscCLSensorInfo* psFscCLSensorInfo = NULL; INT32U u32Tick = 0; u32Tick = psFscInfo->sFscRunningInfo.u32Tick; for(u8SensorIndex = 0; u8SensorIndex < psFscInfo->sFscCLSensor.u8TotalCLSensor; u8SensorIndex++) { psFscCLSensorInfo = &psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex]; if(0 != LuxStrncmp(psFscCLSensorInfo->acCLSensorStatus, "Enable", LuxStrlen("Enable"))) { /*LuxPrintf("Closeloop sensor %s is not enable, skip\n",psFscCLSensorInfo->acSensorName);*/ psFscCLSensorInfo->u8PwmPIDCalculate = 0; continue; } /*every sensor has it's polling cycles */ if(0 == (u32Tick % psFscCLSensorInfo->u8DT)) { if(FSC_SENSOR_NOT_PRESENT == psFscCLSensorInfo->u8Present) { /*no need to do fsc control if sensor is not present */ /*LuxPrintf("Sensor %s no need to do fsc control because sensor is not preset\n",psFscCLSensorInfo->acSensorName);*/ psFscCLSensorInfo->u8PwmPIDCalculate=0; continue; } /*if sensor status is abnormal, skip calculate pwm. Abnormal event handle it. */ if(FSC_SENSOR_ABNORMAL == psFscCLSensorInfo->u8Abnormal) { /*LuxPrintf("Sensor %s is abnormal, skip.\n",psFscCLSensorInfo->acSensorName);*/ psFscCLSensorInfo->u8PwmPIDCalculate = 0; continue; } /*Closeloop sensor cache reading need >= 3, because PID need sensor reading at t-2, t-1, t. if buffer is not full, skip*/ if(SENSOR_REAL_VALUE_INITIAL == psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE - 1]) { /*LuxPrintf("Sensor %s reading cache is less than 3, skip.\n",psFscCLSensorInfo->acSensorName);*/ psFscCLSensorInfo->u8PwmPIDCalculate = 0; continue; } /*lookup true setpoint */ LuxFSCGetTureSetpoint(psFscCLSensorInfo, u8SensorIndex); /*lookup true PID parameter from e and ec array */ LuxFSCGetTruePID(psFscCLSensorInfo, psFscInfo->sFscCLSensor.u8CLSensorESection, psFscInfo->sFscCLSensor.u8CLSensorECSection); /*do openloop sensor pwm calculate */ LuxFSCCloseloopCalculateDuty(psFscCLSensorInfo, psFscInfo->sFscFanConfig.u8MaxFanDuty, psFscInfo->sFscFanConfig.u8MinFanDuty); } else { continue; } } return FUNC_OK; } EFuncRetCode LuxSetCPLDPTCHeatPWM(INT8U u8PwmNumber, INT8U u8PTCPWM) { char acCmdbuff[512] = {0}; EFuncRetCode eRet; LuxSprintf(acCmdbuff, "i2ctransfer -y -a %d w3@0x%x 0x%x 0x00 0x%x",FCB_I2C_BUS, \ FCB_CPLD_SLAVE_ADDR, (REG_FCB_PTC_DIMM0_SET_PWM + u8PwmNumber), u8PTCPWM); LuxPrintf("LuxSetPTCHeatPWM : %s\n",acCmdbuff); eRet = LuxSystem(acCmdbuff); return eRet; } EFuncRetCode LuxSetCPLDPWM(INT8U u8PwmNumber, INT8U u8DutycycleValue) { INT8U au8WriteData[32] = {0}; INT8U u8WriteLen = 0; INT8U au8ReadBuf[32] = {0}; INT8U u8ReadLen = 0; au8WriteData[0] = sSFscFanReg[u8PwmNumber - MAX_MB_PWM_CHANNEL].u16Reg; au8WriteData[1] = 0x00; au8WriteData[2] = u8DutycycleValue; u8WriteLen = 3; if(FUNC_FAILED == i2cReadWrite(FCB_I2C_BUS, FCB_CPLD_SLAVE_ADDR, au8WriteData, u8WriteLen, au8ReadBuf, u8ReadLen)) { LuxPrintf("Set DIMM Fan Write FCB data fail\n"); return FUNC_FAILED; } else { //LuxPrintf("Set DIMM Fan Write CPLD Reg 0x%x Data 0x%x \n",au8WriteData[0], u8DutycycleValue); } return FUNC_OK; } EFuncRetCode LuxSetCPLD6056FanPWM(INT8U u8PwmNumber, INT8U u8DutycycleValue) { INT8U au8WriteData[32] = {0}; INT8U u8WriteLen = 0; INT8U au8ReadBuf[32] = {0}; INT8U u8ReadLen = 0; au8WriteData[0] = sFsc6056FanReg[u8PwmNumber].u16Reg; au8WriteData[1] = 0x00; au8WriteData[2] = u8DutycycleValue; u8WriteLen = 3; if(FUNC_FAILED == i2cReadWrite(FCB_I2C_BUS, FCB_CPLD_SLAVE_ADDR, au8WriteData, u8WriteLen, au8ReadBuf, u8ReadLen)) { LuxPrintf("Set 6056 Fan Write FCB data fail\n"); return FUNC_FAILED; } else { //LuxPrintf("Set 6056 Fan Write CPLD Reg 0x%x Data 0x%x \n",au8WriteData[0], u8DutycycleValue); } if(0 == u8PwmNumber) { /*CPU0 A-F 6056 fan */ LuxSetCPLDPWM(5, u8DutycycleValue); LuxSetCPLDPWM(6, u8DutycycleValue); LuxSetCPLDPWM(7, u8DutycycleValue); LuxSetCPLDPWM(8, u8DutycycleValue); LuxSetCPLDPWM(9, u8DutycycleValue); LuxSetCPLDPWM(10, u8DutycycleValue); } if(1 == u8PwmNumber) { /*CPU0 G-L 6056 fan */ LuxSetCPLDPWM(11, u8DutycycleValue); LuxSetCPLDPWM(12, u8DutycycleValue); LuxSetCPLDPWM(13, u8DutycycleValue); LuxSetCPLDPWM(14, u8DutycycleValue); LuxSetCPLDPWM(15, u8DutycycleValue); LuxSetCPLDPWM(16, u8DutycycleValue); } if(2 == u8PwmNumber) { /*CPU1 A-F 6056 fan */ LuxSetCPLDPWM(17, u8DutycycleValue); LuxSetCPLDPWM(18, u8DutycycleValue); LuxSetCPLDPWM(19, u8DutycycleValue); LuxSetCPLDPWM(20, u8DutycycleValue); LuxSetCPLDPWM(21, u8DutycycleValue); LuxSetCPLDPWM(22, u8DutycycleValue); } if(3 == u8PwmNumber) { /*CPU1 G-L 6056 fan */ LuxSetCPLDPWM(23, u8DutycycleValue); LuxSetCPLDPWM(24, u8DutycycleValue); LuxSetCPLDPWM(25, u8DutycycleValue); LuxSetCPLDPWM(26, u8DutycycleValue); LuxSetCPLDPWM(27, u8DutycycleValue); LuxSetCPLDPWM(28, u8DutycycleValue); } return FUNC_OK; } EFuncRetCode LuxSetMBPWM(INT8U u8PwmNumber, INT8U u8DutycycleValue) { char acCmdbuff[512] = {0}; EFuncRetCode eRet; /*MB pwm need change max 100 to max 255 */ u8DutycycleValue *= 2.55; LuxSprintf(acCmdbuff, "echo %d > /sys/class/hwmon/hwmon0/pwm%d",u8DutycycleValue,(2 + u8PwmNumber)); eRet = LuxSystem(acCmdbuff); return eRet; } EFuncRetCode LuxFSCOutputPWM(INT8U u8PwmChannel, INT8U u8Pwm) { if(u8Pwm >= 100) { u8Pwm = 100; } if(u8PwmChannel < MAX_MB_PWM_CHANNEL) { /*In mobile project, pwm 4 and pwm 5 is for liquid. force set to 100% */ if((3 == u8PwmChannel) || (4 == u8PwmChannel)) { u8Pwm = 100; } else { if(u8Pwm < CPU_FAN_MIN_PWM) { u8Pwm = CPU_FAN_MIN_PWM; } } if(FUNC_FAILED == LuxSetMBPWM(u8PwmChannel, u8Pwm)) { LuxPrintf("Set MB pwm %d dutycycle to %d failed\n",u8PwmChannel, u8Pwm); return FUNC_FAILED; } } else { //LuxPrintf("u8MaxCoverTemp = %d\n",psFscInfo.sFscRunningInfo.u8MaxCoverTemp); //LuxPrintf("u16DIMMTotalPower = %d\n",psFscInfo.sFscRunningInfo.u16DIMMTotalPower); //LuxPrintf("u8MaxDIMMSensorTemp = %d\n",psFscInfo.sFscRunningInfo.u8MaxDIMMSensorTemp); //LuxPrintf("psFscInfo.sFscCLSensor.asFscCLSensorInfo[0].s8Setpoint = %d\n",psFscInfo.sFscCLSensor.asFscCLSensorInfo[0].s8Setpoint); if(60 <= psFscInfo.sFscCLSensor.asFscCLSensorInfo[0].s8Setpoint) { #if 0 if((psFscInfo.sFscRunningInfo.u8MaxCoverTemp < 60) && (psFscInfo.sFscRunningInfo.u16DIMMTotalPower < 150) && (psFscInfo.sFscRunningInfo.u8MaxDIMMSensorTemp < 68)) { //LuxPrintf("Because Cover sensor temperature is very low, set DIMM fan to 0\n"); u8Pwm = 0; } else { if(u8Pwm < DIMM_FAN_MIN_PWM) { u8Pwm = DIMM_FAN_MIN_PWM; } } #endif if(u8Pwm < DIMM_FAN_MIN_PWM) { u8Pwm = DIMM_FAN_MIN_PWM; } } if(0 == g_u8FSCEnable) { u8Pwm = 0; } #if 0 if(TRUE == g_u8FSCPresent) { if(FUNC_FAILED == LuxSetCPLDPWM(u8PwmChannel, u8Pwm)) { LuxPrintf("Set FCB CPLD pwm %d dutycycle to %d failed\n",u8PwmChannel, u8Pwm); return FUNC_FAILED; } } #endif } return FUNC_OK; } EFuncRetCode LuxFSCManualOutputPWM(INT8U u8PwmChannel, INT8U u8Pwm) { if(u8PwmChannel < MAX_MB_PWM_CHANNEL) { if(FUNC_FAILED == LuxSetMBPWM(u8PwmChannel, u8Pwm)) { LuxPrintf("Manual set MB pwm %d dutycycle to %d failed\n",u8PwmChannel, u8Pwm); return FUNC_FAILED; } } else { if(TRUE == g_u8FSCPresent) { if(FUNC_FAILED == LuxSetCPLDPWM(u8PwmChannel, u8Pwm)) { LuxPrintf("Manual set FCB CPLD pwm %d dutycycle to %d failed\n",u8PwmChannel, u8Pwm); return FUNC_FAILED; } } } return FUNC_OK; } EFuncRetCode LuxFSCCoverPreHeat(SFscInfo* psFscInfo) { INT8U u8DIMMIndex = 0; for(u8DIMMIndex = 0; u8DIMMIndex < MAX_DIMM_SLOT; u8DIMMIndex++) { LuxSetCPLDPTCHeatPWM(u8DIMMIndex, PTC_PRE_HEAT_PWM); } return FUNC_OK; } EFuncRetCode LuxFSCHandlePwmOut(SFscInfo* psFscInfo) { INT8U u8SensorIndex = 0; INT8U u8PwmIndex = 0; INT8U u8OLPwm = 0; INT8U u8AbnormalPwm = 0; INT8U u8AbnormalSensorIncreasePwm = 0; INT8U u8IncreasePwm[MAX_FSC_PWM_CHANNEL] = {0}; INT8U au8CLPwm[MAX_FSC_PWM_CHANNEL] = {0}; INT8U au8PwmTemp[MAX_FSC_PWM_CHANNEL] = {0}; char acOLMaxPwmSensorName[MAX_SENSOR_NAME_LENGTH] = {0}; char acCLMaxPwmSensorName[MAX_SENSOR_NAME_LENGTH] = {0}; char acMaxAbnormalPwmSensorName[MAX_SENSOR_NAME_LENGTH] = {0}; /*step 1, get closeloop sensor pwm output */ for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { for(u8SensorIndex = 0; u8SensorIndex < psFscInfo->sFscCLSensor.u8TotalCLSensor; u8SensorIndex++) { if(psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8PwmAfterHysteresis[u8PwmIndex] > au8CLPwm[u8PwmIndex]) { au8CLPwm[u8PwmIndex] = psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8PwmAfterHysteresis[u8PwmIndex]; LuxMemset(acCLMaxPwmSensorName, 0, MAX_SENSOR_NAME_LENGTH); memcpy(acCLMaxPwmSensorName, psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].acSensorName, \ LuxStrlen(psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].acSensorName)); } } } LuxMemcpy(psFscInfo->sFscRunningInfo.au8CLPwm,au8CLPwm, MAX_FSC_PWM_CHANNEL); /*step 2, output auto pwm */ for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex] = psFscInfo->sFscRunningInfo.au8CLPwm[u8PwmIndex]; if(psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex] > psFscInfo->sFscFanConfig.u8MaxFanDuty) { psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex] = psFscInfo->sFscFanConfig.u8MaxFanDuty; } if(psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex] < psFscInfo->sFscFanConfig.u8MinFanDuty) { psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex] = psFscInfo->sFscFanConfig.u8MinFanDuty; } LuxFSCOutputPWM(u8PwmIndex, psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex]); } return FUNC_OK; } EFuncRetCode LuxFSCHandleCoverHeat(SFscInfo* psFscInfo) { #if 0 INT8U u8DIMMIndex = 0; SFscCLSensorInfo* psFscCLSensorInfo = NULL; for(u8DIMMIndex = 0; u8DIMMIndex < MAX_DIMM_SLOT; u8DIMMIndex++) { psFscCLSensorInfo = &psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8DIMMIndex]; /*if DIMM temperature lower than setpoint, need turn on heat*/ if(psFscCLSensorInfo->as8RealValue[MAX_READING_CACHE-1] < psFscCLSensorInfo->s8Setpoint) { LuxSetCPLDPTCHeatPWM(u8DIMMIndex, PTC_PRE_HEAT_MAX_PWM); } else { LuxSetCPLDPTCHeatPWM(u8DIMMIndex, PTC_PRE_HEAT_MIN_PWM); } } #endif return FUNC_OK; } EFuncRetCode LuxFSCHandleThermalDebug(SFscInfo* psFscInfo) { INT8U u8PwmIndex = 0; INT8U u8SensorIndex = 0; /*check if thermal debug message opened */ psFscInfo->sFscRunningInfo.u8ThermalDebug = FSC_OPEN_THERMAL_DEBUG; if(FSC_OPEN_THERMAL_DEBUG == psFscInfo->sFscRunningInfo.u8ThermalDebug) { LuxPrintf("\t************************ Thermal Debug **********************\n"); LuxPrintf("\tpsFscInfo->sFscRunningInfo.u8ControlMode = %d\n",psFscInfo->sFscRunningInfo.u8ControlMode); LuxPrintf("\tCloseloop:\n"); for(u8SensorIndex = 0; u8SensorIndex < psFscInfo->sFscCLSensor.u8TotalCLSensor; u8SensorIndex++) { LuxPrintf("\tCloseloop sensor %d name: %s\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].acSensorName); LuxPrintf("\tCloseloop sensor %d number: 0x%x\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8SensorNumber); LuxPrintf("\tCloseloop sensor %d u8Present: %d\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8Present); LuxPrintf("\tCloseloop sensor %d u8Abnormal: %d\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8Abnormal); LuxPrintf("\tCloseloop sensor %d u8Health: %d\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8Health); LuxPrintf("\tCloseloop sensor %d s8Setpoint: %d\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].s8Setpoint); LuxPrintf("\tCloseloop sensor %d p: %f\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].fP); LuxPrintf("\tCloseloop sensor %d i: %f\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].fI); LuxPrintf("\tCloseloop sensor %d d: %f\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].fD); LuxPrintf("\tCloseloop sensor %d reading: %lf,%lf,%lf\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[MAX_READING_CACHE - 3],\ psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[MAX_READING_CACHE - 2],\ psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[MAX_READING_CACHE - 1]); LuxPrintf("\tCloseloop sensor %d s16LastPwmPIDCalculate: %d\n\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].s16LastPwmPIDCalculate); LuxPrintf("\tCloseloop sensor %d fPIncrement: %lf\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].dPIncrement); LuxPrintf("\tCloseloop sensor %d fIIncrement: %lf\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].dIIncrement); LuxPrintf("\tCloseloop sensor %d fDIncrement: %lf\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].dDIncrement); LuxPrintf("\tCloseloop sensor %d u8PwmPIDCalculate: %d\n",(u8SensorIndex+1), psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8PwmPIDCalculate); LuxPrintf("\tCloseloop sensor %d u8PwmAfterWeighting:",(u8SensorIndex+1)); for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { LuxPrintf("%d ",psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8PwmAfterWeighting[u8PwmIndex]); } LuxPrintf("\n"); LuxPrintf("\tCloseloop sensor %d u8PwmAfterHysteresis:",(u8SensorIndex+1)); for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { LuxPrintf("%d ",psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8PwmAfterHysteresis[u8PwmIndex]); } LuxPrintf("\n"); LuxPrintf("\tCloseloop sensor %d u8PwmAfterHysteresis:",(u8SensorIndex+1)); for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { LuxPrintf("%d ",psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].u8PwmAfterHysteresis[u8PwmIndex]); } LuxPrintf("\n\n"); } LuxPrintf("\tFinally output:\n"); for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { LuxPrintf("\tpwm channel %d output: %d\n",u8PwmIndex,psFscInfo->sFscRunningInfo.au8PwmOut[u8PwmIndex]); } for(u8PwmIndex = 0; u8PwmIndex < MAX_FSC_PWM_CHANNEL; u8PwmIndex++) { //LuxPrintf("\tManual output: %d\n",psFscInfo->sFscRunningInfo.au8ManualPwmOut[u8PwmIndex]); } } return FUNC_OK; } EFuncRetCode LuxPrintDIMMTemp(SFscInfo* psFscInfo) { INT8U u8PwmIndex = 0; INT8U u8SensorIndex = 0; /*check if thermal debug message opened */ psFscInfo->sFscRunningInfo.u8ThermalDebug = FSC_OPEN_THERMAL_DEBUG; if(FSC_OPEN_THERMAL_DEBUG == psFscInfo->sFscRunningInfo.u8ThermalDebug) { LuxPrintf("\t************************ DIMM Temperature Print **********************\n"); for(u8SensorIndex = 0; u8SensorIndex < 24; u8SensorIndex++) { LuxPrintf("\tDIMM Temp sensor %d reading: %d\n",(u8SensorIndex+1),psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8SensorIndex].as8RealValue[MAX_READING_CACHE - 1]); } } LuxPrintf("\n\n"); return FUNC_OK; } EFuncRetCode LuxFSCGetEnableStatus(INT8U* pu8Value) { FILE* fp = NULL; char acCmdbuff[512] = {0}; char acCmdstr[1024] = {0}; INT8U u8Value = 0; if(0 != LuxAccess(FSC_ENABLE_STATUS_PATH, F_OK)) { return FUNC_FAILED; } LuxSprintf(acCmdstr, "cat %s",FSC_ENABLE_STATUS_PATH); if ((fp = LuxPopen(acCmdstr, "r")) != NULL) { fgets(acCmdbuff, sizeof(acCmdbuff), fp); u8Value = strtoul(acCmdbuff, NULL, 10); LuxPclose(fp); if (u8Value > 1) { return FUNC_FAILED; } else { *pu8Value = (INT8U)u8Value; return FUNC_OK; } } else { return FUNC_FAILED; } return FUNC_OK; } EFuncRetCode LuxCheckFCBPresent() { INT8U au8WriteData[32] = {0}; INT8U u8WriteLen = 0; INT8U au8ReadBuf[32] = {0}; INT8U u8ReadLen = 0; au8WriteData[0] = 0x05; au8WriteData[1] = 0x00; u8WriteLen = 2; u8ReadLen = 1; if(FUNC_FAILED == i2cReadWrite(FCB_I2C_BUS, FCB_CPLD_SLAVE_ADDR, au8WriteData, u8WriteLen, au8ReadBuf, u8ReadLen)) { LuxPrintf("FCB is not present!!!\n"); return FUNC_FAILED; } else { LuxPrintf("FCB is present.\n"); } return FUNC_OK; } EFuncRetCode LuxFSCGetDIMMTotalPower(SFscInfo* psFscInfo) { INT8U u8SensorIndex = 0; double dSensorReading = 0; INT8U u8Status = 0; INT8U u8Present = 0; INT16U u16Power = 0; for(u8SensorIndex = 0; u8SensorIndex < MAX_DIMM_POWER_SLOT; u8SensorIndex++) { LuxFSCDbusGetDIMMPowerValue(sSDIMMPowerDbus[u8SensorIndex].acDbusPath, &dSensorReading, &u8Present, &u8Status); //LuxPrintf("DIMMPower %d u8Power = %d\n",u8SensorIndex,s8SensorReading); u16Power += (INT16U)dSensorReading; } psFscInfo->sFscRunningInfo.u16DIMMTotalPower = u16Power; //LuxPrintf("u8Power = %d\n",u16Power); return FUNC_OK; } EFuncRetCode LuxFSCHandle6056Fan(SFscInfo* psFscInfo) { INT8U u85056FanIndex = 0; INT8U u8PwmChannel = 0; INT8U u8Pwm = 0; INT8U u8DIMMSensorIndex = 0; INT8U u8MaxDIMMSensorTemp = 0; for(u8DIMMSensorIndex = 0; u8DIMMSensorIndex < MAX_DIMM_SLOT; u8DIMMSensorIndex++) { if(u8MaxDIMMSensorTemp < psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8DIMMSensorIndex].as8RealValue[MAX_READING_CACHE - 1]) { u8MaxDIMMSensorTemp = psFscInfo->sFscCLSensor.asFscCLSensorInfo[u8DIMMSensorIndex].as8RealValue[MAX_READING_CACHE - 1]; } } //LuxPrintf("u8MaxDIMMSensorTemp = %d\n",u8MaxDIMMSensorTemp); psFscInfo->sFscRunningInfo.u8MaxDIMMSensorTemp = u8MaxDIMMSensorTemp; /*if DIMM setpoint if 40, need 6056 fan 100% pwm output */ for(u8PwmChannel = 0; u8PwmChannel < FCB_6056_FAN_NUM; u8PwmChannel++) { //LuxPrintf("6056 fan %d DIMMGroup Temp = %d\n",u8PwmChannel, psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[3 - u8PwmChannel]); if(40 == psFscInfo->sFscCLSensor.asFscCLSensorInfo[0].s8Setpoint) { if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] >= 45) { u8Pwm = 100; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] >= 44) { u8Pwm = 95; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] >= 43) { u8Pwm = 90; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] >= 42) { u8Pwm = 85; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] >= 41) { u8Pwm = 80; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] >= 36) { u8Pwm = 70; } else { u8Pwm = 60; } } else { if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] > 78) { u8Pwm = 100; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] > 77) { u8Pwm = 90; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] > 76) { u8Pwm = 80; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] > 75) { u8Pwm = 60; } else if(psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[u8PwmChannel] > 74) { u8Pwm = 30; } else { u8Pwm = 10; } } if(0 == g_u8FSCEnable) { u8Pwm = 0; } if(TRUE == g_u8FSCPresent) { if(FUNC_FAILED == LuxSetCPLD6056FanPWM(u8PwmChannel, u8Pwm)) { LuxPrintf("Set FCB 6056 fan pwm %d dutycycle to %d failed\n",u8PwmChannel, u8Pwm); return FUNC_FAILED; } } } return FUNC_OK; } void get_timestamp(char *buffer, size_t size) { time_t now = time(NULL); struct tm *tm_info = localtime(&now); strftime(buffer, size, "%Y-%m-%d %H:%M:%S", tm_info); } EFuncRetCode LuxFSCGetCoverTemp(INT8U* pu8Value, INT8U* pu8Present, INT8U* pu8Status) { INT8U au8WriteData[32] = {0}; INT8U u8WriteLen = 0; INT8U au8ReadBuf[32] = {0}; INT8U u8ReadLen = 0; INT8U u8CoverTempSensorIndex = 0; INT8U u8SensorTemp = 0; INT8U u8CoverMaxTemp = 0; FILE* fp = NULL; char timestamp[64]; get_timestamp(timestamp, sizeof(timestamp)); fp = fopen("/home/root/cover_temp.log", "a"); if(NULL == fp) { LuxPrintf("Can't open /home/root/cover_temp.log\n"); } for(u8CoverTempSensorIndex = 0; u8CoverTempSensorIndex < 4; u8CoverTempSensorIndex++) { u8SensorTemp = 0; au8WriteData[0] = (u8CoverTempSensorIndex + 1); //TMP468 sensor channel count from 1 u8WriteLen = 1; u8ReadLen = 2; if(FUNC_FAILED == i2cReadWrite(FCB_I2C_BUS, FCB_TMP468_ADDR >> 1, au8WriteData, u8WriteLen, au8ReadBuf, u8ReadLen)) { LuxPrintf("Read Cover TMP468 channel %d fail\n",u8CoverTempSensorIndex); fclose(fp); return FUNC_FAILED; } else { //LuxPrintf("Channel %d read buffer 0x%x 0x%x\n",u8CoverTempSensorIndex+1, au8ReadBuf[0], au8ReadBuf[1]); if(0 == (au8ReadBuf[0] & 0x80)) { u8SensorTemp = (INT8U)((((INT16U)((au8ReadBuf[0] << 8) + au8ReadBuf[1])) >> 3) * 0.0625); fprintf(fp, "%s, Channel %d temp = %d\n",timestamp, u8CoverTempSensorIndex+1, u8SensorTemp); if(u8CoverMaxTemp < u8SensorTemp) { u8CoverMaxTemp = u8SensorTemp; } } } } //LuxPrintf("Max temp = %d\n",u8CoverMaxTemp); fclose(fp); *pu8Value = u8CoverMaxTemp; *pu8Present = TRUE; return FUNC_OK; } EFuncRetCode LuxFSCCoverMaxTemp(SFscInfo* psFscInfo) { INT8U u8DIMMIndex = 0; INT8U u8Status = 0; INT8U u8Present = 0; INT8S s8Temp = 0; if(FUNC_FAILED != LuxFSCGetCoverTemp(&psFscInfo->sFscRunningInfo.u8MaxCoverTemp, &u8Present, &u8Status)) { //LuxPrintf("Cover max temp = %d\n",psFscInfo->sFscRunningInfo.u8MaxCoverTemp); } return FUNC_OK; } int LuxCoverHighTempProtect(SFscInfo* psFscInfo) { if((psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[0] >= DIMM_PROTECT_TEMPERATURE) || (psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[1] >= DIMM_PROTECT_TEMPERATURE) \ || (psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[2] >= DIMM_PROTECT_TEMPERATURE) || (psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[3] >= DIMM_PROTECT_TEMPERATURE)) { if(0 == g_u8DIMMHighTempProtect) { LuxPrintf("DIMM temperature is over 85 degree, power off system!!!\n"); LuxPrintf("DIMM group 0 temp = %f\n",psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[0]); LuxPrintf("DIMM group 1 temp = %f\n",psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[1]); LuxPrintf("DIMM group 2 temp = %f\n",psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[2]); LuxPrintf("DIMM group 3 temp = %f\n",psFscInfo->sFscRunningInfo.u8DIMMGroupMaxTemp[3]); system("ipmitool raw 0 2 0"); g_u8DIMMHighTempProtect = 1; } } } int main(void) { INT32U u32Tick = 0; LuxPrintf("******************************************************************************\n"); LuxPrintf("************************ Luxshare DIMM FSC Task Begin ************************\n"); LuxPrintf("******************************************************************************\n"); INT8U u8TurnOnSystemFlag = 0; INT8U u8PwmChannel = 0; EFuncRetCode eRet; INT8U u8DIMMFSCChannnel = 0; INT8U u8FSC6056Channnel = 0; INT8U u8FSCEnableVaule = 0; LuxFSCInit(); if(FUNC_OK == LuxCheckFCBPresent()) { g_u8FSCPresent = TRUE; } while(1) { usleep(100*1000); /*Check fan table update flag. */ LuxFSCFanTableUpdate(&psFscInfo); /*if fan table load fail, return error */ if(FSC_FAN_TABLE_LOAD_FAIL == psFscInfo.sFscRunningInfo.u8FanTableLoadStatus) { LuxPrintf("Fan table load fail, return error.\n"); return FUNC_FAILED; } /*Check fsc enable status, if not enable by OEM command, don't do dimm fsc logic and turn off 6056*/ eRet = LuxFSCGetEnableStatus(&u8FSCEnableVaule); if((FUNC_FAILED == eRet) || (0 == u8FSCEnableVaule)) { g_u8FSCEnable = 0; } else { g_u8FSCEnable = 1; } LuxFSCGetFSCControlMode(&psFscInfo); /*Check if manual control */ if(FSC_FAN_TABLE_MANUAL == psFscInfo.sFscRunningInfo.u8ControlMode) { for(u8PwmChannel = 0; u8PwmChannel < MAX_FSC_PWM_CHANNEL; u8PwmChannel++) { LuxFSCManualOutputPWM(u8PwmChannel, psFscInfo.sFscRunningInfo.au8ManualPwmOut[u8PwmChannel]); } continue; } /*check if power on in 120 seconds */ if(PS_GOOD_OK == LuxPDKGetPSGood()) { //LuxPrintf("PSGood is on\n"); psFscInfo.sFscRunningInfo.u32Tick ++; if(psFscInfo.sFscRunningInfo.u32Tick < POWERON_FSC_DELAY) { continue; } } else { g_u8DIMMHighTempProtect = 0; continue; } #if 0 if(TRUE == g_u8FSCPresent) { if(TRUE == g_u8FSCEnable) { if(0 == (psFscInfo.sFscRunningInfo.u32Tick % 600)) { LuxFSCCoverMaxTemp(&psFscInfo); } } } #endif LuxFSCGetDIMMTotalPower(&psFscInfo); /*Get sensor status and reading every second */ LuxFSCGetSensorStatus(&psFscInfo); /*Handle closeloop sensor */ LuxFSCHandleCloseloop(&psFscInfo); /*Handle closeloop sensor */ LuxFSCHandle6056Fan(&psFscInfo); /*Handle output pwm */ LuxFSCHandlePwmOut(&psFscInfo); LuxCoverHighTempProtect(&psFscInfo); /*Handle high-temperature Cover heat */ //LuxFSCHandleCoverHeat(&psFscInfo); /*Handle thermal debug */ //LuxFSCHandleThermalDebug(&psFscInfo); //LuxPrintDIMMTemp(&psFscInfo); } return 0; }