Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <libipmi.h>
     28 #include <stddef.h>
     29 
     30 #include "ipmi_impl.h"
     31 
     32 #define	IPMI_CMD_SUNOEM_LED_GET		0x21
     33 #define	IPMI_CMD_SUNOEM_LED_SET		0x22
     34 
     35 typedef struct ipmi_cmd_sunoem_led_set {
     36 	DECL_BITFIELD2(
     37 	    ic_sls_channel_msb		:1,	/* device slave address */
     38 	    ic_sls_slaveaddr		:7);	/* (from SDR record) */
     39 	uint8_t		ic_sls_type;		/* led type */
     40 	DECL_BITFIELD2(
     41 	    __reserved			:1,	/* device access address */
     42 	    ic_sls_accessaddr		:7);	/* (from SDR record */
     43 	uint8_t		ic_sls_hwinfo;		/* OEM hardware info */
     44 	uint8_t		ic_sls_mode;		/* LED mode */
     45 	uint8_t		ic_sls_eid;		/* entity ID */
     46 	uint8_t		ic_sls_einst;		/* entity instance */
     47 	uint8_t		ic_sls_force;		/* force direct access */
     48 	uint8_t		ic_sls_role;		/* BMC authorization */
     49 } ipmi_cmd_sunoem_led_set_t;
     50 
     51 typedef struct ipmi_cmd_sunoem_led_get {
     52 	DECL_BITFIELD2(
     53 	    ic_slg_channel_msb		:1,	/* device slave address */
     54 	    ic_slg_slaveaddr		:7);	/* (from SDR record) */
     55 	uint8_t		ic_slg_type;		/* led type */
     56 	DECL_BITFIELD2(
     57 	    __reserved			:1,	/* device access address */
     58 	    ic_slg_accessaddr		:7);	/* (from SDR record */
     59 	uint8_t		ic_slg_hwinfo;		/* OEM hardware info */
     60 	uint8_t		ic_slg_eid;		/* entity ID */
     61 	uint8_t		ic_slg_einst;		/* entity instance */
     62 	uint8_t		ic_slg_force;		/* force direct access */
     63 } ipmi_cmd_sunoem_led_get_t;
     64 
     65 #define	IPMI_SUNOEM_LED_TYPE_OK2RM	0
     66 #define	IPMI_SUNOEM_LED_TYPE_SERVICE	1
     67 #define	IPMI_SUNOEM_LED_TYPE_ACT	2
     68 #define	IPMI_SUNOEM_LED_TYPE_LOCATE	3
     69 #define	IPMI_SUNOEM_LED_TYPE_ANY	0xFF
     70 
     71 boolean_t
     72 ipmi_is_sun_ilom(ipmi_deviceid_t *dp)
     73 {
     74 	return (ipmi_devid_manufacturer(dp) == IPMI_OEM_SUN &&
     75 	    dp->id_product == IPMI_PROD_SUN_ILOM);
     76 }
     77 
     78 static int
     79 check_sunoem(ipmi_handle_t *ihp)
     80 {
     81 	ipmi_deviceid_t *devid;
     82 
     83 	if ((devid = ipmi_get_deviceid(ihp)) == NULL)
     84 		return (-1);
     85 
     86 	if (!ipmi_is_sun_ilom(devid))
     87 		return (ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, NULL));
     88 
     89 	return (0);
     90 }
     91 
     92 static int
     93 ipmi_send_sunoem_led_set(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_set_t *req)
     94 {
     95 	ipmi_cmd_t cmd, *resp;
     96 
     97 	cmd.ic_netfn = IPMI_NETFN_OEM;
     98 	cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_SET;
     99 	cmd.ic_lun = 0;
    100 	cmd.ic_data = req;
    101 	cmd.ic_dlen = sizeof (*req);
    102 
    103 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
    104 		return (-1);
    105 
    106 	if (resp->ic_dlen != 0)
    107 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
    108 
    109 	return (0);
    110 }
    111 
    112 static int
    113 ipmi_send_sunoem_led_get(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_get_t *req,
    114     uint8_t *result)
    115 {
    116 	ipmi_cmd_t cmd, *resp;
    117 
    118 	cmd.ic_netfn = IPMI_NETFN_OEM;
    119 	cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_GET;
    120 	cmd.ic_lun = 0;
    121 	cmd.ic_data = req;
    122 	cmd.ic_dlen = sizeof (*req);
    123 
    124 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
    125 		return (-1);
    126 
    127 	if (resp->ic_dlen != 1)
    128 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
    129 
    130 	*result = *((uint8_t *)resp->ic_data);
    131 	return (0);
    132 }
    133 
    134 int
    135 ipmi_sunoem_led_set(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev,
    136     uint8_t mode)
    137 {
    138 	ipmi_cmd_sunoem_led_set_t cmd = { 0 };
    139 
    140 	if (check_sunoem(ihp) != 0)
    141 		return (-1);
    142 
    143 	cmd.ic_sls_slaveaddr = dev->is_gl_slaveaddr;
    144 	cmd.ic_sls_channel_msb = dev->is_gl_channel_msb;
    145 	cmd.ic_sls_type = dev->is_gl_oem;
    146 	cmd.ic_sls_accessaddr = dev->is_gl_accessaddr;
    147 	cmd.ic_sls_hwinfo = dev->is_gl_oem;
    148 	cmd.ic_sls_mode = mode;
    149 	cmd.ic_sls_eid = dev->is_gl_entity;
    150 	cmd.ic_sls_einst = dev->is_gl_instance;
    151 
    152 	return (ipmi_send_sunoem_led_set(ihp, &cmd));
    153 }
    154 
    155 int
    156 ipmi_sunoem_led_get(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev,
    157     uint8_t *mode)
    158 {
    159 	ipmi_cmd_sunoem_led_get_t cmd = { 0 };
    160 
    161 	if (check_sunoem(ihp) != 0)
    162 		return (-1);
    163 
    164 	cmd.ic_slg_slaveaddr = dev->is_gl_slaveaddr;
    165 	cmd.ic_slg_channel_msb = dev->is_gl_channel_msb;
    166 	cmd.ic_slg_type = dev->is_gl_oem;
    167 	cmd.ic_slg_accessaddr = dev->is_gl_accessaddr;
    168 	cmd.ic_slg_hwinfo = dev->is_gl_oem;
    169 	cmd.ic_slg_eid = dev->is_gl_entity;
    170 	cmd.ic_slg_einst = dev->is_gl_instance;
    171 
    172 	return (ipmi_send_sunoem_led_get(ihp, &cmd, mode));
    173 }
    174 
    175 int
    176 ipmi_sunoem_uptime(ipmi_handle_t *ihp, uint32_t *uptime, uint32_t *gen)
    177 {
    178 	ipmi_cmd_t cmd, *resp;
    179 	uint8_t unused;
    180 
    181 	if (check_sunoem(ihp) != 0)
    182 		return (-1);
    183 
    184 	cmd.ic_netfn = IPMI_NETFN_OEM;
    185 	cmd.ic_lun = 0;
    186 	cmd.ic_cmd = IPMI_CMD_SUNOEM_UPTIME;
    187 	cmd.ic_dlen = sizeof (unused);
    188 	cmd.ic_data = &unused;
    189 
    190 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
    191 		return (-1);
    192 
    193 	if (resp->ic_dlen != 2 * sizeof (uint32_t))
    194 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
    195 
    196 	if (uptime)
    197 		*uptime = BE_IN32(&((uint32_t *)resp->ic_data)[0]);
    198 	if (gen)
    199 		*gen = BE_IN32(&((uint32_t *)resp->ic_data)[1]);
    200 
    201 	return (0);
    202 }
    203 
    204 int
    205 ipmi_sunoem_update_fru(ipmi_handle_t *ihp, ipmi_sunoem_fru_t *req)
    206 {
    207 	ipmi_cmd_t cmd, *resp;
    208 
    209 	if (check_sunoem(ihp) != 0)
    210 		return (-1);
    211 
    212 	switch (req->isf_type) {
    213 	case IPMI_SUNOEM_FRU_DIMM:
    214 		req->isf_datalen = sizeof (req->isf_data.dimm);
    215 		break;
    216 
    217 	case IPMI_SUNOEM_FRU_CPU:
    218 		req->isf_datalen = sizeof (req->isf_data.cpu);
    219 		break;
    220 
    221 	case IPMI_SUNOEM_FRU_BIOS:
    222 		req->isf_datalen = sizeof (req->isf_data.bios);
    223 		break;
    224 
    225 	case IPMI_SUNOEM_FRU_DISK:
    226 		req->isf_datalen = sizeof (req->isf_data.disk);
    227 		break;
    228 	}
    229 
    230 	cmd.ic_netfn = IPMI_NETFN_OEM;
    231 	cmd.ic_cmd = IPMI_CMD_SUNOEM_FRU_UPDATE;
    232 	cmd.ic_lun = 0;
    233 	cmd.ic_dlen = offsetof(ipmi_sunoem_fru_t, isf_data) +
    234 	    req->isf_datalen;
    235 	cmd.ic_data = req;
    236 
    237 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
    238 		return (-1);
    239 
    240 	if (resp->ic_dlen != 0)
    241 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
    242 
    243 	return (0);
    244 }
    245