1 /*
2  * control.c
3  *
4  * MontaVista IPMI code for handling 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 #include <string.h>
35 #include <stdio.h>
36 #include <limits.h>
37 
38 #include <OpenIPMI/ipmiif.h>
39 #include <OpenIPMI/ipmi_err.h>
40 
41 #include <OpenIPMI/internal/opq.h>
42 #include <OpenIPMI/internal/locked_list.h>
43 #include <OpenIPMI/internal/ipmi_int.h>
44 #include <OpenIPMI/internal/ipmi_domain.h>
45 #include <OpenIPMI/internal/ipmi_mc.h>
46 #include <OpenIPMI/internal/ipmi_control.h>
47 
48 struct ipmi_control_info_s
49 {
50     int                      destroyed;
51 
52     /* Indexed by control # */
53     ipmi_control_t           **controls_by_idx;
54     /* Size of above control array.  This will be 0 if the LUN has no
55        controls. */
56     unsigned int             idx_size;
57 
58     ipmi_lock_t              *idx_lock;
59 
60     /* Total number of controls we have in this. */
61     unsigned int             control_count;
62 
63     opq_t *control_wait_q;
64     int  wait_err;
65 };
66 
67 #define CONTROL_ID_LEN 32
68 struct ipmi_control_s
69 {
70     unsigned int usecount;
71 
72     ipmi_domain_t *domain;
73     ipmi_mc_t *mc;
74     unsigned char lun;
75     unsigned char num;
76 
77     ipmi_mc_t *source_mc;
78 
79     ipmi_entity_t *entity;
80 
81     int destroyed;
82 
83     /* After the control is added, it will not be reported immediately.
84        Instead, it will wait until the usecount goes to zero before
85        being reported.  This marks that the add report is pending */
86     int add_pending;
87 
88     int type;
89     const char *type_str;
90 
91     int settable;
92     int readable;
93 
94     unsigned int num_vals;
95 
96     int hot_swap_indicator;
97     int hot_swap_active_val;
98     int hot_swap_inactive_val;
99     int hot_swap_req_act_val;
100     int hot_swap_req_deact_val;
101 
102     int hot_swap_power;
103 
104     int has_events;
105 
106     int ignore_if_no_entity : 1;
107     int ignore_for_presence : 1;
108 
109     /* A list of handlers to call when an event for the control comes
110        in. */
111     locked_list_t *handler_list, *handler_list_cl;
112 
113     /* For light types. */
114 #define MAX_LIGHTS 10
115     ipmi_control_light_t *lights;
116     unsigned int         colors[MAX_LIGHTS];
117     int                  has_local_control[MAX_LIGHTS];
118 
119     /* For display types. */
120     unsigned int columns;
121     unsigned int rows;
122 
123     /* For identifier types. */
124     unsigned int identifier_length;
125 
126     /* Note that this is *not* nil terminated. */
127     enum ipmi_str_type_e id_type;
128     unsigned int id_len;
129     char id[CONTROL_ID_LEN];
130 
131     ipmi_control_cbs_t cbs;
132     opq_t *waitq;
133 
134     void                             *oem_info;
135     ipmi_control_cleanup_oem_info_cb oem_info_cleanup_handler;
136 
137     ipmi_control_destroy_cb destroy_handler;
138     void                    *destroy_handler_cb_data;
139 
140     /* Name we use for reporting.  We add a ' ' onto the end, thus
141        the +1. */
142     char name[IPMI_CONTROL_NAME_LEN+1];
143 };
144 
145 static void control_final_destroy(ipmi_control_t *control);
146 
147 /***********************************************************************
148  *
149  * Control ID handling.
150  *
151  **********************************************************************/
152 
153 /* Must be called with the domain entity lock held. */
154 int
i_ipmi_control_get(ipmi_control_t * control)155 i_ipmi_control_get(ipmi_control_t *control)
156 {
157     if (control->destroyed)
158 	return EINVAL;
159     control->usecount++;
160     return 0;
161 }
162 
163 void
i_ipmi_control_put(ipmi_control_t * control)164 i_ipmi_control_put(ipmi_control_t *control)
165 {
166     i_ipmi_domain_entity_lock(control->domain);
167     if (control->usecount == 1) {
168 	if (control->add_pending) {
169 	    control->add_pending = 0;
170 	    i_ipmi_domain_entity_unlock(control->domain);
171 	    i_ipmi_entity_call_control_handlers(control->entity,
172 					       control, IPMI_ADDED);
173 	    i_ipmi_domain_entity_lock(control->domain);
174 	}
175 	if (control->destroyed
176 	    && (!control->waitq
177 		|| (!opq_stuff_in_progress(control->waitq))))
178 	{
179 	    i_ipmi_domain_entity_unlock(control->domain);
180 	    control_final_destroy(control);
181 	    return;
182 	}
183     }
184     control->usecount--;
185     i_ipmi_domain_entity_unlock(control->domain);
186 }
187 
188 ipmi_control_id_t
ipmi_control_convert_to_id(ipmi_control_t * control)189 ipmi_control_convert_to_id(ipmi_control_t *control)
190 {
191     ipmi_control_id_t val;
192 
193     CHECK_CONTROL_LOCK(control);
194 
195     val.mcid = ipmi_mc_convert_to_id(control->mc);
196     val.lun = control->lun;
197     val.control_num = control->num;
198 
199     return val;
200 }
201 
202 typedef struct mc_cb_info_s
203 {
204     ipmi_control_ptr_cb   handler;
205     void                  *cb_data;
206     ipmi_control_id_t     id;
207     int                   err;
208 } mc_cb_info_t;
209 
210 static void
mc_cb(ipmi_mc_t * mc,void * cb_data)211 mc_cb(ipmi_mc_t *mc, void *cb_data)
212 {
213     mc_cb_info_t        *info = cb_data;
214     ipmi_control_info_t *controls;
215     ipmi_domain_t       *domain = ipmi_mc_get_domain(mc);
216     ipmi_control_t      *control;
217     ipmi_entity_t       *entity = NULL;
218 
219     controls = i_ipmi_mc_get_controls(mc);
220     i_ipmi_domain_entity_lock(domain);
221     if (info->id.lun > 4) {
222 	info->err = EINVAL;
223 	goto out_unlock;
224     }
225 
226     if (info->id.control_num >= controls->idx_size) {
227 	info->err = EINVAL;
228 	goto out_unlock;
229     }
230 
231     control = controls->controls_by_idx[info->id.control_num];
232     if (!control) {
233 	info->err = EINVAL;
234 	goto out_unlock;
235     }
236 
237     info->err = i_ipmi_entity_get(control->entity);
238     if (info->err)
239 	goto out_unlock;
240     entity = control->entity;
241 
242     info->err = i_ipmi_control_get(control);
243     if (info->err)
244 	goto out_unlock;
245 
246     i_ipmi_domain_entity_unlock(domain);
247 
248     info->handler(control, info->cb_data);
249 
250     i_ipmi_control_put(control);
251     i_ipmi_entity_put(entity);
252     return;
253 
254  out_unlock:
255     i_ipmi_domain_entity_unlock(domain);
256     if (entity)
257 	i_ipmi_entity_put(entity);
258 }
259 
260 int
ipmi_control_pointer_cb(ipmi_control_id_t id,ipmi_control_ptr_cb handler,void * cb_data)261 ipmi_control_pointer_cb(ipmi_control_id_t   id,
262 			ipmi_control_ptr_cb handler,
263 			void                *cb_data)
264 {
265     int               rv;
266     mc_cb_info_t      info;
267 
268     if (id.lun >= 5)
269 	return EINVAL;
270 
271     info.handler = handler;
272     info.cb_data = cb_data;
273     info.id = id;
274     info.err = 0;
275 
276     rv = ipmi_mc_pointer_cb(id.mcid, mc_cb, &info);
277     if (!rv)
278 	rv = info.err;
279 
280     return rv;
281 }
282 
283 int
ipmi_control_pointer_noseq_cb(ipmi_control_id_t id,ipmi_control_ptr_cb handler,void * cb_data)284 ipmi_control_pointer_noseq_cb(ipmi_control_id_t   id,
285 			      ipmi_control_ptr_cb handler,
286 			      void                *cb_data)
287 {
288     int               rv;
289     mc_cb_info_t      info;
290 
291     if (id.lun >= 5)
292 	return EINVAL;
293 
294     info.handler = handler;
295     info.cb_data = cb_data;
296     info.id = id;
297     info.err = 0;
298 
299     rv = ipmi_mc_pointer_noseq_cb(id.mcid, mc_cb, &info);
300     if (!rv)
301 	rv = info.err;
302 
303     return rv;
304 }
305 
306 typedef struct control_find_info_s
307 {
308     ipmi_control_id_t id;
309     char              *id_name;
310     int               rv;
311 } control_find_info_t;
312 
313 static void
control_search_cmp(ipmi_entity_t * entity,ipmi_control_t * control,void * cb_data)314 control_search_cmp(ipmi_entity_t  *entity,
315 		   ipmi_control_t *control,
316 		   void           *cb_data)
317 {
318     control_find_info_t *info = cb_data;
319     char               id[33];
320     int                rv;
321 
322     rv = ipmi_control_get_id(control, id, 33);
323     if (rv)
324 	return;
325     if (strcmp(info->id_name, id) == 0) {
326 	info->id = ipmi_control_convert_to_id(control);
327 	info->rv = 0;
328     }
329 }
330 
331 static void
control_search(ipmi_entity_t * entity,void * cb_data)332 control_search(ipmi_entity_t *entity, void *cb_data)
333 {
334     control_find_info_t *info = cb_data;
335 
336     ipmi_entity_iterate_controls(entity, control_search_cmp, info);
337 }
338 
339 int
ipmi_control_find_id(ipmi_domain_id_t domain_id,int entity_id,int entity_instance,int channel,int slave_address,char * id_name,ipmi_control_id_t * id)340 ipmi_control_find_id(ipmi_domain_id_t domain_id,
341 		    int entity_id, int entity_instance,
342 		    int channel, int slave_address,
343 		    char *id_name,
344 		    ipmi_control_id_t *id)
345 {
346     int                rv;
347     ipmi_entity_id_t   entity;
348     control_find_info_t info;
349 
350     rv = ipmi_entity_find_id(domain_id, entity_id, entity_instance,
351 			     channel, slave_address, &entity);
352     if (rv)
353 	return rv;
354 
355     info.id_name = id_name;
356     info.rv = EINVAL;
357 
358     rv = ipmi_entity_pointer_cb(entity, control_search, &info);
359     if (!rv)
360 	rv = info.rv;
361     if (!rv)
362 	*id = info.id;
363 
364     return rv;
365 }
366 
367 /***********************************************************************
368  *
369  * Various control allocation/deallocation/opq/etc.
370  *
371  **********************************************************************/
372 
373 static int
control_ok_to_use(ipmi_control_t * control)374 control_ok_to_use(ipmi_control_t *control)
375 {
376     return (   !control->destroyed
377 	    && !i_ipmi_domain_in_shutdown(control->domain));
378 }
379 
380 typedef struct handler_cl_info_s
381 {
382     ipmi_control_val_event_cb handler;
383     void                      *handler_data;
384 } handler_cl_info_t;
385 
386 static int
iterate_handler_cl(void * cb_data,void * item1,void * item2)387 iterate_handler_cl(void *cb_data, void *item1, void *item2)
388 {
389     handler_cl_info_t            *info = cb_data;
390     ipmi_control_val_event_cl_cb handler = item1;
391 
392     handler(info->handler, info->handler_data, item2);
393     return LOCKED_LIST_ITER_CONTINUE;
394 }
395 
396 static int
handler_list_cleanup(void * cb_data,void * item1,void * item2)397 handler_list_cleanup(void *cb_data, void *item1, void *item2)
398 {
399     ipmi_control_t    *control = cb_data;
400     handler_cl_info_t info;
401 
402     info.handler = item1;
403     info.handler_data = item2;
404     locked_list_iterate(control->handler_list_cl,
405 			iterate_handler_cl,
406 			&info);
407     return LOCKED_LIST_ITER_CONTINUE;
408 }
409 
410 static void
control_final_destroy(ipmi_control_t * control)411 control_final_destroy(ipmi_control_t *control)
412 {
413     i_ipmi_entity_get(control->entity);
414     i_ipmi_entity_call_control_handlers(control->entity, control, IPMI_DELETED);
415 
416     control->mc = NULL;
417 
418     if (control->destroy_handler)
419 	control->destroy_handler(control,
420 				 control->destroy_handler_cb_data);
421 
422     if (control->handler_list) {
423 	locked_list_iterate(control->handler_list_cl, handler_list_cleanup,
424 			    control);
425 	locked_list_destroy(control->handler_list);
426     }
427 
428     if (control->handler_list_cl)
429 	locked_list_destroy(control->handler_list_cl);
430 
431     if (control->waitq)
432 	opq_destroy(control->waitq);
433 
434     ipmi_entity_remove_control(control->entity, control);
435 
436     if (control->oem_info_cleanup_handler)
437 	control->oem_info_cleanup_handler(control, control->oem_info);
438 
439     i_ipmi_entity_put(control->entity);
440     ipmi_mem_free(control);
441 }
442 
443 int
ipmi_control_destroy(ipmi_control_t * control)444 ipmi_control_destroy(ipmi_control_t *control)
445 {
446     ipmi_control_info_t *controls;
447     ipmi_mc_t           *mc = control->mc;
448 
449     i_ipmi_domain_mc_lock(control->domain);
450     i_ipmi_mc_get(mc);
451     i_ipmi_domain_mc_unlock(control->domain);
452     controls = i_ipmi_mc_get_controls(control->mc);
453 
454     ipmi_lock(controls->idx_lock);
455     if (controls->controls_by_idx[control->num] == control) {
456 	controls->control_count--;
457 	controls->controls_by_idx[control->num] = NULL;
458     }
459 
460     i_ipmi_control_get(control);
461 
462     ipmi_unlock(controls->idx_lock);
463 
464     control->destroyed = 1;
465     i_ipmi_control_put(control);
466     i_ipmi_mc_put(mc);
467 
468     return 0;
469 }
470 
471 static void
control_set_name(ipmi_control_t * control)472 control_set_name(ipmi_control_t *control)
473 {
474     int length;
475 
476     length = ipmi_entity_get_name(control->entity, control->name,
477 				  sizeof(control->name)-2);
478     control->name[length] = '.';
479     length++;
480     length += snprintf(control->name+length, IPMI_CONTROL_NAME_LEN-length-2,
481 		       "%s", control->id);
482     control->name[length] = ' ';
483     length++;
484     control->name[length] = '\0';
485     length++;
486 }
487 
488 const char *
i_ipmi_control_name(const ipmi_control_t * control)489 i_ipmi_control_name(const ipmi_control_t *control)
490 {
491     return control->name;
492 }
493 
494 int
ipmi_control_get_name(ipmi_control_t * control,char * name,int length)495 ipmi_control_get_name(ipmi_control_t *control, char *name, int length)
496 {
497     int rv = 0;
498 
499     if (control->entity)
500 	rv = ipmi_entity_get_name(control->entity, name, length);
501     if (length > (int) (control->id_len + 2))
502 	length = control->id_len + 2; /* Leave space for the nil */
503     rv += snprintf(name+rv, length, ".%s", control->id);
504     return rv;
505 }
506 
507 /***********************************************************************
508  *
509  * Control message handling.
510  *
511  **********************************************************************/
512 
513 static void
control_opq_ready2(ipmi_control_t * control,void * cb_data)514 control_opq_ready2(ipmi_control_t *control, void *cb_data)
515 {
516     ipmi_control_op_info_t *info = cb_data;
517     if (info->__handler)
518 	info->__handler(control, 0, info->__cb_data);
519 }
520 
521 static int
control_opq_ready(void * cb_data,int shutdown)522 control_opq_ready(void *cb_data, int shutdown)
523 {
524     ipmi_control_op_info_t *info = cb_data;
525     int                   rv;
526 
527     if (shutdown) {
528 	ipmi_log(IPMI_LOG_ERR_INFO,
529 		 "%scontrol.c(control_opq_ready): "
530 		 "Control was destroyed while an operation was in progress",
531 		 CONTROL_NAME(info->__control));
532 	if (info->__handler)
533 	    info->__handler(info->__control, ECANCELED, info->__cb_data);
534 	return OPQ_HANDLER_STARTED;
535     }
536 
537     rv = ipmi_control_pointer_cb(info->__control_id, control_opq_ready2, info);
538     if (rv)
539 	if (info->__handler)
540 	    info->__handler(info->__control, rv, info->__cb_data);
541     return OPQ_HANDLER_STARTED;
542 }
543 
544 int
ipmi_control_add_opq(ipmi_control_t * control,ipmi_control_op_cb handler,ipmi_control_op_info_t * info,void * cb_data)545 ipmi_control_add_opq(ipmi_control_t         *control,
546 		     ipmi_control_op_cb     handler,
547 		     ipmi_control_op_info_t *info,
548 		     void                   *cb_data)
549 {
550     if (control->destroyed)
551 	return EINVAL;
552 
553     info->__control = control;
554     info->__control_id = ipmi_control_convert_to_id(control);
555     info->__cb_data = cb_data;
556     info->__handler = handler;
557     if (!opq_new_op(control->waitq, control_opq_ready, info, 0))
558 	return ENOMEM;
559     return 0;
560 }
561 
562 void
ipmi_control_opq_done(ipmi_control_t * control)563 ipmi_control_opq_done(ipmi_control_t *control)
564 {
565     /* Protect myself from NULL controls.  This way, it doesn't have to
566        be done in each call. */
567     if (!control)
568 	return;
569 
570      /* This gets called on ECANCELED error cases, if the control is
571 	already we need to clear out the opq. */
572     if (control->destroyed) {
573 	if (control->waitq) {
574 	    opq_destroy(control->waitq);
575 	    control->waitq = NULL;
576 	}
577  	return;
578     }
579 
580     /* No check for the lock.  It will sometimes fail at destruction
581        time. */
582 
583     opq_op_done(control->waitq);
584 }
585 
586 static void
control_rsp_handler2(ipmi_control_t * control,void * cb_data)587 control_rsp_handler2(ipmi_control_t *control, void *cb_data)
588 {
589     ipmi_control_op_info_t *info = cb_data;
590 
591     if (info->__rsp_handler)
592 	info->__rsp_handler(control, 0, info->__rsp, info->__cb_data);
593 }
594 
595 static void
control_rsp_handler(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)596 control_rsp_handler(ipmi_mc_t  *mc,
597 		    ipmi_msg_t *rsp,
598 		    void       *rsp_data)
599 {
600     ipmi_control_op_info_t *info = rsp_data;
601     int                    rv;
602     ipmi_control_t         *control = info->__control;
603     ipmi_entity_t          *entity = NULL;
604 
605     if (control->destroyed) {
606 	ipmi_entity_t *entity = NULL;
607 
608 	i_ipmi_domain_entity_lock(control->domain);
609 	control->usecount++;
610 	i_ipmi_domain_entity_unlock(control->domain);
611 
612 	rv = i_ipmi_entity_get(control->entity);
613 	if (! rv)
614 	    entity = control->entity;
615 
616 	ipmi_log(IPMI_LOG_ERR_INFO,
617 		 "%scontrol.c(control_rsp_handler): "
618 		 "Control was destroyed while an operation was in progress",
619 		 CONTROL_NAME(control));
620 	if (info->__rsp_handler)
621 	    info->__rsp_handler(control, ECANCELED, NULL, info->__cb_data);
622 
623 	i_ipmi_control_put(control);
624 	if (entity)
625 	    i_ipmi_entity_put(entity);
626 	return;
627     }
628 
629     if (!mc) {
630 	ipmi_log(IPMI_LOG_ERR_INFO,
631 		 "control.c(control_rsp_handler): "
632 		 "MC was destroyed while a control operation was in progress");
633 
634 	i_ipmi_domain_entity_lock(control->domain);
635 	control->usecount++;
636 	i_ipmi_domain_entity_unlock(control->domain);
637 
638 	rv = i_ipmi_entity_get(control->entity);
639 	if (! rv)
640 	    entity = control->entity;
641 
642 	if (info->__rsp_handler)
643 	    info->__rsp_handler(control, ECANCELED, NULL, info->__cb_data);
644 
645 	i_ipmi_control_put(control);
646 	if (entity)
647 	    i_ipmi_entity_put(entity);
648 
649 	return;
650     }
651 
652     /* Call the next stage with the lock held. */
653     info->__rsp = rsp;
654     rv = ipmi_control_pointer_cb(info->__control_id,
655 				 control_rsp_handler2,
656 				 info);
657     if (rv) {
658 	int nrv;
659 
660 	ipmi_log(IPMI_LOG_ERR_INFO,
661 		 "%scontrol.c(control_rsp_handler): "
662 		 "Could not convert control id to a pointer",
663 		 MC_NAME(mc));
664 	i_ipmi_domain_entity_lock(control->domain);
665 	control->usecount++;
666 	i_ipmi_domain_entity_unlock(control->domain);
667 
668 	nrv = i_ipmi_entity_get(control->entity);
669 	if (! nrv)
670 	    entity = control->entity;
671 
672 	if (info->__rsp_handler)
673 	    info->__rsp_handler(control, rv, NULL, info->__cb_data);
674 
675 	i_ipmi_control_put(control);
676 	if (entity)
677 	    i_ipmi_entity_put(entity);
678     }
679 }
680 
681 int
ipmi_control_send_command(ipmi_control_t * control,ipmi_mc_t * mc,unsigned int lun,ipmi_msg_t * msg,ipmi_control_rsp_cb handler,ipmi_control_op_info_t * info,void * cb_data)682 ipmi_control_send_command(ipmi_control_t         *control,
683 			  ipmi_mc_t              *mc,
684 			  unsigned int           lun,
685 			  ipmi_msg_t             *msg,
686 			  ipmi_control_rsp_cb    handler,
687 			  ipmi_control_op_info_t *info,
688 			  void                   *cb_data)
689 {
690     int rv;
691 
692     CHECK_MC_LOCK(mc);
693     CHECK_CONTROL_LOCK(control);
694 
695     if (control->destroyed)
696 	return EINVAL;
697 
698     info->__control = control;
699     info->__control_id = ipmi_control_convert_to_id(control);
700     info->__cb_data = cb_data;
701     info->__rsp_handler = handler;
702     rv = ipmi_mc_send_command(mc, lun, msg, control_rsp_handler, info);
703     return rv;
704 }
705 
706 static int
control_addr_response_handler(ipmi_domain_t * domain,ipmi_msgi_t * rspi)707 control_addr_response_handler(ipmi_domain_t *domain, ipmi_msgi_t *rspi)
708 {
709     ipmi_msg_t             *msg = &rspi->msg;
710     ipmi_control_op_info_t *info = rspi->data1;
711     int                    rv;
712     ipmi_control_t         *control = info->__control;
713 
714     if (control->destroyed) {
715 	ipmi_log(IPMI_LOG_ERR_INFO,
716 		 "%scontrol.c(control_addr_response_handler): "
717 		 "Control was destroyed while an operation was in progress",
718 		 DOMAIN_NAME(domain));
719 	if (info->__rsp_handler)
720 	    info->__rsp_handler(control, ECANCELED, NULL, info->__cb_data);
721 
722 	i_ipmi_domain_entity_lock(control->domain);
723 	control->usecount++;
724 	i_ipmi_domain_entity_unlock(control->domain);
725 	i_ipmi_control_put(control);
726 	return IPMI_MSG_ITEM_NOT_USED;
727     }
728 
729     /* Call the next stage with the lock held. */
730     info->__rsp = msg;
731     rv = ipmi_control_pointer_cb(info->__control_id,
732 				 control_rsp_handler2,
733 				 info);
734     if (rv) {
735 	ipmi_log(IPMI_LOG_ERR_INFO,
736 		 "%scontrol.c(control_addr_response_handler): "
737 		 "Could not convert control id to a pointer",
738 		 DOMAIN_NAME(domain));
739 	if (info->__rsp_handler) {
740 	    i_ipmi_domain_entity_lock(control->domain);
741 	    control->usecount++;
742 	    i_ipmi_domain_entity_unlock(control->domain);
743 	    info->__rsp_handler(control, rv, NULL, info->__cb_data);
744 	    i_ipmi_control_put(control);
745 	}
746     }
747     return IPMI_MSG_ITEM_NOT_USED;
748 }
749 
750 int
ipmi_control_send_command_addr(ipmi_domain_t * domain,ipmi_control_t * control,ipmi_addr_t * addr,unsigned int addr_len,ipmi_msg_t * msg,ipmi_control_rsp_cb handler,ipmi_control_op_info_t * info,void * cb_data)751 ipmi_control_send_command_addr(ipmi_domain_t          *domain,
752 			       ipmi_control_t         *control,
753 			       ipmi_addr_t            *addr,
754 			       unsigned int           addr_len,
755 			       ipmi_msg_t             *msg,
756 			       ipmi_control_rsp_cb    handler,
757 			       ipmi_control_op_info_t *info,
758 			       void                   *cb_data)
759 {
760     int rv;
761 
762     CHECK_CONTROL_LOCK(control);
763     CHECK_MC_LOCK(control->mc);
764 
765     info->__control = control;
766     info->__control_id = ipmi_control_convert_to_id(control);
767     info->__cb_data = cb_data;
768     info->__rsp_handler = handler;
769     rv = ipmi_send_command_addr(domain, addr, addr_len,
770 				msg, control_addr_response_handler, info, NULL);
771     return rv;
772 }
773 
774 int
ipmi_controls_alloc(ipmi_mc_t * mc,ipmi_control_info_t ** new_controls)775 ipmi_controls_alloc(ipmi_mc_t *mc, ipmi_control_info_t **new_controls)
776 {
777     ipmi_control_info_t *controls;
778     ipmi_domain_t       *domain;
779     os_handler_t        *os_hnd;
780     int                 rv;
781 
782     CHECK_MC_LOCK(mc);
783 
784     domain = ipmi_mc_get_domain(mc);
785     os_hnd = ipmi_domain_get_os_hnd(domain);
786 
787     controls = ipmi_mem_alloc(sizeof(*controls));
788     if (!controls)
789 	return ENOMEM;
790     memset(controls, 0, sizeof(*controls));
791 
792     controls->control_wait_q = opq_alloc(os_hnd);
793     if (! controls->control_wait_q) {
794 	ipmi_mem_free(controls);
795 	return ENOMEM;
796     }
797 
798     rv = ipmi_create_lock_os_hnd(os_hnd, &controls->idx_lock);
799     if (rv) {
800 	opq_destroy(controls->control_wait_q);
801 	ipmi_mem_free(controls);
802 	return rv;
803     }
804 
805     *new_controls = controls;
806     return 0;
807 }
808 
809 unsigned int
ipmi_controls_get_count(ipmi_control_info_t * controls)810 ipmi_controls_get_count(ipmi_control_info_t *controls)
811 {
812     return controls->control_count;
813 }
814 
815 int
ipmi_control_alloc_nonstandard(ipmi_control_t ** new_control)816 ipmi_control_alloc_nonstandard(ipmi_control_t **new_control)
817 {
818     ipmi_control_t *control;
819 
820     control = ipmi_mem_alloc(sizeof(*control));
821     if (!control)
822 	return ENOMEM;
823 
824     memset(control, 0, sizeof(*control));
825 
826     control->usecount = 1;
827     *new_control = control;
828     return 0;
829 }
830 
831 int
ipmi_control_add_nonstandard(ipmi_mc_t * mc,ipmi_mc_t * source_mc,ipmi_control_t * control,unsigned int num,ipmi_entity_t * ent,ipmi_control_destroy_cb destroy_handler,void * destroy_handler_cb_data)832 ipmi_control_add_nonstandard(ipmi_mc_t               *mc,
833 			     ipmi_mc_t               *source_mc,
834 			     ipmi_control_t          *control,
835 			     unsigned int            num,
836 			     ipmi_entity_t           *ent,
837 			     ipmi_control_destroy_cb destroy_handler,
838 			     void                    *destroy_handler_cb_data)
839 {
840     ipmi_domain_t       *domain;
841     os_handler_t        *os_hnd;
842     ipmi_control_info_t *controls = i_ipmi_mc_get_controls(mc);
843     locked_list_entry_t *link;
844     int                 err;
845     unsigned int        i;
846 
847     CHECK_MC_LOCK(mc);
848     CHECK_ENTITY_LOCK(ent);
849 
850     domain = ipmi_mc_get_domain(mc);
851     os_hnd = ipmi_domain_get_os_hnd(domain);
852 
853     if ((num >= 256) && (num != UINT_MAX))
854 	return EINVAL;
855 
856     i_ipmi_domain_entity_lock(domain);
857     ipmi_lock(controls->idx_lock);
858 
859     if (num == UINT_MAX){
860 	for (i=0; i<controls->idx_size; i++) {
861 	    if (! controls->controls_by_idx[i])
862 		break;
863 	}
864 	num = i;
865 	if (num >= 256) {
866 	    err = EAGAIN;
867 	    goto out_err;
868 	}
869     }
870 
871     if (num >= controls->idx_size) {
872 	ipmi_control_t **new_array;
873 	unsigned int   new_size;
874 	unsigned int   i;
875 
876 	/* Allocate the array in multiples of 16 (to avoid thrashing malloc
877 	   too much). */
878 	new_size = ((num / 16) * 16) + 16;
879 	new_array = ipmi_mem_alloc(sizeof(*new_array) * new_size);
880 	if (!new_array) {
881 	    err = ENOMEM;
882 	    goto out_err;
883 	}
884 	if (controls->controls_by_idx)
885 	    memcpy(new_array, controls->controls_by_idx,
886 		   sizeof(*new_array) * (controls->idx_size));
887 	for (i=controls->idx_size; i<new_size; i++)
888 	    new_array[i] = NULL;
889 	if (controls->controls_by_idx)
890 	    ipmi_mem_free(controls->controls_by_idx);
891 	controls->controls_by_idx = new_array;
892 	controls->idx_size = new_size;
893     }
894 
895     control->waitq = opq_alloc(os_hnd);
896     if (! control->waitq) {
897 	err = ENOMEM;
898 	goto out_err;
899     }
900 
901     control->handler_list_cl = locked_list_alloc(os_hnd);
902     if (! control->handler_list_cl) {
903 	opq_destroy(control->waitq);
904 	err = ENOMEM;
905 	goto out_err;
906     }
907 
908     control->handler_list = locked_list_alloc(os_hnd);
909     if (! control->handler_list) {
910 	opq_destroy(control->waitq);
911 	locked_list_destroy(control->handler_list_cl);
912 	err = ENOMEM;
913 	goto out_err;
914     }
915 
916     link = locked_list_alloc_entry();
917     if (!link) {
918 	opq_destroy(control->waitq);
919 	control->waitq = NULL;
920 	locked_list_destroy(control->handler_list);
921 	locked_list_destroy(control->handler_list_cl);
922 	control->handler_list = NULL;
923 	err = ENOMEM;
924 	goto out_err;
925     }
926 
927     control->domain = domain;
928     control->mc = mc;
929     control->source_mc = source_mc;
930     control->entity = ent;
931     control->lun = 4;
932     control->num = num;
933     if (controls->controls_by_idx[num]) {
934 	ipmi_log(IPMI_LOG_WARNING,
935 		 "%scontrol.c(ipmi_control_add_nonstandard): "
936 		 " Add a control at index %d, but there was already a"
937 		 " control there, overwriting the old control",
938 		 MC_NAME(mc), num);
939     } else {
940 	controls->control_count++;
941     }
942     controls->controls_by_idx[num] = control;
943     control->destroy_handler = destroy_handler;
944     control->destroy_handler_cb_data = destroy_handler_cb_data;
945     control_set_name(control);
946 
947     ipmi_unlock(controls->idx_lock);
948 
949     i_ipmi_domain_entity_unlock(domain);
950 
951     ipmi_entity_add_control(ent, control, link);
952 
953     control->add_pending = 1;
954 
955     return 0;
956 
957  out_err:
958     ipmi_unlock(controls->idx_lock);
959     i_ipmi_domain_entity_unlock(domain);
960     return err;
961 }
962 
963 int
ipmi_controls_destroy(ipmi_control_info_t * controls)964 ipmi_controls_destroy(ipmi_control_info_t *controls)
965 {
966     unsigned int j;
967 
968     if (controls->destroyed)
969 	return EINVAL;
970 
971     controls->destroyed = 1;
972     for (j=0; j<controls->idx_size; j++) {
973 	if (controls->controls_by_idx[j]) {
974 	    ipmi_control_destroy(controls->controls_by_idx[j]);
975 	}
976     }
977     if (controls->controls_by_idx)
978 	ipmi_mem_free(controls->controls_by_idx);
979 
980     if (controls->control_wait_q)
981 	opq_destroy(controls->control_wait_q);
982     if (controls->idx_lock)
983 	ipmi_destroy_lock(controls->idx_lock);
984     ipmi_mem_free(controls);
985     return 0;
986 }
987 
988 /***********************************************************************
989  *
990  * Polymorphic calls to the callback handlers.
991  *
992  **********************************************************************/
993 
994 int
ipmi_control_set_val(ipmi_control_t * control,int * val,ipmi_control_op_cb handler,void * cb_data)995 ipmi_control_set_val(ipmi_control_t     *control,
996 		     int                *val,
997 		     ipmi_control_op_cb handler,
998 		     void               *cb_data)
999 {
1000     if (!control_ok_to_use(control))
1001 	return ECANCELED;
1002 
1003     CHECK_CONTROL_LOCK(control);
1004 
1005     if (!control->cbs.set_val)
1006 	return ENOSYS;
1007     return control->cbs.set_val(control, val, handler, cb_data);
1008 }
1009 
1010 int
ipmi_control_get_val(ipmi_control_t * control,ipmi_control_val_cb handler,void * cb_data)1011 ipmi_control_get_val(ipmi_control_t      *control,
1012 		     ipmi_control_val_cb handler,
1013 		     void                *cb_data)
1014 {
1015     if (!control_ok_to_use(control))
1016 	return ECANCELED;
1017 
1018     CHECK_CONTROL_LOCK(control);
1019 
1020     if (!control->cbs.get_val)
1021 	return ENOSYS;
1022     return control->cbs.get_val(control, handler, cb_data);
1023 }
1024 
1025 int
ipmi_control_set_display_string(ipmi_control_t * control,unsigned int start_row,unsigned int start_column,char * str,unsigned int len,ipmi_control_op_cb handler,void * cb_data)1026 ipmi_control_set_display_string(ipmi_control_t     *control,
1027 				unsigned int       start_row,
1028 				unsigned int       start_column,
1029 				char               *str,
1030 				unsigned int       len,
1031 				ipmi_control_op_cb handler,
1032 				void               *cb_data)
1033 {
1034     if (!control_ok_to_use(control))
1035 	return ECANCELED;
1036 
1037     CHECK_CONTROL_LOCK(control);
1038 
1039     if (!control->cbs.set_display_string)
1040 	return ENOSYS;
1041     return control->cbs.set_display_string(control,
1042 					   start_row,
1043 					   start_column,
1044 					   str, len,
1045 					   handler, cb_data);
1046 }
1047 
1048 int
ipmi_control_get_display_string(ipmi_control_t * control,unsigned int start_row,unsigned int start_column,unsigned int len,ipmi_control_str_cb handler,void * cb_data)1049 ipmi_control_get_display_string(ipmi_control_t      *control,
1050 				unsigned int        start_row,
1051 				unsigned int        start_column,
1052 				unsigned int        len,
1053 				ipmi_control_str_cb handler,
1054 				void                *cb_data)
1055 {
1056     if (!control_ok_to_use(control))
1057 	return ECANCELED;
1058 
1059     CHECK_CONTROL_LOCK(control);
1060 
1061     if (!control->cbs.get_display_string)
1062 	return ENOSYS;
1063     return control->cbs.get_display_string(control,
1064 					   start_row,
1065 					   start_column,
1066 					   len,
1067 					   handler, cb_data);
1068 }
1069 
1070 int
ipmi_control_identifier_get_val(ipmi_control_t * control,ipmi_control_identifier_val_cb handler,void * cb_data)1071 ipmi_control_identifier_get_val(ipmi_control_t                 *control,
1072 				ipmi_control_identifier_val_cb handler,
1073 				void                           *cb_data)
1074 {
1075     if (!control_ok_to_use(control))
1076 	return ECANCELED;
1077 
1078     CHECK_CONTROL_LOCK(control);
1079 
1080     if (!control->cbs.get_identifier_val)
1081 	return ENOSYS;
1082     return control->cbs.get_identifier_val(control, handler, cb_data);
1083 }
1084 
1085 int
ipmi_control_identifier_set_val(ipmi_control_t * control,unsigned char * val,int length,ipmi_control_op_cb handler,void * cb_data)1086 ipmi_control_identifier_set_val(ipmi_control_t     *control,
1087 				unsigned char      *val,
1088 				int                length,
1089 				ipmi_control_op_cb handler,
1090 				void               *cb_data)
1091 {
1092     if (!control_ok_to_use(control))
1093 	return ECANCELED;
1094 
1095     CHECK_CONTROL_LOCK(control);
1096 
1097     if (!control->cbs.set_identifier_val)
1098 	return ENOSYS;
1099     return control->cbs.set_identifier_val(control,
1100 					   val,
1101 					   length,
1102 					   handler,
1103 					   cb_data);
1104 }
1105 
1106 /***********************************************************************
1107  *
1108  * Polymorphic calls that take control ids.
1109  *
1110  **********************************************************************/
1111 
1112 typedef struct control_id_set_val_s
1113 {
1114     int                *val;
1115     ipmi_control_op_cb handler;
1116     void               *cb_data;
1117     int                rv;
1118 } control_id_set_val_t;
1119 
1120 static void
control_id_set_val_cb(ipmi_control_t * control,void * cb_data)1121 control_id_set_val_cb(ipmi_control_t *control, void *cb_data)
1122 {
1123     control_id_set_val_t *info = cb_data;
1124 
1125     info->rv = ipmi_control_set_val(control,
1126 				    info->val,
1127 				    info->handler,
1128 				    info->cb_data);
1129 }
1130 
1131 int
ipmi_control_id_set_val(ipmi_control_id_t control_id,int * val,ipmi_control_op_cb handler,void * cb_data)1132 ipmi_control_id_set_val(ipmi_control_id_t  control_id,
1133 			int                *val,
1134 			ipmi_control_op_cb handler,
1135 			void               *cb_data)
1136 {
1137     control_id_set_val_t info;
1138     int                  rv;
1139 
1140     info.val = val;
1141     info.handler = handler;
1142     info.cb_data = cb_data;
1143     rv = ipmi_control_pointer_cb(control_id, control_id_set_val_cb, &info);
1144     if (!rv)
1145 	rv = info.rv;
1146     return rv;
1147 }
1148 
1149 typedef struct control_id_get_val_s
1150 {
1151     ipmi_control_val_cb handler;
1152     void                *cb_data;
1153     int                 rv;
1154 } control_id_get_val_t;
1155 
1156 static void
control_id_get_val_cb(ipmi_control_t * control,void * cb_data)1157 control_id_get_val_cb(ipmi_control_t *control, void *cb_data)
1158 {
1159     control_id_get_val_t *info = cb_data;
1160 
1161     info->rv = ipmi_control_get_val(control,
1162 				    info->handler,
1163 				    info->cb_data);
1164 }
1165 
1166 int
ipmi_control_id_get_val(ipmi_control_id_t control_id,ipmi_control_val_cb handler,void * cb_data)1167 ipmi_control_id_get_val(ipmi_control_id_t   control_id,
1168 			ipmi_control_val_cb handler,
1169 			void                *cb_data)
1170 {
1171     control_id_get_val_t info;
1172     int                  rv;
1173 
1174     info.handler = handler;
1175     info.cb_data = cb_data;
1176     rv = ipmi_control_pointer_cb(control_id, control_id_get_val_cb, &info);
1177     if (!rv)
1178 	rv = info.rv;
1179     return rv;
1180 }
1181 
1182 typedef struct control_id_identifier_set_val_s
1183 {
1184     unsigned char      *val;
1185     int                length;
1186     ipmi_control_op_cb handler;
1187     void               *cb_data;
1188     int                rv;
1189 } control_id_identifier_set_val_t;
1190 
1191 static void
control_id_identifier_set_val_cb(ipmi_control_t * control,void * cb_data)1192 control_id_identifier_set_val_cb(ipmi_control_t *control, void *cb_data)
1193 {
1194     control_id_identifier_set_val_t *info = cb_data;
1195 
1196     info->rv = ipmi_control_identifier_set_val(control,
1197 					       info->val,
1198 					       info->length,
1199 					       info->handler,
1200 					       info->cb_data);
1201 }
1202 
1203 int
ipmi_control_id_identifier_set_val(ipmi_control_id_t control_id,unsigned char * val,int length,ipmi_control_op_cb handler,void * cb_data)1204 ipmi_control_id_identifier_set_val(ipmi_control_id_t  control_id,
1205 				   unsigned char      *val,
1206 				   int                length,
1207 				   ipmi_control_op_cb handler,
1208 				   void               *cb_data)
1209 {
1210     control_id_identifier_set_val_t info;
1211     int                             rv;
1212 
1213     info.val = val;
1214     info.length = length;
1215     info.handler = handler;
1216     info.cb_data = cb_data;
1217     rv = ipmi_control_pointer_cb(control_id,
1218 				 control_id_identifier_set_val_cb, &info);
1219     if (!rv)
1220 	rv = info.rv;
1221     return rv;
1222 }
1223 
1224 typedef struct control_id_identifier_get_val_s
1225 {
1226     ipmi_control_identifier_val_cb handler;
1227     void                           *cb_data;
1228     int                            rv;
1229 } control_id_identifier_get_val_t;
1230 
1231 static void
control_id_identifier_get_val_cb(ipmi_control_t * control,void * cb_data)1232 control_id_identifier_get_val_cb(ipmi_control_t *control, void *cb_data)
1233 {
1234     control_id_identifier_get_val_t *info = cb_data;
1235 
1236     info->rv = ipmi_control_identifier_get_val(control,
1237 					       info->handler,
1238 					       info->cb_data);
1239 }
1240 
1241 int
ipmi_control_id_identifier_get_val(ipmi_control_id_t control_id,ipmi_control_identifier_val_cb handler,void * cb_data)1242 ipmi_control_id_identifier_get_val(ipmi_control_id_t              control_id,
1243 				   ipmi_control_identifier_val_cb handler,
1244 				   void                           *cb_data)
1245 {
1246     control_id_identifier_get_val_t info;
1247     int                             rv;
1248 
1249     info.handler = handler;
1250     info.cb_data = cb_data;
1251     rv = ipmi_control_pointer_cb(control_id,
1252 				 control_id_identifier_get_val_cb, &info);
1253     if (!rv)
1254 	rv = info.rv;
1255     return rv;
1256 }
1257 
1258 /***********************************************************************
1259  *
1260  * Event handling for controls.
1261  *
1262  **********************************************************************/
1263 
1264 void
ipmi_control_set_has_events(ipmi_control_t * control,int val)1265 ipmi_control_set_has_events(ipmi_control_t *control, int val)
1266 {
1267     control->has_events = val;
1268 }
1269 
1270 int
ipmi_control_has_events(ipmi_control_t * control)1271 ipmi_control_has_events(ipmi_control_t *control)
1272 {
1273     return control->has_events;
1274 }
1275 
1276 typedef struct control_event_info_s
1277 {
1278     ipmi_control_t *control;
1279     int            handled;
1280 
1281     int            *valid_vals;
1282     int            *vals;
1283 
1284     ipmi_event_t   *event;
1285 } control_event_info_t;
1286 
1287 static int
control_val_event_call_handler(void * cb_data,void * item1,void * item2)1288 control_val_event_call_handler(void *cb_data, void *item1, void *item2)
1289 {
1290     ipmi_control_val_event_cb handler = item1;
1291     control_event_info_t      *info = cb_data;
1292     int                       handled;
1293 
1294     handled = handler(info->control,
1295 		      info->valid_vals,
1296 		      info->vals,
1297 		      item2,
1298 		      info->event);
1299     if (handled != IPMI_EVENT_NOT_HANDLED) {
1300 	if (info->handled != IPMI_EVENT_HANDLED)
1301 	    /* Allow handled to override handled_pass, but not the
1302 	       other way. */
1303 	    info->handled = handled;
1304 	if (handled == IPMI_EVENT_HANDLED)
1305 	    info->event = NULL;
1306     }
1307     return LOCKED_LIST_ITER_CONTINUE;
1308 }
1309 
1310 void
ipmi_control_call_val_event_handlers(ipmi_control_t * control,int * valid_vals,int * vals,ipmi_event_t ** event,int * handled)1311 ipmi_control_call_val_event_handlers(ipmi_control_t *control,
1312 				     int            *valid_vals,
1313 				     int            *vals,
1314 				     ipmi_event_t   **event,
1315 				     int            *handled)
1316 {
1317     control_event_info_t info;
1318 
1319     info.control = control;
1320     info.valid_vals = valid_vals;
1321     info.vals = vals;
1322     info.event = *event;
1323     info.handled = IPMI_EVENT_NOT_HANDLED;
1324 
1325     locked_list_iterate(control->handler_list,
1326 			control_val_event_call_handler, &info);
1327 
1328     if (handled)
1329 	*handled = info.handled;
1330     *event = info.event;
1331 }
1332 
1333 int
ipmi_control_add_val_event_handler(ipmi_control_t * control,ipmi_control_val_event_cb handler,void * cb_data)1334 ipmi_control_add_val_event_handler(ipmi_control_t            *control,
1335 				   ipmi_control_val_event_cb handler,
1336 				   void                      *cb_data)
1337 {
1338     CHECK_CONTROL_LOCK(control);
1339 
1340     if (! locked_list_add(control->handler_list, handler, cb_data))
1341 	return ENOMEM;
1342 
1343     return 0;
1344 }
1345 
ipmi_control_remove_val_event_handler(ipmi_control_t * control,ipmi_control_val_event_cb handler,void * cb_data)1346 int ipmi_control_remove_val_event_handler(ipmi_control_t            *control,
1347 					  ipmi_control_val_event_cb handler,
1348 					  void                      *cb_data)
1349 {
1350     CHECK_CONTROL_LOCK(control);
1351 
1352     if (! locked_list_remove(control->handler_list, handler, cb_data))
1353 	return ENOENT;
1354 
1355     return 0;
1356 }
1357 
1358 int
ipmi_control_add_val_event_handler_cl(ipmi_control_t * control,ipmi_control_val_event_cl_cb handler,void * cb_data)1359 ipmi_control_add_val_event_handler_cl(ipmi_control_t            *control,
1360 				      ipmi_control_val_event_cl_cb handler,
1361 				      void                      *cb_data)
1362 {
1363     CHECK_CONTROL_LOCK(control);
1364 
1365     if (! locked_list_add(control->handler_list_cl, handler, cb_data))
1366 	return ENOMEM;
1367 
1368     return 0;
1369 }
1370 
ipmi_control_remove_val_event_handler_cl(ipmi_control_t * control,ipmi_control_val_event_cl_cb handler,void * cb_data)1371 int ipmi_control_remove_val_event_handler_cl(ipmi_control_t         *control,
1372 					  ipmi_control_val_event_cl_cb handler,
1373 					  void                      *cb_data)
1374 {
1375     CHECK_CONTROL_LOCK(control);
1376 
1377     if (! locked_list_remove(control->handler_list_cl, handler, cb_data))
1378 	return ENOENT;
1379 
1380     return 0;
1381 }
1382 
1383 /***********************************************************************
1384  *
1385  * Get/set various local information about a control.
1386  *
1387  **********************************************************************/
1388 
1389 int
ipmi_control_get_type(ipmi_control_t * control)1390 ipmi_control_get_type(ipmi_control_t *control)
1391 {
1392     CHECK_CONTROL_LOCK(control);
1393 
1394     return control->type;
1395 }
1396 
1397 void
ipmi_control_set_type(ipmi_control_t * control,int val)1398 ipmi_control_set_type(ipmi_control_t *control, int val)
1399 {
1400     control->type = val;
1401     control->type_str = ipmi_get_control_type_string(val);
1402 }
1403 
1404 const char *
ipmi_control_get_type_string(ipmi_control_t * control)1405 ipmi_control_get_type_string(ipmi_control_t *control)
1406 {
1407     CHECK_CONTROL_LOCK(control);
1408 
1409     return control->type_str;
1410 }
1411 
1412 int
ipmi_control_get_id_length(ipmi_control_t * control)1413 ipmi_control_get_id_length(ipmi_control_t *control)
1414 {
1415     CHECK_CONTROL_LOCK(control);
1416 
1417     if (control->id_type == IPMI_ASCII_STR)
1418 	return control->id_len+1;
1419     else
1420 	return control->id_len;
1421 }
1422 
1423 enum ipmi_str_type_e
ipmi_control_get_id_type(ipmi_control_t * control)1424 ipmi_control_get_id_type(ipmi_control_t *control)
1425 {
1426     CHECK_CONTROL_LOCK(control);
1427 
1428     return control->id_type;
1429 }
1430 
1431 int
ipmi_control_get_id(ipmi_control_t * control,char * id,int length)1432 ipmi_control_get_id(ipmi_control_t *control, char *id, int length)
1433 {
1434     int clen;
1435 
1436     CHECK_CONTROL_LOCK(control);
1437 
1438     if ((int) control->id_len > length)
1439 	clen = length;
1440     else
1441 	clen = control->id_len;
1442     memcpy(id, control->id, clen);
1443 
1444     if (control->id_type == IPMI_ASCII_STR) {
1445 	/* NIL terminate the ASCII string. */
1446 	if (clen == length)
1447 	    clen--;
1448 
1449 	id[clen] = '\0';
1450     }
1451 
1452     return clen;
1453 }
1454 
1455 void
ipmi_control_set_id(ipmi_control_t * control,char * id,enum ipmi_str_type_e type,int length)1456 ipmi_control_set_id(ipmi_control_t *control, char *id,
1457 		    enum ipmi_str_type_e type, int length)
1458 {
1459     if (length > CONTROL_ID_LEN)
1460 	length = CONTROL_ID_LEN;
1461 
1462     memcpy(control->id, id, length);
1463     control->id_type = type;
1464     control->id_len = length;
1465     if (control->entity)
1466 	control_set_name(control);
1467 }
1468 
1469 int
ipmi_control_is_settable(ipmi_control_t * control)1470 ipmi_control_is_settable(ipmi_control_t *control)
1471 {
1472     CHECK_CONTROL_LOCK(control);
1473 
1474     return control->settable;
1475 }
1476 
1477 int
ipmi_control_is_readable(ipmi_control_t * control)1478 ipmi_control_is_readable(ipmi_control_t *control)
1479 {
1480     CHECK_CONTROL_LOCK(control);
1481 
1482     return control->readable;
1483 }
1484 
1485 void
ipmi_control_set_settable(ipmi_control_t * control,int val)1486 ipmi_control_set_settable(ipmi_control_t *control, int val)
1487 {
1488     control->settable = val;
1489 }
1490 
1491 void
ipmi_control_set_readable(ipmi_control_t * control,int val)1492 ipmi_control_set_readable(ipmi_control_t *control, int val)
1493 {
1494     control->readable = val;
1495 }
1496 
1497 int
ipmi_control_get_entity_id(ipmi_control_t * control)1498 ipmi_control_get_entity_id(ipmi_control_t *control)
1499 {
1500     return ipmi_entity_get_entity_id(control->entity);
1501 }
1502 
1503 int
ipmi_control_get_entity_instance(ipmi_control_t * control)1504 ipmi_control_get_entity_instance(ipmi_control_t *control)
1505 {
1506     CHECK_CONTROL_LOCK(control);
1507 
1508     return ipmi_entity_get_entity_instance(control->entity);
1509 }
1510 
1511 ipmi_entity_t *
ipmi_control_get_entity(ipmi_control_t * control)1512 ipmi_control_get_entity(ipmi_control_t *control)
1513 {
1514     return control->entity;
1515 }
1516 
1517 void
ipmi_control_set_oem_info(ipmi_control_t * control,void * oem_info,ipmi_control_cleanup_oem_info_cb cleanup_handler)1518 ipmi_control_set_oem_info(ipmi_control_t *control, void *oem_info,
1519 			  ipmi_control_cleanup_oem_info_cb cleanup_handler)
1520 {
1521     control->oem_info = oem_info;
1522     control->oem_info_cleanup_handler = cleanup_handler;
1523 }
1524 
1525 void *
ipmi_control_get_oem_info(ipmi_control_t * control)1526 ipmi_control_get_oem_info(ipmi_control_t *control)
1527 {
1528     CHECK_CONTROL_LOCK(control);
1529 
1530     return control->oem_info;
1531 }
1532 
1533 void
ipmi_control_get_display_dimensions(ipmi_control_t * control,unsigned int * columns,unsigned int * rows)1534 ipmi_control_get_display_dimensions(ipmi_control_t *control,
1535 				    unsigned int   *columns,
1536 				    unsigned int   *rows)
1537 {
1538     CHECK_CONTROL_LOCK(control);
1539 
1540     *columns = control->columns;
1541     *rows = control->rows;
1542 }
1543 
1544 void
ipmi_control_set_num_elements(ipmi_control_t * control,unsigned int val)1545 ipmi_control_set_num_elements(ipmi_control_t *control, unsigned int val)
1546 {
1547     control->num_vals = val;
1548 }
1549 
1550 unsigned int
ipmi_control_identifier_get_max_length(ipmi_control_t * control)1551 ipmi_control_identifier_get_max_length(ipmi_control_t *control)
1552 {
1553     CHECK_CONTROL_LOCK(control);
1554 
1555     return control->identifier_length;
1556 }
1557 
1558 void
ipmi_control_identifier_set_max_length(ipmi_control_t * control,unsigned int val)1559 ipmi_control_identifier_set_max_length(ipmi_control_t *control,
1560 				       unsigned int   val)
1561 {
1562     control->identifier_length = val;
1563 }
1564 
1565 void
ipmi_control_get_callbacks(ipmi_control_t * control,ipmi_control_cbs_t * cbs)1566 ipmi_control_get_callbacks(ipmi_control_t *control, ipmi_control_cbs_t *cbs)
1567 {
1568     *cbs = control->cbs;
1569 }
1570 
1571 void
ipmi_control_set_callbacks(ipmi_control_t * control,ipmi_control_cbs_t * cbs)1572 ipmi_control_set_callbacks(ipmi_control_t *control, ipmi_control_cbs_t *cbs)
1573 {
1574     control->cbs = *cbs;
1575 }
1576 
1577 ipmi_mc_t *
ipmi_control_get_mc(ipmi_control_t * control)1578 ipmi_control_get_mc(ipmi_control_t *control)
1579 {
1580     return control->mc;
1581 }
1582 
1583 ipmi_mc_t *
ipmi_control_get_source_mc(ipmi_control_t * control)1584 ipmi_control_get_source_mc(ipmi_control_t *control)
1585 {
1586     CHECK_CONTROL_LOCK(control);
1587 
1588     return control->source_mc;
1589 }
1590 
1591 int
ipmi_control_get_num(ipmi_control_t * control,int * lun,int * num)1592 ipmi_control_get_num(ipmi_control_t *control,
1593 		     int            *lun,
1594 		     int            *num)
1595 {
1596     CHECK_CONTROL_LOCK(control);
1597 
1598     if (lun)
1599 	*lun = control->lun;
1600     if (num)
1601 	*num = control->num;
1602     return 0;
1603 }
1604 
1605 int
ipmi_control_light_set_with_setting(ipmi_control_t * control)1606 ipmi_control_light_set_with_setting(ipmi_control_t *control)
1607 {
1608     return ((control->cbs.set_light != NULL)
1609 	    || (control->cbs.get_light != NULL));
1610 }
1611 
1612 void
ipmi_control_light_set_lights(ipmi_control_t * control,unsigned int num_lights,ipmi_control_light_t * lights)1613 ipmi_control_light_set_lights(ipmi_control_t       *control,
1614 			      unsigned int         num_lights,
1615 			      ipmi_control_light_t *lights)
1616 {
1617     control->num_vals = num_lights;
1618     control->lights = lights;
1619 }
1620 
1621 int
ipmi_control_get_num_vals(ipmi_control_t * control)1622 ipmi_control_get_num_vals(ipmi_control_t *control)
1623 {
1624     CHECK_CONTROL_LOCK(control);
1625 
1626     return control->num_vals;
1627 }
1628 
1629 int
ipmi_control_get_num_light_values(ipmi_control_t * control,unsigned int light)1630 ipmi_control_get_num_light_values(ipmi_control_t *control,
1631 				  unsigned int   light)
1632 {
1633     CHECK_CONTROL_LOCK(control);
1634 
1635     if (!control->lights)
1636 	return -1;
1637     if (light >= control->num_vals)
1638 	return -1;
1639 
1640     return control->lights[light].num_values;
1641 }
1642 
1643 int
ipmi_control_get_num_light_transitions(ipmi_control_t * control,unsigned int light,unsigned int set)1644 ipmi_control_get_num_light_transitions(ipmi_control_t   *control,
1645 				       unsigned int     light,
1646 				       unsigned int     set)
1647 {
1648     CHECK_CONTROL_LOCK(control);
1649 
1650     if (!control->lights)
1651 	return -1;
1652     if (light >= control->num_vals)
1653 	return -1;
1654     if (set >= control->lights[light].num_values)
1655 	return -1;
1656 
1657     return control->lights[light].values[set].num_transitions;
1658 }
1659 
1660 int
ipmi_control_get_light_color(ipmi_control_t * control,unsigned int light,unsigned int set,unsigned int num)1661 ipmi_control_get_light_color(ipmi_control_t   *control,
1662 			     unsigned int     light,
1663 			     unsigned int     set,
1664 			     unsigned int     num)
1665 {
1666     CHECK_CONTROL_LOCK(control);
1667 
1668     if (!control->lights)
1669 	return -1;
1670     if (light >= control->num_vals)
1671 	return -1;
1672     if (set >= control->lights[light].num_values)
1673 	return -1;
1674     if (num > control->lights[light].values[set].num_transitions)
1675 	return -1;
1676 
1677     return control->lights[light].values[set].transitions[num].color;
1678 }
1679 
1680 int
ipmi_control_get_light_color_time(ipmi_control_t * control,unsigned int light,unsigned int set,unsigned int num)1681 ipmi_control_get_light_color_time(ipmi_control_t   *control,
1682 				  unsigned int     light,
1683 				  unsigned int     set,
1684 				  unsigned int     num)
1685 {
1686     CHECK_CONTROL_LOCK(control);
1687 
1688     if (!control->lights)
1689 	return -1;
1690     if (light >= control->num_vals)
1691 	return -1;
1692     if (set >= control->lights[light].num_values)
1693 	return -1;
1694     if (num > control->lights[light].values[set].num_transitions)
1695 	return -1;
1696 
1697     return control->lights[light].values[set].transitions[num].time;
1698 }
1699 
1700 int
ipmi_control_set_light(ipmi_control_t * control,ipmi_light_setting_t * settings,ipmi_control_op_cb handler,void * cb_data)1701 ipmi_control_set_light(ipmi_control_t       *control,
1702 		       ipmi_light_setting_t *settings,
1703 		       ipmi_control_op_cb   handler,
1704 		       void                 *cb_data)
1705 {
1706     CHECK_CONTROL_LOCK(control);
1707 
1708     if (!control->cbs.set_light)
1709 	return ENOSYS;
1710     return control->cbs.set_light(control, settings, handler, cb_data);
1711 }
1712 
1713 int
ipmi_control_get_light(ipmi_control_t * control,ipmi_light_settings_cb handler,void * cb_data)1714 ipmi_control_get_light(ipmi_control_t         *control,
1715 		       ipmi_light_settings_cb handler,
1716 		       void                   *cb_data)
1717 {
1718     CHECK_CONTROL_LOCK(control);
1719 
1720     if (!control->cbs.get_light)
1721 	return ENOSYS;
1722     return control->cbs.get_light(control, handler, cb_data);
1723 }
1724 
1725 
1726 typedef struct ipmi_light_s
1727 {
1728     int color;
1729     int on_time;
1730     int off_time;
1731     int local_control;
1732 } ipmi_light_t;
1733 
1734 struct ipmi_light_setting_s
1735 {
1736     int          count;
1737     ipmi_light_t *lights;
1738 };
1739 
1740 unsigned int
ipmi_light_setting_get_count(ipmi_light_setting_t * setting)1741 ipmi_light_setting_get_count(ipmi_light_setting_t *setting)
1742 {
1743     return setting->count;
1744 }
1745 
1746 int
ipmi_light_setting_in_local_control(ipmi_light_setting_t * setting,int num,int * lc)1747 ipmi_light_setting_in_local_control(ipmi_light_setting_t *setting,
1748 				    int                  num,
1749 				    int                  *lc)
1750 {
1751     if (num > setting->count)
1752 	return EINVAL;
1753 
1754     *lc = setting->lights[num].local_control;
1755     return 0;
1756 }
1757 
1758 int
ipmi_light_setting_set_local_control(ipmi_light_setting_t * setting,int num,int lc)1759 ipmi_light_setting_set_local_control(ipmi_light_setting_t *setting,
1760 				     int                  num,
1761 				     int                  lc)
1762 {
1763     if (num > setting->count)
1764 	return EINVAL;
1765 
1766     setting->lights[num].local_control = lc;
1767     return 0;
1768 }
1769 
1770 int
ipmi_light_setting_get_color(ipmi_light_setting_t * setting,int num,int * color)1771 ipmi_light_setting_get_color(ipmi_light_setting_t *setting, int num,
1772 			     int *color)
1773 {
1774     if (num > setting->count)
1775 	return EINVAL;
1776 
1777     *color = setting->lights[num].color;
1778     return 0;
1779 }
1780 
1781 int
ipmi_light_setting_set_color(ipmi_light_setting_t * setting,int num,int color)1782 ipmi_light_setting_set_color(ipmi_light_setting_t *setting, int num,
1783 			     int color)
1784 {
1785     if (num > setting->count)
1786 	return EINVAL;
1787 
1788     setting->lights[num].color = color;
1789     return 0;
1790 }
1791 
1792 int
ipmi_light_setting_get_on_time(ipmi_light_setting_t * setting,int num,int * time)1793 ipmi_light_setting_get_on_time(ipmi_light_setting_t *setting, int num,
1794 			       int *time)
1795 {
1796     if (num > setting->count)
1797 	return EINVAL;
1798 
1799     *time = setting->lights[num].on_time;
1800     return 0;
1801 }
1802 
1803 int
ipmi_light_setting_set_on_time(ipmi_light_setting_t * setting,int num,int time)1804 ipmi_light_setting_set_on_time(ipmi_light_setting_t *setting, int num,
1805 			       int time)
1806 {
1807     if (num > setting->count)
1808 	return EINVAL;
1809 
1810     setting->lights[num].on_time = time;
1811     return 0;
1812 }
1813 
1814 int
ipmi_light_setting_get_off_time(ipmi_light_setting_t * setting,int num,int * time)1815 ipmi_light_setting_get_off_time(ipmi_light_setting_t *setting, int num,
1816 				int *time)
1817 {
1818     if (num > setting->count)
1819 	return EINVAL;
1820 
1821     *time = setting->lights[num].off_time;
1822     return 0;
1823 }
1824 
1825 int
ipmi_light_setting_set_off_time(ipmi_light_setting_t * setting,int num,int time)1826 ipmi_light_setting_set_off_time(ipmi_light_setting_t *setting, int num,
1827 				int time)
1828 {
1829     if (num > setting->count)
1830 	return EINVAL;
1831 
1832     setting->lights[num].off_time = time;
1833     return 0;
1834 }
1835 
1836 ipmi_light_setting_t *
ipmi_alloc_light_settings(unsigned int count)1837 ipmi_alloc_light_settings(unsigned int count)
1838 {
1839     ipmi_light_setting_t *rv;
1840 
1841     if (count == 0)
1842 	return NULL;
1843 
1844     rv = ipmi_mem_alloc(sizeof(*rv));
1845     if (!rv)
1846 	return NULL;
1847 
1848     rv->lights = ipmi_mem_alloc(sizeof(ipmi_light_t) * count);
1849     if (!rv->lights) {
1850 	ipmi_mem_free(rv);
1851 	return NULL;
1852     }
1853 
1854     rv->count = count;
1855     memset(rv->lights, 0, sizeof(ipmi_light_t) * count);
1856     return rv;
1857 }
1858 
1859 void
ipmi_free_light_settings(ipmi_light_setting_t * settings)1860 ipmi_free_light_settings(ipmi_light_setting_t *settings)
1861 {
1862     ipmi_mem_free(settings->lights);
1863     ipmi_mem_free(settings);
1864 }
1865 
1866 ipmi_light_setting_t *
ipmi_light_settings_dup(ipmi_light_setting_t * settings)1867 ipmi_light_settings_dup(ipmi_light_setting_t *settings)
1868 {
1869     ipmi_light_setting_t *rv;
1870 
1871     rv = ipmi_mem_alloc(sizeof(*rv));
1872     if (!rv)
1873 	return NULL;
1874 
1875     rv->lights = ipmi_mem_alloc(sizeof(ipmi_light_t) * settings->count);
1876     if (!rv->lights) {
1877 	ipmi_mem_free(rv);
1878 	return NULL;
1879     }
1880 
1881     rv->count = settings->count;
1882     memcpy(rv->lights, settings->lights,
1883 	   sizeof(ipmi_light_t) * settings->count);
1884     return rv;
1885 }
1886 
1887 int
ipmi_control_add_light_color_support(ipmi_control_t * control,int light_num,unsigned int color)1888 ipmi_control_add_light_color_support(ipmi_control_t *control,
1889 				     int            light_num,
1890 				     unsigned int   color)
1891 {
1892     if (light_num >= MAX_LIGHTS)
1893 	return EINVAL;
1894     control->colors[light_num] |= (1 << color);
1895     return 0;
1896 }
1897 
1898 int
ipmi_control_light_is_color_sup(ipmi_control_t * control,int light_num,unsigned int color)1899 ipmi_control_light_is_color_sup(ipmi_control_t *control,
1900 				int            light_num,
1901 				unsigned int   color)
1902 {
1903     CHECK_CONTROL_LOCK(control);
1904 
1905     if (light_num >= MAX_LIGHTS)
1906 	return 0;
1907     return (control->colors[light_num] & (1 << color)) != 0;
1908 }
1909 
1910 int
ipmi_control_light_set_has_local_control(ipmi_control_t * control,int light_num,int val)1911 ipmi_control_light_set_has_local_control(ipmi_control_t *control,
1912 					 int            light_num,
1913 					 int            val)
1914 {
1915     if (light_num >= MAX_LIGHTS)
1916 	return EINVAL;
1917      control->has_local_control[light_num] = val;
1918      return 0;
1919 }
1920 
1921 int
ipmi_control_light_has_loc_ctrl(ipmi_control_t * control,int light_num)1922 ipmi_control_light_has_loc_ctrl(ipmi_control_t *control,
1923 				int            light_num)
1924 {
1925     CHECK_CONTROL_LOCK(control);
1926 
1927     if (light_num >= MAX_LIGHTS)
1928 	return 0;
1929     return control->has_local_control[light_num];
1930 }
1931 
1932 int
ipmi_cmp_control_id(ipmi_control_id_t id1,ipmi_control_id_t id2)1933 ipmi_cmp_control_id(ipmi_control_id_t id1, ipmi_control_id_t id2)
1934 {
1935     int rv = ipmi_cmp_mc_id(id1.mcid, id2.mcid);
1936     if (rv)
1937 	return rv;
1938     if (id1.lun > id2.lun)
1939 	return 1;
1940     if (id1.lun < id2.lun)
1941 	return -1;
1942     if (id1.control_num > id2.control_num)
1943 	return 1;
1944     if (id1.control_num < id2.control_num)
1945 	return -1;
1946     return 0;
1947 }
1948 
1949 void
ipmi_control_id_set_invalid(ipmi_control_id_t * id)1950 ipmi_control_id_set_invalid(ipmi_control_id_t *id)
1951 {
1952     memset(id, 0, sizeof(*id));
1953 }
1954 
1955 int
ipmi_control_id_is_invalid(const ipmi_control_id_t * id)1956 ipmi_control_id_is_invalid(const ipmi_control_id_t *id)
1957 {
1958     return (id->mcid.domain_id.domain == NULL);
1959 }
1960 
1961 
1962 void
ipmi_control_set_hot_swap_indicator(ipmi_control_t * control,int val,int req_act_val,int active_val,int req_deact_val,int inactive_val)1963 ipmi_control_set_hot_swap_indicator(ipmi_control_t *control,
1964 				    int            val,
1965 				    int            req_act_val,
1966 				    int            active_val,
1967 				    int            req_deact_val,
1968 				    int            inactive_val)
1969 {
1970     control->hot_swap_indicator = val;
1971     control->hot_swap_active_val = active_val;
1972     control->hot_swap_inactive_val = inactive_val;
1973     control->hot_swap_req_act_val = req_act_val;
1974     control->hot_swap_req_deact_val = req_deact_val;
1975 }
1976 
1977 int
ipmi_control_is_hot_swap_indicator(ipmi_control_t * control,int * req_act_val,int * active_val,int * req_deact_val,int * inactive_val)1978 ipmi_control_is_hot_swap_indicator(ipmi_control_t *control,
1979 				   int            *req_act_val,
1980 				   int            *active_val,
1981 				   int            *req_deact_val,
1982 				   int            *inactive_val)
1983 {
1984     CHECK_CONTROL_LOCK(control);
1985 
1986     if (control->hot_swap_indicator) {
1987 	if (active_val)
1988 	    *active_val = control->hot_swap_active_val;
1989 	if (inactive_val)
1990 	    *inactive_val = control->hot_swap_inactive_val;
1991 	if (req_act_val)
1992 	    *req_act_val = control->hot_swap_req_act_val;
1993 	if (req_deact_val)
1994 	    *req_deact_val = control->hot_swap_req_deact_val;
1995 	return 1;
1996     }
1997     return 0;
1998 }
1999 
2000 void
ipmi_control_set_hot_swap_power(ipmi_control_t * control,int val)2001 ipmi_control_set_hot_swap_power(ipmi_control_t *control, int val)
2002 {
2003     control->hot_swap_power = val;
2004 }
2005 
2006 int
ipmi_control_is_hot_swap_power(ipmi_control_t * control)2007 ipmi_control_is_hot_swap_power(ipmi_control_t *control)
2008 {
2009     CHECK_CONTROL_LOCK(control);
2010 
2011     return control->hot_swap_power;
2012 }
2013 
2014 int
ipmi_control_get_ignore_if_no_entity(ipmi_control_t * control)2015 ipmi_control_get_ignore_if_no_entity(ipmi_control_t *control)
2016 {
2017     CHECK_CONTROL_LOCK(control);
2018 
2019     return control->ignore_if_no_entity;
2020 }
2021 
2022 void
ipmi_control_set_ignore_if_no_entity(ipmi_control_t * control,int ignore_if_no_entity)2023 ipmi_control_set_ignore_if_no_entity(ipmi_control_t *control,
2024 				     int            ignore_if_no_entity)
2025 {
2026     control->ignore_if_no_entity = ignore_if_no_entity;
2027 }
2028 
2029 int
ipmi_control_get_ignore_for_presence(ipmi_control_t * control)2030 ipmi_control_get_ignore_for_presence(ipmi_control_t *control)
2031 {
2032     CHECK_CONTROL_LOCK(control);
2033 
2034     return control->ignore_for_presence;
2035 }
2036 
2037 void
ipmi_control_set_ignore_for_presence(ipmi_control_t * control,int ignore)2038 ipmi_control_set_ignore_for_presence(ipmi_control_t *control, int ignore)
2039 {
2040     control->ignore_for_presence = ignore;
2041 }
2042 
2043 ipmi_domain_t *
ipmi_control_get_domain(ipmi_control_t * control)2044 ipmi_control_get_domain(ipmi_control_t *control)
2045 {
2046     return control->domain;
2047 }
2048 
2049 #ifdef IPMI_CHECK_LOCKS
2050 void
i__ipmi_check_control_lock(const ipmi_control_t * control)2051 i__ipmi_check_control_lock(const ipmi_control_t *control)
2052 {
2053     if (!control)
2054 	return;
2055 
2056     if (!DEBUG_LOCKS)
2057 	return;
2058 
2059     CHECK_ENTITY_LOCK(control->entity);
2060     CHECK_MC_LOCK(control->mc);
2061 
2062     if (control->usecount == 0)
2063 	ipmi_report_lock_error(ipmi_domain_get_os_hnd(control->domain),
2064 			       "control not locked when it should have been");
2065 }
2066 #endif
2067 
2068 /***********************************************************************
2069  *
2070  * Crufty backwards-compatible interfaces.  Don't use these as they
2071  * are deprecated.
2072  *
2073  **********************************************************************/
2074 
2075 int
ipmi_control_get_num_light_settings(ipmi_control_t * control,unsigned int light)2076 ipmi_control_get_num_light_settings(ipmi_control_t *control,
2077 				    unsigned int   light)
2078 {
2079     return ipmi_control_get_num_light_values(control, light);
2080 }
2081 
2082 int
ipmi_control_light_is_color_supported(ipmi_control_t * control,unsigned int color)2083 ipmi_control_light_is_color_supported(ipmi_control_t *control,
2084 				      unsigned int   color)
2085 {
2086     return ipmi_control_light_is_color_sup(control, 0, color);
2087 }
2088 
2089 int
ipmi_control_light_has_local_control(ipmi_control_t * control)2090 ipmi_control_light_has_local_control(ipmi_control_t *control)
2091 {
2092     return ipmi_control_light_has_loc_ctrl(control, 0);
2093 }
2094