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 2010 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 ipmi_devid_product(dp) == 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