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