xref: /titanic_51/usr/src/lib/libipmi/common/ipmi_sunoem.c (revision 81d9f076db88c1f40c85831ce1ebb444a209c5a8)
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