1 /*
2  * ipmi_control.h
3  *
4  * MontaVista IPMI interface for dealing with controls
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002,2003 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #ifndef OPENIPMI_CONTROL_H
35 #define OPENIPMI_CONTROL_H
36 
37 #include <OpenIPMI/ipmi_types.h>
38 #include <OpenIPMI/ipmi_addr.h>
39 
40 /* The abstract type for controls. */
41 typedef struct ipmi_control_info_s ipmi_control_info_t;
42 
43 /* Allocate a repository for holding controls for an MC. */
44 int ipmi_controls_alloc(ipmi_mc_t *mc, ipmi_control_info_t **new_controls);
45 
46 /* Destroy a control repository and all the controls in it. */
47 int ipmi_controls_destroy(ipmi_control_info_t *controls);
48 
49 /* Must be called with the i_ipmi_domain_entity_lock() held. */
50 int i_ipmi_control_get(ipmi_control_t *control);
51 
52 /* Must be called with no locks held. */
53 void i_ipmi_control_put(ipmi_control_t *control);
54 
55 /* Return the number of controls in the data structure. */
56 unsigned int ipmi_controls_get_count(ipmi_control_info_t *controls);
57 
58 /* Operations and callbacks for control operations.  Operations on a
59    control that can be delayed should be serialized (to avoid user
60    confusion and for handling multi-part operations properly), thus
61    each control has an operation queue, only one operation at a time
62    may be running.  If you want to do an operation that requires
63    sending a message and getting a response, you must put that
64    operation into the opq.  When the handler you registered in the opq
65    is called, you can actually perform the operation.  When your
66    operation completes (no matter what, you must call it, even if the
67    operation fails), you must call ipmi_control_opq_done.  The control
68    will be locked properly for your callback.  To handle the control
69    locking for you for command responses, you can send the message
70    with ipmi_control_send_command, it will return the response when it
71    comes in to your handler with the control locked. */
72 
73 typedef void (*ipmi_control_rsp_cb)(ipmi_control_t *control,
74 				    int            err,
75 				    ipmi_msg_t     *rsp,
76 				    void           *cb_data);
77 
78 typedef struct ipmi_control_op_info_s
79 {
80     ipmi_control_id_t   __control_id;
81     ipmi_control_t      *__control;
82     void                *__cb_data;
83     ipmi_control_op_cb  __handler;
84     ipmi_control_rsp_cb __rsp_handler;
85     ipmi_msg_t          *__rsp;
86 } ipmi_control_op_info_t;
87 
88 /* Add an operation to the control operation queue.  If nothing is in
89    the operation queue, the handler will be performed immediately.  If
90    something else is currently being operated on, the operation will
91    be queued until other operations before it have been completed.
92    Then the handler will be called. */
93 int ipmi_control_add_opq(ipmi_control_t        *control,
94 			ipmi_control_op_cb     handler,
95 			ipmi_control_op_info_t *info,
96 			void                   *cb_data);
97 
98 /* When an operation is completed (even if it fails), this *MUST* be
99    called to cause the next operation to run. */
100 void ipmi_control_opq_done(ipmi_control_t *control);
101 
102 /* Send an IPMI command to a specific MC.  The response handler will
103    be called with the control locked. */
104 int ipmi_control_send_command(ipmi_control_t        *control,
105 			     ipmi_mc_t              *mc,
106 			     unsigned int           lun,
107 			     ipmi_msg_t             *msg,
108 			     ipmi_control_rsp_cb    handler,
109 			     ipmi_control_op_info_t *info,
110 			     void                   *cb_data);
111 
112 /* Send an IPMI command to a specific address on the BMC.  This way,
113    if you don't have an MC to represent the address, you can still
114    send the command.  The response handler will be called with the
115    control locked. */
116 int ipmi_control_send_command_addr(ipmi_domain_t          *domain,
117 				   ipmi_control_t         *control,
118 				   ipmi_addr_t            *addr,
119 				   unsigned int           addr_len,
120 				   ipmi_msg_t             *msg,
121 				   ipmi_control_rsp_cb    handler,
122 				   ipmi_control_op_info_t *info,
123 				   void                   *cb_data);
124 
125 /* Set this if the control should be ignored for presence handling. */
126 void ipmi_control_set_ignore_for_presence(ipmi_control_t *control, int ignore);
127 int ipmi_control_get_ignore_for_presence(ipmi_control_t *control);
128 
129 
130 /* Allocate a control, it will not be associated with anything yet. */
131 int ipmi_control_alloc_nonstandard(ipmi_control_t **new_control);
132 
133 /* Destroy a control. */
134 int ipmi_control_destroy(ipmi_control_t *control);
135 
136 typedef void (*ipmi_control_destroy_cb)(ipmi_control_t *control,
137 					void           *cb_data);
138 /* Add a control for the given MC and put it into the given entity.
139    Note that control will NOT appear as owned by the MC, the MC is
140    used for the OS handler and such.  The source_mc is used to show
141    which MC "owns" the creation of the control, and may be NULL if the
142    control is presumed to come from the "main" SDR repository. */
143 int ipmi_control_add_nonstandard(
144     ipmi_mc_t               *mc,
145     ipmi_mc_t               *source_mc,
146     ipmi_control_t          *control,
147     unsigned int            num,
148     ipmi_entity_t           *ent,
149     ipmi_control_destroy_cb destroy_handler,
150     void                    *destroy_handler_cb_data);
151 
152 typedef int (*ipmi_control_set_val_cb)(ipmi_control_t     *control,
153 				       int                *val,
154 				       ipmi_control_op_cb handler,
155 				       void               *cb_data);
156 
157 typedef int (*ipmi_control_get_val_cb)(ipmi_control_t      *control,
158 				       ipmi_control_val_cb handler,
159 				       void                *cb_data);
160 
161 typedef int (*ipmi_control_set_display_string_cb)(ipmi_control_t *control,
162 						  unsigned int   start_row,
163 						  unsigned int   start_column,
164 						  char           *str,
165 						  unsigned int   len,
166 						  ipmi_control_op_cb handler,
167 						  void           *cb_data);
168 
169 typedef int (*ipmi_control_get_display_string_cb)(ipmi_control_t  *control,
170 						  unsigned int    start_row,
171 						  unsigned int    start_column,
172 						  unsigned int    len,
173 						  ipmi_control_str_cb handler,
174 						  void            *cb_data);
175 typedef int (*ipmi_control_identifier_get_val_cb)(
176     ipmi_control_t                 *control,
177     ipmi_control_identifier_val_cb handler,
178     void                           *cb_data);
179 
180 typedef int (*ipmi_control_identifier_set_val_cb)(ipmi_control_t     *control,
181 						  unsigned char      *val,
182 						  int                length,
183 						  ipmi_control_op_cb handler,
184 						  void               *cb_data);
185 
186 typedef int (*ipmi_control_set_light_cb)(ipmi_control_t       *control,
187 					 ipmi_light_setting_t *settings,
188 					 ipmi_control_op_cb   handler,
189 					 void                 *cb_data);
190 typedef int (*ipmi_control_get_light_cb)(ipmi_control_t         *control,
191 					 ipmi_light_settings_cb handler,
192 					 void                   *cb_data);
193 
194 typedef struct ipmi_control_cbs_s
195 {
196     ipmi_control_set_val_cb	          set_val;
197     ipmi_control_get_val_cb	          get_val;
198     ipmi_control_set_display_string_cb    set_display_string;
199     ipmi_control_get_display_string_cb    get_display_string;
200     ipmi_control_identifier_get_val_cb    get_identifier_val;
201     ipmi_control_identifier_set_val_cb    set_identifier_val;
202     ipmi_control_set_light_cb             set_light;
203     ipmi_control_get_light_cb             get_light;
204 } ipmi_control_cbs_t;
205 
206 /* For settings-based LEDs. */
207 int ipmi_control_add_light_color_support(ipmi_control_t *control,
208 					 int            light_num,
209 					 unsigned int   color);
210 int ipmi_control_light_set_has_local_control(ipmi_control_t *control,
211 					     int            light_num,
212 					     int            val);
213 
214 void ipmi_control_identifier_set_max_length(ipmi_control_t *control,
215 					    unsigned int   val);
216 
217 void ipmi_control_set_id(ipmi_control_t *control, char *id,
218 			 enum ipmi_str_type_e type, int length);
219 void ipmi_control_set_type(ipmi_control_t *control, int val);
220 void ipmi_control_set_settable(ipmi_control_t *control, int val);
221 void ipmi_control_set_readable(ipmi_control_t *control, int val);
222 void ipmi_control_set_ignore_if_no_entity(ipmi_control_t *control,
223 				          int            ignore_if_no_entity);
224 ipmi_domain_t *ipmi_control_get_domain(ipmi_control_t *control);
225 
226 /* Returns true if this control is a hot-swap indicator, meaning that
227    is is used to indicate to the operator when it is save to remove a
228    hot-swappable device.  Setting "val" to one enables the control as
229    a hot-swap power control.  The 'val" setting is retured by the get
230    function.  The active_val is the value to use to turn off the
231    indicator (in active state).  The req_act_val is the value to set
232    when requesting deactivation.  The req_deact_val is the value to set
233    when requesting deactivation.  The inactive val is the value to use
234    when inactive. */
235 int ipmi_control_is_hot_swap_indicator(ipmi_control_t *control,
236 				       int            *req_act_val,
237 				       int            *active_val,
238 				       int            *req_deact_val,
239 				       int            *inactive_val);
240 void ipmi_control_set_hot_swap_indicator(ipmi_control_t *control,
241 					 int            val,
242 					 int            req_act_val,
243 					 int            active_val,
244 					 int            req_deact_val,
245 					 int            inactive_val);
246 
247 /* Get/set the control as a hot-swap power control.  This must be set
248    to 1 to turn the power on and zero to turn it off. */
249 int ipmi_control_is_hot_swap_power(ipmi_control_t *control);
250 void ipmi_control_set_hot_swap_power(ipmi_control_t *control, int val);
251 
252 /* Can this control generate events? */
253 void ipmi_control_set_has_events(ipmi_control_t *control, int val);
254 
255 /* Allow OEM code to call the event handlers.  Note that if the event
256    is handled by the handlers, then "*event" will be set to NULL and
257    *handled will be set to true.  If the event is not handled, then
258    *handled will be set to false and the event value will be
259    unchanged.  This is to help the OEM handlers only deliver the event
260    once to the user. */
261 void ipmi_control_call_val_event_handlers(ipmi_control_t *control,
262 					  int            *valid_vals,
263 					  int            *vals,
264 					  ipmi_event_t   **event,
265 					  int            *handled);
266 
267 typedef struct ipmi_control_transition_s
268 {
269     unsigned int color;
270     unsigned int time;
271 } ipmi_control_transition_t;
272 typedef struct ipmi_control_value_s
273 {
274     unsigned int          num_transitions;
275     ipmi_control_transition_t *transitions;
276 } ipmi_control_value_t;
277 typedef struct ipmi_control_light_s
278 {
279     unsigned int         num_values;
280     ipmi_control_value_t *values;
281 } ipmi_control_light_t;
282 void ipmi_control_light_set_lights(ipmi_control_t       *control,
283 				   unsigned int         num_lights,
284 				   ipmi_control_light_t *lights);
285 
286 void ipmi_control_set_num_elements(ipmi_control_t *control, unsigned int val);
287 
288 int ipmi_control_get_num(ipmi_control_t *control,
289 			 int            *lun,
290 			 int            *num);
291 
292 typedef void (*ipmi_control_cleanup_oem_info_cb)(ipmi_control_t *control,
293 						 void           *oem_info);
294 void ipmi_control_set_oem_info(ipmi_control_t *control, void *oem_info,
295 			       ipmi_control_cleanup_oem_info_cb cleanup_handler);
296 void *ipmi_control_get_oem_info(ipmi_control_t *control);
297 
298 /* Can be used by OEM code to replace some or all of the callbacks for
299    a control. */
300 void ipmi_control_get_callbacks(ipmi_control_t     *control,
301 				ipmi_control_cbs_t *cbs);
302 void ipmi_control_set_callbacks(ipmi_control_t     *control,
303 				ipmi_control_cbs_t *cbs);
304 
305 /* Get the MC that the control is in. */
306 ipmi_mc_t *ipmi_control_get_mc(ipmi_control_t *control);
307 
308 /* OpenIPMI defines controls f0-ff for its own use, don't use them for your
309    controls.  Here's some controls it defines. */
310 #define IPMI_CHASSIS_POWER_CONTROL	0xf0
311 #define IPMI_CHASSIS_RESET_CONTROL	0xf1
312 
313 /* Do a pointer callback but ignore the sequence number in the MC.
314    This is primarily for handling incoming events, where the sequence
315    number doesn't matter. */
316 int ipmi_control_pointer_noseq_cb(ipmi_control_id_t   id,
317 				  ipmi_control_ptr_cb handler,
318 				  void                *cb_data);
319 
320 #endif /* OPENIPMI_CONTROL_H */
321