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*81d9f076SRobert Johnston * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 239113a79cSeschrock * Use is subject to license terms. 249113a79cSeschrock */ 259113a79cSeschrock 269113a79cSeschrock #include <libipmi.h> 279113a79cSeschrock #include <string.h> 289113a79cSeschrock 299113a79cSeschrock #include "ipmi_impl.h" 309113a79cSeschrock 319113a79cSeschrock ipmi_handle_t * 32*81d9f076SRobert Johnston ipmi_open(int *errp, char **msg, uint_t xport_type, nvlist_t *params) 339113a79cSeschrock { 349113a79cSeschrock ipmi_handle_t *ihp; 352eeaed14Srobj static char errmsg[48]; 369113a79cSeschrock 379113a79cSeschrock if (msg) 389113a79cSeschrock *msg = NULL; 399113a79cSeschrock 409113a79cSeschrock if ((ihp = calloc(sizeof (ipmi_handle_t), 1)) == NULL) { 419113a79cSeschrock *errp = EIPMI_NOMEM; 429113a79cSeschrock if (msg) 439113a79cSeschrock *msg = "memory allocation failure"; 449113a79cSeschrock return (NULL); 459113a79cSeschrock } 469113a79cSeschrock 47*81d9f076SRobert Johnston switch (xport_type) { 48*81d9f076SRobert Johnston case IPMI_TRANSPORT_BMC: 499113a79cSeschrock ihp->ih_transport = &ipmi_transport_bmc; 50*81d9f076SRobert Johnston break; 51*81d9f076SRobert Johnston case IPMI_TRANSPORT_LAN: 52*81d9f076SRobert Johnston ihp->ih_transport = &ipmi_transport_lan; 53*81d9f076SRobert Johnston break; 54*81d9f076SRobert Johnston default: 55*81d9f076SRobert Johnston *msg = "invalid transport type specified"; 56*81d9f076SRobert Johnston return (NULL); 57*81d9f076SRobert Johnston } 589113a79cSeschrock 599113a79cSeschrock ihp->ih_retries = 3; 609113a79cSeschrock 61*81d9f076SRobert Johnston if ((ihp->ih_tdata = ihp->ih_transport->it_open(ihp, params)) == NULL || 622eeaed14Srobj ipmi_sdr_init(ihp) != 0 || ipmi_entity_init(ihp) != 0) { 639113a79cSeschrock *errp = ihp->ih_errno; 649113a79cSeschrock if (msg) { 652eeaed14Srobj (void) strncpy(errmsg, ipmi_errmsg(ihp), 47); 662eeaed14Srobj errmsg[47] = '\0'; 672eeaed14Srobj *msg = errmsg; 689113a79cSeschrock } 699113a79cSeschrock ipmi_close(ihp); 709113a79cSeschrock return (NULL); 719113a79cSeschrock } 729113a79cSeschrock 739113a79cSeschrock return (ihp); 749113a79cSeschrock } 759113a79cSeschrock 769113a79cSeschrock void 779113a79cSeschrock ipmi_close(ipmi_handle_t *ihp) 789113a79cSeschrock { 799113a79cSeschrock if (ihp->ih_transport && ihp->ih_tdata) 809113a79cSeschrock ihp->ih_transport->it_close(ihp->ih_tdata); 812eeaed14Srobj ipmi_free(ihp, ihp->ih_deviceid); 822eeaed14Srobj ipmi_free(ihp, ihp->ih_firmware_rev); 831af98250Seschrock ipmi_user_clear(ihp); 842eeaed14Srobj ipmi_sdr_fini(ihp); 852eeaed14Srobj ipmi_entity_fini(ihp); 869113a79cSeschrock free(ihp); 879113a79cSeschrock } 889113a79cSeschrock 899113a79cSeschrock /* 909113a79cSeschrock * See section 5.2 for a description of the completion codes. 919113a79cSeschrock */ 929113a79cSeschrock static struct ipmi_err_conv { 939113a79cSeschrock int bmc_err; 949113a79cSeschrock int ipmi_err; 959113a79cSeschrock } ipmi_errtable[] = { 969113a79cSeschrock { 0xC0, EIPMI_BUSY }, 979113a79cSeschrock { 0xC1, EIPMI_INVALID_COMMAND }, 989113a79cSeschrock { 0xC2, EIPMI_INVALID_COMMAND }, 999113a79cSeschrock { 0xC3, EIPMI_COMMAND_TIMEOUT }, 1009113a79cSeschrock { 0xC4, EIPMI_NOSPACE }, 1019113a79cSeschrock { 0xC5, EIPMI_INVALID_RESERVATION }, 1029113a79cSeschrock { 0xC6, EIPMI_INVALID_REQUEST }, 1039113a79cSeschrock { 0xC7, EIPMI_INVALID_REQUEST }, 1049113a79cSeschrock { 0xC8, EIPMI_INVALID_REQUEST }, 1059113a79cSeschrock { 0xC9, EIPMI_INVALID_REQUEST }, 1069113a79cSeschrock { 0xCA, EIPMI_DATA_LENGTH_EXCEEDED }, 1079113a79cSeschrock { 0xCB, EIPMI_NOT_PRESENT }, 1089113a79cSeschrock { 0xCC, EIPMI_INVALID_REQUEST }, 1099113a79cSeschrock { 0xCD, EIPMI_INVALID_COMMAND }, 1109113a79cSeschrock { 0xCE, EIPMI_UNAVAILABLE }, 1119113a79cSeschrock { 0xCF, EIPMI_UNAVAILABLE }, 1129113a79cSeschrock { 0xD0, EIPMI_BUSY }, 1139113a79cSeschrock { 0xD1, EIPMI_BUSY }, 1149113a79cSeschrock { 0xD2, EIPMI_BUSY }, 1159113a79cSeschrock { 0xD3, EIPMI_NOT_PRESENT }, 1169113a79cSeschrock { 0xD4, EIPMI_ACCESS }, 1179113a79cSeschrock { 0xD5, EIPMI_UNAVAILABLE }, 1189113a79cSeschrock { 0xD6, EIPMI_UNAVAILABLE }, 1199113a79cSeschrock { 0xFF, EIPMI_UNSPECIFIED }, 1209113a79cSeschrock }; 1219113a79cSeschrock 1229113a79cSeschrock #define IPMI_ERROR_COUNT \ 1239113a79cSeschrock (sizeof (ipmi_errtable) / sizeof (ipmi_errtable[0])) 1249113a79cSeschrock 1259113a79cSeschrock ipmi_cmd_t * 1269113a79cSeschrock ipmi_send(ipmi_handle_t *ihp, ipmi_cmd_t *cmd) 1279113a79cSeschrock { 1289113a79cSeschrock int i; 1299113a79cSeschrock 1309113a79cSeschrock if (ihp->ih_transport->it_send(ihp->ih_tdata, cmd, &ihp->ih_response, 131283bfb4dSEric Schrock &ihp->ih_completion) != 0) 1329113a79cSeschrock return (NULL); 1339113a79cSeschrock 134283bfb4dSEric Schrock if (ihp->ih_completion != 0) { 1359113a79cSeschrock for (i = 0; i < IPMI_ERROR_COUNT; i++) { 136283bfb4dSEric Schrock if (ihp->ih_completion == ipmi_errtable[i].bmc_err) { 1379113a79cSeschrock (void) ipmi_set_error(ihp, 1389113a79cSeschrock ipmi_errtable[i].ipmi_err, 139283bfb4dSEric Schrock "IPMI completion code 0x%x", 140283bfb4dSEric Schrock ihp->ih_completion); 1419113a79cSeschrock return (NULL); 1429113a79cSeschrock } 1439113a79cSeschrock } 1449113a79cSeschrock 1459113a79cSeschrock (void) ipmi_set_error(ihp, EIPMI_UNKNOWN, 146283bfb4dSEric Schrock "IPMI completion code 0x%x", ihp->ih_completion); 1479113a79cSeschrock return (NULL); 1489113a79cSeschrock } 1499113a79cSeschrock 1509113a79cSeschrock return (&ihp->ih_response); 1519113a79cSeschrock } 152