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 /* 226070Srobj * Copyright 2008 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 * 343798Seschrock ipmi_open(int *errp, char **msg) 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 493798Seschrock /* /dev/bmc is the only currently available transport */ 503798Seschrock ihp->ih_transport = &ipmi_transport_bmc; 513798Seschrock 523798Seschrock ihp->ih_retries = 3; 533798Seschrock 546070Srobj if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp)) == NULL || 556070Srobj ipmi_sdr_init(ihp) != 0 || ipmi_entity_init(ihp) != 0) { 563798Seschrock *errp = ihp->ih_errno; 573798Seschrock if (msg) { 586070Srobj (void) strncpy(errmsg, ipmi_errmsg(ihp), 47); 596070Srobj errmsg[47] = '\0'; 606070Srobj *msg = errmsg; 613798Seschrock } 623798Seschrock ipmi_close(ihp); 633798Seschrock return (NULL); 643798Seschrock } 653798Seschrock 663798Seschrock return (ihp); 673798Seschrock } 683798Seschrock 693798Seschrock void 703798Seschrock ipmi_close(ipmi_handle_t *ihp) 713798Seschrock { 723798Seschrock if (ihp->ih_transport && ihp->ih_tdata) 733798Seschrock ihp->ih_transport->it_close(ihp->ih_tdata); 746070Srobj ipmi_free(ihp, ihp->ih_deviceid); 756070Srobj ipmi_free(ihp, ihp->ih_firmware_rev); 765345Seschrock ipmi_user_clear(ihp); 776070Srobj ipmi_sdr_fini(ihp); 786070Srobj ipmi_entity_fini(ihp); 793798Seschrock free(ihp); 803798Seschrock } 813798Seschrock 823798Seschrock /* 833798Seschrock * See section 5.2 for a description of the completion codes. 843798Seschrock */ 853798Seschrock static struct ipmi_err_conv { 863798Seschrock int bmc_err; 873798Seschrock int ipmi_err; 883798Seschrock } ipmi_errtable[] = { 893798Seschrock { 0xC0, EIPMI_BUSY }, 903798Seschrock { 0xC1, EIPMI_INVALID_COMMAND }, 913798Seschrock { 0xC2, EIPMI_INVALID_COMMAND }, 923798Seschrock { 0xC3, EIPMI_COMMAND_TIMEOUT }, 933798Seschrock { 0xC4, EIPMI_NOSPACE }, 943798Seschrock { 0xC5, EIPMI_INVALID_RESERVATION }, 953798Seschrock { 0xC6, EIPMI_INVALID_REQUEST }, 963798Seschrock { 0xC7, EIPMI_INVALID_REQUEST }, 973798Seschrock { 0xC8, EIPMI_INVALID_REQUEST }, 983798Seschrock { 0xC9, EIPMI_INVALID_REQUEST }, 993798Seschrock { 0xCA, EIPMI_DATA_LENGTH_EXCEEDED }, 1003798Seschrock { 0xCB, EIPMI_NOT_PRESENT }, 1013798Seschrock { 0xCC, EIPMI_INVALID_REQUEST }, 1023798Seschrock { 0xCD, EIPMI_INVALID_COMMAND }, 1033798Seschrock { 0xCE, EIPMI_UNAVAILABLE }, 1043798Seschrock { 0xCF, EIPMI_UNAVAILABLE }, 1053798Seschrock { 0xD0, EIPMI_BUSY }, 1063798Seschrock { 0xD1, EIPMI_BUSY }, 1073798Seschrock { 0xD2, EIPMI_BUSY }, 1083798Seschrock { 0xD3, EIPMI_NOT_PRESENT }, 1093798Seschrock { 0xD4, EIPMI_ACCESS }, 1103798Seschrock { 0xD5, EIPMI_UNAVAILABLE }, 1113798Seschrock { 0xD6, EIPMI_UNAVAILABLE }, 1123798Seschrock { 0xFF, EIPMI_UNSPECIFIED }, 1133798Seschrock { BMC_IPMI_OEM_FAILURE_SENDBMC, EIPMI_SEND_FAILED }, 1143798Seschrock }; 1153798Seschrock 1163798Seschrock #define IPMI_ERROR_COUNT \ 1173798Seschrock (sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0])) 1183798Seschrock 1193798Seschrock ipmi_cmd_t * 1203798Seschrock ipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd) 1213798Seschrock { 1223798Seschrock int i; 1233798Seschrock 1243798Seschrock if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response, 125*8339SEric.Schrock@Sun.COM &ihp->ih_completion) != 0) 1263798Seschrock return (NULL); 1273798Seschrock 128*8339SEric.Schrock@Sun.COM if (ihp->ih_completion != 0) { 1293798Seschrock for (i = 0; i < IPMI_ERROR_COUNT; i++) { 130*8339SEric.Schrock@Sun.COM if (ihp->ih_completion == ipmi_errtable[i].bmc_err) { 1313798Seschrock (void) ipmi_set_error(ihp, 1323798Seschrock ipmi_errtable[i].ipmi_err, 133*8339SEric.Schrock@Sun.COM "IPMI completion code 0x%x", 134*8339SEric.Schrock@Sun.COM ihp->ih_completion); 1353798Seschrock return (NULL); 1363798Seschrock } 1373798Seschrock } 1383798Seschrock 1393798Seschrock (void) ipmi_set_error(ihp, EIPMI_UNKNOWN, 140*8339SEric.Schrock@Sun.COM "IPMI completion code 0x%x", ihp->ih_completion); 1413798Seschrock return (NULL); 1423798Seschrock } 1433798Seschrock 1443798Seschrock return (&ihp->ih_response); 1453798Seschrock } 146