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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <libipmi.h> 30 #include <stddef.h> 31 32 #include "ipmi_impl.h" 33 34 #define IPMI_CMD_SUNOEM_LED_GET 0x21 35 #define IPMI_CMD_SUNOEM_LED_SET 0x22 36 37 typedef struct ipmi_cmd_sunoem_led_set { 38 DECL_BITFIELD2( 39 ic_sls_channel_msb :1, /* device slave address */ 40 ic_sls_slaveaddr :7); /* (from SDR record) */ 41 uint8_t ic_sls_type; /* led type */ 42 DECL_BITFIELD2( 43 __reserved :1, /* device access address */ 44 ic_sls_accessaddr :7); /* (from SDR record */ 45 uint8_t ic_sls_hwinfo; /* OEM hardware info */ 46 uint8_t ic_sls_mode; /* LED mode */ 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_force; /* force direct access */ 61 } ipmi_cmd_sunoem_led_get_t; 62 63 #define IPMI_SUNOEM_LED_TYPE_OK2RM 0 64 #define IPMI_SUNOEM_LED_TYPE_SERVICE 1 65 #define IPMI_SUNOEM_LED_TYPE_ACT 2 66 #define IPMI_SUNOEM_LED_TYPE_LOCATE 3 67 #define IPMI_SUNOEM_LED_TYPE_ANY 0xFF 68 69 boolean_t 70 ipmi_is_sun_ilom(ipmi_deviceid_t *dp) 71 { 72 return (ipmi_devid_manufacturer(dp) == IPMI_OEM_SUN && 73 dp->id_product == IPMI_PROD_SUN_ILOM); 74 } 75 76 static int 77 check_sunoem(ipmi_handle_t *ihp) 78 { 79 ipmi_deviceid_t *devid; 80 81 if ((devid = ipmi_get_deviceid(ihp)) == NULL) 82 return (-1); 83 84 if (!ipmi_is_sun_ilom(devid)) 85 return (ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, NULL)); 86 87 return (0); 88 } 89 90 static int 91 ipmi_send_sunoem_led_set(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_set_t *req) 92 { 93 ipmi_cmd_t cmd, *resp; 94 95 cmd.ic_netfn = IPMI_NETFN_OEM; 96 cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_SET; 97 cmd.ic_lun = 0; 98 cmd.ic_data = req; 99 cmd.ic_dlen = sizeof (*req); 100 101 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 102 return (-1); 103 104 if (resp->ic_dlen != 0) 105 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 106 107 return (0); 108 } 109 110 static int 111 ipmi_send_sunoem_led_get(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_get_t *req, 112 uint8_t *result) 113 { 114 ipmi_cmd_t cmd, *resp; 115 116 cmd.ic_netfn = IPMI_NETFN_OEM; 117 cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_GET; 118 cmd.ic_lun = 0; 119 cmd.ic_data = req; 120 cmd.ic_dlen = sizeof (*req); 121 122 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 123 return (-1); 124 125 if (resp->ic_dlen != 1) 126 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 127 128 *result = *((uint8_t *)resp->ic_data); 129 return (0); 130 } 131 132 int 133 ipmi_sunoem_led_set(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev, 134 uint8_t mode) 135 { 136 ipmi_cmd_sunoem_led_set_t cmd = { 0 }; 137 138 if (check_sunoem(ihp) != 0) 139 return (-1); 140 141 cmd.ic_sls_slaveaddr = dev->is_gl_slaveaddr; 142 cmd.ic_sls_channel_msb = dev->is_gl_channel_msb; 143 cmd.ic_sls_type = dev->is_gl_oem; 144 cmd.ic_sls_accessaddr = dev->is_gl_accessaddr; 145 cmd.ic_sls_hwinfo = dev->is_gl_oem; 146 cmd.ic_sls_mode = mode; 147 148 return (ipmi_send_sunoem_led_set(ihp, &cmd)); 149 } 150 151 int 152 ipmi_sunoem_led_get(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev, 153 uint8_t *mode) 154 { 155 ipmi_cmd_sunoem_led_get_t cmd = { 0 }; 156 157 if (check_sunoem(ihp) != 0) 158 return (-1); 159 160 cmd.ic_slg_slaveaddr = dev->is_gl_slaveaddr; 161 cmd.ic_slg_channel_msb = dev->is_gl_channel_msb; 162 cmd.ic_slg_type = dev->is_gl_oem; 163 cmd.ic_slg_accessaddr = dev->is_gl_accessaddr; 164 cmd.ic_slg_hwinfo = dev->is_gl_oem; 165 166 return (ipmi_send_sunoem_led_get(ihp, &cmd, mode)); 167 } 168 169 int 170 ipmi_sunoem_uptime(ipmi_handle_t *ihp, uint32_t *uptime, uint32_t *gen) 171 { 172 ipmi_cmd_t cmd, *resp; 173 uint8_t unused; 174 175 if (check_sunoem(ihp) != 0) 176 return (-1); 177 178 cmd.ic_netfn = IPMI_NETFN_OEM; 179 cmd.ic_lun = 0; 180 cmd.ic_cmd = IPMI_CMD_SUNOEM_UPTIME; 181 cmd.ic_dlen = sizeof (unused); 182 cmd.ic_data = &unused; 183 184 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 185 return (-1); 186 187 if (resp->ic_dlen != 2 * sizeof (uint32_t)) 188 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 189 190 if (uptime) 191 *uptime = BE_IN32(&((uint32_t *)resp->ic_data)[0]); 192 if (gen) 193 *gen = BE_IN32(&((uint32_t *)resp->ic_data)[1]); 194 195 return (0); 196 } 197 198 int 199 ipmi_sunoem_update_fru(ipmi_handle_t *ihp, ipmi_sunoem_fru_t *req) 200 { 201 ipmi_cmd_t cmd, *resp; 202 203 if (check_sunoem(ihp) != 0) 204 return (-1); 205 206 switch (req->isf_type) { 207 case IPMI_SUNOEM_FRU_DIMM: 208 req->isf_datalen = sizeof (req->isf_data.dimm); 209 break; 210 211 case IPMI_SUNOEM_FRU_CPU: 212 req->isf_datalen = sizeof (req->isf_data.cpu); 213 break; 214 215 case IPMI_SUNOEM_FRU_BIOS: 216 req->isf_datalen = sizeof (req->isf_data.bios); 217 break; 218 219 case IPMI_SUNOEM_FRU_DISK: 220 req->isf_datalen = sizeof (req->isf_data.disk); 221 break; 222 } 223 224 cmd.ic_netfn = IPMI_NETFN_OEM; 225 cmd.ic_cmd = IPMI_CMD_SUNOEM_FRU_UPDATE; 226 cmd.ic_lun = 0; 227 cmd.ic_dlen = offsetof(ipmi_sunoem_fru_t, isf_data) + 228 req->isf_datalen; 229 cmd.ic_data = req; 230 231 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 232 return (-1); 233 234 if (resp->ic_dlen != 0) 235 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 236 237 return (0); 238 } 239