int api_ssif_cmd (ipmi_ctx_t ctx, fiid_obj_t obj_cmd_rq, fiid_obj_t obj_cmd_rs) { uint8_t cmd = 0; /* used for debugging */ uint8_t group_extension = 0; /* used for debugging */ uint64_t val; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && ctx->type == IPMI_DEVICE_SSIF && fiid_obj_valid (obj_cmd_rq) && fiid_obj_packet_valid (obj_cmd_rq) == 1 && fiid_obj_valid (obj_cmd_rs)); if (ctx->flags & IPMI_FLAGS_DEBUG_DUMP) { /* ignore error, continue on */ if (FIID_OBJ_GET (obj_cmd_rq, "cmd", &val) < 0) API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq); else cmd = val; if (IPMI_NET_FN_GROUP_EXTENSION (ctx->target.net_fn)) { /* ignore error, continue on */ if (FIID_OBJ_GET (obj_cmd_rq, "group_extension_identification", &val) < 0) API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq); else group_extension = val; } } if (_ssif_cmd_write (ctx, cmd, group_extension, obj_cmd_rq) < 0) return (-1); if (_ssif_cmd_read (ctx, cmd, group_extension, obj_cmd_rs) < 0) return (-1); return (0); }
int debug_hdr_cmd (uint8_t packet_type, uint8_t packet_direction, uint8_t net_fn, uint8_t cmd, uint8_t group_extension, char *hdrbuf, unsigned int hdrbuf_len) { const char *str_cmd; unsigned int packet_flags = 0; if (IPMI_NET_FN_GROUP_EXTENSION (net_fn)) { if (group_extension == IPMI_NET_FN_GROUP_EXTENSION_IDENTIFICATION_DCMI) str_cmd = ipmi_cmd_dcmi_str (cmd); else str_cmd = "Unknown"; packet_flags = DEBUG_UTIL_FLAGS_GROUP_EXTENSION; } else if (IPMI_NET_FN_OEM_GROUP (net_fn)) { str_cmd = "Unknown"; packet_flags = DEBUG_UTIL_FLAGS_OEM_GROUP; } else if (IPMI_NET_FN_CONTROLLER_SPECIFIC_OEM_GROUP (net_fn)) { str_cmd = "Unknown"; packet_flags = DEBUG_UTIL_FLAGS_OEM; } else str_cmd = ipmi_cmd_str (net_fn, cmd); return (debug_hdr_str (packet_type, packet_direction, packet_flags, str_cmd, hdrbuf, hdrbuf_len)); }
int api_ssif_cmd (ipmi_ctx_t ctx, fiid_obj_t obj_cmd_rq, fiid_obj_t obj_cmd_rs) { uint8_t cmd = 0; /* used for debugging */ uint8_t group_extension = 0; /* used for debugging */ uint64_t val; struct timespec request, remain; uint8_t retry = IPMI_SSIF_RETRY_DEFAULT; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && ctx->type == IPMI_DEVICE_SSIF && fiid_obj_valid (obj_cmd_rq) && fiid_obj_packet_valid (obj_cmd_rq) == 1 && fiid_obj_valid (obj_cmd_rs)); if (ctx->flags & IPMI_FLAGS_DEBUG_DUMP) { /* ignore error, continue on */ if (FIID_OBJ_GET (obj_cmd_rq, "cmd", &val) < 0) API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq); else cmd = val; if (IPMI_NET_FN_GROUP_EXTENSION (ctx->target.net_fn)) { /* ignore error, continue on */ if (FIID_OBJ_GET (obj_cmd_rq, "group_extension_identification", &val) < 0) API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq); else group_extension = val; } } if (_ssif_cmd_write (ctx, cmd, group_extension, obj_cmd_rq) < 0) return (-1); /****************************************************************************** 12.9 SMBus NACKs and Error Recovery: ==================================== The BMC can NACK the SMBus host controller if it is not ready to accept a new transaction. Typically, this will be exhibited by the BMC NACK'ing its slave address. If the BMC NACKs a single part transaction, software can simply retry it. If a 'middle' or 'end' transaction is NACK'd, software should not retry the particular but should restart the multi-part read or write from the beginning Start transaction for the transfer. *******************************************************************************/ if (_ssif_cmd_read (ctx, cmd, group_extension, obj_cmd_rs) < 0) { while (1) { request.tv_sec = 0; request.tv_nsec = IPMI_SSIF_TIMEOUT_DEFAULT; if (nanosleep (&request, &remain) < 0 ) return (-1); if (_ssif_cmd_read (ctx, cmd, group_extension, obj_cmd_rs) < 0) { if (retry == 0) return (-1); retry--; } else break; } } return (0); }