13798Seschrock /*
23798Seschrock * CDDL HEADER START
33798Seschrock *
43798Seschrock * The contents of this file are subject to the terms of the
53798Seschrock * Common Development and Distribution License (the "License").
63798Seschrock * You may not use this file except in compliance with the License.
73798Seschrock *
83798Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93798Seschrock * or http://www.opensolaris.org/os/licensing.
103798Seschrock * See the License for the specific language governing permissions
113798Seschrock * and limitations under the License.
123798Seschrock *
133798Seschrock * When distributing Covered Code, include this CDDL HEADER in each
143798Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153798Seschrock * If applicable, add the following below this CDDL HEADER, with the
163798Seschrock * fields enclosed by brackets "[]" replaced with your own identifying
173798Seschrock * information: Portions Copyright [yyyy] [name of copyright owner]
183798Seschrock *
193798Seschrock * CDDL HEADER END
203798Seschrock */
213798Seschrock /*
22*11756SRobert.Johnston@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
233798Seschrock * Use is subject to license terms.
243798Seschrock */
253798Seschrock
263798Seschrock #include <libipmi.h>
273798Seschrock #include <string.h>
283798Seschrock
293798Seschrock #include <sys/bmc_intf.h>
303798Seschrock
313798Seschrock #include "ipmi_impl.h"
323798Seschrock
333798Seschrock ipmi_handle_t *
ipmi_open(int * errp,char ** msg,uint_t xport_type,nvlist_t * params)34*11756SRobert.Johnston@Sun.COM ipmi_open(int *errp, char **msg, uint_t xport_type, nvlist_t *params)
353798Seschrock {
363798Seschrock ipmi_handle_t *ihp;
376070Srobj static char errmsg[48];
383798Seschrock
393798Seschrock if (msg)
403798Seschrock *msg = NULL;
413798Seschrock
423798Seschrock if ((ihp = calloc(sizeof (ipmi_handle_t), 1)) == NULL) {
433798Seschrock *errp = EIPMI_NOMEM;
443798Seschrock if (msg)
453798Seschrock *msg = "memory allocation failure";
463798Seschrock return (NULL);
473798Seschrock }
483798Seschrock
49*11756SRobert.Johnston@Sun.COM switch (xport_type) {
50*11756SRobert.Johnston@Sun.COM case IPMI_TRANSPORT_BMC:
51*11756SRobert.Johnston@Sun.COM ihp->ih_transport = &ipmi_transport_bmc;
52*11756SRobert.Johnston@Sun.COM break;
53*11756SRobert.Johnston@Sun.COM case IPMI_TRANSPORT_LAN:
54*11756SRobert.Johnston@Sun.COM ihp->ih_transport = &ipmi_transport_lan;
55*11756SRobert.Johnston@Sun.COM break;
56*11756SRobert.Johnston@Sun.COM default:
57*11756SRobert.Johnston@Sun.COM *msg = "invalid transport type specified";
58*11756SRobert.Johnston@Sun.COM return (NULL);
59*11756SRobert.Johnston@Sun.COM }
603798Seschrock
613798Seschrock ihp->ih_retries = 3;
623798Seschrock
63*11756SRobert.Johnston@Sun.COM if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp, params)) == NULL ||
646070Srobj ipmi_sdr_init(ihp) != 0 || ipmi_entity_init(ihp) != 0) {
653798Seschrock *errp = ihp->ih_errno;
663798Seschrock if (msg) {
676070Srobj (void) strncpy(errmsg, ipmi_errmsg(ihp), 47);
686070Srobj errmsg[47] = '\0';
696070Srobj *msg = errmsg;
703798Seschrock }
713798Seschrock ipmi_close(ihp);
723798Seschrock return (NULL);
733798Seschrock }
743798Seschrock
753798Seschrock return (ihp);
763798Seschrock }
773798Seschrock
783798Seschrock void
ipmi_close(ipmi_handle_t * ihp)793798Seschrock ipmi_close(ipmi_handle_t *ihp)
803798Seschrock {
813798Seschrock if (ihp->ih_transport && ihp->ih_tdata)
823798Seschrock ihp->ih_transport->it_close(ihp->ih_tdata);
836070Srobj ipmi_free(ihp, ihp->ih_deviceid);
846070Srobj ipmi_free(ihp, ihp->ih_firmware_rev);
855345Seschrock ipmi_user_clear(ihp);
866070Srobj ipmi_sdr_fini(ihp);
876070Srobj ipmi_entity_fini(ihp);
883798Seschrock free(ihp);
893798Seschrock }
903798Seschrock
913798Seschrock /*
923798Seschrock * See section 5.2 for a description of the completion codes.
933798Seschrock */
943798Seschrock static struct ipmi_err_conv {
953798Seschrock int bmc_err;
963798Seschrock int ipmi_err;
973798Seschrock } ipmi_errtable[] = {
983798Seschrock { 0xC0, EIPMI_BUSY },
993798Seschrock { 0xC1, EIPMI_INVALID_COMMAND },
1003798Seschrock { 0xC2, EIPMI_INVALID_COMMAND },
1013798Seschrock { 0xC3, EIPMI_COMMAND_TIMEOUT },
1023798Seschrock { 0xC4, EIPMI_NOSPACE },
1033798Seschrock { 0xC5, EIPMI_INVALID_RESERVATION },
1043798Seschrock { 0xC6, EIPMI_INVALID_REQUEST },
1053798Seschrock { 0xC7, EIPMI_INVALID_REQUEST },
1063798Seschrock { 0xC8, EIPMI_INVALID_REQUEST },
1073798Seschrock { 0xC9, EIPMI_INVALID_REQUEST },
1083798Seschrock { 0xCA, EIPMI_DATA_LENGTH_EXCEEDED },
1093798Seschrock { 0xCB, EIPMI_NOT_PRESENT },
1103798Seschrock { 0xCC, EIPMI_INVALID_REQUEST },
1113798Seschrock { 0xCD, EIPMI_INVALID_COMMAND },
1123798Seschrock { 0xCE, EIPMI_UNAVAILABLE },
1133798Seschrock { 0xCF, EIPMI_UNAVAILABLE },
1143798Seschrock { 0xD0, EIPMI_BUSY },
1153798Seschrock { 0xD1, EIPMI_BUSY },
1163798Seschrock { 0xD2, EIPMI_BUSY },
1173798Seschrock { 0xD3, EIPMI_NOT_PRESENT },
1183798Seschrock { 0xD4, EIPMI_ACCESS },
1193798Seschrock { 0xD5, EIPMI_UNAVAILABLE },
1203798Seschrock { 0xD6, EIPMI_UNAVAILABLE },
1213798Seschrock { 0xFF, EIPMI_UNSPECIFIED },
1223798Seschrock { BMC_IPMI_OEM_FAILURE_SENDBMC, EIPMI_SEND_FAILED },
1233798Seschrock };
1243798Seschrock
1253798Seschrock #define IPMI_ERROR_COUNT \
1263798Seschrock (sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0]))
1273798Seschrock
1283798Seschrock ipmi_cmd_t *
ipmi_send(ipmi_handle_t * ihp,ipmi_cmd_t * cmd)1293798Seschrock ipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd)
1303798Seschrock {
1313798Seschrock int i;
1323798Seschrock
1333798Seschrock if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response,
1348339SEric.Schrock@Sun.COM &ihp->ih_completion) != 0)
1353798Seschrock return (NULL);
1363798Seschrock
1378339SEric.Schrock@Sun.COM if (ihp->ih_completion != 0) {
1383798Seschrock for (i = 0; i < IPMI_ERROR_COUNT; i++) {
1398339SEric.Schrock@Sun.COM if (ihp->ih_completion == ipmi_errtable[i].bmc_err) {
1403798Seschrock (void) ipmi_set_error(ihp,
1413798Seschrock ipmi_errtable[i].ipmi_err,
1428339SEric.Schrock@Sun.COM "IPMI completion code 0x%x",
1438339SEric.Schrock@Sun.COM ihp->ih_completion);
1443798Seschrock return (NULL);
1453798Seschrock }
1463798Seschrock }
1473798Seschrock
1483798Seschrock (void) ipmi_set_error(ihp, EIPMI_UNKNOWN,
1498339SEric.Schrock@Sun.COM "IPMI completion code 0x%x", ihp->ih_completion);
1503798Seschrock return (NULL);
1513798Seschrock }
1523798Seschrock
1533798Seschrock return (&ihp->ih_response);
1543798Seschrock }
155