19113a79cSeschrock /* 29113a79cSeschrock * CDDL HEADER START 39113a79cSeschrock * 49113a79cSeschrock * The contents of this file are subject to the terms of the 59113a79cSeschrock * Common Development and Distribution License (the "License"). 69113a79cSeschrock * You may not use this file except in compliance with the License. 79113a79cSeschrock * 89113a79cSeschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99113a79cSeschrock * or http://www.opensolaris.org/os/licensing. 109113a79cSeschrock * See the License for the specific language governing permissions 119113a79cSeschrock * and limitations under the License. 129113a79cSeschrock * 139113a79cSeschrock * When distributing Covered Code, include this CDDL HEADER in each 149113a79cSeschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159113a79cSeschrock * If applicable, add the following below this CDDL HEADER, with the 169113a79cSeschrock * fields enclosed by brackets "[]" replaced with your own identifying 179113a79cSeschrock * information: Portions Copyright [yyyy] [name of copyright owner] 189113a79cSeschrock * 199113a79cSeschrock * CDDL HEADER END 209113a79cSeschrock */ 219113a79cSeschrock /* 22*2eeaed14Srobj * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 239113a79cSeschrock * Use is subject to license terms. 249113a79cSeschrock */ 259113a79cSeschrock 269113a79cSeschrock #pragma ident "%Z%%M% %I% %E% SMI" 279113a79cSeschrock 289113a79cSeschrock #include <libipmi.h> 299113a79cSeschrock #include <string.h> 309113a79cSeschrock 319113a79cSeschrock #include <sys/bmc_intf.h> 329113a79cSeschrock 339113a79cSeschrock #include "ipmi_impl.h" 349113a79cSeschrock 359113a79cSeschrock ipmi_handle_t * 369113a79cSeschrock ipmi_open(int *errp, char **msg) 379113a79cSeschrock { 389113a79cSeschrock ipmi_handle_t *ihp; 39*2eeaed14Srobj static char errmsg[48]; 409113a79cSeschrock 419113a79cSeschrock if (msg) 429113a79cSeschrock *msg = NULL; 439113a79cSeschrock 449113a79cSeschrock if ((ihp = calloc(sizeof (ipmi_handle_t), 1)) == NULL) { 459113a79cSeschrock *errp = EIPMI_NOMEM; 469113a79cSeschrock if (msg) 479113a79cSeschrock *msg = "memory allocation failure"; 489113a79cSeschrock return (NULL); 499113a79cSeschrock } 509113a79cSeschrock 519113a79cSeschrock /* /dev/bmc is the only currently available transport */ 529113a79cSeschrock ihp->ih_transport = &ipmi_transport_bmc; 539113a79cSeschrock 549113a79cSeschrock ihp->ih_retries = 3; 559113a79cSeschrock 56*2eeaed14Srobj if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp)) == NULL || 57*2eeaed14Srobj ipmi_sdr_init(ihp) != 0 || ipmi_entity_init(ihp) != 0) { 589113a79cSeschrock *errp = ihp->ih_errno; 599113a79cSeschrock if (msg) { 60*2eeaed14Srobj (void) strncpy(errmsg, ipmi_errmsg(ihp), 47); 61*2eeaed14Srobj errmsg[47] = '\0'; 62*2eeaed14Srobj *msg = errmsg; 639113a79cSeschrock } 649113a79cSeschrock ipmi_close(ihp); 659113a79cSeschrock return (NULL); 669113a79cSeschrock } 679113a79cSeschrock 689113a79cSeschrock return (ihp); 699113a79cSeschrock } 709113a79cSeschrock 719113a79cSeschrock void 729113a79cSeschrock ipmi_close(ipmi_handle_t *ihp) 739113a79cSeschrock { 749113a79cSeschrock if (ihp->ih_transport && ihp->ih_tdata) 759113a79cSeschrock ihp->ih_transport->it_close(ihp->ih_tdata); 76*2eeaed14Srobj ipmi_free(ihp, ihp->ih_deviceid); 77*2eeaed14Srobj ipmi_free(ihp, ihp->ih_firmware_rev); 781af98250Seschrock ipmi_user_clear(ihp); 79*2eeaed14Srobj ipmi_sdr_fini(ihp); 80*2eeaed14Srobj ipmi_entity_fini(ihp); 819113a79cSeschrock free(ihp); 829113a79cSeschrock } 839113a79cSeschrock 849113a79cSeschrock /* 859113a79cSeschrock * See section 5.2 for a description of the completion codes. 869113a79cSeschrock */ 879113a79cSeschrock static struct ipmi_err_conv { 889113a79cSeschrock int bmc_err; 899113a79cSeschrock int ipmi_err; 909113a79cSeschrock } ipmi_errtable[] = { 919113a79cSeschrock { 0xC0, EIPMI_BUSY }, 929113a79cSeschrock { 0xC1, EIPMI_INVALID_COMMAND }, 939113a79cSeschrock { 0xC2, EIPMI_INVALID_COMMAND }, 949113a79cSeschrock { 0xC3, EIPMI_COMMAND_TIMEOUT }, 959113a79cSeschrock { 0xC4, EIPMI_NOSPACE }, 969113a79cSeschrock { 0xC5, EIPMI_INVALID_RESERVATION }, 979113a79cSeschrock { 0xC6, EIPMI_INVALID_REQUEST }, 989113a79cSeschrock { 0xC7, EIPMI_INVALID_REQUEST }, 999113a79cSeschrock { 0xC8, EIPMI_INVALID_REQUEST }, 1009113a79cSeschrock { 0xC9, EIPMI_INVALID_REQUEST }, 1019113a79cSeschrock { 0xCA, EIPMI_DATA_LENGTH_EXCEEDED }, 1029113a79cSeschrock { 0xCB, EIPMI_NOT_PRESENT }, 1039113a79cSeschrock { 0xCC, EIPMI_INVALID_REQUEST }, 1049113a79cSeschrock { 0xCD, EIPMI_INVALID_COMMAND }, 1059113a79cSeschrock { 0xCE, EIPMI_UNAVAILABLE }, 1069113a79cSeschrock { 0xCF, EIPMI_UNAVAILABLE }, 1079113a79cSeschrock { 0xD0, EIPMI_BUSY }, 1089113a79cSeschrock { 0xD1, EIPMI_BUSY }, 1099113a79cSeschrock { 0xD2, EIPMI_BUSY }, 1109113a79cSeschrock { 0xD3, EIPMI_NOT_PRESENT }, 1119113a79cSeschrock { 0xD4, EIPMI_ACCESS }, 1129113a79cSeschrock { 0xD5, EIPMI_UNAVAILABLE }, 1139113a79cSeschrock { 0xD6, EIPMI_UNAVAILABLE }, 1149113a79cSeschrock { 0xFF, EIPMI_UNSPECIFIED }, 1159113a79cSeschrock { BMC_IPMI_OEM_FAILURE_SENDBMC, EIPMI_SEND_FAILED }, 1169113a79cSeschrock }; 1179113a79cSeschrock 1189113a79cSeschrock #define IPMI_ERROR_COUNT \ 1199113a79cSeschrock (sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0])) 1209113a79cSeschrock 1219113a79cSeschrock ipmi_cmd_t * 1229113a79cSeschrock ipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd) 1239113a79cSeschrock { 1249113a79cSeschrock int completion; 1259113a79cSeschrock int i; 1269113a79cSeschrock 1279113a79cSeschrock if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response, 1289113a79cSeschrock &completion) != 0) 1299113a79cSeschrock return (NULL); 1309113a79cSeschrock 1319113a79cSeschrock if (completion != 0) { 1329113a79cSeschrock for (i = 0; i < IPMI_ERROR_COUNT; i++) { 1339113a79cSeschrock if (completion == ipmi_errtable[i].bmc_err) { 1349113a79cSeschrock (void) ipmi_set_error(ihp, 1359113a79cSeschrock ipmi_errtable[i].ipmi_err, 1369113a79cSeschrock "IPMI completion code 0x%x", completion); 1379113a79cSeschrock return (NULL); 1389113a79cSeschrock } 1399113a79cSeschrock } 1409113a79cSeschrock 1419113a79cSeschrock (void) ipmi_set_error(ihp, EIPMI_UNKNOWN, 1429113a79cSeschrock "IPMI completion code 0x%x", completion); 1439113a79cSeschrock return (NULL); 1449113a79cSeschrock } 1459113a79cSeschrock 1469113a79cSeschrock return (&ihp->ih_response); 1479113a79cSeschrock } 148