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
ipmi_is_sun_ilom(ipmi_deviceid_t * dp)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
check_sunoem(ipmi_handle_t * ihp)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
ipmi_send_sunoem_led_set(ipmi_handle_t * ihp,ipmi_cmd_sunoem_led_set_t * req)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
ipmi_send_sunoem_led_get(ipmi_handle_t * ihp,ipmi_cmd_sunoem_led_get_t * req,uint8_t * result)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
ipmi_sunoem_led_set(ipmi_handle_t * ihp,ipmi_sdr_generic_locator_t * dev,uint8_t mode)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
ipmi_sunoem_led_get(ipmi_handle_t * ihp,ipmi_sdr_generic_locator_t * dev,uint8_t * mode)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
ipmi_sunoem_uptime(ipmi_handle_t * ihp,uint32_t * uptime,uint32_t * gen)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
ipmi_sunoem_update_fru(ipmi_handle_t * ihp,ipmi_sunoem_fru_t * req)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