xref: /titanic_53/usr/src/lib/libipmi/common/libipmi.c (revision 9113a79cf228b8f7bd509b1328adf88659dfe218)
1*9113a79cSeschrock /*
2*9113a79cSeschrock  * CDDL HEADER START
3*9113a79cSeschrock  *
4*9113a79cSeschrock  * The contents of this file are subject to the terms of the
5*9113a79cSeschrock  * Common Development and Distribution License (the "License").
6*9113a79cSeschrock  * You may not use this file except in compliance with the License.
7*9113a79cSeschrock  *
8*9113a79cSeschrock  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9113a79cSeschrock  * or http://www.opensolaris.org/os/licensing.
10*9113a79cSeschrock  * See the License for the specific language governing permissions
11*9113a79cSeschrock  * and limitations under the License.
12*9113a79cSeschrock  *
13*9113a79cSeschrock  * When distributing Covered Code, include this CDDL HEADER in each
14*9113a79cSeschrock  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9113a79cSeschrock  * If applicable, add the following below this CDDL HEADER, with the
16*9113a79cSeschrock  * fields enclosed by brackets "[]" replaced with your own identifying
17*9113a79cSeschrock  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9113a79cSeschrock  *
19*9113a79cSeschrock  * CDDL HEADER END
20*9113a79cSeschrock  */
21*9113a79cSeschrock /*
22*9113a79cSeschrock  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*9113a79cSeschrock  * Use is subject to license terms.
24*9113a79cSeschrock  */
25*9113a79cSeschrock 
26*9113a79cSeschrock #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*9113a79cSeschrock 
28*9113a79cSeschrock #include <libipmi.h>
29*9113a79cSeschrock #include <string.h>
30*9113a79cSeschrock 
31*9113a79cSeschrock #include <sys/bmc_intf.h>
32*9113a79cSeschrock 
33*9113a79cSeschrock #include "ipmi_impl.h"
34*9113a79cSeschrock 
35*9113a79cSeschrock ipmi_handle_t *
36*9113a79cSeschrock ipmi_open(int *errp, char **msg)
37*9113a79cSeschrock {
38*9113a79cSeschrock 	ipmi_handle_t *ihp;
39*9113a79cSeschrock 
40*9113a79cSeschrock 	if (msg)
41*9113a79cSeschrock 		*msg = NULL;
42*9113a79cSeschrock 
43*9113a79cSeschrock 	if ((ihp = calloc(sizeof (ipmi_handle_t), 1)) == NULL) {
44*9113a79cSeschrock 		*errp = EIPMI_NOMEM;
45*9113a79cSeschrock 		if (msg)
46*9113a79cSeschrock 			*msg = "memory allocation failure";
47*9113a79cSeschrock 		return (NULL);
48*9113a79cSeschrock 	}
49*9113a79cSeschrock 
50*9113a79cSeschrock 	/* /dev/bmc is the only currently available transport */
51*9113a79cSeschrock 	ihp->ih_transport = &ipmi_transport_bmc;
52*9113a79cSeschrock 
53*9113a79cSeschrock 	ihp->ih_retries = 3;
54*9113a79cSeschrock 
55*9113a79cSeschrock 	if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp)) == NULL) {
56*9113a79cSeschrock 		*errp = ihp->ih_errno;
57*9113a79cSeschrock 		if (msg) {
58*9113a79cSeschrock 			if ((*msg = strdup(ipmi_errmsg(ihp))) == NULL)
59*9113a79cSeschrock 				*msg = "memory allocation failure";
60*9113a79cSeschrock 		}
61*9113a79cSeschrock 		ipmi_close(ihp);
62*9113a79cSeschrock 		return (NULL);
63*9113a79cSeschrock 	}
64*9113a79cSeschrock 
65*9113a79cSeschrock 	return (ihp);
66*9113a79cSeschrock }
67*9113a79cSeschrock 
68*9113a79cSeschrock void
69*9113a79cSeschrock ipmi_close(ipmi_handle_t *ihp)
70*9113a79cSeschrock {
71*9113a79cSeschrock 	if (ihp->ih_transport && ihp->ih_tdata)
72*9113a79cSeschrock 		ihp->ih_transport->it_close(ihp->ih_tdata);
73*9113a79cSeschrock 	free(ihp);
74*9113a79cSeschrock }
75*9113a79cSeschrock 
76*9113a79cSeschrock /*
77*9113a79cSeschrock  * See section 5.2 for a description of the completion codes.
78*9113a79cSeschrock  */
79*9113a79cSeschrock static struct ipmi_err_conv {
80*9113a79cSeschrock 	int	bmc_err;
81*9113a79cSeschrock 	int	ipmi_err;
82*9113a79cSeschrock } ipmi_errtable[] = {
83*9113a79cSeschrock 	{ 0xC0,			EIPMI_BUSY },
84*9113a79cSeschrock 	{ 0xC1,			EIPMI_INVALID_COMMAND },
85*9113a79cSeschrock 	{ 0xC2,			EIPMI_INVALID_COMMAND },
86*9113a79cSeschrock 	{ 0xC3,			EIPMI_COMMAND_TIMEOUT },
87*9113a79cSeschrock 	{ 0xC4,			EIPMI_NOSPACE },
88*9113a79cSeschrock 	{ 0xC5,			EIPMI_INVALID_RESERVATION },
89*9113a79cSeschrock 	{ 0xC6,			EIPMI_INVALID_REQUEST },
90*9113a79cSeschrock 	{ 0xC7,			EIPMI_INVALID_REQUEST },
91*9113a79cSeschrock 	{ 0xC8,			EIPMI_INVALID_REQUEST },
92*9113a79cSeschrock 	{ 0xC9,			EIPMI_INVALID_REQUEST },
93*9113a79cSeschrock 	{ 0xCA,			EIPMI_DATA_LENGTH_EXCEEDED },
94*9113a79cSeschrock 	{ 0xCB,			EIPMI_NOT_PRESENT },
95*9113a79cSeschrock 	{ 0xCC,			EIPMI_INVALID_REQUEST },
96*9113a79cSeschrock 	{ 0xCD,			EIPMI_INVALID_COMMAND },
97*9113a79cSeschrock 	{ 0xCE,			EIPMI_UNAVAILABLE },
98*9113a79cSeschrock 	{ 0xCF,			EIPMI_UNAVAILABLE },
99*9113a79cSeschrock 	{ 0xD0,			EIPMI_BUSY },
100*9113a79cSeschrock 	{ 0xD1,			EIPMI_BUSY },
101*9113a79cSeschrock 	{ 0xD2,			EIPMI_BUSY },
102*9113a79cSeschrock 	{ 0xD3,			EIPMI_NOT_PRESENT },
103*9113a79cSeschrock 	{ 0xD4,			EIPMI_ACCESS },
104*9113a79cSeschrock 	{ 0xD5,			EIPMI_UNAVAILABLE },
105*9113a79cSeschrock 	{ 0xD6,			EIPMI_UNAVAILABLE },
106*9113a79cSeschrock 	{ 0xFF,			EIPMI_UNSPECIFIED },
107*9113a79cSeschrock 	{ BMC_IPMI_OEM_FAILURE_SENDBMC,	EIPMI_SEND_FAILED },
108*9113a79cSeschrock };
109*9113a79cSeschrock 
110*9113a79cSeschrock #define	IPMI_ERROR_COUNT \
111*9113a79cSeschrock 	(sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0]))
112*9113a79cSeschrock 
113*9113a79cSeschrock ipmi_cmd_t *
114*9113a79cSeschrock ipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd)
115*9113a79cSeschrock {
116*9113a79cSeschrock 	int completion;
117*9113a79cSeschrock 	int i;
118*9113a79cSeschrock 
119*9113a79cSeschrock 	if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response,
120*9113a79cSeschrock 	    &completion) != 0)
121*9113a79cSeschrock 		return (NULL);
122*9113a79cSeschrock 
123*9113a79cSeschrock 	if (completion != 0) {
124*9113a79cSeschrock 		for (i = 0; i < IPMI_ERROR_COUNT; i++) {
125*9113a79cSeschrock 			if (completion == ipmi_errtable[i].bmc_err) {
126*9113a79cSeschrock 				(void) ipmi_set_error(ihp,
127*9113a79cSeschrock 				    ipmi_errtable[i].ipmi_err,
128*9113a79cSeschrock 				    "IPMI completion code 0x%x", completion);
129*9113a79cSeschrock 				return (NULL);
130*9113a79cSeschrock 			}
131*9113a79cSeschrock 		}
132*9113a79cSeschrock 
133*9113a79cSeschrock 		(void) ipmi_set_error(ihp, EIPMI_UNKNOWN,
134*9113a79cSeschrock 		    "IPMI completion code 0x%x", completion);
135*9113a79cSeschrock 		return (NULL);
136*9113a79cSeschrock 	}
137*9113a79cSeschrock 
138*9113a79cSeschrock 	return (&ihp->ih_response);
139*9113a79cSeschrock }
140