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 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); }