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 /* 223798Seschrock * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233798Seschrock * Use is subject to license terms. 243798Seschrock */ 253798Seschrock 263798Seschrock #pragma ident "%Z%%M% %I% %E% SMI" 273798Seschrock 283798Seschrock #include <libipmi.h> 293798Seschrock #include <string.h> 303798Seschrock 313798Seschrock #include <sys/bmc_intf.h> 323798Seschrock 333798Seschrock #include "ipmi_impl.h" 343798Seschrock 353798Seschrock ipmi_handle_t * 363798Seschrock ipmi_open(int *errp, char **msg) 373798Seschrock { 383798Seschrock ipmi_handle_t *ihp; 393798Seschrock 403798Seschrock if (msg) 413798Seschrock *msg = NULL; 423798Seschrock 433798Seschrock if ((ihp = calloc(sizeof (ipmi_handle_t), 1)) == NULL) { 443798Seschrock *errp = EIPMI_NOMEM; 453798Seschrock if (msg) 463798Seschrock *msg = "memory allocation failure"; 473798Seschrock return (NULL); 483798Seschrock } 493798Seschrock 503798Seschrock /* /dev/bmc is the only currently available transport */ 513798Seschrock ihp->ih_transport = &ipmi_transport_bmc; 523798Seschrock 533798Seschrock ihp->ih_retries = 3; 543798Seschrock 553798Seschrock if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp)) == NULL) { 563798Seschrock *errp = ihp->ih_errno; 573798Seschrock if (msg) { 583798Seschrock if ((*msg = strdup(ipmi_errmsg(ihp))) == NULL) 593798Seschrock *msg = "memory allocation failure"; 603798Seschrock } 613798Seschrock ipmi_close(ihp); 623798Seschrock return (NULL); 633798Seschrock } 643798Seschrock 653798Seschrock return (ihp); 663798Seschrock } 673798Seschrock 683798Seschrock void 693798Seschrock ipmi_close(ipmi_handle_t *ihp) 703798Seschrock { 713798Seschrock if (ihp->ih_transport && ihp->ih_tdata) 723798Seschrock ihp->ih_transport->it_close(ihp->ih_tdata); 735017Seschrock ipmi_sdr_clear(ihp); 74*5345Seschrock ipmi_user_clear(ihp); 753798Seschrock free(ihp); 763798Seschrock } 773798Seschrock 783798Seschrock /* 793798Seschrock * See section 5.2 for a description of the completion codes. 803798Seschrock */ 813798Seschrock static struct ipmi_err_conv { 823798Seschrock int bmc_err; 833798Seschrock int ipmi_err; 843798Seschrock } ipmi_errtable[] = { 853798Seschrock { 0xC0, EIPMI_BUSY }, 863798Seschrock { 0xC1, EIPMI_INVALID_COMMAND }, 873798Seschrock { 0xC2, EIPMI_INVALID_COMMAND }, 883798Seschrock { 0xC3, EIPMI_COMMAND_TIMEOUT }, 893798Seschrock { 0xC4, EIPMI_NOSPACE }, 903798Seschrock { 0xC5, EIPMI_INVALID_RESERVATION }, 913798Seschrock { 0xC6, EIPMI_INVALID_REQUEST }, 923798Seschrock { 0xC7, EIPMI_INVALID_REQUEST }, 933798Seschrock { 0xC8, EIPMI_INVALID_REQUEST }, 943798Seschrock { 0xC9, EIPMI_INVALID_REQUEST }, 953798Seschrock { 0xCA, EIPMI_DATA_LENGTH_EXCEEDED }, 963798Seschrock { 0xCB, EIPMI_NOT_PRESENT }, 973798Seschrock { 0xCC, EIPMI_INVALID_REQUEST }, 983798Seschrock { 0xCD, EIPMI_INVALID_COMMAND }, 993798Seschrock { 0xCE, EIPMI_UNAVAILABLE }, 1003798Seschrock { 0xCF, EIPMI_UNAVAILABLE }, 1013798Seschrock { 0xD0, EIPMI_BUSY }, 1023798Seschrock { 0xD1, EIPMI_BUSY }, 1033798Seschrock { 0xD2, EIPMI_BUSY }, 1043798Seschrock { 0xD3, EIPMI_NOT_PRESENT }, 1053798Seschrock { 0xD4, EIPMI_ACCESS }, 1063798Seschrock { 0xD5, EIPMI_UNAVAILABLE }, 1073798Seschrock { 0xD6, EIPMI_UNAVAILABLE }, 1083798Seschrock { 0xFF, EIPMI_UNSPECIFIED }, 1093798Seschrock { BMC_IPMI_OEM_FAILURE_SENDBMC, EIPMI_SEND_FAILED }, 1103798Seschrock }; 1113798Seschrock 1123798Seschrock #define IPMI_ERROR_COUNT \ 1133798Seschrock (sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0])) 1143798Seschrock 1153798Seschrock ipmi_cmd_t * 1163798Seschrock ipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd) 1173798Seschrock { 1183798Seschrock int completion; 1193798Seschrock int i; 1203798Seschrock 1213798Seschrock if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response, 1223798Seschrock &completion) != 0) 1233798Seschrock return (NULL); 1243798Seschrock 1253798Seschrock if (completion != 0) { 1263798Seschrock for (i = 0; i < IPMI_ERROR_COUNT; i++) { 1273798Seschrock if (completion == ipmi_errtable[i].bmc_err) { 1283798Seschrock (void) ipmi_set_error(ihp, 1293798Seschrock ipmi_errtable[i].ipmi_err, 1303798Seschrock "IPMI completion code 0x%x", completion); 1313798Seschrock return (NULL); 1323798Seschrock } 1333798Seschrock } 1343798Seschrock 1353798Seschrock (void) ipmi_set_error(ihp, EIPMI_UNKNOWN, 1363798Seschrock "IPMI completion code 0x%x", completion); 1373798Seschrock return (NULL); 1383798Seschrock } 1393798Seschrock 1403798Seschrock return (&ihp->ih_response); 1413798Seschrock } 142