1 /*
2  * bmc_picmg.c
3  *
4  * MontaVista IPMI code for emulating a MC.
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2003,2012 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  * Modified BSD Licence
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  *
39  *   1. Redistributions of source code must retain the above copyright
40  *      notice, this list of conditions and the following disclaimer.
41  *   2. Redistributions in binary form must reproduce the above
42  *      copyright notice, this list of conditions and the following
43  *      disclaimer in the documentation and/or other materials provided
44  *      with the distribution.
45  *   3. The name of the author may not be used to endorse or promote
46  *      products derived from this software without specific prior
47  *      written permission.
48  */
49 
50 #include "bmc.h"
51 
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <string.h>
55 
56 #include <OpenIPMI/ipmi_err.h>
57 #include <OpenIPMI/ipmi_msgbits.h>
58 #include <OpenIPMI/ipmi_picmg.h>
59 
60 int
ipmi_mc_set_power(lmc_data_t * mc,unsigned char power,int gen_event)61 ipmi_mc_set_power(lmc_data_t *mc, unsigned char power, int gen_event)
62 {
63     lmc_data_t    *dest_mc;
64     unsigned char data[13];
65     int           rv;
66 
67     if (mc->power_value == power)
68 	return 0;
69 
70     mc->power_value = power;
71 
72     if ((mc->event_receiver == 0)
73 	|| (!gen_event))
74 	return 0;
75 
76     rv = ipmi_emu_get_mc_by_addr(mc->emu, mc->event_receiver, &dest_mc);
77     if (rv)
78 	return 0;
79 
80     /* Timestamp is ignored. */
81     data[0] = 0;
82     data[1] = 0;
83     data[2] = 0;
84     data[3] = 0;
85 
86     data[4] = 0x20; /* These come from 0x20. */
87     data[5] = 0;
88     data[6] = 0x01; /* Version 1. */
89     data[7] = 0;
90     data[8] = 0x40; /* IPMB of the device being powered. */
91     data[9] = 0;
92     data[10] = power;
93     data[11] = 0;
94     data[12] = 0;
95 
96     mc_new_event(dest_mc, 0xc0, data);
97 
98     return 0;
99 }
100 
101 static void
handle_set_power(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)102 handle_set_power(lmc_data_t    *mc,
103 		 msg_t         *msg,
104 		 unsigned char *rdata,
105 		 unsigned int  *rdata_len,
106 		 void          *cb_data)
107 {
108     if (check_msg_length(msg, 1, rdata, rdata_len))
109 	return;
110 
111     ipmi_mc_set_power(mc, msg->data[0], 1);
112 
113     rdata[0] = 0;
114     *rdata_len = 1;
115 }
116 
117 static void
handle_get_power(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)118 handle_get_power(lmc_data_t    *mc,
119 		 msg_t         *msg,
120 		 unsigned char *rdata,
121 		 unsigned int  *rdata_len,
122 		 void          *cb_data)
123 {
124     rdata[0] = 0;
125     rdata[1] = mc->power_value;
126     *rdata_len = 2;
127 }
128 
129 static void
handle_set_hs_led(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)130 handle_set_hs_led(lmc_data_t    *mc,
131 		  msg_t         *msg,
132 		  unsigned char *rdata,
133 		  unsigned int  *rdata_len,
134 		  void          *cb_data)
135 {
136     if (check_msg_length(msg, 1, rdata, rdata_len))
137 	return;
138 
139     mc->leds[0].color = msg->data[0];
140 
141     printf("Setting hotswap LED to %d\n", msg->data[0]);
142 
143     rdata[0] = 0;
144     *rdata_len = 1;
145 }
146 
147 static void
handle_get_hs_led(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)148 handle_get_hs_led(lmc_data_t    *mc,
149 		  msg_t         *msg,
150 		  unsigned char *rdata,
151 		  unsigned int  *rdata_len,
152 		  void          *cb_data)
153 {
154     rdata[0] = 0;
155     rdata[1] = mc->leds[0].color;
156     *rdata_len = 2;
157 }
158 
159 cmd_handler_f oem0_netfn_handlers[256] = {
160     [0x01] = handle_set_power,
161     [0x02] = handle_get_power,
162     [0x03] = handle_set_hs_led,
163     [0x04] = handle_get_hs_led
164 };
165 
166 static void
handle_picmg_get_properties(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)167 handle_picmg_get_properties(lmc_data_t    *mc,
168 			    msg_t         *msg,
169 			    unsigned char *rdata,
170 			    unsigned int  *rdata_len,
171 			    void          *cb_data)
172 {
173     rdata[0] = 0;
174     rdata[1] = IPMI_PICMG_GRP_EXT;
175     rdata[2] = 0x22; /* Version 2.2 */
176     rdata[3] = 0; /* Only have one FRU. */
177     rdata[4] = 0; /* As defined by spec. */
178     *rdata_len = 5;
179 }
180 
181 static void
handle_picmg_get_address_info(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)182 handle_picmg_get_address_info(lmc_data_t    *mc,
183 			      msg_t         *msg,
184 			      unsigned char *rdata,
185 			      unsigned int  *rdata_len,
186 			      void          *cb_data)
187 {
188     atca_site_t  *sites = mc->emu->atca_sites;
189     unsigned char hw_addr = mc->ipmb >> 1;
190     unsigned char devid = 0;
191     int           i;
192 
193     if (msg->len == 3) {
194 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
195 	*rdata_len = 1;
196 	return;
197     }
198 
199     if (msg->len >= 2)
200 	devid = msg->data[1];
201 
202     if (msg->len >= 4) {
203 	switch (msg->data[2]) {
204 	case 0:
205 	    hw_addr = msg->data[3];
206 	    break;
207 
208 	case 1:
209 	    hw_addr = msg->data[3] >> 1;
210 	    break;
211 
212 	case 3:
213 	    if (msg->len < 5) {
214 		rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
215 		*rdata_len = 1;
216 		return;
217 	    }
218 	    for (i=0; i<128; i++) {
219 		if (sites[i].valid
220 		    && (sites[i].site_type == msg->data[4])
221 		    && (sites[i].site_number == msg->data[3]))
222 		{
223 		    break;
224 		}
225 	    }
226 	    if (i == 128) {
227 		rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
228 		*rdata_len = 1;
229 		return;
230 	    }
231 	    hw_addr = i;
232 	    break;
233 
234 	default:
235 	    rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
236 	    *rdata_len = 1;
237 	    return;
238 	}
239     }
240 
241     if ((hw_addr >= 128) || (!sites[hw_addr].valid) || (devid > 0)) {
242 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
243 	*rdata_len = 1;
244 	return;
245     }
246 
247     rdata[0] = 0;
248     rdata[1] = IPMI_PICMG_GRP_EXT;
249     rdata[2] = hw_addr;
250     rdata[3] = hw_addr << 1;
251     rdata[4] = 0xff;
252     rdata[5] = devid;
253     rdata[6] = sites[hw_addr].site_number;
254     rdata[7] = sites[hw_addr].site_type;
255     *rdata_len = 8;
256 }
257 
258 static void
handle_picmg_cmd_fru_control(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)259 handle_picmg_cmd_fru_control(lmc_data_t    *mc,
260 			     msg_t         *msg,
261 			     unsigned char *rdata,
262 			     unsigned int  *rdata_len,
263 			     void          *cb_data)
264 {
265     if (check_msg_length(msg, 3, rdata, rdata_len))
266 	return;
267 
268     if (msg->data[1] != 0) {
269 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
270 	*rdata_len = 1;
271 	return;
272     }
273 
274     if (msg->data[2] >= 4) {
275 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
276 	*rdata_len = 1;
277 	return;
278     }
279 
280     /* Nothing to reset. */
281     printf("Fru control set to %d\n", msg->data[2]);
282 
283     rdata[0] = 0;
284     rdata[1] = IPMI_PICMG_GRP_EXT;
285     *rdata_len = 2;
286 }
287 
288 static void
handle_picmg_cmd_get_fru_led_properties(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)289 handle_picmg_cmd_get_fru_led_properties(lmc_data_t    *mc,
290 					msg_t         *msg,
291 					unsigned char *rdata,
292 					unsigned int  *rdata_len,
293 					void          *cb_data)
294 {
295     if (check_msg_length(msg, 2, rdata, rdata_len))
296 	return;
297 
298     if (msg->data[1] != 0) {
299 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
300 	*rdata_len = 1;
301 	return;
302     }
303 
304     rdata[0] = 0;
305     rdata[1] = IPMI_PICMG_GRP_EXT;
306     if (mc->num_leds <= 2) {
307 	mc->num_leds = 2;
308 	rdata[2] = 0x03; /* We support the first 2 LEDs. */
309 	rdata[3] = 0x00;
310     } else if (mc->num_leds == 3) {
311 	rdata[2] = 0x07; /* We support the first 3 LEDs. */
312 	rdata[3] = 0x00;
313     } else {
314 	rdata[2] = 0xf; /* We support the first 4 LEDs. */
315 	rdata[3] = mc->num_leds = 4; /* How many more do we support? */
316     }
317     *rdata_len = 4;
318 }
319 
320 static void
handle_picmg_cmd_get_led_color_capabilities(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)321 handle_picmg_cmd_get_led_color_capabilities(lmc_data_t    *mc,
322 					    msg_t         *msg,
323 					    unsigned char *rdata,
324 					    unsigned int  *rdata_len,
325 					    void          *cb_data)
326 {
327     unsigned int led;
328 
329     if (check_msg_length(msg, 3, rdata, rdata_len))
330 	return;
331 
332     if (msg->data[1] != 0) {
333 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
334 	*rdata_len = 1;
335 	return;
336     }
337 
338     led = msg->data[2];
339     if (led >= mc->num_leds) {
340 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
341 	*rdata_len = 1;
342 	return;
343     }
344 
345     rdata[0] = 0;
346     rdata[1] = IPMI_PICMG_GRP_EXT;
347     rdata[2] = mc->leds[led].color_sup;
348     rdata[3] = mc->leds[led].def_loc_cnt_color;
349     rdata[4] = mc->leds[led].def_override_color;
350 
351     *rdata_len = 5;
352 }
353 
354 void
picmg_led_set(lmc_data_t * mc,sensor_t * sensor)355 picmg_led_set(lmc_data_t *mc, sensor_t *sensor)
356 {
357     printf("ATCA hot-swap state is %d\n", sensor->value);
358 
359     switch (sensor->value) {
360     case 0:
361     case 3:
362     case 4:
363 	/* off */
364 	mc->leds[0].def_off_dur = 0;
365 	mc->leds[0].def_on_dur = 0;
366 	break;
367 
368     case 1:
369 	/* on */
370 	mc->leds[0].def_off_dur = 0xff;
371 	mc->leds[0].def_on_dur = 0;
372 	break;
373 
374     case 2:
375 	/* long blink */
376 	mc->leds[0].def_off_dur = 10;
377 	mc->leds[0].def_on_dur = 90;
378 	break;
379 
380     case 5:
381     case 6:
382 	/* short blink */
383 	mc->leds[0].def_off_dur = 90;
384 	mc->leds[0].def_on_dur = 10;
385 	break;
386 
387     case 7:
388 	/* Nothing to do */
389 	break;
390     }
391 
392     if (mc->leds[0].loc_cnt) {
393 	mc->leds[0].off_dur = mc->leds[0].def_off_dur;
394 	mc->leds[0].on_dur = mc->leds[0].def_on_dur;
395 	printf("Setting ATCA LED %d to %s %x %x %x\n",
396 	       0,
397 	       mc->leds[0].loc_cnt ? "local_control" : "override",
398 	       mc->leds[0].off_dur,
399 	       mc->leds[0].on_dur,
400 	       mc->leds[0].color);
401     }
402 }
403 
404 static void
handle_picmg_cmd_set_fru_led_state(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)405 handle_picmg_cmd_set_fru_led_state(lmc_data_t    *mc,
406 				   msg_t         *msg,
407 				   unsigned char *rdata,
408 				   unsigned int  *rdata_len,
409 				   void          *cb_data)
410 {
411     unsigned int led;
412 
413     if (check_msg_length(msg, 3, rdata, rdata_len))
414 	return;
415 
416     if (msg->data[1] != 0) {
417 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
418 	*rdata_len = 1;
419 	return;
420     }
421 
422     led = msg->data[2];
423     if (led >= mc->num_leds) {
424 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
425 	*rdata_len = 1;
426 	return;
427     }
428 
429     switch (msg->data[3]) {
430     case 0xfc: /* Local control */
431 	if (!mc->leds[led].loc_cnt_sup) {
432 	    rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
433 	    *rdata_len = 1;
434 	    return;
435 	}
436 
437 	mc->leds[led].loc_cnt = 1;
438 
439 	mc->leds[led].off_dur = mc->leds[led].def_off_dur;
440 	mc->leds[led].on_dur = mc->leds[led].def_on_dur;
441 	mc->leds[led].color = mc->leds[led].def_loc_cnt_color;
442 	break;
443 
444     case 0xfb:
445     case 0xfd:
446     case 0xfe:
447 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
448 	*rdata_len = 1;
449 	return;
450 
451     default: /* Override mode */
452 	mc->leds[led].loc_cnt = 0;
453 	mc->leds[led].off_dur = msg->data[3];
454 	mc->leds[led].on_dur = msg->data[4];
455 	if (msg->data[5] == 0xf)
456 	    mc->leds[led].color = mc->leds[led].def_override_color;
457 	else if (msg->data[5] != 0xe) /* 0xe is don't change. */
458 	    mc->leds[led].color = msg->data[5];
459     }
460 
461     printf("Setting ATCA LED %d to %s %x %x %x\n",
462 	   led,
463 	   mc->leds[led].loc_cnt ? "local_control" : "override",
464 	   mc->leds[led].off_dur,
465 	   mc->leds[led].on_dur,
466 	   mc->leds[led].color);
467 
468     rdata[0] = 0;
469     rdata[1] = IPMI_PICMG_GRP_EXT;
470     *rdata_len = 2;
471 }
472 
473 static void
handle_picmg_cmd_get_fru_led_state(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)474 handle_picmg_cmd_get_fru_led_state(lmc_data_t    *mc,
475 				   msg_t         *msg,
476 				   unsigned char *rdata,
477 				   unsigned int  *rdata_len,
478 				   void          *cb_data)
479 {
480     unsigned int led;
481 
482     if (check_msg_length(msg, 3, rdata, rdata_len))
483 	return;
484 
485     if (msg->data[1] != 0) {
486 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
487 	*rdata_len = 1;
488 	return;
489     }
490 
491     led = msg->data[2];
492     if (led >= mc->num_leds) {
493 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
494 	*rdata_len = 1;
495 	return;
496     }
497 
498     rdata[0] = 0;
499     rdata[1] = IPMI_PICMG_GRP_EXT;
500     rdata[2] = 0x00;
501     if (mc->leds[led].loc_cnt_sup)
502 	rdata[2] |= 0x01; /* Local control support */
503 
504     if (mc->leds[led].loc_cnt) {
505 	rdata[3] = mc->leds[led].off_dur;
506 	rdata[4] = mc->leds[led].on_dur;
507 	rdata[5] = mc->leds[led].color;
508 	*rdata_len = 6;
509     } else {
510 	rdata[2] |= 0x02; /* override state. */
511 	rdata[3] = mc->leds[led].def_off_dur;
512 	rdata[4] = mc->leds[led].def_on_dur;
513 	rdata[5] = mc->leds[led].def_loc_cnt_color;
514 	rdata[6] = mc->leds[led].off_dur;
515 	rdata[7] = mc->leds[led].on_dur;
516 	rdata[8] = mc->leds[led].color;
517 	*rdata_len = 9;
518     }
519 }
520 
521 static void
handle_picmg_cmd_get_shelf_address_info(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)522 handle_picmg_cmd_get_shelf_address_info(lmc_data_t    *mc,
523 					msg_t         *msg,
524 					unsigned char *rdata,
525 					unsigned int  *rdata_len,
526 					void          *cb_data)
527 {
528     handle_invalid_cmd(mc, rdata, rdata_len);
529 }
530 
531 static void
handle_picmg_cmd_set_shelf_address_info(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)532 handle_picmg_cmd_set_shelf_address_info(lmc_data_t    *mc,
533 					msg_t         *msg,
534 					unsigned char *rdata,
535 					unsigned int  *rdata_len,
536 					void          *cb_data)
537 {
538     handle_invalid_cmd(mc, rdata, rdata_len);
539 }
540 
541 static void
handle_picmg_cmd_set_ipmb_state(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)542 handle_picmg_cmd_set_ipmb_state(lmc_data_t    *mc,
543 				msg_t         *msg,
544 				unsigned char *rdata,
545 				unsigned int  *rdata_len,
546 				void          *cb_data)
547 {
548     handle_invalid_cmd(mc, rdata, rdata_len);
549 }
550 
551 static void
handle_picmg_cmd_set_fru_activation_policy(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)552 handle_picmg_cmd_set_fru_activation_policy(lmc_data_t    *mc,
553 					   msg_t         *msg,
554 					   unsigned char *rdata,
555 					   unsigned int  *rdata_len,
556 					   void          *cb_data)
557 {
558     handle_invalid_cmd(mc, rdata, rdata_len);
559 }
560 
561 static void
handle_picmg_cmd_get_fru_activation_policy(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)562 handle_picmg_cmd_get_fru_activation_policy(lmc_data_t    *mc,
563 					   msg_t         *msg,
564 					   unsigned char *rdata,
565 					   unsigned int  *rdata_len,
566 					   void          *cb_data)
567 {
568     handle_invalid_cmd(mc, rdata, rdata_len);
569 }
570 
571 static void
handle_picmg_cmd_set_fru_activation(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)572 handle_picmg_cmd_set_fru_activation(lmc_data_t    *mc,
573 				    msg_t         *msg,
574 				    unsigned char *rdata,
575 				    unsigned int  *rdata_len,
576 				    void          *cb_data)
577 {
578     int      op;
579     sensor_t *hssens;
580 
581     if (check_msg_length(msg, 3, rdata, rdata_len))
582 	return;
583 
584     if (msg->data[1] != 0) {
585 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
586 	*rdata_len = 1;
587 	return;
588     }
589 
590     if (! mc->hs_sensor) {
591 	handle_invalid_cmd(mc, rdata, rdata_len);
592 	return;
593     }
594 
595     op = msg->data[2];
596     if (op >= 2) {
597 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
598 	*rdata_len = 1;
599 	return;
600     }
601 
602     hssens = mc->hs_sensor;
603     switch (op) {
604     case 0:
605 	if (bit_set(hssens->event_status, 3)
606 	    || bit_set(hssens->event_status, 4)
607 	    || bit_set(hssens->event_status, 5))
608 	{
609 	    /* Transition to m6. */
610 	    ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num,
611 					    6, 1);
612 
613 	    /* Transition to m1. */
614 	    ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num,
615 					    1, 1);
616 	}
617 	break;
618 
619     case 1:
620 	if (bit_set(hssens->event_status, 2)) {
621 	    /* Transition to m3. */
622 	    ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num,
623 					    3, 1);
624 
625 	    /* Transition to m4. */
626 	    ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num,
627 					    4, 1);
628 	}
629     }
630 
631     rdata[0] = 0;
632     rdata[1] = IPMI_PICMG_GRP_EXT;
633     *rdata_len = 2;
634 }
635 
636 static void
handle_picmg_cmd_get_device_locator_record(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)637 handle_picmg_cmd_get_device_locator_record(lmc_data_t    *mc,
638 					   msg_t         *msg,
639 					   unsigned char *rdata,
640 					   unsigned int  *rdata_len,
641 					   void          *cb_data)
642 {
643     handle_invalid_cmd(mc, rdata, rdata_len);
644 }
645 
646 static void
handle_picmg_cmd_set_port_state(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)647 handle_picmg_cmd_set_port_state(lmc_data_t    *mc,
648 				msg_t         *msg,
649 				unsigned char *rdata,
650 				unsigned int  *rdata_len,
651 				void          *cb_data)
652 {
653     handle_invalid_cmd(mc, rdata, rdata_len);
654 }
655 
656 static void
handle_picmg_cmd_get_port_state(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)657 handle_picmg_cmd_get_port_state(lmc_data_t    *mc,
658 				msg_t         *msg,
659 				unsigned char *rdata,
660 				unsigned int  *rdata_len,
661 				void          *cb_data)
662 {
663     handle_invalid_cmd(mc, rdata, rdata_len);
664 }
665 
666 static void
handle_picmg_cmd_compute_power_properties(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)667 handle_picmg_cmd_compute_power_properties(lmc_data_t    *mc,
668 					  msg_t         *msg,
669 					  unsigned char *rdata,
670 					  unsigned int  *rdata_len,
671 					  void          *cb_data)
672 {
673     handle_invalid_cmd(mc, rdata, rdata_len);
674 }
675 
676 static void
handle_picmg_cmd_set_power_level(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)677 handle_picmg_cmd_set_power_level(lmc_data_t    *mc,
678 				 msg_t         *msg,
679 				 unsigned char *rdata,
680 				 unsigned int  *rdata_len,
681 				 void          *cb_data)
682 {
683     handle_invalid_cmd(mc, rdata, rdata_len);
684 }
685 
686 static void
handle_picmg_cmd_get_power_level(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)687 handle_picmg_cmd_get_power_level(lmc_data_t    *mc,
688 				 msg_t         *msg,
689 				 unsigned char *rdata,
690 				 unsigned int  *rdata_len,
691 				 void          *cb_data)
692 {
693     handle_invalid_cmd(mc, rdata, rdata_len);
694 }
695 
696 static void
handle_picmg_cmd_renegotiate_power(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)697 handle_picmg_cmd_renegotiate_power(lmc_data_t    *mc,
698 				   msg_t         *msg,
699 				   unsigned char *rdata,
700 				   unsigned int  *rdata_len,
701 				   void          *cb_data)
702 {
703     handle_invalid_cmd(mc, rdata, rdata_len);
704 }
705 
706 static void
handle_picmg_cmd_get_fan_speed_properties(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)707 handle_picmg_cmd_get_fan_speed_properties(lmc_data_t    *mc,
708 					  msg_t         *msg,
709 					  unsigned char *rdata,
710 					  unsigned int  *rdata_len,
711 					  void          *cb_data)
712 {
713     handle_invalid_cmd(mc, rdata, rdata_len);
714 }
715 
716 static void
handle_picmg_cmd_set_fan_level(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)717 handle_picmg_cmd_set_fan_level(lmc_data_t    *mc,
718 			       msg_t         *msg,
719 			       unsigned char *rdata,
720 			       unsigned int  *rdata_len,
721 			       void          *cb_data)
722 {
723     handle_invalid_cmd(mc, rdata, rdata_len);
724 }
725 
726 static void
handle_picmg_cmd_get_fan_level(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)727 handle_picmg_cmd_get_fan_level(lmc_data_t    *mc,
728 			       msg_t         *msg,
729 			       unsigned char *rdata,
730 			       unsigned int  *rdata_len,
731 			       void          *cb_data)
732 {
733     handle_invalid_cmd(mc, rdata, rdata_len);
734 }
735 
736 static void
handle_picmg_cmd_bused_resource(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)737 handle_picmg_cmd_bused_resource(lmc_data_t    *mc,
738 				msg_t         *msg,
739 				unsigned char *rdata,
740 				unsigned int  *rdata_len,
741 				void          *cb_data)
742 {
743     handle_invalid_cmd(mc, rdata, rdata_len);
744 }
745 
746 static void
handle_picmg_cmd_ipmb_link_info(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)747 handle_picmg_cmd_ipmb_link_info(lmc_data_t    *mc,
748 				msg_t         *msg,
749 				unsigned char *rdata,
750 				unsigned int  *rdata_len,
751 				void          *cb_data)
752 {
753     handle_invalid_cmd(mc, rdata, rdata_len);
754 }
755 
756 static void
handle_picmg_cmd_shelf_power_allocation(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)757 handle_picmg_cmd_shelf_power_allocation(lmc_data_t    *mc,
758 					msg_t         *msg,
759 					unsigned char *rdata,
760 					unsigned int  *rdata_len,
761 					void          *cb_data)
762 {
763     if (check_msg_length(msg, 2, rdata, rdata_len))
764 	return;
765 
766     if (msg->data[1] > 1) {
767 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
768 	*rdata_len = 1;
769 	return;
770     }
771 
772     rdata[0] = 0;
773     rdata[1] = IPMI_PICMG_GRP_EXT;
774     ipmi_set_uint16(rdata+2, 0);
775     if (msg->data[1] == 0) {
776 	ipmi_set_uint16(rdata+4, 105);
777 	ipmi_set_uint16(rdata+6, 227);
778 	*rdata_len = 8;
779     } else {
780 	ipmi_set_uint16(rdata+4, 227);
781 	*rdata_len = 6;
782     }
783 }
784 
785 static void
handle_picmg_cmd_shelf_manager_ipmb_address(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)786 handle_picmg_cmd_shelf_manager_ipmb_address(lmc_data_t    *mc,
787 					    msg_t         *msg,
788 					    unsigned char *rdata,
789 					    unsigned int  *rdata_len,
790 					    void          *cb_data)
791 {
792     handle_invalid_cmd(mc, rdata, rdata_len);
793 }
794 
795 static void
handle_picmg_cmd_set_fan_policy(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)796 handle_picmg_cmd_set_fan_policy(lmc_data_t    *mc,
797 				msg_t         *msg,
798 				unsigned char *rdata,
799 				unsigned int  *rdata_len,
800 				void          *cb_data)
801 {
802     handle_invalid_cmd(mc, rdata, rdata_len);
803 }
804 
805 static void
handle_picmg_cmd_get_fan_policy(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)806 handle_picmg_cmd_get_fan_policy(lmc_data_t    *mc,
807 				msg_t         *msg,
808 				unsigned char *rdata,
809 				unsigned int  *rdata_len,
810 				void          *cb_data)
811 {
812     handle_invalid_cmd(mc, rdata, rdata_len);
813 }
814 
815 
816 static void
handle_picmg_cmd_fru_control_capabilities(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)817 handle_picmg_cmd_fru_control_capabilities(lmc_data_t    *mc,
818 					  msg_t         *msg,
819 					  unsigned char *rdata,
820 					  unsigned int  *rdata_len,
821 					  void          *cb_data)
822 {
823     if (check_msg_length(msg, 2, rdata, rdata_len))
824 	return;
825 
826     if (msg->data[1] != 0) {
827 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
828 	*rdata_len = 1;
829 	return;
830     }
831 
832     rdata[0] = 0;
833     rdata[1] = IPMI_PICMG_GRP_EXT;
834     rdata[2] = 0x0e;
835     *rdata_len = 3;
836 }
837 
838 static void
handle_picmg_cmd_fru_inventory_device_lock_control(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)839 handle_picmg_cmd_fru_inventory_device_lock_control(lmc_data_t    *mc,
840 						   msg_t         *msg,
841 						   unsigned char *rdata,
842 						   unsigned int  *rdata_len,
843 						   void          *cb_data)
844 {
845     emu_data_t *emu = mc->emu;
846     uint16_t   lock_id;
847     fru_data_t *fru;
848 
849     if (mc->ipmb != 0x20) {
850 	handle_invalid_cmd(mc, rdata, rdata_len);
851 	return;
852     }
853 
854     if (check_msg_length(msg, 5, rdata, rdata_len))
855 	return;
856 
857     if (msg->data[1] != 254) {
858 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
859 	*rdata_len = 1;
860 	return;
861     }
862 
863     rdata[0] = 0;
864     rdata[1] = IPMI_PICMG_GRP_EXT;
865 
866     switch (msg->data[2]) {
867     case 0:
868 	rdata[2] = 0;
869 	rdata[3] = 0;
870 	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
871 	*rdata_len = 8;
872 	break;
873 
874     case 1:
875 	if (emu->atca_fru_inv_locked) {
876 	    rdata[0] = 0x81;
877 	    *rdata_len = 1;
878 	    break;
879 	}
880 	fru = find_fru(mc, 254);
881 	if (!fru || fru->length == 0) {
882 	    rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC;
883 	    *rdata_len = 1;
884 	    break;
885 	}
886 	emu->temp_fru_inv_data = malloc(fru->length);
887 	if (!emu->temp_fru_inv_data) {
888 	    rdata[0] = IPMI_OUT_OF_SPACE_CC;
889 	    *rdata_len = 1;
890 	    break;
891 	}
892 	emu->temp_fru_inv_data_len = fru->length;
893 	memcpy(emu->temp_fru_inv_data, fru->data,
894 	       emu->temp_fru_inv_data_len);
895 
896 	emu->atca_fru_inv_locked = 1;
897 	emu->atca_fru_inv_curr_lock_id++;
898 	ipmi_set_uint16(rdata+2, emu->atca_fru_inv_curr_lock_id);
899 	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
900 	*rdata_len = 8;
901 	emu->atca_fru_inv_lock_timeout = 20;
902 	break;
903 
904     case 2:
905 	lock_id = ipmi_get_uint16(msg->data+3);
906 	if (!emu->atca_fru_inv_locked
907 	    || (lock_id != emu->atca_fru_inv_curr_lock_id))
908 	{
909 	    rdata[0] = 0x81;
910 	    *rdata_len = 1;
911 	    break;
912 	}
913 	emu->atca_fru_inv_locked = 0;
914 	rdata[2] = 0;
915 	rdata[3] = 0;
916 	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
917 	*rdata_len = 8;
918 	free(emu->temp_fru_inv_data);
919 	emu->temp_fru_inv_data = NULL;
920 	break;
921 
922     case 3:
923 	lock_id = ipmi_get_uint16(msg->data+3);
924 	if (!emu->atca_fru_inv_locked
925 	    || (lock_id != emu->atca_fru_inv_curr_lock_id))
926 	{
927 	    rdata[0] = 0x81;
928 	    *rdata_len = 1;
929 	    break;
930 	}
931 	emu->atca_fru_inv_locked = 0;
932 	rdata[2] = 0;
933 	rdata[3] = 0;
934 	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
935 	*rdata_len = 8;
936 	emu->atca_fru_inv_curr_timestamp++;
937 	/* FIXME - validate data. */
938 	fru = find_fru(mc, 254);
939 	if (!fru || fru->length == 0) {
940 	    rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC;
941 	    *rdata_len = 1;
942 	    break;
943 	}
944 	memcpy(fru->data, emu->temp_fru_inv_data,
945 	       emu->temp_fru_inv_data_len);
946 	free(emu->temp_fru_inv_data);
947 	emu->temp_fru_inv_data = NULL;
948 	break;
949 
950     default:
951 	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
952 	*rdata_len = 1;
953 	break;
954     }
955 }
956 
957 static void
handle_picmg_cmd_fru_inventory_device_write(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)958 handle_picmg_cmd_fru_inventory_device_write(lmc_data_t    *mc,
959 					    msg_t         *msg,
960 					    unsigned char *rdata,
961 					    unsigned int  *rdata_len,
962 					    void          *cb_data)
963 {
964     emu_data_t   *emu = mc->emu;
965     uint16_t     lock_id;
966     unsigned int offset;
967     unsigned int count;
968 
969     if (mc->ipmb != 0x20) {
970 	handle_invalid_cmd(mc, rdata, rdata_len);
971 	return;
972     }
973 
974     if (check_msg_length(msg, 6, rdata, rdata_len))
975 	return;
976 
977     if (msg->data[1] != 254) {
978 	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
979 	*rdata_len = 1;
980 	return;
981     }
982 
983     lock_id = ipmi_get_uint16(msg->data+2);
984     if (!emu->atca_fru_inv_locked
985 	|| (lock_id != emu->atca_fru_inv_curr_lock_id))
986     {
987 	rdata[0] = 0x80;
988 	*rdata_len = 1;
989 	return;
990     }
991 
992     /* Reset the timer. */
993     emu->atca_fru_inv_lock_timeout = 20;
994 
995     offset = ipmi_get_uint16(msg->data+4);
996     count = msg->len - 6;
997 
998     if (offset >= emu->temp_fru_inv_data_len) {
999 	rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC;
1000 	*rdata_len = 1;
1001 	return;
1002     }
1003 
1004     if ((offset+count) > emu->temp_fru_inv_data_len) {
1005 	/* Too much data to put into FRU. */
1006 	rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC;
1007 	*rdata_len = 1;
1008 	return;
1009     }
1010 
1011     memcpy(emu->temp_fru_inv_data+offset, msg->data+6, count);
1012 
1013     rdata[0] = 0;
1014     rdata[1] = IPMI_PICMG_GRP_EXT;
1015     rdata[2] = count;
1016     *rdata_len = 3;
1017 }
1018 
1019 static void
handle_picmg_cmd_get_shelf_manager_ip_addresses(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)1020 handle_picmg_cmd_get_shelf_manager_ip_addresses(lmc_data_t    *mc,
1021 						msg_t         *msg,
1022 						unsigned char *rdata,
1023 						unsigned int  *rdata_len,
1024 						void          *cb_data)
1025 {
1026     emu_data_t   *emu = mc->emu;
1027     unsigned int addr;
1028     unsigned int count;
1029     emu_addr_t   *ap = NULL;
1030     int          i;
1031 
1032     if (check_msg_length(msg, 2, rdata, rdata_len))
1033 	return;
1034 
1035     addr = msg->data[1];
1036 
1037     for (count=0, i=0; i<MAX_EMU_ADDR; i++) {
1038 	if (emu->addr[i].valid) {
1039 	    if (count == addr)
1040 		ap = &(emu->addr[i]);
1041 	    count++;
1042 	}
1043     }
1044 
1045     if (addr >= count) {
1046 	rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC;
1047 	*rdata_len = 1;
1048 	return;
1049     }
1050 
1051     rdata[0] = 0;
1052     ipmi_set_uint32(rdata+1, emu->last_addr_change_time.tv_sec);
1053     rdata[5] = count;
1054     rdata[6] = 0x03;
1055     rdata[7] = addr - 1;
1056     rdata[8] = 20;
1057 
1058     rdata[9] = ap->addr_type;
1059     if (addr == 0)
1060 	rdata[9] |= 0x80;
1061     memcpy(rdata+10, ap->addr_data, ap->addr_len);
1062     *rdata_len = 10 + ap->addr_len;
1063 }
1064 
1065 void handle_picmg_msg(lmc_data_t    *mc,
1066 		      msg_t         *msg,
1067 		      unsigned char *rdata,
1068 		      unsigned int  *rdata_len,
1069 		      void          *cb_data);
1070 
1071 int
ipmi_emu_atca_enable(emu_data_t * emu)1072 ipmi_emu_atca_enable(emu_data_t *emu)
1073 {
1074     emu->atca_mode = 1;
1075     ipmi_emu_register_group_extension_handler(IPMI_PICMG_GRP_EXT,
1076 					      handle_picmg_msg, NULL);
1077     return 0;
1078 }
1079 
1080 int
ipmi_emu_atca_set_site(emu_data_t * emu,unsigned char hw_address,unsigned char site_type,unsigned char site_number)1081 ipmi_emu_atca_set_site(emu_data_t    *emu,
1082 		       unsigned char hw_address,
1083 		       unsigned char site_type,
1084 		       unsigned char site_number)
1085 {
1086     if (hw_address >= 128)
1087 	return EINVAL;
1088 
1089     emu->atca_sites[hw_address].valid = 1;
1090     emu->atca_sites[hw_address].hw_address = hw_address;
1091     emu->atca_sites[hw_address].site_type = site_type;
1092     emu->atca_sites[hw_address].site_number = site_number;
1093     return 0;
1094 }
1095 
1096 void
handle_picmg_msg(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)1097 handle_picmg_msg(lmc_data_t    *mc,
1098 		 msg_t         *msg,
1099 		 unsigned char *rdata,
1100 		 unsigned int  *rdata_len,
1101 		 void          *cb_data)
1102 {
1103     switch(msg->cmd) {
1104     case IPMI_PICMG_CMD_GET_PROPERTIES:
1105 	handle_picmg_get_properties(mc, msg, rdata, rdata_len, NULL);
1106 	break;
1107 
1108     case IPMI_PICMG_CMD_GET_ADDRESS_INFO:
1109 	handle_picmg_get_address_info(mc, msg, rdata, rdata_len, NULL);
1110 	break;
1111 
1112     case IPMI_PICMG_CMD_FRU_CONTROL:
1113 	handle_picmg_cmd_fru_control(mc, msg, rdata, rdata_len, NULL);
1114 	break;
1115 
1116     case IPMI_PICMG_CMD_GET_FRU_LED_PROPERTIES:
1117 	handle_picmg_cmd_get_fru_led_properties(mc, msg, rdata, rdata_len,
1118 						NULL);
1119 	break;
1120 
1121     case IPMI_PICMG_CMD_GET_LED_COLOR_CAPABILITIES:
1122 	handle_picmg_cmd_get_led_color_capabilities(mc, msg, rdata, rdata_len,
1123 						    NULL);
1124 	break;
1125 
1126     case IPMI_PICMG_CMD_SET_FRU_LED_STATE:
1127 	handle_picmg_cmd_set_fru_led_state(mc, msg, rdata, rdata_len, NULL);
1128 	break;
1129 
1130     case IPMI_PICMG_CMD_GET_FRU_LED_STATE:
1131 	handle_picmg_cmd_get_fru_led_state(mc, msg, rdata, rdata_len, NULL);
1132 	break;
1133 
1134     case IPMI_PICMG_CMD_GET_SHELF_ADDRESS_INFO:
1135 	handle_picmg_cmd_get_shelf_address_info(mc, msg, rdata, rdata_len,
1136 						NULL);
1137 	break;
1138 
1139     case IPMI_PICMG_CMD_SET_SHELF_ADDRESS_INFO:
1140 	handle_picmg_cmd_set_shelf_address_info(mc, msg, rdata, rdata_len,
1141 						NULL);
1142 	break;
1143 
1144     case IPMI_PICMG_CMD_SET_IPMB_STATE:
1145 	handle_picmg_cmd_set_ipmb_state(mc, msg, rdata, rdata_len, NULL);
1146 	break;
1147 
1148     case IPMI_PICMG_CMD_SET_FRU_ACTIVATION_POLICY:
1149 	handle_picmg_cmd_set_fru_activation_policy(mc, msg, rdata, rdata_len,
1150 						   NULL);
1151 	break;
1152 
1153     case IPMI_PICMG_CMD_GET_FRU_ACTIVATION_POLICY:
1154 	handle_picmg_cmd_get_fru_activation_policy(mc, msg, rdata, rdata_len,
1155 						   NULL);
1156 	break;
1157 
1158     case IPMI_PICMG_CMD_SET_FRU_ACTIVATION:
1159 	handle_picmg_cmd_set_fru_activation(mc, msg, rdata, rdata_len, NULL);
1160 	break;
1161 
1162     case IPMI_PICMG_CMD_GET_DEVICE_LOCATOR_RECORD:
1163 	handle_picmg_cmd_get_device_locator_record(mc, msg, rdata, rdata_len,
1164 						   NULL);
1165 	break;
1166 
1167     case IPMI_PICMG_CMD_SET_PORT_STATE:
1168 	handle_picmg_cmd_set_port_state(mc, msg, rdata, rdata_len, NULL);
1169 	break;
1170 
1171     case IPMI_PICMG_CMD_GET_PORT_STATE:
1172 	handle_picmg_cmd_get_port_state(mc, msg, rdata, rdata_len, NULL);
1173 	break;
1174 
1175     case IPMI_PICMG_CMD_COMPUTE_POWER_PROPERTIES:
1176 	handle_picmg_cmd_compute_power_properties(mc, msg, rdata, rdata_len,
1177 						  NULL);
1178 	break;
1179 
1180     case IPMI_PICMG_CMD_SET_POWER_LEVEL:
1181 	handle_picmg_cmd_set_power_level(mc, msg, rdata, rdata_len, NULL);
1182 	break;
1183 
1184     case IPMI_PICMG_CMD_GET_POWER_LEVEL:
1185 	handle_picmg_cmd_get_power_level(mc, msg, rdata, rdata_len, NULL);
1186 	break;
1187 
1188     case IPMI_PICMG_CMD_RENEGOTIATE_POWER:
1189 	handle_picmg_cmd_renegotiate_power(mc, msg, rdata, rdata_len, NULL);
1190 	break;
1191 
1192     case IPMI_PICMG_CMD_GET_FAN_SPEED_PROPERTIES:
1193 	handle_picmg_cmd_get_fan_speed_properties(mc, msg, rdata, rdata_len,
1194 						  NULL);
1195 	break;
1196 
1197     case IPMI_PICMG_CMD_SET_FAN_LEVEL:
1198 	handle_picmg_cmd_set_fan_level(mc, msg, rdata, rdata_len, NULL);
1199 	break;
1200 
1201     case IPMI_PICMG_CMD_GET_FAN_LEVEL:
1202 	handle_picmg_cmd_get_fan_level(mc, msg, rdata, rdata_len, NULL);
1203 	break;
1204 
1205     case IPMI_PICMG_CMD_BUSED_RESOURCE:
1206 	handle_picmg_cmd_bused_resource(mc, msg, rdata, rdata_len, NULL);
1207 	break;
1208 
1209     case IPMI_PICMG_CMD_IPMB_LINK_INFO:
1210 	handle_picmg_cmd_ipmb_link_info(mc, msg, rdata, rdata_len, NULL);
1211 	break;
1212 
1213     case IPMI_PICMG_CMD_SHELF_POWER_ALLOCATION:
1214 	handle_picmg_cmd_shelf_power_allocation(mc, msg, rdata, rdata_len,
1215 						NULL);
1216 	break;
1217 
1218     case IPMI_PICMG_CMD_SHELF_MANAGER_IPMB_ADDRESS:
1219 	handle_picmg_cmd_shelf_manager_ipmb_address(mc, msg, rdata, rdata_len,
1220 						    NULL);
1221 	break;
1222 
1223     case IPMI_PICMG_CMD_SET_FAN_POLICY:
1224 	handle_picmg_cmd_set_fan_policy(mc, msg, rdata, rdata_len, NULL);
1225 	break;
1226 
1227     case IPMI_PICMG_CMD_GET_FAN_POLICY:
1228 	handle_picmg_cmd_get_fan_policy(mc, msg, rdata, rdata_len, NULL);
1229 	break;
1230 
1231     case IPMI_PICMG_CMD_FRU_CONTROL_CAPABILITIES:
1232 	handle_picmg_cmd_fru_control_capabilities(mc, msg, rdata, rdata_len,
1233 						  NULL);
1234 	break;
1235 
1236     case IPMI_PICMG_CMD_FRU_INVENTORY_DEVICE_LOCK_CONTROL:
1237 	handle_picmg_cmd_fru_inventory_device_lock_control(mc, msg, rdata,
1238 							   rdata_len, NULL);
1239 	break;
1240 
1241     case IPMI_PICMG_CMD_FRU_INVENTORY_DEVICE_WRITE:
1242 	handle_picmg_cmd_fru_inventory_device_write(mc, msg, rdata, rdata_len,
1243 						    NULL);
1244 	break;
1245 
1246     case IPMI_PICMG_CMD_GET_SHELF_MANAGER_IP_ADDRESSES:
1247 	handle_picmg_cmd_get_shelf_manager_ip_addresses(mc, msg, rdata,
1248 							rdata_len, NULL);
1249 	break;
1250 
1251     default:
1252 	handle_invalid_cmd(mc, rdata, rdata_len);
1253 	break;
1254     }
1255 }
1256