2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#include <libipmi.h>
2N/A#include <string.h>
2N/A
2N/A#include <sys/bmc_intf.h>
2N/A
2N/A#include "ipmi_impl.h"
2N/A
2N/Aipmi_handle_t *
2N/Aipmi_open(int *errp, char **msg, uint_t xport_type, nvlist_t *params)
2N/A{
2N/A ipmi_handle_t *ihp;
2N/A static char errmsg[48];
2N/A
2N/A if (msg)
2N/A *msg = NULL;
2N/A
2N/A if ((ihp = calloc(sizeof (ipmi_handle_t), 1)) == NULL) {
2N/A *errp = EIPMI_NOMEM;
2N/A if (msg)
2N/A *msg = "memory allocation failure";
2N/A return (NULL);
2N/A }
2N/A
2N/A switch (xport_type) {
2N/A case IPMI_TRANSPORT_BMC:
2N/A ihp->ih_transport = &ipmi_transport_bmc;
2N/A break;
2N/A case IPMI_TRANSPORT_LAN:
2N/A ihp->ih_transport = &ipmi_transport_lan;
2N/A break;
2N/A default:
2N/A *msg = "invalid transport type specified";
2N/A return (NULL);
2N/A }
2N/A
2N/A ihp->ih_retries = 3;
2N/A
2N/A if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp, params)) == NULL ||
2N/A ipmi_sdr_init(ihp) != 0 || ipmi_entity_init(ihp) != 0) {
2N/A *errp = ihp->ih_errno;
2N/A if (msg) {
2N/A (void) strncpy(errmsg, ipmi_errmsg(ihp), 47);
2N/A errmsg[47] = '\0';
2N/A *msg = errmsg;
2N/A }
2N/A ipmi_close(ihp);
2N/A return (NULL);
2N/A }
2N/A
2N/A return (ihp);
2N/A}
2N/A
2N/Avoid
2N/Aipmi_close(ipmi_handle_t *ihp)
2N/A{
2N/A if (ihp->ih_transport && ihp->ih_tdata)
2N/A ihp->ih_transport->it_close(ihp->ih_tdata);
2N/A ipmi_free(ihp, ihp->ih_deviceid);
2N/A ipmi_free(ihp, ihp->ih_firmware_rev);
2N/A ipmi_user_clear(ihp);
2N/A ipmi_sdr_fini(ihp);
2N/A ipmi_entity_fini(ihp);
2N/A free(ihp);
2N/A}
2N/A
2N/A/*
2N/A * See section 5.2 for a description of the completion codes.
2N/A */
2N/Astatic struct ipmi_err_conv {
2N/A int bmc_err;
2N/A int ipmi_err;
2N/A} ipmi_errtable[] = {
2N/A { 0xC0, EIPMI_BUSY },
2N/A { 0xC1, EIPMI_INVALID_COMMAND },
2N/A { 0xC2, EIPMI_INVALID_COMMAND },
2N/A { 0xC3, EIPMI_COMMAND_TIMEOUT },
2N/A { 0xC4, EIPMI_NOSPACE },
2N/A { 0xC5, EIPMI_INVALID_RESERVATION },
2N/A { 0xC6, EIPMI_INVALID_REQUEST },
2N/A { 0xC7, EIPMI_INVALID_REQUEST },
2N/A { 0xC8, EIPMI_INVALID_REQUEST },
2N/A { 0xC9, EIPMI_INVALID_REQUEST },
2N/A { 0xCA, EIPMI_DATA_LENGTH_EXCEEDED },
2N/A { 0xCB, EIPMI_NOT_PRESENT },
2N/A { 0xCC, EIPMI_INVALID_REQUEST },
2N/A { 0xCD, EIPMI_INVALID_COMMAND },
2N/A { 0xCE, EIPMI_UNAVAILABLE },
2N/A { 0xCF, EIPMI_UNAVAILABLE },
2N/A { 0xD0, EIPMI_BUSY },
2N/A { 0xD1, EIPMI_BUSY },
2N/A { 0xD2, EIPMI_BUSY },
2N/A { 0xD3, EIPMI_NOT_PRESENT },
2N/A { 0xD4, EIPMI_ACCESS },
2N/A { 0xD5, EIPMI_UNAVAILABLE },
2N/A { 0xD6, EIPMI_UNAVAILABLE },
2N/A { 0xFF, EIPMI_UNSPECIFIED },
2N/A { BMC_IPMI_OEM_FAILURE_SENDBMC, EIPMI_SEND_FAILED },
2N/A};
2N/A
2N/A#define IPMI_ERROR_COUNT \
2N/A (sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0]))
2N/A
2N/Aipmi_cmd_t *
2N/Aipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd)
2N/A{
2N/A int i;
2N/A
2N/A if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response,
2N/A &ihp->ih_completion) != 0)
2N/A return (NULL);
2N/A
2N/A if (ihp->ih_completion != 0) {
2N/A for (i = 0; i < IPMI_ERROR_COUNT; i++) {
2N/A if (ihp->ih_completion == ipmi_errtable[i].bmc_err) {
2N/A (void) ipmi_set_error(ihp,
2N/A ipmi_errtable[i].ipmi_err,
2N/A "IPMI completion code 0x%x",
2N/A ihp->ih_completion);
2N/A return (NULL);
2N/A }
2N/A }
2N/A
2N/A (void) ipmi_set_error(ihp, EIPMI_UNKNOWN,
2N/A "IPMI completion code 0x%x", ihp->ih_completion);
2N/A return (NULL);
2N/A }
2N/A
2N/A return (&ihp->ih_response);
2N/A}