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 2007 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 static int 70 check_sunoem(ipmi_handle_t *ihp) 71 { 72 ipmi_deviceid_t *devid; 73 74 if ((devid = ipmi_get_deviceid(ihp)) == NULL) 75 return (-1); 76 77 if (ipmi_devid_manufacturer(devid) != IPMI_OEM_SUN) 78 return (ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, NULL)); 79 80 return (0); 81 } 82 83 static int 84 ipmi_send_sunoem_led_set(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_set_t *req) 85 { 86 ipmi_cmd_t cmd, *resp; 87 88 cmd.ic_netfn = IPMI_NETFN_OEM; 89 cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_SET; 90 cmd.ic_lun = 0; 91 cmd.ic_data = req; 92 cmd.ic_dlen = sizeof (*req); 93 94 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 95 return (-1); 96 97 if (resp->ic_dlen != 0) 98 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 99 100 return (0); 101 } 102 103 static int 104 ipmi_send_sunoem_led_get(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_get_t *req, 105 uint8_t *result) 106 { 107 ipmi_cmd_t cmd, *resp; 108 109 cmd.ic_netfn = IPMI_NETFN_OEM; 110 cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_GET; 111 cmd.ic_lun = 0; 112 cmd.ic_data = req; 113 cmd.ic_dlen = sizeof (*req); 114 115 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 116 return (-1); 117 118 if (resp->ic_dlen != 1) 119 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 120 121 *result = *((uint8_t *)resp->ic_data); 122 return (0); 123 } 124 125 int 126 ipmi_sunoem_led_set(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev, 127 uint8_t mode) 128 { 129 ipmi_cmd_sunoem_led_set_t cmd = { 0 }; 130 131 if (check_sunoem(ihp) != 0) 132 return (-1); 133 134 cmd.ic_sls_slaveaddr = dev->is_gl_slaveaddr; 135 cmd.ic_sls_channel_msb = dev->is_gl_channel_msb; 136 cmd.ic_sls_type = dev->is_gl_oem; 137 cmd.ic_sls_accessaddr = dev->is_gl_accessaddr; 138 cmd.ic_sls_hwinfo = dev->is_gl_oem; 139 cmd.ic_sls_mode = mode; 140 141 return (ipmi_send_sunoem_led_set(ihp, &cmd)); 142 } 143 144 int 145 ipmi_sunoem_led_get(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev, 146 uint8_t *mode) 147 { 148 ipmi_cmd_sunoem_led_get_t cmd = { 0 }; 149 150 if (check_sunoem(ihp) != 0) 151 return (-1); 152 153 cmd.ic_slg_slaveaddr = dev->is_gl_slaveaddr; 154 cmd.ic_slg_channel_msb = dev->is_gl_channel_msb; 155 cmd.ic_slg_type = dev->is_gl_oem; 156 cmd.ic_slg_accessaddr = dev->is_gl_accessaddr; 157 cmd.ic_slg_hwinfo = dev->is_gl_oem; 158 159 return (ipmi_send_sunoem_led_get(ihp, &cmd, mode)); 160 } 161 162 int 163 ipmi_sunoem_uptime(ipmi_handle_t *ihp, uint32_t *uptime, uint32_t *gen) 164 { 165 ipmi_cmd_t cmd, *resp; 166 uint8_t unused; 167 168 if (check_sunoem(ihp) != 0) 169 return (-1); 170 171 cmd.ic_netfn = IPMI_NETFN_OEM; 172 cmd.ic_lun = 0; 173 cmd.ic_cmd = IPMI_CMD_SUNOEM_UPTIME; 174 cmd.ic_dlen = sizeof (unused); 175 cmd.ic_data = &unused; 176 177 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 178 return (-1); 179 180 if (resp->ic_dlen != 2 * sizeof (uint32_t)) 181 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 182 183 if (uptime) 184 *uptime = BE_32(((uint32_t *)resp->ic_data)[0]); 185 if (gen) 186 *gen = BE_32(((uint32_t *)resp->ic_data)[1]); 187 188 return (0); 189 } 190 191 int 192 ipmi_sunoem_update_fru(ipmi_handle_t *ihp, ipmi_sunoem_fru_t *req) 193 { 194 ipmi_cmd_t cmd, *resp; 195 196 if (check_sunoem(ihp) != 0) 197 return (-1); 198 199 switch (req->isf_type) { 200 case IPMI_SUNOEM_FRU_DIMM: 201 req->isf_datalen = sizeof (req->isf_data.dimm); 202 break; 203 204 case IPMI_SUNOEM_FRU_CPU: 205 req->isf_datalen = sizeof (req->isf_data.cpu); 206 break; 207 208 case IPMI_SUNOEM_FRU_BIOS: 209 req->isf_datalen = sizeof (req->isf_data.bios); 210 break; 211 212 case IPMI_SUNOEM_FRU_DISK: 213 req->isf_datalen = sizeof (req->isf_data.disk); 214 break; 215 } 216 217 cmd.ic_netfn = IPMI_NETFN_OEM; 218 cmd.ic_cmd = IPMI_CMD_SUNOEM_FRU_UPDATE; 219 cmd.ic_lun = 0; 220 cmd.ic_dlen = offsetof(ipmi_sunoem_fru_t, isf_data) + 221 req->isf_datalen; 222 cmd.ic_data = req; 223 224 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 225 return (-1); 226 227 if (resp->ic_dlen != 0) 228 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL)); 229 230 return (0); 231 } 232