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 229113a79cSeschrock /* 23*81d9f076SRobert Johnston * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 249113a79cSeschrock * Use is subject to license terms. 259113a79cSeschrock */ 269113a79cSeschrock 279113a79cSeschrock #include <libipmi.h> 289113a79cSeschrock #include <stddef.h> 299113a79cSeschrock 309113a79cSeschrock #include "ipmi_impl.h" 319113a79cSeschrock 322c32020fSeschrock #define IPMI_CMD_SUNOEM_LED_GET 0x21 332c32020fSeschrock #define IPMI_CMD_SUNOEM_LED_SET 0x22 342c32020fSeschrock 352c32020fSeschrock typedef struct ipmi_cmd_sunoem_led_set { 362c32020fSeschrock DECL_BITFIELD2( 372c32020fSeschrock ic_sls_channel_msb :1, /* device slave address */ 382c32020fSeschrock ic_sls_slaveaddr :7); /* (from SDR record) */ 392c32020fSeschrock uint8_t ic_sls_type; /* led type */ 402c32020fSeschrock DECL_BITFIELD2( 412c32020fSeschrock __reserved :1, /* device access address */ 422c32020fSeschrock ic_sls_accessaddr :7); /* (from SDR record */ 432c32020fSeschrock uint8_t ic_sls_hwinfo; /* OEM hardware info */ 442c32020fSeschrock uint8_t ic_sls_mode; /* LED mode */ 4588045cffSRobert Johnston uint8_t ic_sls_eid; /* entity ID */ 4688045cffSRobert Johnston uint8_t ic_sls_einst; /* entity instance */ 472c32020fSeschrock uint8_t ic_sls_force; /* force direct access */ 482c32020fSeschrock uint8_t ic_sls_role; /* BMC authorization */ 492c32020fSeschrock } ipmi_cmd_sunoem_led_set_t; 502c32020fSeschrock 512c32020fSeschrock typedef struct ipmi_cmd_sunoem_led_get { 522c32020fSeschrock DECL_BITFIELD2( 532c32020fSeschrock ic_slg_channel_msb :1, /* device slave address */ 542c32020fSeschrock ic_slg_slaveaddr :7); /* (from SDR record) */ 552c32020fSeschrock uint8_t ic_slg_type; /* led type */ 562c32020fSeschrock DECL_BITFIELD2( 572c32020fSeschrock __reserved :1, /* device access address */ 582c32020fSeschrock ic_slg_accessaddr :7); /* (from SDR record */ 592c32020fSeschrock uint8_t ic_slg_hwinfo; /* OEM hardware info */ 6088045cffSRobert Johnston uint8_t ic_slg_eid; /* entity ID */ 6188045cffSRobert Johnston uint8_t ic_slg_einst; /* entity instance */ 622c32020fSeschrock uint8_t ic_slg_force; /* force direct access */ 632c32020fSeschrock } ipmi_cmd_sunoem_led_get_t; 642c32020fSeschrock 652c32020fSeschrock #define IPMI_SUNOEM_LED_TYPE_OK2RM 0 662c32020fSeschrock #define IPMI_SUNOEM_LED_TYPE_SERVICE 1 672c32020fSeschrock #define IPMI_SUNOEM_LED_TYPE_ACT 2 682c32020fSeschrock #define IPMI_SUNOEM_LED_TYPE_LOCATE 3 692c32020fSeschrock #define IPMI_SUNOEM_LED_TYPE_ANY 0xFF 702c32020fSeschrock 712eeaed14Srobj boolean_t 722eeaed14Srobj ipmi_is_sun_ilom(ipmi_deviceid_t *dp) 732eeaed14Srobj { 742eeaed14Srobj return (ipmi_devid_manufacturer(dp) == IPMI_OEM_SUN && 75*81d9f076SRobert Johnston ipmi_devid_product(dp) == IPMI_PROD_SUN_ILOM); 762eeaed14Srobj } 772eeaed14Srobj 789113a79cSeschrock static int 799113a79cSeschrock check_sunoem(ipmi_handle_t *ihp) 809113a79cSeschrock { 819113a79cSeschrock ipmi_deviceid_t *devid; 829113a79cSeschrock 839113a79cSeschrock if ((devid = ipmi_get_deviceid(ihp)) == NULL) 849113a79cSeschrock return (-1); 859113a79cSeschrock 862eeaed14Srobj if (!ipmi_is_sun_ilom(devid)) 879113a79cSeschrock return (ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, NULL)); 889113a79cSeschrock 899113a79cSeschrock return (0); 909113a79cSeschrock } 919113a79cSeschrock 929113a79cSeschrock static int 939113a79cSeschrock ipmi_send_sunoem_led_set(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_set_t *req) 949113a79cSeschrock { 959113a79cSeschrock ipmi_cmd_t cmd, *resp; 969113a79cSeschrock 979113a79cSeschrock cmd.ic_netfn = IPMI_NETFN_OEM; 989113a79cSeschrock cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_SET; 999113a79cSeschrock cmd.ic_lun = 0; 1009113a79cSeschrock cmd.ic_data = req; 1019113a79cSeschrock cmd.ic_dlen = sizeof (*req); 1029113a79cSeschrock 1039113a79cSeschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 1049113a79cSeschrock return (-1); 1059113a79cSeschrock 1069113a79cSeschrock if (resp->ic_dlen != 0) 1079113a79cSeschrock return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 1089113a79cSeschrock 1099113a79cSeschrock return (0); 1109113a79cSeschrock } 1119113a79cSeschrock 1129113a79cSeschrock static int 1139113a79cSeschrock ipmi_send_sunoem_led_get(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_get_t *req, 1149113a79cSeschrock uint8_t *result) 1159113a79cSeschrock { 1169113a79cSeschrock ipmi_cmd_t cmd, *resp; 1179113a79cSeschrock 1189113a79cSeschrock cmd.ic_netfn = IPMI_NETFN_OEM; 1199113a79cSeschrock cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_GET; 1209113a79cSeschrock cmd.ic_lun = 0; 1219113a79cSeschrock cmd.ic_data = req; 1229113a79cSeschrock cmd.ic_dlen = sizeof (*req); 1239113a79cSeschrock 1249113a79cSeschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 1259113a79cSeschrock return (-1); 1269113a79cSeschrock 1279113a79cSeschrock if (resp->ic_dlen != 1) 1289113a79cSeschrock return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 1299113a79cSeschrock 1309113a79cSeschrock *result = *((uint8_t *)resp->ic_data); 1319113a79cSeschrock return (0); 1329113a79cSeschrock } 1339113a79cSeschrock 1349113a79cSeschrock int 1359113a79cSeschrock ipmi_sunoem_led_set(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev, 1369113a79cSeschrock uint8_t mode) 1379113a79cSeschrock { 1389113a79cSeschrock ipmi_cmd_sunoem_led_set_t cmd = { 0 }; 1399113a79cSeschrock 1409113a79cSeschrock if (check_sunoem(ihp) != 0) 1419113a79cSeschrock return (-1); 1429113a79cSeschrock 143a10acbd6Seschrock cmd.ic_sls_slaveaddr = dev->is_gl_slaveaddr; 144a10acbd6Seschrock cmd.ic_sls_channel_msb = dev->is_gl_channel_msb; 1459113a79cSeschrock cmd.ic_sls_type = dev->is_gl_oem; 146a10acbd6Seschrock cmd.ic_sls_accessaddr = dev->is_gl_accessaddr; 1479113a79cSeschrock cmd.ic_sls_hwinfo = dev->is_gl_oem; 1489113a79cSeschrock cmd.ic_sls_mode = mode; 14988045cffSRobert Johnston cmd.ic_sls_eid = dev->is_gl_entity; 15088045cffSRobert Johnston cmd.ic_sls_einst = dev->is_gl_instance; 1519113a79cSeschrock 1529113a79cSeschrock return (ipmi_send_sunoem_led_set(ihp, &cmd)); 1539113a79cSeschrock } 1549113a79cSeschrock 1559113a79cSeschrock int 1569113a79cSeschrock ipmi_sunoem_led_get(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev, 1579113a79cSeschrock uint8_t *mode) 1589113a79cSeschrock { 1599113a79cSeschrock ipmi_cmd_sunoem_led_get_t cmd = { 0 }; 1609113a79cSeschrock 1619113a79cSeschrock if (check_sunoem(ihp) != 0) 1629113a79cSeschrock return (-1); 1639113a79cSeschrock 164a10acbd6Seschrock cmd.ic_slg_slaveaddr = dev->is_gl_slaveaddr; 165a10acbd6Seschrock cmd.ic_slg_channel_msb = dev->is_gl_channel_msb; 1669113a79cSeschrock cmd.ic_slg_type = dev->is_gl_oem; 167a10acbd6Seschrock cmd.ic_slg_accessaddr = dev->is_gl_accessaddr; 1689113a79cSeschrock cmd.ic_slg_hwinfo = dev->is_gl_oem; 16988045cffSRobert Johnston cmd.ic_slg_eid = dev->is_gl_entity; 17088045cffSRobert Johnston cmd.ic_slg_einst = dev->is_gl_instance; 1719113a79cSeschrock 1729113a79cSeschrock return (ipmi_send_sunoem_led_get(ihp, &cmd, mode)); 1739113a79cSeschrock } 1749113a79cSeschrock 1759113a79cSeschrock int 1769113a79cSeschrock ipmi_sunoem_uptime(ipmi_handle_t *ihp, uint32_t *uptime, uint32_t *gen) 1779113a79cSeschrock { 1789113a79cSeschrock ipmi_cmd_t cmd, *resp; 1799113a79cSeschrock uint8_t unused; 1809113a79cSeschrock 1819113a79cSeschrock if (check_sunoem(ihp) != 0) 1829113a79cSeschrock return (-1); 1839113a79cSeschrock 1849113a79cSeschrock cmd.ic_netfn = IPMI_NETFN_OEM; 1859113a79cSeschrock cmd.ic_lun = 0; 1869113a79cSeschrock cmd.ic_cmd = IPMI_CMD_SUNOEM_UPTIME; 1879113a79cSeschrock cmd.ic_dlen = sizeof (unused); 1889113a79cSeschrock cmd.ic_data = &unused; 1899113a79cSeschrock 1909113a79cSeschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 1919113a79cSeschrock return (-1); 1929113a79cSeschrock 1939113a79cSeschrock if (resp->ic_dlen != 2 * sizeof (uint32_t)) 1949113a79cSeschrock return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 1959113a79cSeschrock 1969113a79cSeschrock if (uptime) 197918a0d8aSrobj *uptime = BE_IN32(&((uint32_t *)resp->ic_data)[0]); 1989113a79cSeschrock if (gen) 199918a0d8aSrobj *gen = BE_IN32(&((uint32_t *)resp->ic_data)[1]); 2009113a79cSeschrock 2019113a79cSeschrock return (0); 2029113a79cSeschrock } 2039113a79cSeschrock 2049113a79cSeschrock int 2059113a79cSeschrock ipmi_sunoem_update_fru(ipmi_handle_t *ihp, ipmi_sunoem_fru_t *req) 2069113a79cSeschrock { 2079113a79cSeschrock ipmi_cmd_t cmd, *resp; 2089113a79cSeschrock 2099113a79cSeschrock if (check_sunoem(ihp) != 0) 2109113a79cSeschrock return (-1); 2119113a79cSeschrock 2129113a79cSeschrock switch (req->isf_type) { 2139113a79cSeschrock case IPMI_SUNOEM_FRU_DIMM: 2149113a79cSeschrock req->isf_datalen = sizeof (req->isf_data.dimm); 2159113a79cSeschrock break; 2169113a79cSeschrock 2179113a79cSeschrock case IPMI_SUNOEM_FRU_CPU: 2189113a79cSeschrock req->isf_datalen = sizeof (req->isf_data.cpu); 2199113a79cSeschrock break; 2209113a79cSeschrock 2219113a79cSeschrock case IPMI_SUNOEM_FRU_BIOS: 2229113a79cSeschrock req->isf_datalen = sizeof (req->isf_data.bios); 2239113a79cSeschrock break; 2249113a79cSeschrock 2259113a79cSeschrock case IPMI_SUNOEM_FRU_DISK: 2269113a79cSeschrock req->isf_datalen = sizeof (req->isf_data.disk); 2279113a79cSeschrock break; 2289113a79cSeschrock } 2299113a79cSeschrock 2309113a79cSeschrock cmd.ic_netfn = IPMI_NETFN_OEM; 2319113a79cSeschrock cmd.ic_cmd = IPMI_CMD_SUNOEM_FRU_UPDATE; 2329113a79cSeschrock cmd.ic_lun = 0; 2339113a79cSeschrock cmd.ic_dlen = offsetof(ipmi_sunoem_fru_t, isf_data) + 2349113a79cSeschrock req->isf_datalen; 2359113a79cSeschrock cmd.ic_data = req; 2369113a79cSeschrock 2379113a79cSeschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 2389113a79cSeschrock return (-1); 2399113a79cSeschrock 2409113a79cSeschrock if (resp->ic_dlen != 0) 2419113a79cSeschrock return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 2429113a79cSeschrock 2439113a79cSeschrock return (0); 2449113a79cSeschrock } 245