int ipmi_kcs_ctx_set_poll_interval (ipmi_kcs_ctx_t ctx, uint8_t poll_interval) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } ctx->poll_interval = poll_interval; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_set_driver_address (ipmi_kcs_ctx_t ctx, uint16_t driver_address) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } ctx->driver_address = driver_address; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_set_register_spacing (ipmi_kcs_ctx_t ctx, uint8_t register_spacing) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } ctx->register_spacing = register_spacing; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_io_init (ipmi_kcs_ctx_t ctx) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (ctx->io_init) goto out; #ifdef __FreeBSD__ #ifdef USE_IOPERM /* i386_set_ioperm has known problems on FBSD 5.x (bus errors). */ if (i386_set_ioperm (ctx->driver_address, 0x02, 0x01)) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); return (-1); } #else /* !USE_IOPERM */ /* Opening /dev/io raises IOPL bits for current process. */ if ((ctx->dev_fd = open ("/dev/io", O_RDONLY)) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); return (-1); } #endif /* !USE_IOPERM */ #else /* !__FreeBSD__ */ #if HAVE_IOPL if (iopl (3) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); return (-1); } #else /* !HAVE_IOPL */ /* otherwise, we always return a system error */ KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_SYSTEM_ERROR); return (-1); #endif /* !HAVE_IOPL */ #endif /* !__FreeBSD__ */ ctx->io_init = 1; out: ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_set_flags (ipmi_kcs_ctx_t ctx, unsigned int flags) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (flags & ~IPMI_KCS_FLAGS_MASK) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); return (-1); } ctx->flags = flags; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_get_register_spacing (ipmi_kcs_ctx_t ctx, uint8_t *register_spacing) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (!register_spacing) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); return (-1); } *register_spacing = ctx->register_spacing; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_get_poll_interval (ipmi_kcs_ctx_t ctx, uint8_t *poll_interval) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (!poll_interval) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); return (-1); } *poll_interval = ctx->poll_interval; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_ctx_get_driver_address (ipmi_kcs_ctx_t ctx, uint16_t *driver_address) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (!driver_address) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); return (-1); } *driver_address = ctx->driver_address; ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (0); }
int ipmi_kcs_cmd (ipmi_kcs_ctx_t ctx, uint8_t lun, uint8_t net_fn, fiid_obj_t obj_cmd_rq, fiid_obj_t obj_cmd_rs) { if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (!IPMI_BMC_LUN_VALID (lun) || !IPMI_NET_FN_RQ_VALID (net_fn) || !fiid_obj_valid (obj_cmd_rq) || !fiid_obj_valid (obj_cmd_rs) || fiid_obj_packet_valid (obj_cmd_rq) <= 0) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); return (-1); } if (!ctx->io_init) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_IO_NOT_INITIALIZED); return (-1); } if (_ipmi_kcs_cmd_write (ctx, lun, net_fn, obj_cmd_rq) < 0) return (-1); if (_ipmi_kcs_cmd_read (ctx, obj_cmd_rs) < 0) return (-1); return (0); }
/* * Main read loop. */ int ipmi_kcs_read (ipmi_kcs_ctx_t ctx, void *buf, unsigned int buf_len) { uint8_t *p = buf; unsigned int count = 0; int rv = -1; if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); goto cleanup; } if (!buf || !buf_len) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); goto cleanup; } if (!ctx->io_init) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_IO_NOT_INITIALIZED); goto cleanup; } if (_ipmi_kcs_wait_for_ibf_clear (ctx) < 0) goto cleanup; if (!_ipmi_kcs_test_if_state (ctx, IPMI_KCS_STATE_READ)) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_BUSY); goto cleanup; } while (_ipmi_kcs_test_if_state (ctx, IPMI_KCS_STATE_READ)) { char c; if (_ipmi_kcs_wait_for_obf_set (ctx) < 0) goto cleanup; c = _ipmi_kcs_read_byte (ctx); if (count < buf_len) { *(p++) = c; count++; } _ipmi_kcs_read_next (ctx); if (_ipmi_kcs_wait_for_ibf_clear (ctx) < 0) goto cleanup; } if (_ipmi_kcs_test_if_state (ctx, IPMI_KCS_STATE_IDLE)) { /* Clean up */ if (_ipmi_kcs_wait_for_obf_set (ctx) < 0) goto cleanup; _ipmi_kcs_read_byte (ctx); /* toss it, ACK */ } else { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_DRIVER_TIMEOUT); goto cleanup; } if (count > buf_len) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_OVERFLOW); goto cleanup; } if (count > INT_MAX) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_OVERFLOW); goto cleanup; } ctx->errnum = IPMI_KCS_ERR_SUCCESS; rv = count; cleanup: if (ctx && ctx->magic == IPMI_KCS_CTX_MAGIC) driver_mutex_unlock (ctx->semid); return (rv); }
int ipmi_kcs_write (ipmi_kcs_ctx_t ctx, const void *buf, unsigned int buf_len) { const uint8_t *p = buf; unsigned int count = 0; int lock_flag = 0; if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC) { ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx)); return (-1); } if (!buf || !buf_len) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS); return (-1); } if (!ctx->io_init) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_IO_NOT_INITIALIZED); return (-1); } if (!(ctx->flags & IPMI_KCS_FLAGS_NONBLOCKING)) { if (driver_mutex_lock (ctx->semid) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } } else { if (driver_mutex_lock_interruptible (ctx->semid) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } } lock_flag++; if (_ipmi_kcs_wait_for_ibf_clear (ctx) < 0) goto cleanup; _ipmi_kcs_clear_obf (ctx); _ipmi_kcs_start_write (ctx); if (_ipmi_kcs_wait_for_ibf_clear (ctx) < 0) goto cleanup; if (!_ipmi_kcs_test_if_state (ctx, IPMI_KCS_STATE_WRITE)) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_BUSY); goto cleanup; } _ipmi_kcs_clear_obf (ctx); /* note we have to save last byte. */ /* for (buf=data; data+len-1 < buf; buf++) */ for (; buf_len > 1; buf_len--) { _ipmi_kcs_write_byte (ctx, *p); if (_ipmi_kcs_wait_for_ibf_clear (ctx) < 0) goto cleanup; if (!_ipmi_kcs_test_if_state (ctx, IPMI_KCS_STATE_WRITE)) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_BUSY); goto cleanup; } _ipmi_kcs_clear_obf (ctx); p++; count++; } _ipmi_kcs_end_write (ctx); if (_ipmi_kcs_wait_for_ibf_clear (ctx) < 0) goto cleanup; if (!_ipmi_kcs_test_if_state (ctx, IPMI_KCS_STATE_WRITE)) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_BUSY); goto cleanup; } _ipmi_kcs_clear_obf (ctx); _ipmi_kcs_write_byte (ctx, *p); count++; #if 0 if (!_ipmi_kcs_test_if_state (IPMI_KCS_STATE_READ)) { printf ("Not in READ state after writing last byte?\n"); ipmi_kcs_print_state (ipmi_kcs_get_state ()); exit (EXIT_FAILURE); } #endif if (count > INT_MAX) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_OVERFLOW); goto cleanup; } ctx->errnum = IPMI_KCS_ERR_SUCCESS; return (count); cleanup: if (lock_flag) driver_mutex_unlock (ctx->semid); return (-1); }
char * ipmi_kcs_ctx_errormsg (ipmi_kcs_ctx_t ctx) { return (ipmi_kcs_ctx_strerror (ipmi_kcs_ctx_errnum (ctx))); }
static int _kcs_cmd_read (ipmi_ctx_t ctx, uint8_t cmd, uint8_t group_extension, fiid_obj_t obj_cmd_rs) { uint8_t *pkt = NULL; unsigned int pkt_len; int hdr_len, cmd_len, read_len; fiid_field_t *tmpl = NULL; int ret, rv = -1; unsigned int intf_flags = IPMI_INTERFACE_FLAGS_DEFAULT; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && fiid_obj_valid (obj_cmd_rs)); if (ctx->flags & IPMI_FLAGS_NO_LEGAL_CHECK) intf_flags |= IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK; if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (!(tmpl = fiid_obj_template (obj_cmd_rs))) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } if ((cmd_len = fiid_template_len_bytes (tmpl)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } pkt_len = hdr_len + cmd_len; if (!(pkt = malloc (pkt_len))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } memset (pkt, '\0', pkt_len); if ((read_len = ipmi_kcs_read (ctx->io.inband.kcs_ctx, pkt, pkt_len)) < 0) { API_KCS_ERRNUM_TO_API_ERRNUM (ctx, ipmi_kcs_ctx_errnum (ctx->io.inband.kcs_ctx)); goto cleanup; } if (!read_len) { API_SET_ERRNUM (ctx, IPMI_ERR_SYSTEM_ERROR); goto cleanup; } if (ctx->flags & IPMI_FLAGS_DEBUG_DUMP && read_len) _api_kcs_dump_rs (ctx, pkt, read_len, cmd, ctx->target.net_fn, group_extension, obj_cmd_rs); if ((ret = unassemble_ipmi_kcs_pkt (pkt, read_len, ctx->io.inband.rs.obj_hdr, obj_cmd_rs, intf_flags)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } /* IPMI didn't return enough data back to you */ if (!ret) { API_SET_ERRNUM (ctx, IPMI_ERR_IPMI_ERROR); goto cleanup; } rv = 0; cleanup: free (pkt); fiid_template_free (tmpl); return (rv); }
static int _kcs_cmd_write (ipmi_ctx_t ctx, uint8_t cmd, uint8_t group_extension, fiid_obj_t obj_cmd_rq) { uint8_t *pkt = NULL; unsigned int pkt_len; int hdr_len, cmd_len, send_len, rv = -1; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && fiid_obj_valid (obj_cmd_rq)); if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if ((cmd_len = fiid_obj_len_bytes (obj_cmd_rq)) < 0) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq); goto cleanup; } pkt_len = hdr_len + cmd_len; if (!(pkt = malloc (pkt_len))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } memset (pkt, '\0', pkt_len); if (fill_hdr_ipmi_kcs (ctx->target.lun, ctx->target.net_fn, ctx->io.inband.rq.obj_hdr) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if ((send_len = assemble_ipmi_kcs_pkt (ctx->io.inband.rq.obj_hdr, obj_cmd_rq, pkt, pkt_len, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (ctx->flags & IPMI_FLAGS_DEBUG_DUMP && send_len) _api_kcs_dump_rq (ctx, pkt, send_len, cmd, ctx->target.net_fn, group_extension, obj_cmd_rq); if (ipmi_kcs_write (ctx->io.inband.kcs_ctx, pkt, send_len) < 0) { API_KCS_ERRNUM_TO_API_ERRNUM (ctx, ipmi_kcs_ctx_errnum (ctx->io.inband.kcs_ctx)); goto cleanup; } rv = 0; cleanup: free (pkt); return (rv); }