xref: /onnv-gate/usr/src/lib/libipmi/common/libipmi.c (revision 11756:3ae81edcfbf7)
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