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 static int
35 check_sunoem(ipmi_handle_t *ihp)
36 {
37 	ipmi_deviceid_t *devid;
38 
39 	if ((devid = ipmi_get_deviceid(ihp)) == NULL)
40 		return (-1);
41 
42 	if (ipmi_devid_manufacturer(devid) != IPMI_OEM_SUN)
43 		return (ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, NULL));
44 
45 	return (0);
46 }
47 
48 static int
49 ipmi_send_sunoem_led_set(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_set_t *req)
50 {
51 	ipmi_cmd_t cmd, *resp;
52 
53 	cmd.ic_netfn = IPMI_NETFN_OEM;
54 	cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_SET;
55 	cmd.ic_lun = 0;
56 	cmd.ic_data = req;
57 	cmd.ic_dlen = sizeof (*req);
58 
59 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
60 		return (-1);
61 
62 	if (resp->ic_dlen != 0)
63 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
64 
65 	return (0);
66 }
67 
68 static int
69 ipmi_send_sunoem_led_get(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_get_t *req,
70     uint8_t *result)
71 {
72 	ipmi_cmd_t cmd, *resp;
73 
74 	cmd.ic_netfn = IPMI_NETFN_OEM;
75 	cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_GET;
76 	cmd.ic_lun = 0;
77 	cmd.ic_data = req;
78 	cmd.ic_dlen = sizeof (*req);
79 
80 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
81 		return (-1);
82 
83 	if (resp->ic_dlen != 1)
84 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
85 
86 	*result = *((uint8_t *)resp->ic_data);
87 	return (0);
88 }
89 
90 int
91 ipmi_sunoem_led_set(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev,
92     uint8_t mode)
93 {
94 	ipmi_cmd_sunoem_led_set_t cmd = { 0 };
95 
96 	if (check_sunoem(ihp) != 0)
97 		return (-1);
98 
99 	cmd.ic_sls_slaveaddr = dev->is_gl_slaveaddr;
100 	cmd.ic_sls_channel_msb = dev->is_gl_channel_msb;
101 	cmd.ic_sls_type = dev->is_gl_oem;
102 	cmd.ic_sls_accessaddr = dev->is_gl_accessaddr;
103 	cmd.ic_sls_hwinfo = dev->is_gl_oem;
104 	cmd.ic_sls_mode = mode;
105 
106 	return (ipmi_send_sunoem_led_set(ihp, &cmd));
107 }
108 
109 int
110 ipmi_sunoem_led_get(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev,
111     uint8_t *mode)
112 {
113 	ipmi_cmd_sunoem_led_get_t cmd = { 0 };
114 
115 	if (check_sunoem(ihp) != 0)
116 		return (-1);
117 
118 	cmd.ic_slg_slaveaddr = dev->is_gl_slaveaddr;
119 	cmd.ic_slg_channel_msb = dev->is_gl_channel_msb;
120 	cmd.ic_slg_type = dev->is_gl_oem;
121 	cmd.ic_slg_accessaddr = dev->is_gl_accessaddr;
122 	cmd.ic_slg_hwinfo = dev->is_gl_oem;
123 
124 	return (ipmi_send_sunoem_led_get(ihp, &cmd, mode));
125 }
126 
127 int
128 ipmi_sunoem_uptime(ipmi_handle_t *ihp, uint32_t *uptime, uint32_t *gen)
129 {
130 	ipmi_cmd_t cmd, *resp;
131 	uint8_t unused;
132 
133 	if (check_sunoem(ihp) != 0)
134 		return (-1);
135 
136 	cmd.ic_netfn = IPMI_NETFN_OEM;
137 	cmd.ic_lun = 0;
138 	cmd.ic_cmd = IPMI_CMD_SUNOEM_UPTIME;
139 	cmd.ic_dlen = sizeof (unused);
140 	cmd.ic_data = &unused;
141 
142 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
143 		return (-1);
144 
145 	if (resp->ic_dlen != 2 * sizeof (uint32_t))
146 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
147 
148 	if (uptime)
149 		*uptime = BE_32(((uint32_t *)resp->ic_data)[0]);
150 	if (gen)
151 		*gen = BE_32(((uint32_t *)resp->ic_data)[1]);
152 
153 	return (0);
154 }
155 
156 int
157 ipmi_sunoem_update_fru(ipmi_handle_t *ihp, ipmi_sunoem_fru_t *req)
158 {
159 	ipmi_cmd_t cmd, *resp;
160 
161 	if (check_sunoem(ihp) != 0)
162 		return (-1);
163 
164 	switch (req->isf_type) {
165 	case IPMI_SUNOEM_FRU_DIMM:
166 		req->isf_datalen = sizeof (req->isf_data.dimm);
167 		break;
168 
169 	case IPMI_SUNOEM_FRU_CPU:
170 		req->isf_datalen = sizeof (req->isf_data.cpu);
171 		break;
172 
173 	case IPMI_SUNOEM_FRU_BIOS:
174 		req->isf_datalen = sizeof (req->isf_data.bios);
175 		break;
176 
177 	case IPMI_SUNOEM_FRU_DISK:
178 		req->isf_datalen = sizeof (req->isf_data.disk);
179 		break;
180 	}
181 
182 	cmd.ic_netfn = IPMI_NETFN_OEM;
183 	cmd.ic_cmd = IPMI_CMD_SUNOEM_FRU_UPDATE;
184 	cmd.ic_lun = 0;
185 	cmd.ic_dlen = offsetof(ipmi_sunoem_fru_t, isf_data) +
186 	    req->isf_datalen;
187 	cmd.ic_data = req;
188 
189 	if ((resp = ipmi_send(ihp, &cmd)) == NULL)
190 		return (-1);
191 
192 	if (resp->ic_dlen != 0)
193 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
194 
195 	return (0);
196 }
197